From: Jiexun Wang unix_ioctl() peeks at the receive queue and may check both the head skb and its successor while deciding whether SIOCATMARK should report the mark. However, u->iolock does not stabilize receive-queue element lifetime. Queue teardown paths can purge or splice the queue under sk->sk_receive_queue.lock and free the skb while unix_ioctl() still uses it. Take sk->sk_receive_queue.lock while inspecting the queue so the skb and next_skb stay alive for the whole decision. Fixes: 314001f0bf92 ("af_unix: Add OOB support") Reported-by: Yifan Wu Reported-by: Juefei Pu Co-developed-by: Yuan Tan Signed-off-by: Yuan Tan Suggested-by: Xin Liu Tested-by: Ren Wei Signed-off-by: Jiexun Wang Signed-off-by: Ren Wei --- net/unix/af_unix.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index b23c33df8b46..54f12d5cda37 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -3301,6 +3301,8 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) int answ = 0; mutex_lock(&u->iolock); + /* The receive queue lock keeps skb and next_skb alive. */ + spin_lock(&sk->sk_receive_queue.lock); skb = skb_peek(&sk->sk_receive_queue); if (skb) { @@ -3315,6 +3317,7 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) answ = 1; } + spin_unlock(&sk->sk_receive_queue.lock); mutex_unlock(&u->iolock); err = put_user(answ, (int __user *)arg); -- 2.34.1