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

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
Loading
Loading
Loading
Loading
+31 −9
Original line number Diff line number Diff line
@@ -158,19 +158,41 @@ int parse_stream_name(char *filename, char **stream_name, int *s_type)
 * 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)
		filename = "\\";
	pathname = kmalloc(PATH_MAX, GFP_KERNEL);
	if (!pathname)
		return ERR_PTR(-EACCES);

	ab_pathname = kstrdup(filename, GFP_KERNEL);
	if (!ab_pathname)
		return NULL;
	ab_pathname = d_path(path, pathname, PATH_MAX);
	if (IS_ERR(ab_pathname)) {
		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);
	return ab_pathname;
free_pathname:
	kfree(pathname);
	return nt_pathname;
}

int get_nlink(struct kstat *st)
+2 −1
Original line number Diff line number Diff line
@@ -14,7 +14,8 @@ struct ksmbd_file;
int match_pattern(const char *str, size_t len, const char *pattern);
int ksmbd_validate_filename(char *filename);
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);
void ksmbd_conv_path_to_unix(char *path);
void ksmbd_strip_last_slash(char *path);
+0 −30
Original line number Diff line number Diff line
@@ -1694,33 +1694,3 @@ struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,
	read_unlock(&lease_list_lock);
	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;
}
+0 −2
Original line number Diff line number Diff line
@@ -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,
			struct lease_ctx_info *lctx);
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 */
+16 −18
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <linux/statfs.h>
#include <linux/ethtool.h>
#include <linux/falloc.h>
#include <linux/mount.h>

#include "glob.h"
#include "smbfsctl.h"
@@ -2918,7 +2919,6 @@ int smb2_open(struct ksmbd_work *work)
		goto err_out;
	}

	fp->filename = name;
	fp->cdoption = req->CreateDisposition;
	fp->daccess = daccess;
	fp->saccess = req->ShareAccess;
@@ -3270,14 +3270,13 @@ int smb2_open(struct ksmbd_work *work)
		if (!rsp->hdr.Status)
			rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;

		if (!fp || !fp->filename)
			kfree(name);
		if (fp)
			ksmbd_fd_put(work, fp);
		smb2_set_err_rsp(work);
		ksmbd_debug(SMB, "Error response: %x\n", rsp->hdr.Status);
	}

	kfree(name);
	kfree(lc);

	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, "Directory name is %s\n", dir_fp->filename);

	if (srch_flag & SMB2_REOPEN || srch_flag & SMB2_RESTART_SCANS) {
		ksmbd_debug(SMB, "Restart directory scan\n");
		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;
	}

	filename = convert_to_nt_pathname(fp->filename);
	if (!filename)
		return -ENOMEM;
	filename = convert_to_nt_pathname(work->tcon->share_conf, &fp->filp->f_path);
	if (IS_ERR(filename))
		return PTR_ERR(filename);

	inode = file_inode(fp->filp);
	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:
	{
		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->LogicalBytesPerSector = cpu_to_le32(stfs.f_bsize);
		info->LogicalBytesPerSector = cpu_to_le32(sector_size);
		info->PhysicalBytesPerSectorForAtomicity =
				cpu_to_le32(stfs.f_bsize);
		info->PhysicalBytesPerSectorForPerf = cpu_to_le32(stfs.f_bsize);
				cpu_to_le32(sector_size);
		info->PhysicalBytesPerSectorForPerf = cpu_to_le32(sector_size);
		info->FSEffPhysicalBytesPerSectorForAtomicity =
				cpu_to_le32(stfs.f_bsize);
				cpu_to_le32(sector_size);
		info->Flags = cpu_to_le32(SSINFO_FLAGS_ALIGNED_DEVICE |
				    SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
		info->ByteOffsetForSectorAlignment = 0;
@@ -5683,8 +5682,7 @@ static int set_file_allocation_info(struct ksmbd_work *work,
		size = i_size_read(inode);
		rc = ksmbd_vfs_truncate(work, fp, alloc_blks * 512);
		if (rc) {
			pr_err("truncate failed! filename : %s, err %d\n",
			       fp->filename, rc);
			pr_err("truncate failed!, err %d\n", rc);
			return rc;
		}
		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.
	 */
	if (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC) {
		ksmbd_debug(SMB, "filename : %s truncated to newsize %lld\n",
			    fp->filename, newsize);
		ksmbd_debug(SMB, "truncated to newsize %lld\n", newsize);
		rc = ksmbd_vfs_truncate(work, fp, newsize);
		if (rc) {
			ksmbd_debug(SMB, "truncate failed! filename : %s err %d\n",
				    fp->filename, rc);
			ksmbd_debug(SMB, "truncate failed!, err %d\n", rc);
			if (rc != -EAGAIN)
				rc = -EBADF;
			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->daccess & FILE_DELETE_LE) {
			pr_err("parent dir is opened with delete access\n");
			ksmbd_fd_put(work, parent_fp);
			return -ESHARE;
		}
		ksmbd_fd_put(work, parent_fp);
	}
next:
	return smb2_rename(work, fp, user_ns, rename_info,
Loading