af_unix: check socket state when queuing OOB
authorRao Shoaib <Rao.Shoaib@oracle.com>
Fri, 13 Aug 2021 18:19:34 +0000 (11:19 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 16 Aug 2021 10:12:37 +0000 (11:12 +0100)
edumazet@google.com pointed out that queue_oob
does not check socket state after acquiring
the lock. He also pointed to an incorrect usage
of kfree_skb and an unnecessary setting of skb
length. This patch addresses those issue.

Signed-off-by: Rao Shoaib <Rao.Shoaib@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/unix/af_unix.c

index 1c2224f05b513bda98a9a9f40d5b00b158aea44f..4cf0b1c47f0f99e99c12d37af2494f301a965856 100644 (file)
@@ -1908,7 +1908,6 @@ static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other
                return err;
 
        skb_put(skb, 1);
-       skb->len = 1;
        err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, 1);
 
        if (err) {
@@ -1917,11 +1916,19 @@ static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other
        }
 
        unix_state_lock(other);
+
+       if (sock_flag(other, SOCK_DEAD) ||
+           (other->sk_shutdown & RCV_SHUTDOWN)) {
+               unix_state_unlock(other);
+               kfree_skb(skb);
+               return -EPIPE;
+       }
+
        maybe_add_creds(skb, sock, other);
        skb_get(skb);
 
        if (ousk->oob_skb)
-               kfree_skb(ousk->oob_skb);
+               consume_skb(ousk->oob_skb);
 
        ousk->oob_skb = skb;