Message ID | 20220201022358.330621-1-eric.dumazet@gmail.com (mailing list archive) |
---|---|
State | Accepted |
Commit | e42e70ad6ae2ae511a6143d2e8da929366e58bd9 |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net] af_packet: fix data-race in packet_setsockopt / packet_setsockopt | expand |
Hello: This patch was applied to netdev/net.git (master) by Jakub Kicinski <kuba@kernel.org>: On Mon, 31 Jan 2022 18:23:58 -0800 you wrote: > From: Eric Dumazet <edumazet@google.com> > > When packet_setsockopt( PACKET_FANOUT_DATA ) reads po->fanout, > no lock is held, meaning that another thread can change po->fanout. > > Given that po->fanout can only be set once during the socket lifetime > (it is only cleared from fanout_release()), we can use > READ_ONCE()/WRITE_ONCE() to document the race. > > [...] Here is the summary with links: - [net] af_packet: fix data-race in packet_setsockopt / packet_setsockopt https://git.kernel.org/netdev/net/c/e42e70ad6ae2 You are awesome, thank you!
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 85ea7ddb48db6a50228ae2b9a255bd161d5b12ed..ab87f22cc7ecde517ba4cd0b3804a28c3cccfc85 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1789,7 +1789,10 @@ static int fanout_add(struct sock *sk, struct fanout_args *args) err = -ENOSPC; if (refcount_read(&match->sk_ref) < match->max_num_members) { __dev_remove_pack(&po->prot_hook); - po->fanout = match; + + /* Paired with packet_setsockopt(PACKET_FANOUT_DATA) */ + WRITE_ONCE(po->fanout, match); + po->rollover = rollover; rollover = NULL; refcount_set(&match->sk_ref, refcount_read(&match->sk_ref) + 1); @@ -3934,7 +3937,8 @@ packet_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval, } case PACKET_FANOUT_DATA: { - if (!po->fanout) + /* Paired with the WRITE_ONCE() in fanout_add() */ + if (!READ_ONCE(po->fanout)) return -EINVAL; return fanout_set_data(po, optval, optlen);