Patch "packet: fix races in fanout_add()" 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 races in fanout_add()
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-races-in-fanout_add.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 Feb 23 21:13:19 CET 2017
From: Eric Dumazet <[email protected]>
Date: Tue, 14 Feb 2017 09:03:51 -0800
Subject: packet: fix races in fanout_add()
From: Eric Dumazet <[email protected]>
[ Upstream commit d199fab63c11998a602205f7ee7ff7c05c97164b ]
Multiple threads can call fanout_add() at the same time.
We need to grab fanout_mutex earlier to avoid races that could lead to one thread freeing po->rollover that was set by another thread.
Do the same in fanout_release(), for peace of mind, and to help us finding lockdep issues earlier.
--- net/packet/af_packet.c | 53 ++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 24 deletions(-)
net/packet/af_packet.c +29 -24
@@ -1623,6 +1623,7 @@ static void fanout_release_data(struct pstatic int fanout_add (struct sock *sk,u16 id,u16 type_flags) { +struct packet_rollover *rollover =NULL ;struct packet_sock *po =pkt_sk (sk);struct packet_fanout *f, *match;u8 type = type_flags &0xff ;
@@ -1645,23 +1646,28 @@ static int fanout_add(struct sock *sk, ureturn -EINVAL ; } +mutex_lock (&fanout_mutex); + + err = -EINVAL ;if (!po->running) -return -EINVAL ; + goto out; + err = -EALREADY ;if (po->fanout) -return -EALREADY ; + goto out;if (type ==PACKET_FANOUT_ROLLOVER || (type_flags &PACKET_FANOUT_FLAG_ROLLOVER )) { - po->rollover =kzalloc (sizeof (*po->rollover),GFP_KERNEL ); -if (!po->rollover) -return -ENOMEM ; -atomic_long_set (&po->rollover->num,0 ); -atomic_long_set (&po->rollover->num_huge,0 ); -atomic_long_set (&po->rollover->num_failed,0 ); + err = -ENOMEM ; + rollover =kzalloc (sizeof (*rollover),GFP_KERNEL ); +if (!rollover) + goto out; +atomic_long_set (&rollover->num,0 ); +atomic_long_set (&rollover->num_huge,0 ); +atomic_long_set (&rollover->num_failed,0 ); + po->rollover = rollover; } -mutex_lock (&fanout_mutex); match =NULL ;list_for_each_entry (f, &fanout_list, list) { if (f->id == id &&
@@ -1708,11 +1714,11 @@ static int fanout_add(struct sock *sk, u } } out: -mutex_unlock (&fanout_mutex); -if (err) { -kfree (po->rollover); +if (err && rollover) { +kfree (rollover); po->rollover =NULL ; } +mutex_unlock (&fanout_mutex);return err; }
@@ -1721,23 +1727,22 @@ static void fanout_release(struct sock *struct packet_sock *po =pkt_sk (sk);struct packet_fanout *f; +mutex_lock (&fanout_mutex); f = po->fanout; -if (!f) -return ; +if (f) { + po->fanout =NULL ; -mutex_lock (&fanout_mutex); - po->fanout =NULL ; +if (atomic_dec_and_test (&f->sk_ref)) { +list_del (&f->list); +dev_remove_pack (&f->prot_hook); +fanout_release_data (f); +kfree (f); + } -if (atomic_dec_and_test (&f->sk_ref)) { -list_del (&f->list); -dev_remove_pack (&f->prot_hook); -fanout_release_data (f); -kfree (f); +if (po->rollover) +kfree_rcu (po->rollover, rcu); }mutex_unlock (&fanout_mutex); - -if (po->rollover) -kfree_rcu (po->rollover, rcu); } static bool packet_extra_vlan_len_allowed(const struct net_device *dev,
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/dccp-fix-freeing-skb-too-early-for-ipv6_recvpktinfo.patch queue-4.4/ip-fix-ip_checksum-handling.patch queue-4.4/packet-fix-races-in-fanout_add.patch queue-4.4/packet-do-not-call-fanout_release-from-atomic-contexts.patch queue-4.4/net-llc-avoid-bug_on-in-skb_orphan.patch