3 fixes to ksmbd server
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmJkGaQACgkQiiy9cAdy T1G7Pgv/SHmxsBGIT+YyW+ppWZGIMMpCld3YbovtN2EWdt3NXwvnGrTTFkXe0acJ +63NjNnCoDTKy+XHN0HhMqLsJSep6J63e5rmiuvUxKQIR0n1WzZl7W1YpHKptZog wMkObv0UzKgr6gLEwQeMMqvcyxOVmgssAXou4N8p6rDJLFijM2kcVjpB/B9uyUAR JG0ss8lhX7+YTcRuI0QqyulHlUTiGwu4/XjO9oWs3bF2faADVIfZXOKGMFfRpjCK YDGdh+HieW5y2SngvstdBuVxmZXLjWjWwe9mQCUaF7khZJ0acuGeQh9BCPNopjUD 0CBYe9JWM2NxTjXqmhspCGUi40+EedZgIMxukRyl7MrBX1wBF0ErSYpGmYSZQqoH u2R9Pr8tUwuzVfQ6s7VhWACckKFNwI53lHOhY1ikc2M/NWeLy961Wi9JRykac8cZ ElkJkJUdGttntjwilcKp7NuWmHssDzxNH103WAr3GZrhBDgntUHFBpsLqzQmQW3a Gp3jkj1e =Y9T8 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
22da5264ab
@ -158,19 +158,41 @@ out:
|
|||||||
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
ksmbd_conv_path_to_windows(ab_pathname);
|
if (strncmp(ab_pathname, share->path, share_path_len)) {
|
||||||
return ab_pathname;
|
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);
|
||||||
|
|
||||||
|
free_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;
|
|||||||
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 @@ out:
|
|||||||
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,
|
|||||||
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 @@
|
|||||||
#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)
|
|||||||
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 @@ err_out1:
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
* 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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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 {
|
|||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user