Skip to content

Commit 45a99d5

Browse files
paliSteve French
authored andcommitted
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>
1 parent 78f6946 commit 45a99d5

File tree

5 files changed

+45
-0
lines changed

5 files changed

+45
-0
lines changed

fs/smb/client/cifsfs.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,10 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
715715
cifs_sb->ctx->backupgid));
716716
seq_show_option(s, "reparse",
717717
cifs_reparse_type_str(cifs_sb->ctx->reparse_type));
718+
if (cifs_sb->ctx->nonativesocket)
719+
seq_puts(s, ",nonativesocket");
720+
else
721+
seq_puts(s, ",nativesocket");
718722
seq_show_option(s, "symlink",
719723
cifs_symlink_type_str(get_cifs_symlink_type(cifs_sb)));
720724

fs/smb/client/connect.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2849,6 +2849,8 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
28492849
return 0;
28502850
if (old->ctx->reparse_type != new->ctx->reparse_type)
28512851
return 0;
2852+
if (old->ctx->nonativesocket != new->ctx->nonativesocket)
2853+
return 0;
28522854
if (old->ctx->symlink_type != new->ctx->symlink_type)
28532855
return 0;
28542856

fs/smb/client/fs_context.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
133133
fsparam_flag("rootfs", Opt_rootfs),
134134
fsparam_flag("compress", Opt_compress),
135135
fsparam_flag("witness", Opt_witness),
136+
fsparam_flag_no("nativesocket", Opt_nativesocket),
136137

137138
/* Mount options which take uid or gid */
138139
fsparam_uid("backupuid", Opt_backupuid),
@@ -1784,6 +1785,9 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
17841785
if (parse_reparse_flavor(fc, param->string, ctx))
17851786
goto cifs_parse_mount_err;
17861787
break;
1788+
case Opt_nativesocket:
1789+
ctx->nonativesocket = result.negated;
1790+
break;
17871791
case Opt_symlink:
17881792
if (parse_symlink_flavor(fc, param->string, ctx))
17891793
goto cifs_parse_mount_err;
@@ -1918,6 +1922,7 @@ int smb3_init_fs_context(struct fs_context *fc)
19181922
ctx->retrans = 1;
19191923
ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT;
19201924
ctx->symlink_type = CIFS_SYMLINK_TYPE_DEFAULT;
1925+
ctx->nonativesocket = 0;
19211926

19221927
/*
19231928
* short int override_uid = -1;

fs/smb/client/fs_context.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ enum cifs_param {
179179
Opt_cache,
180180
Opt_reparse,
181181
Opt_upcalltarget,
182+
Opt_nativesocket,
182183
Opt_symlink,
183184
Opt_symlinkroot,
184185

@@ -310,6 +311,7 @@ struct smb3_fs_context {
310311
bool dfs_automount:1; /* set for dfs automount only */
311312
enum cifs_reparse_type reparse_type;
312313
enum cifs_symlink_type symlink_type;
314+
bool nonativesocket:1;
313315
bool dfs_conn:1; /* set for dfs mounts */
314316
char *dns_dom;
315317
char *symlinkroot; /* top level directory for native SMB symlinks in absolute format */

fs/smb/client/reparse.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,35 @@ static int detect_directory_symlink_target(struct cifs_sb_info *cifs_sb,
378378
return 0;
379379
}
380380

381+
static int create_native_socket(const unsigned int xid, struct inode *inode,
382+
struct dentry *dentry, struct cifs_tcon *tcon,
383+
const char *full_path)
384+
{
385+
struct reparse_data_buffer buf = {
386+
.ReparseTag = cpu_to_le32(IO_REPARSE_TAG_AF_UNIX),
387+
.ReparseDataLength = cpu_to_le16(0),
388+
};
389+
struct cifs_open_info_data data = {
390+
.reparse_point = true,
391+
.reparse = { .tag = IO_REPARSE_TAG_AF_UNIX, .buf = &buf, },
392+
};
393+
struct kvec iov = {
394+
.iov_base = &buf,
395+
.iov_len = sizeof(buf),
396+
};
397+
struct inode *new;
398+
int rc = 0;
399+
400+
new = smb2_get_reparse_inode(&data, inode->i_sb, xid,
401+
tcon, full_path, false, &iov, NULL);
402+
if (!IS_ERR(new))
403+
d_instantiate(dentry, new);
404+
else
405+
rc = PTR_ERR(new);
406+
cifs_free_open_info(&data);
407+
return rc;
408+
}
409+
381410
static int nfs_set_reparse_buf(struct reparse_nfs_data_buffer *buf,
382411
mode_t mode, dev_t dev,
383412
struct kvec *iov)
@@ -601,6 +630,9 @@ int smb2_mknod_reparse(unsigned int xid, struct inode *inode,
601630
{
602631
struct smb3_fs_context *ctx = CIFS_SB(inode->i_sb)->ctx;
603632

633+
if (S_ISSOCK(mode) && !ctx->nonativesocket && ctx->reparse_type != CIFS_REPARSE_TYPE_NONE)
634+
return create_native_socket(xid, inode, dentry, tcon, full_path);
635+
604636
switch (ctx->reparse_type) {
605637
case CIFS_REPARSE_TYPE_NFS:
606638
return mknod_nfs(xid, inode, dentry, tcon, full_path, mode, dev, NULL);

0 commit comments

Comments
 (0)