]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ksmbd: check parent directory sharing conflicts on rename
authorNamjae Jeon <linkinjeon@kernel.org>
Sun, 21 Jun 2026 10:37:22 +0000 (19:37 +0900)
committerSteve French <stfrench@microsoft.com>
Tue, 23 Jun 2026 01:15:05 +0000 (20:15 -0500)
When renaming a file, some existing opens on the parent directory must
block the rename with STATUS_SHARING_VIOLATION. This includes parent
directory handles opened with DELETE access and handles opened without
FILE_SHARE_DELETE.

ksmbd checked only the parent's desired access for FILE_DELETE.  That
handled smb2.rename.share_delete_and_delete_access, but missed the case
where the parent directory was opened without delete access and without
delete sharing, so smb2.rename.no_share_delete_no_delete_access incorrectly
succeeded.

Attribute-only parent opens, however, must not block the rename.
smb2.rename.msword opens the parent directory with only SYNCHRONIZE and
FILE_READ_ATTRIBUTES, no share access, and then renames an already-open
child file.  Windows allows this pattern.

Reject parent directory handles that request DELETE access, and reject
non-attribute-only parent opens that deny FILE_SHARE_DELETE, while allowing
attribute-only parent opens to coexist with child rename.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/vfs.c

index 74b0307cb1009595af5a48a5ff60555535334301..80fd27752b2c0a28729b08a54ef6ac8cc54df86d 100644 (file)
@@ -702,8 +702,10 @@ retry:
 
        parent_fp = ksmbd_lookup_fd_inode(old_child->d_parent);
        if (parent_fp) {
-               if (parent_fp->daccess & FILE_DELETE_LE) {
-                       pr_err("parent dir is opened with delete access\n");
+               if ((parent_fp->daccess & FILE_DELETE_LE) ||
+                   (!parent_fp->attrib_only &&
+                    !(parent_fp->saccess & FILE_SHARE_DELETE_LE))) {
+                       pr_err("parent dir blocks delete sharing\n");
                        err = -ESHARE;
                        ksmbd_fd_put(work, parent_fp);
                        goto out3;