From: Kuniyuki Iwashima <kuniyu@amazon.com>
To: "David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>
Cc: Rao Shoaib <Rao.Shoaib@oracle.com>,
Kuniyuki Iwashima <kuniyu@amazon.com>,
Kuniyuki Iwashima <kuni1840@gmail.com>, <netdev@vger.kernel.org>
Subject: [PATCH v1 net 04/11] af_unix: Don't stop recv(MSG_DONTWAIT) if consumed OOB skb is at the head.
Date: Mon, 24 Jun 2024 18:36:38 -0700 [thread overview]
Message-ID: <20240625013645.45034-5-kuniyu@amazon.com> (raw)
In-Reply-To: <20240625013645.45034-1-kuniyu@amazon.com>
Let's say a socket send()s "hello" with MSG_OOB and "world" without flags,
>>> from socket import *
>>> c1, c2 = socketpair(AF_UNIX)
>>> c1.send(b'hello', MSG_OOB)
5
>>> c1.send(b'world')
5
and its peer recv()s "hell" and "o".
>>> c2.recv(10)
b'hell'
>>> c2.recv(1, MSG_OOB)
b'o'
Now the consumed OOB skb stays at the head of recvq to return a correct
value for ioctl(SIOCATMARK), which is broken now and fixed by a later
patch.
Then, if peer issues recv() with MSG_DONTWAIT, manage_oob() returns NULL,
so recv() ends up with -EAGAIN.
>>> c2.setblocking(False) # This causes -EAGAIN even with available data
>>> c2.recv(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
BlockingIOError: [Errno 11] Resource temporarily unavailable
However, next recv() will return the following available data, "world".
>>> c2.recv(5)
b'world'
When the consumed OOB skb is at the head of the queue, we need to fetch
the next skb to fix the weird behaviour.
Note that the issue does not happen without MSG_DONTWAIT because we can
retry after manage_oob().
This patch also adds a test case that covers the issue.
Without fix:
# RUN msg_oob.no_peek.ex_oob_break ...
# msg_oob.c:134:ex_oob_break:AF_UNIX :Resource temporarily unavailable
# msg_oob.c:135:ex_oob_break:Expected:ld
# msg_oob.c:137:ex_oob_break:Expected ret[0] (-1) == expected_len (2)
# ex_oob_break: Test terminated by assertion
# FAIL msg_oob.no_peek.ex_oob_break
not ok 8 msg_oob.no_peek.ex_oob_break
With fix:
# RUN msg_oob.no_peek.ex_oob_break ...
# OK msg_oob.no_peek.ex_oob_break
ok 8 msg_oob.no_peek.ex_oob_break
Fixes: 314001f0bf92 ("af_unix: Add OOB support")
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
net/unix/af_unix.c | 19 +++++++++++++++----
tools/testing/selftests/net/af_unix/msg_oob.c | 11 +++++++++++
2 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 2eaecf9d78a4..b0b97f8d0d09 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2614,12 +2614,23 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
struct unix_sock *u = unix_sk(sk);
if (!unix_skb_len(skb)) {
- if (!(flags & MSG_PEEK)) {
- skb_unlink(skb, &sk->sk_receive_queue);
- consume_skb(skb);
+ struct sk_buff *unlinked_skb = NULL;
+
+ spin_lock(&sk->sk_receive_queue.lock);
+
+ if (copied) {
+ skb = NULL;
+ } else if (flags & MSG_PEEK) {
+ skb = skb_peek_next(skb, &sk->sk_receive_queue);
+ } else {
+ unlinked_skb = skb;
+ skb = skb_peek_next(skb, &sk->sk_receive_queue);
+ __skb_unlink(unlinked_skb, &sk->sk_receive_queue);
}
- skb = NULL;
+ spin_unlock(&sk->sk_receive_queue.lock);
+
+ consume_skb(unlinked_skb);
} else {
struct sk_buff *unlinked_skb = NULL;
diff --git a/tools/testing/selftests/net/af_unix/msg_oob.c b/tools/testing/selftests/net/af_unix/msg_oob.c
index de8d1fcde883..b5226ccec3ec 100644
--- a/tools/testing/selftests/net/af_unix/msg_oob.c
+++ b/tools/testing/selftests/net/af_unix/msg_oob.c
@@ -238,4 +238,15 @@ TEST_F(msg_oob, oob_break_drop)
recvpair("", -EINVAL, 1, MSG_OOB);
}
+TEST_F(msg_oob, ex_oob_break)
+{
+ sendpair("hello", 5, MSG_OOB);
+ sendpair("wor", 3, MSG_OOB);
+ sendpair("ld", 2, 0);
+
+ recvpair("hellowo", 7, 10, 0); /* Break at OOB but not at ex-OOB. */
+ recvpair("r", 1, 1, MSG_OOB);
+ recvpair("ld", 2, 2, 0);
+}
+
TEST_HARNESS_MAIN
--
2.30.2
next prev parent reply other threads:[~2024-06-25 1:38 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-25 1:36 [PATCH v1 net 00/11] af_unix: Fix bunch of MSG_OOB bugs and add new tests Kuniyuki Iwashima
2024-06-25 1:36 ` [PATCH v1 net 01/11] selftest: af_unix: Remove test_unix_oob.c Kuniyuki Iwashima
2024-06-25 1:36 ` [PATCH v1 net 02/11] selftest: af_unix: Add msg_oob.c Kuniyuki Iwashima
2024-06-26 0:44 ` Jakub Kicinski
2024-06-26 1:45 ` Kuniyuki Iwashima
2024-06-26 2:01 ` Jakub Kicinski
2024-06-27 14:05 ` kernel test robot
2024-06-25 1:36 ` [PATCH v1 net 03/11] af_unix: Stop recv(MSG_PEEK) at consumed OOB skb Kuniyuki Iwashima
2024-06-26 16:56 ` Paolo Abeni
2024-06-26 21:10 ` Paolo Abeni
2024-06-26 21:47 ` Kuniyuki Iwashima
2024-06-27 10:04 ` Paolo Abeni
2024-07-06 9:38 ` Rao Shoaib
2024-06-25 1:36 ` Kuniyuki Iwashima [this message]
2024-06-25 1:36 ` [PATCH v1 net 05/11] selftest: af_unix: Add non-TCP-compliant test cases in msg_oob.c Kuniyuki Iwashima
2024-06-25 1:36 ` [PATCH v1 net 06/11] af_unix: Don't stop recv() at consumed ex-OOB skb Kuniyuki Iwashima
2024-06-25 1:36 ` [PATCH v1 net 07/11] selftest: af_unix: Add SO_OOBINLINE test cases in msg_oob.c Kuniyuki Iwashima
2024-06-25 1:36 ` [PATCH v1 net 08/11] selftest: af_unix: Check SIGURG after every send() " Kuniyuki Iwashima
2024-06-25 1:36 ` [PATCH v1 net 09/11] selftest: af_unix: Check EPOLLPRI after every send()/recv() " Kuniyuki Iwashima
2024-06-25 1:36 ` [PATCH v1 net 10/11] af_unix: Fix wrong ioctl(SIOCATMARK) when consumed OOB skb is at the head Kuniyuki Iwashima
2024-06-25 1:36 ` [PATCH v1 net 11/11] selftest: af_unix: Check SIOCATMARK after every send()/recv() in msg_oob.c Kuniyuki Iwashima
2024-06-26 0:43 ` [PATCH v1 net 00/11] af_unix: Fix bunch of MSG_OOB bugs and add new tests Jakub Kicinski
2024-06-26 1:31 ` Kuniyuki Iwashima
2024-06-27 10:10 ` patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240625013645.45034-5-kuniyu@amazon.com \
--to=kuniyu@amazon.com \
--cc=Rao.Shoaib@oracle.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=kuni1840@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).