]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: psp: check for device unregister when creating assoc
authorJakub Kicinski <kuba@kernel.org>
Mon, 27 Apr 2026 19:06:06 +0000 (12:06 -0700)
committerJakub Kicinski <kuba@kernel.org>
Wed, 29 Apr 2026 00:43:32 +0000 (17:43 -0700)
psp_assoc_device_get_locked() obtains a psp_dev reference via
psp_dev_get_for_sock() (which uses psp_dev_tryget() under RCU);
it then acquires psd->lock and drops the reference. Before
the lock is taken, psp_dev_unregister() can run to completion:
take psd->lock, clear out state, unlock, drop the registration
reference.

The expectation is that the lock prevents device unregistration,
but much like with netdevs special care has to be taken when
"upgrading" a reference to a locked device. Add the missing
check if device is still alive. psp_dev_is_registered() exists
already but had no callers, which makes me wonder if I either
forgot to add this or lost the check during refactoring...

Reported-by: Yiming Qian <yimingqian591@gmail.com>
Fixes: 6b46ca260e22 ("net: psp: add socket security association code")
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20260427190606.366101-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/psp/psp_nl.c

index 6afd7707ec12ea33e2b0645d215b8513e42e49ab..0cc744a6e1c9bc9c61282ad7a7027aba49a13fae 100644 (file)
@@ -305,8 +305,13 @@ int psp_assoc_device_get_locked(const struct genl_split_ops *ops,
 
        psd = psp_dev_get_for_sock(socket->sk);
        if (psd) {
-               err = psp_dev_check_access(psd, genl_info_net(info));
-               if (err) {
+               /* Extra care needed here, psp_dev_get_for_sock() only gives
+                * us access to struct psp_dev's memory, which is quite weak.
+                */
+               mutex_lock(&psd->lock);
+               if (!psp_dev_is_registered(psd) ||
+                   psp_dev_check_access(psd, genl_info_net(info))) {
+                       mutex_unlock(&psd->lock);
                        psp_dev_put(psd);
                        psd = NULL;
                }
@@ -319,7 +324,6 @@ int psp_assoc_device_get_locked(const struct genl_split_ops *ops,
 
        id = info->attrs[PSP_A_ASSOC_DEV_ID];
        if (psd) {
-               mutex_lock(&psd->lock);
                if (id && psd->id != nla_get_u32(id)) {
                        mutex_unlock(&psd->lock);
                        NL_SET_ERR_MSG_ATTR(info->extack, id,