]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
cifs: Add support for creating native Windows sockets
authorPali Rohár <pali@kernel.org>
Mon, 16 Sep 2024 18:21:52 +0000 (20:21 +0200)
committerSteve French <stfrench@microsoft.com>
Fri, 31 Jan 2025 18:51:20 +0000 (12:51 -0600)
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>
fs/smb/client/cifsfs.c
fs/smb/client/connect.c
fs/smb/client/fs_context.c
fs/smb/client/fs_context.h
fs/smb/client/reparse.c

index f2c852c9d6a11f42966d2a16d4c53f5067923451..6a3bd652d251d31d1e48dedab0b84cc091bbb132 100644 (file)
@@ -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)));
 
index ebd20f48f6aacc2d851407704c1a9b9b0214fc57..f917de020dd5d873ea207fe40a18cb2c4244973d 100644 (file)
@@ -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;
 
index 821eb149e4b885919d1736344a77ae2c9f05ea54..e9b286d9a7ba37298ca0b2a116e69879fe57cc33 100644 (file)
@@ -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;
index 2ccdda350267ff332ac6d6ffee9b00cb18d2dc26..881bfc08667e7d9d5b78516d0262f073b0ff4ce9 100644 (file)
@@ -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 */
index 24a5f563df26afbe30f86078b152dec32b14e8bb..34bf4e3f28d98d1413cd4473bfb95ec8feb85170 100644 (file)
@@ -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);