summaryrefslogtreecommitdiffstats
path: root/net-packet-fix-tp_reserve-race-in-packet_set_ring.patch
diff options
context:
space:
mode:
Diffstat (limited to 'net-packet-fix-tp_reserve-race-in-packet_set_ring.patch')
-rw-r--r--net-packet-fix-tp_reserve-race-in-packet_set_ring.patch57
1 files changed, 57 insertions, 0 deletions
diff --git a/net-packet-fix-tp_reserve-race-in-packet_set_ring.patch b/net-packet-fix-tp_reserve-race-in-packet_set_ring.patch
new file mode 100644
index 000000000..da7103dbe
--- /dev/null
+++ b/net-packet-fix-tp_reserve-race-in-packet_set_ring.patch
@@ -0,0 +1,57 @@
+From patchwork Thu Aug 10 16:41:58 2017
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [net] packet: fix tp_reserve race in packet_set_ring
+From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
+X-Patchwork-Id: 800274
+X-Patchwork-Delegate: davem@davemloft.net
+Message-Id: <20170810164158.52213-1-willemdebruijn.kernel@gmail.com>
+To: netdev@vger.kernel.org
+Cc: davem@davemloft.net, andreyknvl@gmail.com,
+ Willem de Bruijn <willemb@google.com>
+Date: Thu, 10 Aug 2017 12:41:58 -0400
+
+From: Willem de Bruijn <willemb@google.com>
+
+Updates to tp_reserve can race with reads of the field in
+packet_set_ring. Avoid this by holding the socket lock during
+updates in setsockopt PACKET_RESERVE.
+
+This bug was discovered by syzkaller.
+
+Fixes: 8913336a7e8d ("packet: add PACKET_RESERVE sockopt")
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: Willem de Bruijn <willemb@google.com>
+---
+ net/packet/af_packet.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
+index 0615c2a950fa..008a45ca3112 100644
+--- a/net/packet/af_packet.c
++++ b/net/packet/af_packet.c
+@@ -3700,14 +3700,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:
+ {