Skip to content

Commit b94038d

Browse files
q2venPaolo Abeni
authored andcommitted
af_unix: Stop recv(MSG_PEEK) at consumed OOB skb.
After consuming OOB data, recv() reading the preceding data must break at the OOB skb regardless of MSG_PEEK. Currently, MSG_PEEK does not stop recv() for AF_UNIX, and the behaviour is not compliant with TCP. >>> from socket import * >>> c1, c2 = socketpair(AF_UNIX) >>> c1.send(b'hello', MSG_OOB) 5 >>> c1.send(b'world') 5 >>> c2.recv(1, MSG_OOB) b'o' >>> c2.recv(9, MSG_PEEK) # This should return b'hell' b'hellworld' # even with enough buffer. Let's fix it by returning NULL for consumed skb and unlinking it only if MSG_PEEK is not specified. This patch also adds test cases that add recv(MSG_PEEK) before each recv(). Without fix: # RUN msg_oob.peek.oob_ahead_break ... # msg_oob.c:134:oob_ahead_break:AF_UNIX :hellworld # msg_oob.c:135:oob_ahead_break:Expected:hell # msg_oob.c:137:oob_ahead_break:Expected ret[0] (9) == expected_len (4) # oob_ahead_break: Test terminated by assertion # FAIL msg_oob.peek.oob_ahead_break not ok 13 msg_oob.peek.oob_ahead_break With fix: # RUN msg_oob.peek.oob_ahead_break ... # OK msg_oob.peek.oob_ahead_break ok 13 msg_oob.peek.oob_ahead_break Fixes: 314001f ("af_unix: Add OOB support") Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent d098d77 commit b94038d

2 files changed

Lines changed: 29 additions & 5 deletions

File tree

net/unix/af_unix.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2613,9 +2613,12 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
26132613
{
26142614
struct unix_sock *u = unix_sk(sk);
26152615

2616-
if (!unix_skb_len(skb) && !(flags & MSG_PEEK)) {
2617-
skb_unlink(skb, &sk->sk_receive_queue);
2618-
consume_skb(skb);
2616+
if (!unix_skb_len(skb)) {
2617+
if (!(flags & MSG_PEEK)) {
2618+
skb_unlink(skb, &sk->sk_receive_queue);
2619+
consume_skb(skb);
2620+
}
2621+
26192622
skb = NULL;
26202623
} else {
26212624
struct sk_buff *unlinked_skb = NULL;

tools/testing/selftests/net/af_unix/msg_oob.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,21 @@ FIXTURE(msg_oob)
2121
*/
2222
};
2323

24+
FIXTURE_VARIANT(msg_oob)
25+
{
26+
bool peek;
27+
};
28+
29+
FIXTURE_VARIANT_ADD(msg_oob, no_peek)
30+
{
31+
.peek = false,
32+
};
33+
34+
FIXTURE_VARIANT_ADD(msg_oob, peek)
35+
{
36+
.peek = true
37+
};
38+
2439
static void create_unix_socketpair(struct __test_metadata *_metadata,
2540
FIXTURE_DATA(msg_oob) *self)
2641
{
@@ -156,8 +171,14 @@ static void __recvpair(struct __test_metadata *_metadata,
156171
__sendpair(_metadata, self, buf, len, flags)
157172

158173
#define recvpair(expected_buf, expected_len, buf_len, flags) \
159-
__recvpair(_metadata, self, \
160-
expected_buf, expected_len, buf_len, flags)
174+
do { \
175+
if (variant->peek) \
176+
__recvpair(_metadata, self, \
177+
expected_buf, expected_len, \
178+
buf_len, (flags) | MSG_PEEK); \
179+
__recvpair(_metadata, self, \
180+
expected_buf, expected_len, buf_len, flags); \
181+
} while (0)
161182

162183
TEST_F(msg_oob, non_oob)
163184
{

0 commit comments

Comments
 (0)