]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
smb: client: prevent races in ->query_interfaces()
authorHenrique Carvalho <henrique.carvalho@suse.com>
Mon, 19 Jan 2026 17:54:44 +0000 (14:54 -0300)
committerSteve French <stfrench@microsoft.com>
Sun, 8 Feb 2026 23:07:43 +0000 (17:07 -0600)
It was possible for two query interface works to be concurrently trying
to update the interfaces.

Prevent this by checking and updating iface_last_update under
iface_lock.

Signed-off-by: Henrique Carvalho <henrique.carvalho@suse.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/smb2ops.c

index 653e2f29384d4f04555177bf4e097124160d2cc8..262df6d2c2c8241200555f5071af325868d7031c 100644 (file)
@@ -637,13 +637,6 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
        p = buf;
 
        spin_lock(&ses->iface_lock);
-       /* do not query too frequently, this time with lock held */
-       if (ses->iface_last_update &&
-           time_before(jiffies, ses->iface_last_update +
-                       (SMB_INTERFACE_POLL_INTERVAL * HZ))) {
-               spin_unlock(&ses->iface_lock);
-               return 0;
-       }
 
        /*
         * Go through iface_list and mark them as inactive
@@ -666,7 +659,6 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
                                 "Empty network interface list returned by server %s\n",
                                 ses->server->hostname);
                rc = -EOPNOTSUPP;
-               ses->iface_last_update = jiffies;
                goto out;
        }
 
@@ -795,8 +787,6 @@ next_iface:
             + sizeof(p->Next) && p->Next))
                cifs_dbg(VFS, "%s: incomplete interface info\n", __func__);
 
-       ses->iface_last_update = jiffies;
-
 out:
        /*
         * Go through the list again and put the inactive entries
@@ -825,10 +815,17 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_
        struct TCP_Server_Info *pserver;
 
        /* do not query too frequently */
+       spin_lock(&ses->iface_lock);
        if (ses->iface_last_update &&
            time_before(jiffies, ses->iface_last_update +
-                       (SMB_INTERFACE_POLL_INTERVAL * HZ)))
+                       (SMB_INTERFACE_POLL_INTERVAL * HZ))) {
+               spin_unlock(&ses->iface_lock);
                return 0;
+       }
+
+       ses->iface_last_update = jiffies;
+
+       spin_unlock(&ses->iface_lock);
 
        rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
                        FSCTL_QUERY_NETWORK_INTERFACE_INFO,