Commit a967e758 authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Steve French
Browse files

smb: client: set symlink type as native for POSIX mounts



SMB3.1.1 POSIX mounts require symlinks to be created natively with
IO_REPARSE_TAG_SYMLINK reparse point.

Cc: linux-cifs@vger.kernel.org
Cc: Ralph Boehme <slow@samba.org>
Cc: David Howells <dhowells@redhat.com>
Cc: <stable@vger.kernel.org>
Reported-by: default avatarMatthew Richardson <m.richardson@ed.ac.uk>
Closes: https://marc.info/?i=1124e7cd-6a46-40a6-9f44-b7664a66654b@ed.ac.uk


Signed-off-by: default avatarPaulo Alcantara (Red Hat) <pc@manguebit.org>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent db68e4c8
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -723,7 +723,7 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
	else
		seq_puts(s, ",nativesocket");
	seq_show_option(s, "symlink",
			cifs_symlink_type_str(get_cifs_symlink_type(cifs_sb)));
			cifs_symlink_type_str(cifs_symlink_type(cifs_sb)));

	seq_printf(s, ",rsize=%u", cifs_sb->ctx->rsize);
	seq_printf(s, ",wsize=%u", cifs_sb->ctx->wsize);
+0 −18
Original line number Diff line number Diff line
@@ -1829,24 +1829,6 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
	return -EINVAL;
}

enum cifs_symlink_type get_cifs_symlink_type(struct cifs_sb_info *cifs_sb)
{
	if (cifs_sb->ctx->symlink_type == CIFS_SYMLINK_TYPE_DEFAULT) {
		if (cifs_sb->ctx->mfsymlinks)
			return CIFS_SYMLINK_TYPE_MFSYMLINKS;
		else if (cifs_sb->ctx->sfu_emul)
			return CIFS_SYMLINK_TYPE_SFU;
		else if (cifs_sb->ctx->linux_ext && !cifs_sb->ctx->no_linux_ext)
			return CIFS_SYMLINK_TYPE_UNIX;
		else if (cifs_sb->ctx->reparse_type != CIFS_REPARSE_TYPE_NONE)
			return CIFS_SYMLINK_TYPE_NATIVE;
		else
			return CIFS_SYMLINK_TYPE_NONE;
	} else {
		return cifs_sb->ctx->symlink_type;
	}
}

int smb3_init_fs_context(struct fs_context *fc)
{
	struct smb3_fs_context *ctx;
+17 −1
Original line number Diff line number Diff line
@@ -341,7 +341,23 @@ struct smb3_fs_context {

extern const struct fs_parameter_spec smb3_fs_parameters[];

extern enum cifs_symlink_type get_cifs_symlink_type(struct cifs_sb_info *cifs_sb);
static inline enum cifs_symlink_type cifs_symlink_type(struct cifs_sb_info *cifs_sb)
{
	bool posix = cifs_sb_master_tcon(cifs_sb)->posix_extensions;

	if (cifs_sb->ctx->symlink_type != CIFS_SYMLINK_TYPE_DEFAULT)
		return cifs_sb->ctx->symlink_type;

	if (cifs_sb->ctx->mfsymlinks)
		return CIFS_SYMLINK_TYPE_MFSYMLINKS;
	else if (cifs_sb->ctx->sfu_emul)
		return CIFS_SYMLINK_TYPE_SFU;
	else if (cifs_sb->ctx->linux_ext && !cifs_sb->ctx->no_linux_ext)
		return posix ? CIFS_SYMLINK_TYPE_NATIVE : CIFS_SYMLINK_TYPE_UNIX;
	else if (cifs_sb->ctx->reparse_type != CIFS_REPARSE_TYPE_NONE)
		return CIFS_SYMLINK_TYPE_NATIVE;
	return CIFS_SYMLINK_TYPE_NONE;
}

extern int smb3_init_fs_context(struct fs_context *fc);
extern void smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx);
+3 −8
Original line number Diff line number Diff line
@@ -605,14 +605,7 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,

	/* BB what if DFS and this volume is on different share? BB */
	rc = -EOPNOTSUPP;
	switch (get_cifs_symlink_type(cifs_sb)) {
	case CIFS_SYMLINK_TYPE_DEFAULT:
		/* should not happen, get_cifs_symlink_type() resolves the default */
		break;

	case CIFS_SYMLINK_TYPE_NONE:
		break;

	switch (cifs_symlink_type(cifs_sb)) {
	case CIFS_SYMLINK_TYPE_UNIX:
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
		if (pTcon->unix_ext) {
@@ -648,6 +641,8 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
			goto symlink_exit;
		}
		break;
	default:
		break;
	}

	if (rc == 0) {
+1 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ int create_reparse_symlink(const unsigned int xid, struct inode *inode,
				struct dentry *dentry, struct cifs_tcon *tcon,
				const char *full_path, const char *symname)
{
	switch (get_cifs_symlink_type(CIFS_SB(inode->i_sb))) {
	switch (cifs_symlink_type(CIFS_SB(inode->i_sb))) {
	case CIFS_SYMLINK_TYPE_NATIVE:
		return create_native_symlink(xid, inode, dentry, tcon, full_path, symname);
	case CIFS_SYMLINK_TYPE_NFS: