ksmbd: fix dentry racy with rename()
Using ->d_name can be broken due to races with rename(). So use %pd with ->d_name to print filename and In other cases, use it under ->d_lock. Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
a5a25a114a
commit
493fa2fbe4
@ -3711,8 +3711,8 @@ int smb2_query_dir(struct ksmbd_work *work)
|
|||||||
if (!(dir_fp->daccess & FILE_LIST_DIRECTORY_LE) ||
|
if (!(dir_fp->daccess & FILE_LIST_DIRECTORY_LE) ||
|
||||||
inode_permission(&init_user_ns, file_inode(dir_fp->filp),
|
inode_permission(&init_user_ns, file_inode(dir_fp->filp),
|
||||||
MAY_READ | MAY_EXEC)) {
|
MAY_READ | MAY_EXEC)) {
|
||||||
pr_err("no right to enumerate directory (%s)\n",
|
pr_err("no right to enumerate directory (%pd)\n",
|
||||||
FP_FILENAME(dir_fp));
|
dir_fp->filp->f_path.dentry);
|
||||||
rc = -EACCES;
|
rc = -EACCES;
|
||||||
goto err_out2;
|
goto err_out2;
|
||||||
}
|
}
|
||||||
@ -4266,14 +4266,15 @@ static void get_file_alternate_info(struct ksmbd_work *work,
|
|||||||
{
|
{
|
||||||
struct ksmbd_conn *conn = work->conn;
|
struct ksmbd_conn *conn = work->conn;
|
||||||
struct smb2_file_alt_name_info *file_info;
|
struct smb2_file_alt_name_info *file_info;
|
||||||
|
struct dentry *dentry = fp->filp->f_path.dentry;
|
||||||
int conv_len;
|
int conv_len;
|
||||||
char *filename;
|
|
||||||
|
|
||||||
filename = (char *)FP_FILENAME(fp);
|
spin_lock(&dentry->d_lock);
|
||||||
file_info = (struct smb2_file_alt_name_info *)rsp->Buffer;
|
file_info = (struct smb2_file_alt_name_info *)rsp->Buffer;
|
||||||
conv_len = ksmbd_extract_shortname(conn,
|
conv_len = ksmbd_extract_shortname(conn,
|
||||||
filename,
|
dentry->d_name.name,
|
||||||
file_info->FileName);
|
file_info->FileName);
|
||||||
|
spin_unlock(&dentry->d_lock);
|
||||||
file_info->FileNameLength = cpu_to_le32(conv_len);
|
file_info->FileNameLength = cpu_to_le32(conv_len);
|
||||||
rsp->OutputBufferLength =
|
rsp->OutputBufferLength =
|
||||||
cpu_to_le32(sizeof(struct smb2_file_alt_name_info) + conv_len);
|
cpu_to_le32(sizeof(struct smb2_file_alt_name_info) + conv_len);
|
||||||
@ -5938,8 +5939,8 @@ int smb2_read(struct ksmbd_work *work)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ksmbd_debug(SMB, "filename %s, offset %lld, len %zu\n", FP_FILENAME(fp),
|
ksmbd_debug(SMB, "filename %pd, offset %lld, len %zu\n",
|
||||||
offset, length);
|
fp->filp->f_path.dentry, offset, length);
|
||||||
|
|
||||||
work->aux_payload_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
|
work->aux_payload_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
|
||||||
if (!work->aux_payload_buf) {
|
if (!work->aux_payload_buf) {
|
||||||
@ -6216,8 +6217,8 @@ int smb2_write(struct ksmbd_work *work)
|
|||||||
if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
|
if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
|
||||||
writethrough = true;
|
writethrough = true;
|
||||||
|
|
||||||
ksmbd_debug(SMB, "filename %s, offset %lld, len %zu\n",
|
ksmbd_debug(SMB, "filename %pd, offset %lld, len %zu\n",
|
||||||
FP_FILENAME(fp), offset, length);
|
fp->filp->f_path.dentry, offset, length);
|
||||||
err = ksmbd_vfs_write(work, fp, data_buf, length, &offset,
|
err = ksmbd_vfs_write(work, fp, data_buf, length, &offset,
|
||||||
writethrough, &nbytes);
|
writethrough, &nbytes);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
@ -365,7 +365,8 @@ int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count,
|
|||||||
|
|
||||||
if (work->conn->connection_type) {
|
if (work->conn->connection_type) {
|
||||||
if (!(fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
|
if (!(fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
|
||||||
pr_err("no right to read(%s)\n", FP_FILENAME(fp));
|
pr_err("no right to read(%pd)\n",
|
||||||
|
fp->filp->f_path.dentry);
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -473,7 +474,8 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
|
|||||||
|
|
||||||
if (sess->conn->connection_type) {
|
if (sess->conn->connection_type) {
|
||||||
if (!(fp->daccess & FILE_WRITE_DATA_LE)) {
|
if (!(fp->daccess & FILE_WRITE_DATA_LE)) {
|
||||||
pr_err("no right to write(%s)\n", FP_FILENAME(fp));
|
pr_err("no right to write(%pd)\n",
|
||||||
|
fp->filp->f_path.dentry);
|
||||||
err = -EACCES;
|
err = -EACCES;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -512,8 +514,8 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
|
|||||||
if (sync) {
|
if (sync) {
|
||||||
err = vfs_fsync_range(filp, offset, offset + *written, 0);
|
err = vfs_fsync_range(filp, offset, offset + *written, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
pr_err("fsync failed for filename = %s, err = %d\n",
|
pr_err("fsync failed for filename = %pd, err = %d\n",
|
||||||
FP_FILENAME(fp), err);
|
fp->filp->f_path.dentry, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -1707,11 +1709,11 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
|
|||||||
*total_size_written = 0;
|
*total_size_written = 0;
|
||||||
|
|
||||||
if (!(src_fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
|
if (!(src_fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
|
||||||
pr_err("no right to read(%s)\n", FP_FILENAME(src_fp));
|
pr_err("no right to read(%pd)\n", src_fp->filp->f_path.dentry);
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
if (!(dst_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE))) {
|
if (!(dst_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE))) {
|
||||||
pr_err("no right to write(%s)\n", FP_FILENAME(dst_fp));
|
pr_err("no right to write(%pd)\n", dst_fp->filp->f_path.dentry);
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#define KSMBD_NO_FID (UINT_MAX)
|
#define KSMBD_NO_FID (UINT_MAX)
|
||||||
#define SMB2_NO_FID (0xFFFFFFFFFFFFFFFFULL)
|
#define SMB2_NO_FID (0xFFFFFFFFFFFFFFFFULL)
|
||||||
|
|
||||||
#define FP_FILENAME(fp) ((fp)->filp->f_path.dentry->d_name.name)
|
|
||||||
#define FP_INODE(fp) d_inode((fp)->filp->f_path.dentry)
|
#define FP_INODE(fp) d_inode((fp)->filp->f_path.dentry)
|
||||||
#define PARENT_INODE(fp) d_inode((fp)->filp->f_path.dentry->d_parent)
|
#define PARENT_INODE(fp) d_inode((fp)->filp->f_path.dentry->d_parent)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user