summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorKuniyuki Iwashima <kuniyu@amazon.com>2024-04-10 20:10:15 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-04-27 18:11:32 +0300
commitaea3cb8cfb307fa17938159416a65c7f3fc2cdcc (patch)
tree59d16d84fed7acf5d126500d577f36728c4a5b7b /net
parent4ed82dd368ad883dc4284292937b882f044e625d (diff)
downloadlinux-aea3cb8cfb307fa17938159416a65c7f3fc2cdcc.tar.xz
af_unix: Call manage_oob() for every skb in unix_stream_read_generic().
[ Upstream commit 283454c8a123072e5c386a5a2b5fc576aa455b6f ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'net')
-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 918724844231..1340cb86f104 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2665,6 +2665,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);
@@ -2676,7 +2677,6 @@ redo:
}
}
#endif
-again:
if (skb == NULL) {
if (copied >= target)
goto unlock;