aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuniyuki Iwashima <kuniyu@amazon.com>2024-04-10 10:10:15 -0700
committerJakub Kicinski <kuba@kernel.org>2024-04-12 19:05:48 -0700
commit283454c8a123072e5c386a5a2b5fc576aa455b6f (patch)
treea7412e9dbf296da8d1654cd5d8ca6144d788df60
parent90be7a5ce0e5faec62782c8af37ad4ea0b9ecd40 (diff)
downloadlinux-283454c8a123072e5c386a5a2b5fc576aa455b6f.tar.gz
af_unix: Call manage_oob() for every skb in unix_stream_read_generic().
When we call recv() for AF_UNIX socket, we first peek one skb and calls manage_oob() to check if the skb is sent with MSG_OOB. However, when we fetch the next (and the following) skb, manage_oob() is not called now, leading a wrong behaviour. Let's say a socket send()s "hello" with MSG_OOB and the peer tries to recv() 5 bytes with MSG_PEEK. Here, we should get only "hell" without 'o', but actually not: >>> from socket import * >>> c1, c2 = socketpair(AF_UNIX, SOCK_STREAM) >>> c1.send(b'hello', MSG_OOB) 5 >>> c2.recv(5, MSG_PEEK) b'hello' The first skb fills 4 bytes, and the next skb is peeked but not properly checked by manage_oob(). Let's move up the again label to call manage_oob() for evry skb. With this patch: >>> from socket import * >>> c1, c2 = socketpair(AF_UNIX, SOCK_STREAM) >>> c1.send(b'hello', MSG_OOB) 5 >>> c2.recv(5, MSG_PEEK) b'hell' Fixes: 314001f0bf92 ("af_unix: Add OOB support") Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com> Link: https://lore.kernel.org/r/20240410171016.7621-2-kuniyu@amazon.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--net/unix/af_unix.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index d032eb5fa6df1e..f297320438bfd3 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2741,6 +2741,7 @@ redo:
last = skb = skb_peek(&sk->sk_receive_queue);
last_len = last ? last->len : 0;
+again:
#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
if (skb) {
skb = manage_oob(skb, sk, flags, copied);
@@ -2752,7 +2753,6 @@ redo:
}
}
#endif
-again:
if (skb == NULL) {
if (copied >= target)
goto unlock;