skmsg: Schedule psock work if the cached skb exists on the psock
authorLiu Jian <liujian56@huawei.com>
Wed, 7 Sep 2022 07:13:11 +0000 (15:13 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 Oct 2022 10:34:46 +0000 (12:34 +0200)
[ Upstream commit bec217197b412d74168c6a42fc0f76d0cc9cad00 ]

In sk_psock_backlog function, for ingress direction skb, if no new data
packet arrives after the skb is cached, the cached skb does not have a
chance to be added to the receive queue of psock. As a result, the cached
skb cannot be received by the upper-layer application. Fix this by reschedule
the psock work to dispose the cached skb in sk_msg_recvmsg function.

Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface")
Signed-off-by: Liu Jian <liujian56@huawei.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Link: https://lore.kernel.org/bpf/20220907071311.60534-1-liujian56@huawei.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/core/skmsg.c

index 054073c7cbb958e5c968edb7d061a0c5e36ec61f..736d8b035a67939d2c4af504929ad2d1aa1a12c9 100644 (file)
@@ -435,8 +435,10 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
                        if (copied + copy > len)
                                copy = len - copied;
                        copy = copy_page_to_iter(page, sge->offset, copy, iter);
-                       if (!copy)
-                               return copied ? copied : -EFAULT;
+                       if (!copy) {
+                               copied = copied ? copied : -EFAULT;
+                               goto out;
+                       }
 
                        copied += copy;
                        if (likely(!peek)) {
@@ -456,7 +458,7 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
                                 * didn't copy the entire length lets just break.
                                 */
                                if (copy != sge->length)
-                                       return copied;
+                                       goto out;
                                sk_msg_iter_var_next(i);
                        }
 
@@ -478,7 +480,9 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
                }
                msg_rx = sk_psock_peek_msg(psock);
        }
-
+out:
+       if (psock->work_state.skb && copied > 0)
+               schedule_work(&psock->work);
        return copied;
 }
 EXPORT_SYMBOL_GPL(sk_msg_recvmsg);