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)
committerDaniel Borkmann <daniel@iogearbox.net>
Mon, 26 Sep 2022 15:48:05 +0000 (17:48 +0200)
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
net/core/skmsg.c

index 188f8558d27d15ff8d1a581080208fd7672cdb65..ca70525621c7162da52b9ae446337cbaac378f78 100644 (file)
@@ -434,8 +434,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)) {
@@ -455,7 +457,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);
                        }
 
@@ -477,7 +479,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);