From: Willem de Bruijn Date: Mon, 7 Aug 2017 09:15:40 +0000 (+0200) Subject: net-packet: fix race in packet_set_ring on PACKET_RESERVE X-Git-Tag: Ubuntu-4.10.0-32.36~4 X-Git-Url: https://git.proxmox.com/?p=mirror_ubuntu-zesty-kernel.git;a=commitdiff_plain;h=e824e06eda7dfac325d937c33cda0d45aaf4509c net-packet: fix race in packet_set_ring on PACKET_RESERVE PACKET_RESERVE reserves headroom in memory mapped packet ring frames. The value po->tp_reserve must is verified to be safe in packet_set_ring if (unlikely(req->tp_frame_size < po->tp_hdrlen + po->tp_reserve)) and the setsockopt fails once a ring is set. if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) return -EBUSY; This operation does not take the socket lock. This leads to a race similar to the one with PACKET_VERSION fixed in commit 84ac7260236a ("packet: fix race condition in packet_set_ring"). Fix this issue in the same manner: take the socket lock, which as of that patch is held for the duration of packet_set_ring. This bug was discovered with syzkaller. Reported-by: Andrey Konovalov Signed-off-by: Willem de Bruijn CVE-2017-1000111 (backported from email submission) Signed-off-by: Stefan Bader --- diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 0f074c96f43f..ebde2ef2f122 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -3640,14 +3640,19 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv if (optlen != sizeof(val)) return -EINVAL; - if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) - return -EBUSY; if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; if (val > INT_MAX) return -EINVAL; - po->tp_reserve = val; - return 0; + lock_sock(sk); + if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) + ret = -EBUSY; + else { + po->tp_reserve = val; + ret = 0; + } + release_sock(sk); + return ret; } case PACKET_LOSS: {