Skip to content

Commit

Permalink
ksmbd: smb1: fix smb_rename()
Browse files Browse the repository at this point in the history
Renaming a file from smbclient does not work currently. Change the code
in smb_rename() to use the same codepath as smb2 rename.

Using cifs.ko, renaming works as it uses the trans2/set_file_info
variant.

ksmbd_vfs_rename_slowpath() is removed as it is now unused.

Signed-off-by: Marios Makassikis <[email protected]>
Signed-off-by: Namjae Jeon <[email protected]>
  • Loading branch information
Marios Makassikis authored and namjaejeon committed Nov 21, 2022
1 parent 433d93e commit 133175a
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 78 deletions.
18 changes: 17 additions & 1 deletion smb1pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,7 @@ int smb_rename(struct ksmbd_work *work)
struct ksmbd_share_config *share = work->tcon->share_conf;
bool is_unicode = is_smbreq_unicode(&req->hdr);
char *oldname, *newname;
struct ksmbd_file *fp = NULL;
int oldname_len;
struct path path;
bool file_present = true;
Expand Down Expand Up @@ -784,14 +785,29 @@ int smb_rename(struct ksmbd_work *work)
}

ksmbd_debug(SMB, "rename %s -> %s\n", oldname, newname);
rc = ksmbd_vfs_rename_slowpath(work, oldname, newname);
rc = ksmbd_vfs_kern_path(work, oldname, LOOKUP_NO_SYMLINKS, &path, 1);
if (rc)
goto out;

fp = ksmbd_vfs_dentry_open(work, &path, O_RDONLY, 0, false);
if (IS_ERR(fp)) {
fp = NULL;
path_put(&path);
goto out;
}

rc = ksmbd_vfs_fp_rename(work, fp, newname);
if (rc) {
rsp->hdr.Status.CifsError = STATUS_NO_MEMORY;
path_put(&path);
goto out;
}
path_put(&path);
rsp->hdr.WordCount = 0;
rsp->ByteCount = 0;
out:
if (fp)
ksmbd_close_fd(work, fp->volatile_id);
kfree(oldname);
kfree(newname);
return rc;
Expand Down
75 changes: 0 additions & 75 deletions vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1171,81 +1171,6 @@ int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
return err;
}

#ifdef CONFIG_SMB_INSECURE_SERVER
int ksmbd_vfs_rename_slowpath(struct ksmbd_work *work, char *oldname, char *newname)
{
struct path dst_path, src_path;
struct dentry *src_dent_parent, *dst_dent_parent;
struct dentry *src_dent = NULL, *trap_dent;
char *src_name, *dst_name;
int err;

src_name = extract_last_component(oldname);
if (!src_name)
return -EINVAL;
dst_name = extract_last_component(newname);
if (!dst_name)
return -EINVAL;

err = kern_path(oldname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &src_path);
if (err) {
pr_err("Cannot get path for %s [%d]\n", oldname, err);
return err;
}
src_dent_parent = src_path.dentry;
dget(src_dent_parent);

err = kern_path(newname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &dst_path);
if (err) {
pr_err("Cannot get path for %s [%d]\n", newname, err);
dput(src_dent_parent);
path_put(&src_path);
return err;
}

dst_dent_parent = dst_path.dentry;
dget(dst_dent_parent);

trap_dent = lock_rename(src_dent_parent, dst_dent_parent);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
src_dent = lookup_one(mnt_user_ns(src_path.mnt), src_name,
src_dent_parent, strlen(src_name));
#else
src_dent = lookup_one_len(src_name, src_dent_parent, strlen(src_name));
#endif
err = PTR_ERR(src_dent);
if (IS_ERR(src_dent)) {
src_dent = NULL;
pr_err("%s lookup failed with error = %d\n", src_name, err);
goto out;
}

err = __ksmbd_vfs_rename(work,
mnt_user_ns(src_path.mnt),
src_dent_parent,
src_dent,
mnt_user_ns(dst_path.mnt),
dst_dent_parent,
trap_dent,
dst_name);
out:
if (src_dent)
dput(src_dent);
dput(dst_dent_parent);
dput(src_dent_parent);
unlock_rename(src_dent_parent, dst_dent_parent);
path_put(&src_path);
path_put(&dst_path);
return err;
}
#else
int ksmbd_vfs_rename_slowpath(struct ksmbd_work *work, char *oldname,
char *newname)
{
return 0;
}
#endif

/**
* ksmbd_vfs_truncate() - vfs helper for smb file truncate
* @work: work
Expand Down
2 changes: 0 additions & 2 deletions vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,6 @@ int ksmbd_vfs_readdir_name(struct ksmbd_work *work,
#endif
int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
char *newname);
int ksmbd_vfs_rename_slowpath(struct ksmbd_work *work,
char *oldname, char *newname);
int ksmbd_vfs_truncate(struct ksmbd_work *work,
struct ksmbd_file *fp, loff_t size);
struct srv_copychunk;
Expand Down

0 comments on commit 133175a

Please sign in to comment.