mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
net/packet: avoid fanout hook re-registration after unregister
packet_set_ring() temporarily detaches a socket from packet delivery while
reconfiguring its ring. It records the previous running state, clears
po->num, unregisters the protocol hook when needed, drops po->bind_lock,
and later restores po->num and re-registers the hook from the saved
was_running value.
That unlocked window can race with NETDEV_UNREGISTER. The notifier can
observe the socket as not running, skip __unregister_prot_hook(), and
invalidate the per-socket binding by setting po->ifindex to -1 and clearing
po->prot_hook.dev. A one-member fanout group can still retain its shared
fanout hook device pointer. When packet_set_ring() resumes, re-registering
solely from the stale was_running state can re-add the fanout hook after
the device has been unregistered.
Treat po->ifindex == -1 as an invalidated binding after reacquiring
po->bind_lock. This is distinct from ifindex 0, the normal
unbound/wildcard state: ifindex -1 marks an existing device binding that
was invalidated when the device was unregistered. Restore po->num as
before, but do not re-register the hook if device unregister already
detached the socket.
Fixes: dc99f60069 ("packet: Add fanout support.")
Link: https://lore.kernel.org/netdev/20260701113947.23180-1-david.lee@trailofbits.com/
Signed-off-by: David Lee <david.lee@trailofbits.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20260707104440.833129-1-david.lee@trailofbits.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
f6e3b21608
commit
50aff80475
|
|
@ -4561,7 +4561,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
|
|||
|
||||
spin_lock(&po->bind_lock);
|
||||
WRITE_ONCE(po->num, num);
|
||||
if (was_running)
|
||||
/*
|
||||
* NETDEV_UNREGISTER may have invalidated the binding while bind_lock
|
||||
* was dropped above. Do not re-add a fanout hook to a dead device.
|
||||
*/
|
||||
if (was_running && READ_ONCE(po->ifindex) != -1)
|
||||
register_prot_hook(sk);
|
||||
|
||||
spin_unlock(&po->bind_lock);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user