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: 314001f0bf
("af_unix: Add OOB support")
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
d098d77232
commit
b94038d841
2 changed files with 29 additions and 5 deletions
|
@ -2613,9 +2613,12 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
|
||||||
{
|
{
|
||||||
struct unix_sock *u = unix_sk(sk);
|
struct unix_sock *u = unix_sk(sk);
|
||||||
|
|
||||||
if (!unix_skb_len(skb) && !(flags & MSG_PEEK)) {
|
if (!unix_skb_len(skb)) {
|
||||||
skb_unlink(skb, &sk->sk_receive_queue);
|
if (!(flags & MSG_PEEK)) {
|
||||||
consume_skb(skb);
|
skb_unlink(skb, &sk->sk_receive_queue);
|
||||||
|
consume_skb(skb);
|
||||||
|
}
|
||||||
|
|
||||||
skb = NULL;
|
skb = NULL;
|
||||||
} else {
|
} else {
|
||||||
struct sk_buff *unlinked_skb = NULL;
|
struct sk_buff *unlinked_skb = NULL;
|
||||||
|
|
|
@ -21,6 +21,21 @@ FIXTURE(msg_oob)
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FIXTURE_VARIANT(msg_oob)
|
||||||
|
{
|
||||||
|
bool peek;
|
||||||
|
};
|
||||||
|
|
||||||
|
FIXTURE_VARIANT_ADD(msg_oob, no_peek)
|
||||||
|
{
|
||||||
|
.peek = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
FIXTURE_VARIANT_ADD(msg_oob, peek)
|
||||||
|
{
|
||||||
|
.peek = true
|
||||||
|
};
|
||||||
|
|
||||||
static void create_unix_socketpair(struct __test_metadata *_metadata,
|
static void create_unix_socketpair(struct __test_metadata *_metadata,
|
||||||
FIXTURE_DATA(msg_oob) *self)
|
FIXTURE_DATA(msg_oob) *self)
|
||||||
{
|
{
|
||||||
|
@ -156,8 +171,14 @@ static void __recvpair(struct __test_metadata *_metadata,
|
||||||
__sendpair(_metadata, self, buf, len, flags)
|
__sendpair(_metadata, self, buf, len, flags)
|
||||||
|
|
||||||
#define recvpair(expected_buf, expected_len, buf_len, flags) \
|
#define recvpair(expected_buf, expected_len, buf_len, flags) \
|
||||||
__recvpair(_metadata, self, \
|
do { \
|
||||||
expected_buf, expected_len, buf_len, flags)
|
if (variant->peek) \
|
||||||
|
__recvpair(_metadata, self, \
|
||||||
|
expected_buf, expected_len, \
|
||||||
|
buf_len, (flags) | MSG_PEEK); \
|
||||||
|
__recvpair(_metadata, self, \
|
||||||
|
expected_buf, expected_len, buf_len, flags); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
TEST_F(msg_oob, non_oob)
|
TEST_F(msg_oob, non_oob)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue