mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 08:24:47 +01:00
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 <neil@brown.name> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
a5dc90a9c3
commit
d5fc1400a3
1 changed files with 4 additions and 12 deletions
|
|
@ -6037,7 +6037,6 @@ static int smb2_create_link(struct ksmbd_work *work,
|
|||
{
|
||||
char *link_name = NULL, *target_name = NULL, *pathname = NULL;
|
||||
struct path path, parent_path;
|
||||
bool file_present = false;
|
||||
int rc;
|
||||
|
||||
if (buf_len < (u64)sizeof(struct smb2_file_link_info) +
|
||||
|
|
@ -6070,11 +6069,8 @@ static int smb2_create_link(struct ksmbd_work *work,
|
|||
if (rc) {
|
||||
if (rc != -ENOENT)
|
||||
goto out;
|
||||
} else
|
||||
file_present = true;
|
||||
|
||||
if (file_info->ReplaceIfExists) {
|
||||
if (file_present) {
|
||||
} else {
|
||||
if (file_info->ReplaceIfExists) {
|
||||
rc = ksmbd_vfs_remove_file(work, &path);
|
||||
if (rc) {
|
||||
rc = -EINVAL;
|
||||
|
|
@ -6082,21 +6078,17 @@ static int smb2_create_link(struct ksmbd_work *work,
|
|||
link_name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (file_present) {
|
||||
} else {
|
||||
rc = -EEXIST;
|
||||
ksmbd_debug(SMB, "link already exists\n");
|
||||
goto out;
|
||||
}
|
||||
ksmbd_vfs_kern_path_unlock(&parent_path, &path);
|
||||
}
|
||||
|
||||
rc = ksmbd_vfs_link(work, target_name, link_name);
|
||||
if (rc)
|
||||
rc = -EINVAL;
|
||||
out:
|
||||
if (file_present)
|
||||
ksmbd_vfs_kern_path_unlock(&parent_path, &path);
|
||||
|
||||
if (!IS_ERR(link_name))
|
||||
kfree(link_name);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue