cifs: Add support for creating native Windows sockets
Native Windows sockets created by WinSock on Windows 10 April 2018 Update (version 1803) or Windows Server 2019 (version 1809) or later versions is reparse point with IO_REPARSE_TAG_AF_UNIX tag, with empty reparse point data buffer and without any EAs. Create AF_UNIX sockets in this native format if -o nonativesocket was not specified. This change makes AF_UNIX sockets created by Linux CIFS client compatible with AF_UNIX sockets created by Windows applications on NTFS volumes. Signed-off-by: Pali Rohár <pali@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
78f69467cb
commit
45a99d5d11
|
@ -715,6 +715,10 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
|
|||
cifs_sb->ctx->backupgid));
|
||||
seq_show_option(s, "reparse",
|
||||
cifs_reparse_type_str(cifs_sb->ctx->reparse_type));
|
||||
if (cifs_sb->ctx->nonativesocket)
|
||||
seq_puts(s, ",nonativesocket");
|
||||
else
|
||||
seq_puts(s, ",nativesocket");
|
||||
seq_show_option(s, "symlink",
|
||||
cifs_symlink_type_str(get_cifs_symlink_type(cifs_sb)));
|
||||
|
||||
|
|
|
@ -2849,6 +2849,8 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
|
|||
return 0;
|
||||
if (old->ctx->reparse_type != new->ctx->reparse_type)
|
||||
return 0;
|
||||
if (old->ctx->nonativesocket != new->ctx->nonativesocket)
|
||||
return 0;
|
||||
if (old->ctx->symlink_type != new->ctx->symlink_type)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -133,6 +133,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
|
|||
fsparam_flag("rootfs", Opt_rootfs),
|
||||
fsparam_flag("compress", Opt_compress),
|
||||
fsparam_flag("witness", Opt_witness),
|
||||
fsparam_flag_no("nativesocket", Opt_nativesocket),
|
||||
|
||||
/* Mount options which take uid or gid */
|
||||
fsparam_uid("backupuid", Opt_backupuid),
|
||||
|
@ -1784,6 +1785,9 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
|||
if (parse_reparse_flavor(fc, param->string, ctx))
|
||||
goto cifs_parse_mount_err;
|
||||
break;
|
||||
case Opt_nativesocket:
|
||||
ctx->nonativesocket = result.negated;
|
||||
break;
|
||||
case Opt_symlink:
|
||||
if (parse_symlink_flavor(fc, param->string, ctx))
|
||||
goto cifs_parse_mount_err;
|
||||
|
@ -1918,6 +1922,7 @@ int smb3_init_fs_context(struct fs_context *fc)
|
|||
ctx->retrans = 1;
|
||||
ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT;
|
||||
ctx->symlink_type = CIFS_SYMLINK_TYPE_DEFAULT;
|
||||
ctx->nonativesocket = 0;
|
||||
|
||||
/*
|
||||
* short int override_uid = -1;
|
||||
|
|
|
@ -179,6 +179,7 @@ enum cifs_param {
|
|||
Opt_cache,
|
||||
Opt_reparse,
|
||||
Opt_upcalltarget,
|
||||
Opt_nativesocket,
|
||||
Opt_symlink,
|
||||
Opt_symlinkroot,
|
||||
|
||||
|
@ -310,6 +311,7 @@ struct smb3_fs_context {
|
|||
bool dfs_automount:1; /* set for dfs automount only */
|
||||
enum cifs_reparse_type reparse_type;
|
||||
enum cifs_symlink_type symlink_type;
|
||||
bool nonativesocket:1;
|
||||
bool dfs_conn:1; /* set for dfs mounts */
|
||||
char *dns_dom;
|
||||
char *symlinkroot; /* top level directory for native SMB symlinks in absolute format */
|
||||
|
|
|
@ -378,6 +378,35 @@ static int detect_directory_symlink_target(struct cifs_sb_info *cifs_sb,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int create_native_socket(const unsigned int xid, struct inode *inode,
|
||||
struct dentry *dentry, struct cifs_tcon *tcon,
|
||||
const char *full_path)
|
||||
{
|
||||
struct reparse_data_buffer buf = {
|
||||
.ReparseTag = cpu_to_le32(IO_REPARSE_TAG_AF_UNIX),
|
||||
.ReparseDataLength = cpu_to_le16(0),
|
||||
};
|
||||
struct cifs_open_info_data data = {
|
||||
.reparse_point = true,
|
||||
.reparse = { .tag = IO_REPARSE_TAG_AF_UNIX, .buf = &buf, },
|
||||
};
|
||||
struct kvec iov = {
|
||||
.iov_base = &buf,
|
||||
.iov_len = sizeof(buf),
|
||||
};
|
||||
struct inode *new;
|
||||
int rc = 0;
|
||||
|
||||
new = smb2_get_reparse_inode(&data, inode->i_sb, xid,
|
||||
tcon, full_path, false, &iov, NULL);
|
||||
if (!IS_ERR(new))
|
||||
d_instantiate(dentry, new);
|
||||
else
|
||||
rc = PTR_ERR(new);
|
||||
cifs_free_open_info(&data);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int nfs_set_reparse_buf(struct reparse_nfs_data_buffer *buf,
|
||||
mode_t mode, dev_t dev,
|
||||
struct kvec *iov)
|
||||
|
@ -601,6 +630,9 @@ int smb2_mknod_reparse(unsigned int xid, struct inode *inode,
|
|||
{
|
||||
struct smb3_fs_context *ctx = CIFS_SB(inode->i_sb)->ctx;
|
||||
|
||||
if (S_ISSOCK(mode) && !ctx->nonativesocket && ctx->reparse_type != CIFS_REPARSE_TYPE_NONE)
|
||||
return create_native_socket(xid, inode, dentry, tcon, full_path);
|
||||
|
||||
switch (ctx->reparse_type) {
|
||||
case CIFS_REPARSE_TYPE_NFS:
|
||||
return mknod_nfs(xid, inode, dentry, tcon, full_path, mode, dev, NULL);
|
||||
|
|
Loading…
Reference in New Issue