]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ksmbd: use opener credentials for delete-on-close
authorNamjae Jeon <linkinjeon@kernel.org>
Sat, 13 Jun 2026 13:00:00 +0000 (22:00 +0900)
committerSteve French <stfrench@microsoft.com>
Tue, 16 Jun 2026 23:57:22 +0000 (18:57 -0500)
Delete-on-close can be completed by deferred or durable handle teardown,
where no request work is available. Both the base-file unlink and the ADS
xattr removal consequently run with the ksmbd worker credentials and can
bypass filesystem permission checks.

Run both operations with the credentials captured in struct file when the
handle was opened. This preserves the authenticated user's fsuid, fsgid,
supplementary groups and capability restrictions at final close.

Cc: stable@vger.kernel.org
Reported-by: Musaab Khan <musaab.khan@protonmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/vfs.c
fs/smb/server/vfs_cache.c

index e865ae91650a1c3ab1730aaafa57e6d4eacbd735..c002cc4b1c026a7aac3a22685a9862464f9936c0 100644 (file)
@@ -1001,13 +1001,15 @@ int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap,
 
 int ksmbd_vfs_unlink(struct file *filp)
 {
+       const struct cred *saved_cred;
        int err = 0;
        struct dentry *dir, *dentry = filp->f_path.dentry;
        struct mnt_idmap *idmap = file_mnt_idmap(filp);
 
+       saved_cred = override_creds(filp->f_cred);
        err = mnt_want_write(filp->f_path.mnt);
        if (err)
-               return err;
+               goto out_revert;
 
        dir = dget_parent(dentry);
        dentry = start_removing_dentry(dir, dentry);
@@ -1026,7 +1028,8 @@ int ksmbd_vfs_unlink(struct file *filp)
 out:
        dput(dir);
        mnt_drop_write(filp->f_path.mnt);
-
+out_revert:
+       revert_creds(saved_cred);
        return err;
 }
 
index 4daccc77f9eca1357a3809e35f207dad9cbb978a..8c556e46cc102e85055bad8b7f8c33558c76800e 100644 (file)
@@ -385,10 +385,14 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
                up_write(&ci->m_lock);
 
                if (remove_stream_xattr) {
+                       const struct cred *saved_cred;
+
+                       saved_cred = override_creds(filp->f_cred);
                        err = ksmbd_vfs_remove_xattr(file_mnt_idmap(filp),
                                                     &filp->f_path,
                                                     fp->stream.name,
                                                     true);
+                       revert_creds(saved_cred);
                        if (err)
                                pr_err("remove xattr failed : %s\n",
                                       fp->stream.name);