]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ksmbd: fix use-after-free in smb2_open during durable reconnect
authorAkif <akif.sait111@gmail.com>
Fri, 17 Apr 2026 18:27:09 +0000 (23:57 +0530)
committerSteve French <stfrench@microsoft.com>
Sat, 18 Apr 2026 17:19:59 +0000 (12:19 -0500)
In smb2_open, the call to ksmbd_put_durable_fd(fp) drops the reference
to the durable file descriptor early during the durable reconnect
process. If an error occurs subsequently (eg, ksmbd_iov_pin_rsp fails)
or a scavenger accesses the file, it leads to a use-after-free when
accessing fp properties (eg fp->create_time).

Move the single put to the end of the function below err_out2 so fp
stays valid until smb2_open returns.

Fixes: c8efcc786146 ("ksmbd: add support for durable handles v1/v2")
Signed-off-by: Akif <akif.sait111@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/smb2pdu.c

index ee32e61b6d3c75f9a2e1b69554280fa6ad432bae..395007c82831fa57a26031490bff63907b1318ff 100644 (file)
@@ -3014,29 +3014,23 @@ int smb2_open(struct ksmbd_work *work)
                if (dh_info.reconnected == true) {
                        rc = smb2_check_durable_oplock(conn, share, dh_info.fp,
                                        lc, sess->user, name);
-                       if (rc) {
-                               ksmbd_put_durable_fd(dh_info.fp);
+                       if (rc)
                                goto err_out2;
-                       }
 
                        rc = ksmbd_reopen_durable_fd(work, dh_info.fp);
-                       if (rc) {
-                               ksmbd_put_durable_fd(dh_info.fp);
+                       if (rc)
                                goto err_out2;
-                       }
 
                        fp = dh_info.fp;
 
                        if (ksmbd_override_fsids(work)) {
                                rc = -ENOMEM;
-                               ksmbd_put_durable_fd(dh_info.fp);
                                goto err_out2;
                        }
 
                        file_info = FILE_OPENED;
 
                        rc = ksmbd_vfs_getattr(&fp->filp->f_path, &stat);
-                       ksmbd_put_durable_fd(fp);
                        if (rc)
                                goto err_out2;
 
@@ -3806,6 +3800,9 @@ err_out2:
                ksmbd_debug(SMB, "Error response: %x\n", rsp->hdr.Status);
        }
 
+       if (dh_info.reconnected)
+               ksmbd_put_durable_fd(dh_info.fp);
+
        kfree(name);
        kfree(lc);