Skip to content

Commit 008ba2a

Browse files
wdebruijdavem330
authored andcommitted
packet: hold bind lock when rebinding to fanout hook
Packet socket bind operations must hold the po->bind_lock. This keeps po->running consistent with whether the socket is actually on a ptype list to receive packets. fanout_add unbinds a socket and its packet_rcv/tpacket_rcv call, then binds the fanout object to receive through packet_rcv_fanout. Make it hold the po->bind_lock when testing po->running and rebinding. Else, it can race with other rebind operations, such as that in packet_set_ring from packet_rcv to tpacket_rcv. Concurrent updates can result in a socket being added to a fanout group twice, causing use-after-free KASAN bug reports, among others. Reported independently by both trinity and syzkaller. Verified that the syzkaller reproducer passes after this patch. Fixes: dc99f60 ("packet: Add fanout support.") Reported-by: nixioaming <nixiaoming@huawei.com> Signed-off-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 35e015e commit 008ba2a

File tree

1 file changed

+11
-5
lines changed

1 file changed

+11
-5
lines changed

Diff for: net/packet/af_packet.c

+11-5
Original file line numberDiff line numberDiff line change
@@ -1684,10 +1684,6 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
16841684

16851685
mutex_lock(&fanout_mutex);
16861686

1687-
err = -EINVAL;
1688-
if (!po->running)
1689-
goto out;
1690-
16911687
err = -EALREADY;
16921688
if (po->fanout)
16931689
goto out;
@@ -1749,7 +1745,10 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
17491745
list_add(&match->list, &fanout_list);
17501746
}
17511747
err = -EINVAL;
1752-
if (match->type == type &&
1748+
1749+
spin_lock(&po->bind_lock);
1750+
if (po->running &&
1751+
match->type == type &&
17531752
match->prot_hook.type == po->prot_hook.type &&
17541753
match->prot_hook.dev == po->prot_hook.dev) {
17551754
err = -ENOSPC;
@@ -1761,6 +1760,13 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
17611760
err = 0;
17621761
}
17631762
}
1763+
spin_unlock(&po->bind_lock);
1764+
1765+
if (err && !refcount_read(&match->sk_ref)) {
1766+
list_del(&match->list);
1767+
kfree(match);
1768+
}
1769+
17641770
out:
17651771
if (err && rollover) {
17661772
kfree(rollover);

0 commit comments

Comments
 (0)