[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20241012085549.670-1-pali@kernel.org>
Date: Sat, 12 Oct 2024 10:55:49 +0200
From: Pali Rohár <pali@...nel.org>
To: Steve French <sfrench@...ba.org>,
Paulo Alcantara <pc@...guebit.com>,
Ronnie Sahlberg <ronniesahlberg@...il.com>
Cc: linux-cifs@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [PATCH v2 3/7] 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@...nel.org>
---
fs/smb/client/cifsfs.c | 2 ++
fs/smb/client/connect.c | 2 ++
fs/smb/client/fs_context.c | 5 +++++
fs/smb/client/fs_context.h | 2 ++
fs/smb/client/reparse.c | 32 ++++++++++++++++++++++++++++++++
5 files changed, 43 insertions(+)
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index 39ec67d9808e..eb279d5c6bd3 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -689,6 +689,8 @@ 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");
seq_show_option(s, "symlink",
cifs_symlink_type_str(get_cifs_symlink_type(cifs_sb)));
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
index bc5b5100ac09..3db39f2ef5a8 100644
--- a/fs/smb/client/connect.c
+++ b/fs/smb/client/connect.c
@@ -2831,6 +2831,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;
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
index d68db6ac5f73..7f21630885cb 100644
--- a/fs/smb/client/fs_context.c
+++ b/fs/smb/client/fs_context.c
@@ -178,6 +178,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
fsparam_string("sec", Opt_sec),
fsparam_string("cache", Opt_cache),
fsparam_string("reparse", Opt_reparse),
+ fsparam_string("nativesocket", Opt_nativesocket),
fsparam_string("symlink", Opt_symlink),
fsparam_string("symlinkroot", Opt_symlinkroot),
@@ -1674,6 +1675,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;
@@ -1803,6 +1807,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;
diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h
index 5f306f581fd1..18d39d457145 100644
--- a/fs/smb/client/fs_context.h
+++ b/fs/smb/client/fs_context.h
@@ -170,6 +170,7 @@ enum cifs_param {
Opt_sec,
Opt_cache,
Opt_reparse,
+ Opt_nativesocket,
Opt_symlink,
Opt_symlinkroot,
@@ -300,6 +301,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 *symlinkroot; /* top level directory for native SMB symlinks in absolute format */
};
diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
index d950c60323e8..57320a4c4d79 100644
--- a/fs/smb/client/reparse.c
+++ b/fs/smb/client/reparse.c
@@ -375,6 +375,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 cifs_open_info_data data = {
+ .reparse_point = true,
+ .reparse = { .tag = IO_REPARSE_TAG_AF_UNIX, },
+ };
+ struct reparse_data_buffer buf = {
+ .ReparseTag = cpu_to_le32(IO_REPARSE_TAG_AF_UNIX),
+ .ReparseDataLength = cpu_to_le16(0),
+ };
+ 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_posix_data *buf,
mode_t mode, dev_t dev,
struct kvec *iov)
@@ -598,6 +627,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);
--
2.20.1
Powered by blists - more mailing lists