Skip to content

Commit 638f326

Browse files
mmhalborkmann
authored andcommitted
af_unix: Disable MSG_OOB handling for sockets in sockmap/sockhash
AF_UNIX socket tracks the most recent OOB packet (in its receive queue) with an `oob_skb` pointer. BPF redirecting does not account for that: when an OOB packet is moved between sockets, `oob_skb` is left outdated. This results in a single skb that may be accessed from two different sockets. Take the easy way out: silently drop MSG_OOB data targeting any socket that is in a sockmap or a sockhash. Note that such silent drop is akin to the fate of redirected skb's scm_fp_list (SCM_RIGHTS, SCM_CREDENTIALS). For symmetry, forbid MSG_OOB in unix_bpf_recvmsg(). Fixes: 314001f ("af_unix: Add OOB support") Suggested-by: Kuniyuki Iwashima <[email protected]> Signed-off-by: Michal Luczaj <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Tested-by: Jakub Sitnicki <[email protected]> Reviewed-by: Kuniyuki Iwashima <[email protected]> Reviewed-by: Jakub Sitnicki <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 3c87005 commit 638f326

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

net/unix/af_unix.c

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2721,10 +2721,49 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
27212721

27222722
static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
27232723
{
2724+
struct unix_sock *u = unix_sk(sk);
2725+
struct sk_buff *skb;
2726+
int err;
2727+
27242728
if (unlikely(READ_ONCE(sk->sk_state) != TCP_ESTABLISHED))
27252729
return -ENOTCONN;
27262730

2727-
return unix_read_skb(sk, recv_actor);
2731+
mutex_lock(&u->iolock);
2732+
skb = skb_recv_datagram(sk, MSG_DONTWAIT, &err);
2733+
mutex_unlock(&u->iolock);
2734+
if (!skb)
2735+
return err;
2736+
2737+
#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
2738+
if (unlikely(skb == READ_ONCE(u->oob_skb))) {
2739+
bool drop = false;
2740+
2741+
unix_state_lock(sk);
2742+
2743+
if (sock_flag(sk, SOCK_DEAD)) {
2744+
unix_state_unlock(sk);
2745+
kfree_skb(skb);
2746+
return -ECONNRESET;
2747+
}
2748+
2749+
spin_lock(&sk->sk_receive_queue.lock);
2750+
if (likely(skb == u->oob_skb)) {
2751+
WRITE_ONCE(u->oob_skb, NULL);
2752+
drop = true;
2753+
}
2754+
spin_unlock(&sk->sk_receive_queue.lock);
2755+
2756+
unix_state_unlock(sk);
2757+
2758+
if (drop) {
2759+
WARN_ON_ONCE(skb_unref(skb));
2760+
kfree_skb(skb);
2761+
return -EAGAIN;
2762+
}
2763+
}
2764+
#endif
2765+
2766+
return recv_actor(sk, skb);
27282767
}
27292768

27302769
static int unix_stream_read_generic(struct unix_stream_read_state *state,

net/unix/unix_bpf.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ static int unix_bpf_recvmsg(struct sock *sk, struct msghdr *msg,
5454
struct sk_psock *psock;
5555
int copied;
5656

57+
if (flags & MSG_OOB)
58+
return -EOPNOTSUPP;
59+
5760
if (!len)
5861
return 0;
5962

0 commit comments

Comments
 (0)