Patch "packet: fix race condition in packet_set_ring" has been added to the 4.4-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
packet: fix race condition in packet_set_ring
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
packet-fix-race-condition-in-packet_set_ring.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From foo@baz Thu Dec 8 07:18:57 CET 2016
From: Philip Pettersson <[email protected]>
Date: Wed, 30 Nov 2016 14:55:36 -0800
Subject: packet: fix race condition in packet_set_ring
From: Philip Pettersson <[email protected]>
[ Upstream commit 84ac7260236a49c79eede91617700174c2c19b0c ]
When packet_set_ring creates a ring buffer it will initialize a struct timer_list if the packet version is TPACKET_V3. This value can then be raced by a different thread calling setsockopt to set the version to TPACKET_V1 before packet_set_ring has finished.
This leads to a use-after-free on a function pointer in the struct timer_list when the socket is closed as the previously initialized timer will not be deleted.
The bug is fixed by taking lock_sock(sk) in packet_setsockopt when changing the packet version while also taking the lock at the start of packet_set_ring.
--- net/packet/af_packet.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
net/packet/af_packet.c +12 -6
@@ -3572,19 +3572,25 @@ packet_setsockopt(struct socket *sock, iif (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 ;switch (val) {case TPACKET_V1 :case TPACKET_V2 :case TPACKET_V3 : - po->tp_version = val; -return 0 ; +break ;default :return -EINVAL ; } +lock_sock (sk); +if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { + ret = -EBUSY ; + }else { + po->tp_version = val; + ret =0 ; + } +release_sock (sk); +return ret; }case PACKET_RESERVE : {
@@ -4067,6 +4073,7 @@ static int packet_set_ring(struct sock */* Added to avoid minimal code churn */ struct tpacket_req *req = &req_u->req; +lock_sock (sk);/* Opening a Tx-ring is NOT supported in TPACKET_V3 */ if (!closing && tx_ring && (po->tp_version >TPACKET_V2 )) {WARN (1 ,"Tx-ring is not supported.\n" );
@@ -4148,7 +4155,6 @@ static int packet_set_ring(struct sock * goto out; } -lock_sock (sk);/* Detach socket from network */ spin_lock (&po->bind_lock);
@@ -4197,11 +4203,11 @@ static int packet_set_ring(struct sock *if (!tx_ring)prb_shutdown_retire_blk_timer (po, rb_queue); } -release_sock (sk);if (pg_vec)free_pg_vec (pg_vec, order, req->tp_block_nr); out: +release_sock (sk);return err; }
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/packet-fix-race-condition-in-packet_set_ring.patch