From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 534093ACEF2; Sat, 12 Sep 2026 20:04:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789243495; cv=none; b=Y698gXw5B7d0FlQSMZB2msc18a1NlzH8rMMdFsgYJPB+5+1W/SNwHNLivTjXC4uQprrUYp0VUqkVyWLyv5mqDIxJoh3lFS19xTER8bwQxouxv4lqutffy7oxRumVx1sSWDEqND9G4edvpnbHQtMuCx9t3pF82rmooxaBEbC8QNk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789243495; c=relaxed/simple; bh=jim7N2RJ1OTK/xlihtvA9TOlLHBgUwkKTD+8q6p19s8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=t5sKuitvGMTnF5rGQ7FlPaeOBE66Nn6UG4AkwOURaPd1WCX/fFATpWgVQBSKt61V8Uw4LqnOhNGWBhtzDOrg/YF7Ak02Icg1GWtWdGSMKb0okFHlJdlUG/h7w9hP33KQcVBXN9HhEYR+lW5yNLqSVcbnIoYIk/PK2QfkWQViq5I= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HfRz6occ; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HfRz6occ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 08C691F008A1; Sat, 12 Sep 2026 20:04:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789243482; bh=tqKAsu21oJe6hkeRPmgxmUtzW/GvXgw64VVp3ufpq+I=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=HfRz6occZLkcILXLWhsQ0Vpo+hZYXcbjsVtdQmEen4XTlGYaBVpQi9ijaGdHZ6KHg M4J2Fcpjpgr3uDMMdkaYYS/8zXDvF5zErGc4zpvLMsg5MJOLwZgoji84yS/gihyy8b Z0LYzNVbnfE2Aovgn62Cx6/W9axtPHDY0lZ3mclCAFP5ezrjpEqvTBgaRqofqMEp49 EP81IHa+y+8BlJkFdJuRbECSUwG/dYkLm3YmQNmsoNl/rhRkAR8XiIO7AxqbqNsVGL 28DfuEXD26xMt7TvRpgxYeENwNYUJNwPDTgcaeR0gvMfp2i2c9Ve/pqKYFfm+HgFYl zypTfGHUnx8Xw== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org, daniel.zahka@gmail.com, willemdebruijn.kernel@gmail.com, donald.hunter@gmail.com, shuah@kernel.org, linux-kselftest@vger.kernel.org, Jakub Kicinski Subject: [PATCH net-next 4/6] psp: notify about a disassociation once it has happened Date: Sat, 12 Sep 2026 13:04:24 -0700 Message-ID: <20260912200426.121025-5-kuba@kernel.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260912200426.121025-1-kuba@kernel.org> References: <20260912200426.121025-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit The dev-change-ntf generated by dev-disassoc was built before the association was unlinked, so the assoc-list it carried still contained the device which was going away, and nothing corrected it afterwards. We don't really expect associations to change during a lifetime of a netns but this is still wrong. Netlink listeners need to be able to tell the current "state of the world" based on notifications. The notification had to be sent early because psp_nl_multicast_per_ns() derives the set of namespaces to notify from the association list, so a namespace losing its last associated device becomes unreachable once the entry is gone. In that case - get the netns from the netdev itself, and send that namespace a dev-del-ntf. If the netns had multiple associated netdevs and only one disassoc'd we'll still send a change notification, just with a correct list. Signed-off-by: Jakub Kicinski --- net/psp/psp.h | 1 + net/psp/psp_main.c | 16 +++++++++++----- net/psp/psp_nl.c | 44 +++++++++++++++++++++++++++++++++++++------- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/net/psp/psp.h b/net/psp/psp.h index bbb39e2f5b0a..b123c2427905 100644 --- a/net/psp/psp.h +++ b/net/psp/psp.h @@ -19,6 +19,7 @@ bool psp_has_assoc_dev_in_ns(struct psp_dev *psd, struct net *net); int psp_attach_netdev_notifier(void); void psp_nl_notify_dev(struct psp_dev *psd, u32 cmd); +void psp_nl_notify_disassoc(struct psp_dev *psd, struct net *net); struct psp_assoc *psp_assoc_create(struct psp_dev *psd); struct psp_dev *psp_dev_get_for_sock(struct sock *sk); diff --git a/net/psp/psp_main.c b/net/psp/psp_main.c index 91473f96ad21..273b010d2355 100644 --- a/net/psp/psp_main.c +++ b/net/psp/psp_main.c @@ -408,7 +408,7 @@ int psp_dev_rcv(struct sk_buff *skb, u16 dev_id, u8 generation, bool strip_icv) } EXPORT_SYMBOL(psp_dev_rcv); -static void psp_dev_disassoc_one(struct psp_dev *psd, struct net_device *dev) +static bool psp_dev_disassoc_one(struct psp_dev *psd, struct net_device *dev) { struct psp_assoc_dev *entry; @@ -419,9 +419,11 @@ static void psp_dev_disassoc_one(struct psp_dev *psd, struct net_device *dev) rcu_assign_pointer(entry->assoc_dev->psp_dev, NULL); netdev_put(entry->assoc_dev, &entry->dev_tracker); kfree(entry); - return; + return true; } } + + return false; } static int psp_netdev_event(struct notifier_block *nb, unsigned long event, @@ -438,9 +440,13 @@ static int psp_netdev_event(struct notifier_block *nb, unsigned long event, if (psd && psp_dev_tryget(psd)) { rcu_read_unlock(); mutex_lock(&psd->lock); - if (psp_dev_is_registered(psd)) - psp_nl_notify_dev(psd, PSP_CMD_DEV_CHANGE_NTF); - psp_dev_disassoc_one(psd, dev); + /* Nothing to report if the device was never on the list, + * dev-assoc may have failed after publishing dev->psp_dev, + * and this is also the main netdevice's path. + */ + if (psp_dev_disassoc_one(psd, dev) && + psp_dev_is_registered(psd)) + psp_nl_notify_disassoc(psd, dev_net(dev)); mutex_unlock(&psd->lock); psp_dev_put(psd); } else { diff --git a/net/psp/psp_nl.c b/net/psp/psp_nl.c index b57366b5e032..cdfc2d72fb39 100644 --- a/net/psp/psp_nl.c +++ b/net/psp/psp_nl.c @@ -356,6 +356,40 @@ void psp_nl_notify_dev(struct psp_dev *psd, u32 cmd) psp_nl_build_dev_ntf, &cmd); } +/** + * psp_nl_notify_disassoc() - notify about a device losing an association + * @psd: PSP device (must be locked) + * @net: netns of the netdevice which got disassociated + * + * Must be called once @psd no longer has the association, so that the + * notifications carry the state after the change. + */ +void psp_nl_notify_disassoc(struct psp_dev *psd, struct net *net) +{ + struct sk_buff *ntf; + bool still_visible; + u32 cmd; + + lockdep_assert_held(&psd->lock); + + psp_nl_notify_dev(psd, PSP_CMD_DEV_CHANGE_NTF); + + /* psp_nl_notify_dev() reaches the main netdevice's netns and every + * netns which still has an associated device. If @net is neither, + * the device is gone from @net and we should send a delete ntf. + */ + still_visible = !psp_dev_check_access(psd, net, false); + if (still_visible || !maybe_get_net(net)) + return; + + cmd = PSP_CMD_DEV_DEL_NTF; + ntf = psp_nl_build_dev_ntf(psd, net, &cmd); + if (ntf) + genlmsg_multicast_netns(&psp_nl_family, net, ntf, 0, + PSP_NLGRP_MGMT, GFP_KERNEL); + put_net(net); +} + int psp_nl_dev_get_doit(struct sk_buff *req, struct genl_info *info) { struct psp_dev *psd = info->user_ptr[0]; @@ -620,13 +654,6 @@ int psp_nl_dev_disassoc_doit(struct sk_buff *skb, struct genl_info *info) return -ENOMEM; } - put_net(net); - - /* Notify before removal so listeners in the disassociated namespace - * still receive the notification. - */ - psp_nl_notify_dev(psd, PSP_CMD_DEV_CHANGE_NTF); - /* Remove from the association list */ list_del(&found->dev_list); psd->assoc_dev_cnt--; @@ -634,6 +661,9 @@ int psp_nl_dev_disassoc_doit(struct sk_buff *skb, struct genl_info *info) netdev_put(found->assoc_dev, &found->dev_tracker); kfree(found); + psp_nl_notify_disassoc(psd, net); + put_net(net); + return psp_nl_reply_send(rsp, info); } -- 2.55.0