Commit 22da5264 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '5.18-rc3-ksmbd-fixes' of git://git.samba.org/ksmbd

Pull ksmbd server fixes from Steve French:

 - cap maximum sector size reported to avoid mount problems

 - reference count fix

 - fix filename rename race

* tag '5.18-rc3-ksmbd-fixes' of git://git.samba.org/ksmbd:
  ksmbd: set fixed sector size to FS_SECTOR_SIZE_INFORMATION
  ksmbd: increment reference count of parent fp
  ksmbd: remove filename in ksmbd_file
parents f3935926 02655a70
...@@ -158,19 +158,41 @@ int parse_stream_name(char *filename, char **stream_name, int *s_type) ...@@ -158,19 +158,41 @@ int parse_stream_name(char *filename, char **stream_name, int *s_type)
* Return : windows path string or error * Return : windows path string or error
*/ */
char *convert_to_nt_pathname(char *filename) char *convert_to_nt_pathname(struct ksmbd_share_config *share,
struct path *path)
{ {
char *ab_pathname; char *pathname, *ab_pathname, *nt_pathname;
int share_path_len = share->path_sz;
if (strlen(filename) == 0) pathname = kmalloc(PATH_MAX, GFP_KERNEL);
filename = "\\"; if (!pathname)
return ERR_PTR(-EACCES);
ab_pathname = kstrdup(filename, GFP_KERNEL); ab_pathname = d_path(path, pathname, PATH_MAX);
if (!ab_pathname) if (IS_ERR(ab_pathname)) {
return NULL; nt_pathname = ERR_PTR(-EACCES);
goto free_pathname;
}
if (strncmp(ab_pathname, share->path, share_path_len)) {
nt_pathname = ERR_PTR(-EACCES);
goto free_pathname;
}
nt_pathname = kzalloc(strlen(&ab_pathname[share_path_len]) + 2, GFP_KERNEL);
if (!nt_pathname) {
nt_pathname = ERR_PTR(-ENOMEM);
goto free_pathname;
}
if (ab_pathname[share_path_len] == '\0')
strcpy(nt_pathname, "/");
strcat(nt_pathname, &ab_pathname[share_path_len]);
ksmbd_conv_path_to_windows(nt_pathname);
ksmbd_conv_path_to_windows(ab_pathname); free_pathname:
return ab_pathname; kfree(pathname);
return nt_pathname;
} }
int get_nlink(struct kstat *st) int get_nlink(struct kstat *st)
......
...@@ -14,7 +14,8 @@ struct ksmbd_file; ...@@ -14,7 +14,8 @@ struct ksmbd_file;
int match_pattern(const char *str, size_t len, const char *pattern); int match_pattern(const char *str, size_t len, const char *pattern);
int ksmbd_validate_filename(char *filename); int ksmbd_validate_filename(char *filename);
int parse_stream_name(char *filename, char **stream_name, int *s_type); int parse_stream_name(char *filename, char **stream_name, int *s_type);
char *convert_to_nt_pathname(char *filename); char *convert_to_nt_pathname(struct ksmbd_share_config *share,
struct path *path);
int get_nlink(struct kstat *st); int get_nlink(struct kstat *st);
void ksmbd_conv_path_to_unix(char *path); void ksmbd_conv_path_to_unix(char *path);
void ksmbd_strip_last_slash(char *path); void ksmbd_strip_last_slash(char *path);
......
...@@ -1694,33 +1694,3 @@ struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn, ...@@ -1694,33 +1694,3 @@ struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,
read_unlock(&lease_list_lock); read_unlock(&lease_list_lock);
return ret_op; return ret_op;
} }
int smb2_check_durable_oplock(struct ksmbd_file *fp,
struct lease_ctx_info *lctx, char *name)
{
struct oplock_info *opinfo = opinfo_get(fp);
int ret = 0;
if (opinfo && opinfo->is_lease) {
if (!lctx) {
pr_err("open does not include lease\n");
ret = -EBADF;
goto out;
}
if (memcmp(opinfo->o_lease->lease_key, lctx->lease_key,
SMB2_LEASE_KEY_SIZE)) {
pr_err("invalid lease key\n");
ret = -EBADF;
goto out;
}
if (name && strcmp(fp->filename, name)) {
pr_err("invalid name reconnect %s\n", name);
ret = -EINVAL;
goto out;
}
}
out:
if (opinfo)
opinfo_put(opinfo);
return ret;
}
...@@ -124,6 +124,4 @@ struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn, ...@@ -124,6 +124,4 @@ struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,
int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci, int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci,
struct lease_ctx_info *lctx); struct lease_ctx_info *lctx);
void destroy_lease_table(struct ksmbd_conn *conn); void destroy_lease_table(struct ksmbd_conn *conn);
int smb2_check_durable_oplock(struct ksmbd_file *fp,
struct lease_ctx_info *lctx, char *name);
#endif /* __KSMBD_OPLOCK_H */ #endif /* __KSMBD_OPLOCK_H */
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/statfs.h> #include <linux/statfs.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/falloc.h> #include <linux/falloc.h>
#include <linux/mount.h>
#include "glob.h" #include "glob.h"
#include "smbfsctl.h" #include "smbfsctl.h"
...@@ -2918,7 +2919,6 @@ int smb2_open(struct ksmbd_work *work) ...@@ -2918,7 +2919,6 @@ int smb2_open(struct ksmbd_work *work)
goto err_out; goto err_out;
} }
fp->filename = name;
fp->cdoption = req->CreateDisposition; fp->cdoption = req->CreateDisposition;
fp->daccess = daccess; fp->daccess = daccess;
fp->saccess = req->ShareAccess; fp->saccess = req->ShareAccess;
...@@ -3270,14 +3270,13 @@ int smb2_open(struct ksmbd_work *work) ...@@ -3270,14 +3270,13 @@ int smb2_open(struct ksmbd_work *work)
if (!rsp->hdr.Status) if (!rsp->hdr.Status)
rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR; rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
if (!fp || !fp->filename)
kfree(name);
if (fp) if (fp)
ksmbd_fd_put(work, fp); ksmbd_fd_put(work, fp);
smb2_set_err_rsp(work); smb2_set_err_rsp(work);
ksmbd_debug(SMB, "Error response: %x\n", rsp->hdr.Status); ksmbd_debug(SMB, "Error response: %x\n", rsp->hdr.Status);
} }
kfree(name);
kfree(lc); kfree(lc);
return 0; return 0;
...@@ -3895,8 +3894,6 @@ int smb2_query_dir(struct ksmbd_work *work) ...@@ -3895,8 +3894,6 @@ int smb2_query_dir(struct ksmbd_work *work)
ksmbd_debug(SMB, "Search pattern is %s\n", srch_ptr); ksmbd_debug(SMB, "Search pattern is %s\n", srch_ptr);
} }
ksmbd_debug(SMB, "Directory name is %s\n", dir_fp->filename);
if (srch_flag & SMB2_REOPEN || srch_flag & SMB2_RESTART_SCANS) { if (srch_flag & SMB2_REOPEN || srch_flag & SMB2_RESTART_SCANS) {
ksmbd_debug(SMB, "Restart directory scan\n"); ksmbd_debug(SMB, "Restart directory scan\n");
generic_file_llseek(dir_fp->filp, 0, SEEK_SET); generic_file_llseek(dir_fp->filp, 0, SEEK_SET);
...@@ -4390,9 +4387,9 @@ static int get_file_all_info(struct ksmbd_work *work, ...@@ -4390,9 +4387,9 @@ static int get_file_all_info(struct ksmbd_work *work,
return -EACCES; return -EACCES;
} }
filename = convert_to_nt_pathname(fp->filename); filename = convert_to_nt_pathname(work->tcon->share_conf, &fp->filp->f_path);
if (!filename) if (IS_ERR(filename))
return -ENOMEM; return PTR_ERR(filename);
inode = file_inode(fp->filp); inode = file_inode(fp->filp);
generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat); generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat);
...@@ -4999,15 +4996,17 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work, ...@@ -4999,15 +4996,17 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
case FS_SECTOR_SIZE_INFORMATION: case FS_SECTOR_SIZE_INFORMATION:
{ {
struct smb3_fs_ss_info *info; struct smb3_fs_ss_info *info;
unsigned int sector_size =
min_t(unsigned int, path.mnt->mnt_sb->s_blocksize, 4096);
info = (struct smb3_fs_ss_info *)(rsp->Buffer); info = (struct smb3_fs_ss_info *)(rsp->Buffer);
info->LogicalBytesPerSector = cpu_to_le32(stfs.f_bsize); info->LogicalBytesPerSector = cpu_to_le32(sector_size);
info->PhysicalBytesPerSectorForAtomicity = info->PhysicalBytesPerSectorForAtomicity =
cpu_to_le32(stfs.f_bsize); cpu_to_le32(sector_size);
info->PhysicalBytesPerSectorForPerf = cpu_to_le32(stfs.f_bsize); info->PhysicalBytesPerSectorForPerf = cpu_to_le32(sector_size);
info->FSEffPhysicalBytesPerSectorForAtomicity = info->FSEffPhysicalBytesPerSectorForAtomicity =
cpu_to_le32(stfs.f_bsize); cpu_to_le32(sector_size);
info->Flags = cpu_to_le32(SSINFO_FLAGS_ALIGNED_DEVICE | info->Flags = cpu_to_le32(SSINFO_FLAGS_ALIGNED_DEVICE |
SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE); SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
info->ByteOffsetForSectorAlignment = 0; info->ByteOffsetForSectorAlignment = 0;
...@@ -5683,8 +5682,7 @@ static int set_file_allocation_info(struct ksmbd_work *work, ...@@ -5683,8 +5682,7 @@ static int set_file_allocation_info(struct ksmbd_work *work,
size = i_size_read(inode); size = i_size_read(inode);
rc = ksmbd_vfs_truncate(work, fp, alloc_blks * 512); rc = ksmbd_vfs_truncate(work, fp, alloc_blks * 512);
if (rc) { if (rc) {
pr_err("truncate failed! filename : %s, err %d\n", pr_err("truncate failed!, err %d\n", rc);
fp->filename, rc);
return rc; return rc;
} }
if (size < alloc_blks * 512) if (size < alloc_blks * 512)
...@@ -5714,12 +5712,10 @@ static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp, ...@@ -5714,12 +5712,10 @@ static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp,
* truncated range. * truncated range.
*/ */
if (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC) { if (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC) {
ksmbd_debug(SMB, "filename : %s truncated to newsize %lld\n", ksmbd_debug(SMB, "truncated to newsize %lld\n", newsize);
fp->filename, newsize);
rc = ksmbd_vfs_truncate(work, fp, newsize); rc = ksmbd_vfs_truncate(work, fp, newsize);
if (rc) { if (rc) {
ksmbd_debug(SMB, "truncate failed! filename : %s err %d\n", ksmbd_debug(SMB, "truncate failed!, err %d\n", rc);
fp->filename, rc);
if (rc != -EAGAIN) if (rc != -EAGAIN)
rc = -EBADF; rc = -EBADF;
return rc; return rc;
...@@ -5765,8 +5761,10 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp, ...@@ -5765,8 +5761,10 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
if (parent_fp) { if (parent_fp) {
if (parent_fp->daccess & FILE_DELETE_LE) { if (parent_fp->daccess & FILE_DELETE_LE) {
pr_err("parent dir is opened with delete access\n"); pr_err("parent dir is opened with delete access\n");
ksmbd_fd_put(work, parent_fp);
return -ESHARE; return -ESHARE;
} }
ksmbd_fd_put(work, parent_fp);
} }
next: next:
return smb2_rename(work, fp, user_ns, rename_info, return smb2_rename(work, fp, user_ns, rename_info,
......
...@@ -398,8 +398,7 @@ int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count, ...@@ -398,8 +398,7 @@ int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count,
nbytes = kernel_read(filp, rbuf, count, pos); nbytes = kernel_read(filp, rbuf, count, pos);
if (nbytes < 0) { if (nbytes < 0) {
pr_err("smb read failed for (%s), err = %zd\n", pr_err("smb read failed, err = %zd\n", nbytes);
fp->filename, nbytes);
return nbytes; return nbytes;
} }
...@@ -875,8 +874,7 @@ int ksmbd_vfs_truncate(struct ksmbd_work *work, ...@@ -875,8 +874,7 @@ int ksmbd_vfs_truncate(struct ksmbd_work *work,
err = vfs_truncate(&filp->f_path, size); err = vfs_truncate(&filp->f_path, size);
if (err) if (err)
pr_err("truncate failed for filename : %s err %d\n", pr_err("truncate failed, err %d\n", err);
fp->filename, err);
return err; return err;
} }
......
...@@ -328,7 +328,6 @@ static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp) ...@@ -328,7 +328,6 @@ static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
kfree(smb_lock); kfree(smb_lock);
} }
kfree(fp->filename);
if (ksmbd_stream_fd(fp)) if (ksmbd_stream_fd(fp))
kfree(fp->stream.name); kfree(fp->stream.name);
kmem_cache_free(filp_cache, fp); kmem_cache_free(filp_cache, fp);
...@@ -497,6 +496,7 @@ struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode) ...@@ -497,6 +496,7 @@ struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode)
list_for_each_entry(lfp, &ci->m_fp_list, node) { list_for_each_entry(lfp, &ci->m_fp_list, node) {
if (inode == file_inode(lfp->filp)) { if (inode == file_inode(lfp->filp)) {
atomic_dec(&ci->m_count); atomic_dec(&ci->m_count);
lfp = ksmbd_fp_get(lfp);
read_unlock(&ci->m_lock); read_unlock(&ci->m_lock);
return lfp; return lfp;
} }
......
...@@ -62,7 +62,6 @@ struct ksmbd_inode { ...@@ -62,7 +62,6 @@ struct ksmbd_inode {
struct ksmbd_file { struct ksmbd_file {
struct file *filp; struct file *filp;
char *filename;
u64 persistent_id; u64 persistent_id;
u64 volatile_id; u64 volatile_id;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment