Skip to content

Commit 5be6824

Browse files
wdebruijgregkh
authored andcommitted
packet: hold bind lock when rebinding to fanout hook
[ Upstream commit 008ba2a13f2d04c947adc536d19debb8fe66f110 ] 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent aa90be3 commit 5be6824

1 file changed

Lines changed: 11 additions & 5 deletions

File tree

net/packet/af_packet.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,10 +1652,6 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
16521652

16531653
mutex_lock(&fanout_mutex);
16541654

1655-
err = -EINVAL;
1656-
if (!po->running)
1657-
goto out;
1658-
16591655
err = -EALREADY;
16601656
if (po->fanout)
16611657
goto out;
@@ -1704,7 +1700,10 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
17041700
list_add(&match->list, &fanout_list);
17051701
}
17061702
err = -EINVAL;
1707-
if (match->type == type &&
1703+
1704+
spin_lock(&po->bind_lock);
1705+
if (po->running &&
1706+
match->type == type &&
17081707
match->prot_hook.type == po->prot_hook.type &&
17091708
match->prot_hook.dev == po->prot_hook.dev) {
17101709
err = -ENOSPC;
@@ -1716,6 +1715,13 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
17161715
err = 0;
17171716
}
17181717
}
1718+
spin_unlock(&po->bind_lock);
1719+
1720+
if (err && !refcount_read(&match->sk_ref)) {
1721+
list_del(&match->list);
1722+
kfree(match);
1723+
}
1724+
17191725
out:
17201726
if (err && rollover) {
17211727
kfree(rollover);

0 commit comments

Comments
 (0)