hwsim_mcast_config_msg() sends config notifications. Its info == NULL path uses genlmsg_multicast(), which delivers to init_net only. That path runs on an asynchronous radio destroy, from remove_user_radios() on a closed socket or hwsim_exit_net() on teardown. hwsim is per-namespace, and a radio records its namespace in wiphy_net() of its wiphy. A radio in a non-initial namespace therefore has its DEL_RADIO sent to init_net, with its id and name. An unprivileged listener there receives it, since the config group has no flags and needs no capability to join. The radio's own namespace is never told. Send to the radio's namespace with genlmsg_multicast_netns(), using wiphy_net() of its wiphy, the net the GET and DUMP filters already use. I found this with a static check for multicast that ignores the object's namespace. I reproduced it in a qemu VM as an unprivileged user, with no hardware and no kernel changes. A process creates a radio in its own namespace and exits. An init_net listener receives the DEL_RADIO before the patch, and nothing after it. hwsim is a test driver, so the leaked metadata is low value. The fix still matters, since the radio's own namespace should hear about it. Fixes: 100cb9ff40e0 ("mac80211_hwsim: Allow managing radios from non-initial namespaces") Cc: stable@vger.kernel.org Signed-off-by: Maoyi Xie --- .../wireless/virtual/mac80211_hwsim_main.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_main.c b/drivers/net/wireless/virtual/mac80211_hwsim_main.c index 75caa97becc8d..4a68cae25b7db 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim_main.c +++ b/drivers/net/wireless/virtual/mac80211_hwsim_main.c @@ -4372,15 +4372,15 @@ struct hwsim_new_radio_params { bool background_radar; }; -static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb, +static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb, struct net *net, struct genl_info *info) { if (info) genl_notify(&hwsim_genl_family, mcast_skb, info, HWSIM_MCGRP_CONFIG, GFP_KERNEL); else - genlmsg_multicast(&hwsim_genl_family, mcast_skb, 0, - HWSIM_MCGRP_CONFIG, GFP_KERNEL); + genlmsg_multicast_netns(&hwsim_genl_family, net, mcast_skb, 0, + HWSIM_MCGRP_CONFIG, GFP_KERNEL); } static int append_radio_msg(struct sk_buff *skb, int id, @@ -4464,7 +4464,8 @@ static int append_radio_msg(struct sk_buff *skb, int id, return 0; } -static void hwsim_mcast_new_radio(int id, struct genl_info *info, +static void hwsim_mcast_new_radio(int id, struct net *net, + struct genl_info *info, struct hwsim_new_radio_params *param) { struct sk_buff *mcast_skb; @@ -4484,7 +4485,7 @@ static void hwsim_mcast_new_radio(int id, struct genl_info *info, genlmsg_end(mcast_skb, data); - hwsim_mcast_config_msg(mcast_skb, info); + hwsim_mcast_config_msg(mcast_skb, net, info); return; out_err: @@ -6165,7 +6166,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, hwsim_radios_generation++; spin_unlock_bh(&hwsim_radio_lock); - hwsim_mcast_new_radio(idx, info, param); + hwsim_mcast_new_radio(idx, wiphy_net(data->hw->wiphy), info, param); return idx; @@ -6183,7 +6184,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, } static void hwsim_mcast_del_radio(int id, const char *hwname, - struct genl_info *info) + struct net *net, struct genl_info *info) { struct sk_buff *skb; void *data; @@ -6209,7 +6210,7 @@ static void hwsim_mcast_del_radio(int id, const char *hwname, genlmsg_end(skb, data); - hwsim_mcast_config_msg(skb, info); + hwsim_mcast_config_msg(skb, net, info); return; @@ -6221,7 +6222,7 @@ static void mac80211_hwsim_del_radio(struct mac80211_hwsim_data *data, const char *hwname, struct genl_info *info) { - hwsim_mcast_del_radio(data->idx, hwname, info); + hwsim_mcast_del_radio(data->idx, hwname, wiphy_net(data->hw->wiphy), info); debugfs_remove_recursive(data->debugfs); ieee80211_unregister_hw(data->hw); device_release_driver(data->dev);