Skip to content

Commit d5fc140

Browse files
neilbrownsmfrench
authored andcommitted
smb/server: avoid deadlock when linking with ReplaceIfExists
If smb2_create_link() is called with ReplaceIfExists set and the name does exist then a deadlock will happen. ksmbd_vfs_kern_path_locked() will return with success and the parent directory will be locked. ksmbd_vfs_remove_file() will then remove the file. ksmbd_vfs_link() will then be called while the parent is still locked. It will try to lock the same parent and will deadlock. This patch moves the ksmbd_vfs_kern_path_unlock() call to *before* ksmbd_vfs_link() and then simplifies the code, removing the file_present flag variable. Signed-off-by: NeilBrown <[email protected]> Acked-by: Namjae Jeon <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent a5dc90a commit d5fc140

File tree

1 file changed

+4
-12
lines changed

1 file changed

+4
-12
lines changed

fs/smb/server/smb2pdu.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6037,7 +6037,6 @@ static int smb2_create_link(struct ksmbd_work *work,
60376037
{
60386038
char *link_name = NULL, *target_name = NULL, *pathname = NULL;
60396039
struct path path, parent_path;
6040-
bool file_present = false;
60416040
int rc;
60426041

60436042
if (buf_len < (u64)sizeof(struct smb2_file_link_info) +
@@ -6070,33 +6069,26 @@ static int smb2_create_link(struct ksmbd_work *work,
60706069
if (rc) {
60716070
if (rc != -ENOENT)
60726071
goto out;
6073-
} else
6074-
file_present = true;
6075-
6076-
if (file_info->ReplaceIfExists) {
6077-
if (file_present) {
6072+
} else {
6073+
if (file_info->ReplaceIfExists) {
60786074
rc = ksmbd_vfs_remove_file(work, &path);
60796075
if (rc) {
60806076
rc = -EINVAL;
60816077
ksmbd_debug(SMB, "cannot delete %s\n",
60826078
link_name);
60836079
goto out;
60846080
}
6085-
}
6086-
} else {
6087-
if (file_present) {
6081+
} else {
60886082
rc = -EEXIST;
60896083
ksmbd_debug(SMB, "link already exists\n");
60906084
goto out;
60916085
}
6086+
ksmbd_vfs_kern_path_unlock(&parent_path, &path);
60926087
}
6093-
60946088
rc = ksmbd_vfs_link(work, target_name, link_name);
60956089
if (rc)
60966090
rc = -EINVAL;
60976091
out:
6098-
if (file_present)
6099-
ksmbd_vfs_kern_path_unlock(&parent_path, &path);
61006092

61016093
if (!IS_ERR(link_name))
61026094
kfree(link_name);

0 commit comments

Comments
 (0)