From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
To: Stanislav Fomichev <stfomichev@gmail.com>, netdev@vger.kernel.org
Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, willemdebruijn.kernel@gmail.com,
horms@kernel.org, stfomichev@gmail.com,
linux-kernel@vger.kernel.org,
syzbot+b191b5ccad8d7a986286@syzkaller.appspotmail.com
Subject: Re: [PATCH net] af_packet: move notifier's packet_dev_mc out of rcu critical section
Date: Tue, 20 May 2025 22:41:30 -0400 [thread overview]
Message-ID: <682d3d5a77189_97c02294a3@willemb.c.googlers.com.notmuch> (raw)
In-Reply-To: <20250520202046.2620300-1-stfomichev@gmail.com>
Stanislav Fomichev wrote:
> Calling `PACKET_ADD_MEMBERSHIP` on an ops-locked device can trigger
> the `NETDEV_UNREGISTER` notifier,
This made it sound to me as if the notifier is called as a result of
the setsockopt.
If respinning, please rewrite to make clear that the two are
independent events. The stack trace in the bug also makes clear
that the notifier trigger is a device going away.
> which may require disabling promiscuous
> and/or allmulti mode. Both of these operations require acquiring the netdev
> instance lock. Move the call to `packet_dev_mc` outside of the RCU critical
> section.
>
> Closes: https://syzkaller.appspot.com/bug?extid=b191b5ccad8d7a986286
> Reported-by: syzbot+b191b5ccad8d7a986286@syzkaller.appspotmail.com
> Fixes: ad7c7b2172c3 ("net: hold netdev instance lock during sysfs operations")
> Signed-off-by: Stanislav Fomichev <stfomichev@gmail.com>
> ---
> net/packet/af_packet.c | 20 +++++++++++++++-----
> net/packet/internal.h | 1 +
> 2 files changed, 16 insertions(+), 5 deletions(-)
>
> diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
> index d4dba06297c3..5a6132816b2e 100644
> --- a/net/packet/af_packet.c
> +++ b/net/packet/af_packet.c
> @@ -3713,15 +3713,15 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i,
> }
>
> static void packet_dev_mclist_delete(struct net_device *dev,
> - struct packet_mclist **mlp)
> + struct packet_mclist **mlp,
> + struct list_head *list)
> {
> struct packet_mclist *ml;
>
> while ((ml = *mlp) != NULL) {
> if (ml->ifindex == dev->ifindex) {
> - packet_dev_mc(dev, ml, -1);
> + list_add(&ml->remove_list, list);
> *mlp = ml->next;
> - kfree(ml);
> } else
> mlp = &ml->next;
> }
> @@ -4233,9 +4233,11 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
> static int packet_notifier(struct notifier_block *this,
> unsigned long msg, void *ptr)
> {
> - struct sock *sk;
> struct net_device *dev = netdev_notifier_info_to_dev(ptr);
> struct net *net = dev_net(dev);
> + struct packet_mclist *ml, *tmp;
> + LIST_HEAD(mclist);
> + struct sock *sk;
>
> rcu_read_lock();
> sk_for_each_rcu(sk, &net->packet.sklist) {
> @@ -4244,7 +4246,8 @@ static int packet_notifier(struct notifier_block *this,
> switch (msg) {
> case NETDEV_UNREGISTER:
> if (po->mclist)
> - packet_dev_mclist_delete(dev, &po->mclist);
> + packet_dev_mclist_delete(dev, &po->mclist,
> + &mclist);
> fallthrough;
>
> case NETDEV_DOWN:
> @@ -4277,6 +4280,13 @@ static int packet_notifier(struct notifier_block *this,
> }
> }
> rcu_read_unlock();
> +
> + /* packet_dev_mc might grab instance locks so can't run under rcu */
> + list_for_each_entry_safe(ml, tmp, &mclist, remove_list) {
> + packet_dev_mc(dev, ml, -1);
> + kfree(ml);
> + }
> +
Just verifying my understanding of the not entirely obvious locking:
po->mclist modifications (add, del, flush, unregister) are all
protected by the RTNL, not the RCU. The RCU only protects the sklist
and by extension the sks on it. So moving the mclist operations out of
the RCU is fine.
The delayed operation on the mclist entry is still within the RTNL
from unregister_netdevice_notifier. Which matter as it protects not
only the list, but also the actual operations in packet_dev_mc, such
as inc/dec on dev->promiscuity and associated dev_change_rx_flags.
And new packet_mclist.remove_list too.
> return NOTIFY_DONE;
> }
>
> diff --git a/net/packet/internal.h b/net/packet/internal.h
> index d5d70712007a..1e743d0316fd 100644
> --- a/net/packet/internal.h
> +++ b/net/packet/internal.h
> @@ -11,6 +11,7 @@ struct packet_mclist {
> unsigned short type;
> unsigned short alen;
> unsigned char addr[MAX_ADDR_LEN];
> + struct list_head remove_list;
INIT_LIST_HEAD on alloc in packet_mc_add?
> };
>
> /* kbdq - kernel block descriptor queue */
> --
> 2.49.0
>
next prev parent reply other threads:[~2025-05-21 2:41 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-20 20:20 [PATCH net] af_packet: move notifier's packet_dev_mc out of rcu critical section Stanislav Fomichev
2025-05-21 2:41 ` Willem de Bruijn [this message]
2025-05-21 3:00 ` Jakub Kicinski
2025-05-21 3:53 ` Willem de Bruijn
2025-05-21 16:54 ` Stanislav Fomichev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=682d3d5a77189_97c02294a3@willemb.c.googlers.com.notmuch \
--to=willemdebruijn.kernel@gmail.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=stfomichev@gmail.com \
--cc=syzbot+b191b5ccad8d7a986286@syzkaller.appspotmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).