]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
af_unix: Read with MSG_PEEK loops if the first unread byte is OOB
authorRao Shoaib <Rao.Shoaib@oracle.com>
Tue, 11 Jun 2024 08:46:39 +0000 (01:46 -0700)
committerJakub Kicinski <kuba@kernel.org>
Thu, 13 Jun 2024 15:03:55 +0000 (08:03 -0700)
Read with MSG_PEEK flag loops if the first byte to read is an OOB byte.
commit 22dd70eb2c3d ("af_unix: Don't peek OOB data without MSG_OOB.")
addresses the loop issue but does not address the issue that no data
beyond OOB byte can be read.

>>> from socket import *
>>> c1, c2 = socketpair(AF_UNIX, SOCK_STREAM)
>>> c1.send(b'a', MSG_OOB)
1
>>> c1.send(b'b')
1
>>> c2.recv(1, MSG_PEEK | MSG_DONTWAIT)
b'b'

>>> from socket import *
>>> c1, c2 = socketpair(AF_UNIX, SOCK_STREAM)
>>> c2.setsockopt(SOL_SOCKET, SO_OOBINLINE, 1)
>>> c1.send(b'a', MSG_OOB)
1
>>> c1.send(b'b')
1
>>> c2.recv(1, MSG_PEEK | MSG_DONTWAIT)
b'a'
>>> c2.recv(1, MSG_PEEK | MSG_DONTWAIT)
b'a'
>>> c2.recv(1, MSG_DONTWAIT)
b'a'
>>> c2.recv(1, MSG_PEEK | MSG_DONTWAIT)
b'b'
>>>

Fixes: 314001f0bf92 ("af_unix: Add OOB support")
Signed-off-by: Rao Shoaib <Rao.Shoaib@oracle.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://lore.kernel.org/r/20240611084639.2248934-1-Rao.Shoaib@oracle.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/unix/af_unix.c

index 80846279de9f3b94be5c60eda8be17f2adeeaf6b..5e695a9a609c26a0fb75dfbcef768014df382ace 100644 (file)
@@ -2625,18 +2625,18 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
                if (skb == u->oob_skb) {
                        if (copied) {
                                skb = NULL;
-                       } else if (sock_flag(sk, SOCK_URGINLINE)) {
-                               if (!(flags & MSG_PEEK)) {
+                       } else if (!(flags & MSG_PEEK)) {
+                               if (sock_flag(sk, SOCK_URGINLINE)) {
                                        WRITE_ONCE(u->oob_skb, NULL);
                                        consume_skb(skb);
+                               } else {
+                                       __skb_unlink(skb, &sk->sk_receive_queue);
+                                       WRITE_ONCE(u->oob_skb, NULL);
+                                       unlinked_skb = skb;
+                                       skb = skb_peek(&sk->sk_receive_queue);
                                }
-                       } else if (flags & MSG_PEEK) {
-                               skb = NULL;
-                       } else {
-                               __skb_unlink(skb, &sk->sk_receive_queue);
-                               WRITE_ONCE(u->oob_skb, NULL);
-                               unlinked_skb = skb;
-                               skb = skb_peek(&sk->sk_receive_queue);
+                       } else if (!sock_flag(sk, SOCK_URGINLINE)) {
+                               skb = skb_peek_next(skb, &sk->sk_receive_queue);
                        }
                }