mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/9] smb: support security and trusted xattrs over EAs
@ 2026-07-17  3:39 Ze Tan
  2026-07-17  3:39 ` [RFC PATCH v2 1/9] smb: client: support security.capability " Ze Tan
                   ` (8 more replies)
  0 siblings, 9 replies; 21+ messages in thread
From: Ze Tan @ 2026-07-17  3:39 UTC (permalink / raw)
  To: sfrench, linkinjeon, pc, sprasad, tom, senozhatsky, chenxiaosong,
	linux-cifs
  Cc: linux-kernel, tanze

The CIFS client and ksmbd currently expose SMB extended attributes
mainly through the Linux user.* namespace. This causes security and
trusted xattr names carried through SMB EAs to be stored with an
additional user. prefix on the server.

For example, security.xfstests can be stored as
user.security.xfstests instead of security.xfstests. This also prevents
security.capability from being handled as a file capability.

generic/093 exercises these namespaces through several commands:

  - setcap and getcap use security.capability;
  - _require_attrs security uses security.xfstests;
  - setfattr and getfattr use trusted.name.

This RFC adds end-to-end handling for the xattrs required by those
operations. The client passes security.capability,
security.xfstests and trusted.* names through SMB EAs without adding
the user. prefix. When SMB3 POSIX extensions are available, ksmbd maps
the same names to their native backing filesystem xattr namespaces for
set, get and list operations.

The security namespace is deliberately restricted to
security.capability and security.xfstests. Other security.* xattrs are
not exposed by this series. trusted.* names are supported while
internal POSIX ACL xattrs remain filtered.

The series also avoids an oplock self-deadlock found while running
generic/093. An EA or metadata-only reopen from the same SMB session
can otherwise break an oplock held by that session and wait for the
same client. Oplock breaks from other sessions and opens with share
conflicts continue to use the normal break path.

Patches 1-3 add the CIFS client support. Patches 4-5 refactor the ksmbd
EA name conversion paths without changing behavior. Patches 6-8 add
the corresponding ksmbd mappings. Patch 9 handles the same-session
oplock case.

The series touches both the CIFS client and ksmbd. It is sent as one
RFC so that the end-to-end name mapping and protocol behavior can be
reviewed together. It can be split into client and server patchsets
for merging after the approach is agreed.

Testing:

generic/093 was run with the CIFS test mount mapped to the fsgqa uid
and gid. Both xfstests mount option variables were configured as
follows:

  export CIFS_OPTS="-o username=fsgqa,password=<password>"
  export CIFS_OPTS="${CIFS_OPTS},uid=1001,gid=1001"
  export TEST_FS_MOUNT_OPTS="${CIFS_OPTS}"
  export MOUNT_OPTIONS="${CIFS_OPTS}"
  cd ~/xfstests/
  ./check -d generic/093

generic/093 passed.

Changelog
---------------

rfc v2: Rebase the patch series onto the for-next branch and resubmit it to avoid "Failed to apply" errors.

rfc: https://lore.kernel.org/all/20260715074908.641940-1-tanze@kylinos.cn/

Ze Tan (9):
  smb: client: support security.capability over EAs
  smb: client: support security.xfstests over EAs
  smb: client: support trusted xattrs over EAs
  ksmbd: extract SMB EA backing xattr name mapping
  ksmbd: extract SMB EA response name handling
  ksmbd: support security.capability EAs
  ksmbd: support security.xfstests EAs
  ksmbd: support trusted EAs
  ksmbd: avoid self oplock breaks for EA opens

 fs/smb/client/smb2ops.c |  34 ++++++++-
 fs/smb/client/xattr.c   | 109 ++++++++++++++++++++++++--
 fs/smb/server/oplock.c  |  49 ++++++++++++
 fs/smb/server/smb2pdu.c | 165 +++++++++++++++++++++++++++++++---------
 4 files changed, 311 insertions(+), 46 deletions(-)


base-commit: fce2dfa773ced15f27dd27cd0b482a7473cdcf2a
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 1/9] smb: client: support security.capability over EAs
  2026-07-17  3:39 [RFC PATCH v2 0/9] smb: support security and trusted xattrs over EAs Ze Tan
@ 2026-07-17  3:39 ` Ze Tan
  2026-07-20  5:21   ` Namjae Jeon
  2026-07-17  3:39 ` [RFC PATCH v2 2/9] smb: client: support security.xfstests " Ze Tan
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Ze Tan @ 2026-07-17  3:39 UTC (permalink / raw)
  To: sfrench, linkinjeon, pc, sprasad, tom, senozhatsky, chenxiaosong,
	linux-cifs
  Cc: linux-kernel, tanze

generic/093 uses setcap and getcap to check that a write clears the file
capability. The CIFS client does not have a security xattr handler, so
these commands cannot set or read security.capability through SMB EAs.

Register a security xattr handler and build the complete EA name for
SET_INFO and QUERY_INFO. Keep security.capability unchanged in EA lists.
Reject other security xattrs.

Signed-off-by: Ze Tan <tanze@kylinos.cn>
---
 fs/smb/client/smb2ops.c | 26 ++++++++++++---
 fs/smb/client/xattr.c   | 70 ++++++++++++++++++++++++++++++++++++++---
 2 files changed, 87 insertions(+), 9 deletions(-)

diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index cbd51a08e97e..320742ec3ed8 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -14,6 +14,7 @@
 #include <crypto/aead.h>
 #include <linux/fiemap.h>
 #include <linux/folio_queue.h>
+#include <linux/xattr.h>
 #include <uapi/linux/magic.h>
 #include "cifsfs.h"
 #include "cifsglob.h"
@@ -1043,6 +1044,15 @@ static int smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
 }
 
 #ifdef CONFIG_CIFS_XATTR
+static bool cifs_passthrough(const char *name, size_t name_len)
+{
+	if (name_len == sizeof(XATTR_NAME_CAPS) - 1 &&
+	    !memcmp(name, XATTR_NAME_CAPS, name_len))
+		return true;
+
+	return false;
+}
+
 static ssize_t
 move_smb2_ea_to_cifs(char *dst, size_t dst_size,
 		     struct smb2_file_full_ea_info *src, size_t src_size,
@@ -1085,16 +1095,24 @@ move_smb2_ea_to_cifs(char *dst, size_t dst_size,
 				goto out;
 			}
 		} else {
-			/* 'user.' plus a terminating null */
-			user_name_len = 5 + 1 + name_len;
+			bool passthrough_name;
+
+			passthrough_name = cifs_passthrough(name, name_len);
+			if (passthrough_name)
+				user_name_len = name_len + 1;
+			else
+				/* 'user.' plus a terminating null */
+				user_name_len = 5 + 1 + name_len;
 
 			if (buf_size == 0) {
 				/* skip copy - calc size only */
 				rc += user_name_len;
 			} else if (dst_size >= user_name_len) {
 				dst_size -= user_name_len;
-				memcpy(dst, "user.", 5);
-				dst += 5;
+				if (!passthrough_name) {
+					memcpy(dst, "user.", 5);
+					dst += 5;
+				}
 				memcpy(dst, src->ea_data, name_len);
 				dst += name_len;
 				*dst = 0;
diff --git a/fs/smb/client/xattr.c b/fs/smb/client/xattr.c
index 5091f6c0d7fe..8fa40593bc93 100644
--- a/fs/smb/client/xattr.c
+++ b/fs/smb/client/xattr.c
@@ -36,12 +36,38 @@
 #define SMB3_XATTR_CIFS_NTSD_FULL "system.smb3_ntsd_full" /* owner/DACL/SACL */
 #define SMB3_XATTR_ATTRIB "smb3.dosattrib"  /* full name: user.smb3.dosattrib */
 #define SMB3_XATTR_CREATETIME "smb3.creationtime"  /* user.smb3.creationtime */
-/* BB need to add server (Samba e.g) support for security and trusted prefix */
-
-enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT,
+enum { XATTR_USER, XATTR_SECURITY,
+	XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT,
 	XATTR_CIFS_NTSD_SACL, XATTR_CIFS_NTSD_OWNER,
 	XATTR_CIFS_NTSD, XATTR_CIFS_NTSD_FULL };
 
+static int cifs_build_ea_name(int xattr_flag, const char *name, char *ea_name,
+			      size_t ea_name_size)
+{
+	size_t name_len;
+
+	switch (xattr_flag) {
+	case XATTR_SECURITY:
+		/*
+		 * Only security.capability has native Linux security xattr
+		 * semantics on POSIX-capable servers.
+		 */
+		if (strcmp(name, XATTR_CAPS_SUFFIX))
+			return -EOPNOTSUPP;
+		name_len = strlen(name);
+		if (ea_name_size <= XATTR_SECURITY_PREFIX_LEN ||
+		    name_len > ea_name_size - XATTR_SECURITY_PREFIX_LEN - 1)
+			return -ERANGE;
+		memcpy(ea_name, XATTR_SECURITY_PREFIX,
+		       XATTR_SECURITY_PREFIX_LEN);
+		memcpy(ea_name + XATTR_SECURITY_PREFIX_LEN, name,
+		       name_len + 1);
+		return XATTR_SECURITY_PREFIX_LEN + name_len;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static int cifs_attrib_set(unsigned int xid, struct cifs_tcon *pTcon,
 			   struct inode *inode, const char *full_path,
 			   const void *value, size_t size)
@@ -104,6 +130,8 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
 	struct cifs_tcon *pTcon;
 	const char *full_path;
 	void *page;
+	char ea_name[XATTR_NAME_MAX + 1];
+	const char *server_ea_name = name;
 
 	tlink = cifs_sb_tlink(cifs_sb);
 	if (IS_ERR(tlink))
@@ -131,6 +159,16 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
 	}
 
 	switch (handler->flags) {
+	case XATTR_SECURITY:
+		rc = cifs_build_ea_name(handler->flags, name, ea_name,
+					sizeof(ea_name));
+		if (rc < 0)
+			goto out;
+		server_ea_name = ea_name;
+		cifs_dbg(FYI, "%s: setting security xattr %s\n",
+			 __func__, name);
+		goto set_ea;
+
 	case XATTR_USER:
 		cifs_dbg(FYI, "%s:setting user xattr %s\n", __func__, name);
 		if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) ||
@@ -149,12 +187,13 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
 			break;
 		}
 
+set_ea:
 		if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_XATTR)
 			goto out;
 
 		if (pTcon->ses->server->ops->set_EA) {
 			rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
-				full_path, name, value, (__u16)size,
+				full_path, server_ea_name, value, (__u16)size,
 				cifs_sb->local_nls, cifs_sb);
 			if (rc == 0)
 				inode_set_ctime_current(inode);
@@ -280,6 +319,8 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
 	struct cifs_tcon *pTcon;
 	const char *full_path;
 	void *page;
+	char ea_name[XATTR_NAME_MAX + 1];
+	const char *server_ea_name = name;
 
 	tlink = cifs_sb_tlink(cifs_sb);
 	if (IS_ERR(tlink))
@@ -297,6 +338,16 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
 
 	/* return alt name if available as pseudo attr */
 	switch (handler->flags) {
+	case XATTR_SECURITY:
+		rc = cifs_build_ea_name(handler->flags, name, ea_name,
+					sizeof(ea_name));
+		if (rc < 0)
+			goto out;
+		server_ea_name = ea_name;
+		cifs_dbg(FYI, "%s: querying security xattr %s\n",
+			 __func__, name);
+		goto query_ea;
+
 	case XATTR_USER:
 		cifs_dbg(FYI, "%s:querying user xattr %s\n", __func__, name);
 		if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) ||
@@ -309,12 +360,13 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
 			break;
 		}
 
+query_ea:
 		if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_XATTR)
 			goto out;
 
 		if (pTcon->ses->server->ops->query_all_EAs)
 			rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
-				full_path, name, value, size, cifs_sb);
+				full_path, server_ea_name, value, size, cifs_sb);
 		break;
 
 	case XATTR_CIFS_ACL:
@@ -438,6 +490,13 @@ static const struct xattr_handler cifs_user_xattr_handler = {
 	.set = cifs_xattr_set,
 };
 
+static const struct xattr_handler cifs_security_xattr_handler = {
+	.prefix = XATTR_SECURITY_PREFIX,
+	.flags = XATTR_SECURITY,
+	.get = cifs_xattr_get,
+	.set = cifs_xattr_set,
+};
+
 /* os2.* attributes are treated like user.* attributes */
 static const struct xattr_handler cifs_os2_xattr_handler = {
 	.prefix = XATTR_OS2_PREFIX,
@@ -522,6 +581,7 @@ static const struct xattr_handler smb3_ntsd_full_xattr_handler = {
 
 const struct xattr_handler * const cifs_xattr_handlers[] = {
 	&cifs_user_xattr_handler,
+	&cifs_security_xattr_handler,
 	&cifs_os2_xattr_handler,
 	&cifs_cifs_acl_xattr_handler,
 	&smb3_acl_xattr_handler, /* alias for above since avoiding "cifs" */
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 2/9] smb: client: support security.xfstests over EAs
  2026-07-17  3:39 [RFC PATCH v2 0/9] smb: support security and trusted xattrs over EAs Ze Tan
  2026-07-17  3:39 ` [RFC PATCH v2 1/9] smb: client: support security.capability " Ze Tan
@ 2026-07-17  3:39 ` Ze Tan
  2026-07-17  3:39 ` [RFC PATCH v2 3/9] smb: client: support trusted xattrs " Ze Tan
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Ze Tan @ 2026-07-17  3:39 UTC (permalink / raw)
  To: sfrench, linkinjeon, pc, sprasad, tom, senozhatsky, chenxiaosong,
	linux-cifs
  Cc: linux-kernel, tanze

Before checking file capabilities, generic/093 calls _require_attrs
security. This helper runs "setfattr -n security.xfstests" to check the
security xattr namespace. The security handler supports only
security.capability, so this command returns "Operation not supported".

Add security.xfstests as another exact security EA name. Keep this name
unchanged in EA lists. Continue to reject other security xattrs.

Signed-off-by: Ze Tan <tanze@kylinos.cn>
---
 fs/smb/client/smb2ops.c | 4 ++++
 fs/smb/client/xattr.c   | 7 ++++---
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 320742ec3ed8..9638fdad93cc 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -1050,6 +1050,10 @@ static bool cifs_passthrough(const char *name, size_t name_len)
 	    !memcmp(name, XATTR_NAME_CAPS, name_len))
 		return true;
 
+	if (name_len == sizeof(XATTR_SECURITY_PREFIX "xfstests") - 1 &&
+	    !memcmp(name, XATTR_SECURITY_PREFIX "xfstests", name_len))
+		return true;
+
 	return false;
 }
 
diff --git a/fs/smb/client/xattr.c b/fs/smb/client/xattr.c
index 8fa40593bc93..42db6920901e 100644
--- a/fs/smb/client/xattr.c
+++ b/fs/smb/client/xattr.c
@@ -49,10 +49,11 @@ static int cifs_build_ea_name(int xattr_flag, const char *name, char *ea_name,
 	switch (xattr_flag) {
 	case XATTR_SECURITY:
 		/*
-		 * Only security.capability has native Linux security xattr
-		 * semantics on POSIX-capable servers.
+		 * Only security.capability and the xfstests security namespace
+		 * probe are supported on POSIX-capable servers.
 		 */
-		if (strcmp(name, XATTR_CAPS_SUFFIX))
+		if (strcmp(name, XATTR_CAPS_SUFFIX) &&
+		    strcmp(name, "xfstests"))
 			return -EOPNOTSUPP;
 		name_len = strlen(name);
 		if (ea_name_size <= XATTR_SECURITY_PREFIX_LEN ||
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 3/9] smb: client: support trusted xattrs over EAs
  2026-07-17  3:39 [RFC PATCH v2 0/9] smb: support security and trusted xattrs over EAs Ze Tan
  2026-07-17  3:39 ` [RFC PATCH v2 1/9] smb: client: support security.capability " Ze Tan
  2026-07-17  3:39 ` [RFC PATCH v2 2/9] smb: client: support security.xfstests " Ze Tan
@ 2026-07-17  3:39 ` Ze Tan
  2026-07-17  3:39 ` [RFC PATCH v2 4/9] ksmbd: extract SMB EA backing xattr name mapping Ze Tan
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Ze Tan @ 2026-07-17  3:39 UTC (permalink / raw)
  To: sfrench, linkinjeon, pc, sprasad, tom, senozhatsky, chenxiaosong,
	linux-cifs
  Cc: linux-kernel, tanze

generic/093 uses setfattr and getfattr to check that a write does not
clear trusted.name. The CIFS client does not have a trusted xattr handler,
so these commands cannot set or read trusted xattrs through SMB EAs.

Register a trusted xattr handler and build the complete trusted EA name
for SET_INFO and QUERY_INFO. Keep the trusted prefix in EA lists.

Signed-off-by: Ze Tan <tanze@kylinos.cn>
---
 fs/smb/client/smb2ops.c |  4 ++++
 fs/smb/client/xattr.c   | 40 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 9638fdad93cc..c3a18fafbfa0 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -1046,6 +1046,10 @@ static int smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
 #ifdef CONFIG_CIFS_XATTR
 static bool cifs_passthrough(const char *name, size_t name_len)
 {
+	if (name_len > XATTR_TRUSTED_PREFIX_LEN &&
+	    !memcmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
+		return true;
+
 	if (name_len == sizeof(XATTR_NAME_CAPS) - 1 &&
 	    !memcmp(name, XATTR_NAME_CAPS, name_len))
 		return true;
diff --git a/fs/smb/client/xattr.c b/fs/smb/client/xattr.c
index 42db6920901e..3dae8b23aca7 100644
--- a/fs/smb/client/xattr.c
+++ b/fs/smb/client/xattr.c
@@ -36,7 +36,7 @@
 #define SMB3_XATTR_CIFS_NTSD_FULL "system.smb3_ntsd_full" /* owner/DACL/SACL */
 #define SMB3_XATTR_ATTRIB "smb3.dosattrib"  /* full name: user.smb3.dosattrib */
 #define SMB3_XATTR_CREATETIME "smb3.creationtime"  /* user.smb3.creationtime */
-enum { XATTR_USER, XATTR_SECURITY,
+enum { XATTR_USER, XATTR_TRUSTED, XATTR_SECURITY,
 	XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT,
 	XATTR_CIFS_NTSD_SACL, XATTR_CIFS_NTSD_OWNER,
 	XATTR_CIFS_NTSD, XATTR_CIFS_NTSD_FULL };
@@ -64,6 +64,16 @@ static int cifs_build_ea_name(int xattr_flag, const char *name, char *ea_name,
 		memcpy(ea_name + XATTR_SECURITY_PREFIX_LEN, name,
 		       name_len + 1);
 		return XATTR_SECURITY_PREFIX_LEN + name_len;
+	case XATTR_TRUSTED:
+		name_len = strlen(name);
+		if (ea_name_size <= XATTR_TRUSTED_PREFIX_LEN ||
+		    name_len > ea_name_size - XATTR_TRUSTED_PREFIX_LEN - 1)
+			return -ERANGE;
+		memcpy(ea_name, XATTR_TRUSTED_PREFIX,
+		       XATTR_TRUSTED_PREFIX_LEN);
+		memcpy(ea_name + XATTR_TRUSTED_PREFIX_LEN, name,
+		       name_len + 1);
+		return XATTR_TRUSTED_PREFIX_LEN + name_len;
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -160,6 +170,16 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
 	}
 
 	switch (handler->flags) {
+	case XATTR_TRUSTED:
+		rc = cifs_build_ea_name(handler->flags, name, ea_name,
+					sizeof(ea_name));
+		if (rc < 0)
+			goto out;
+		server_ea_name = ea_name;
+		cifs_dbg(FYI, "%s: setting trusted xattr %s\n",
+			 __func__, name);
+		goto set_ea;
+
 	case XATTR_SECURITY:
 		rc = cifs_build_ea_name(handler->flags, name, ea_name,
 					sizeof(ea_name));
@@ -339,6 +359,16 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
 
 	/* return alt name if available as pseudo attr */
 	switch (handler->flags) {
+	case XATTR_TRUSTED:
+		rc = cifs_build_ea_name(handler->flags, name, ea_name,
+					sizeof(ea_name));
+		if (rc < 0)
+			goto out;
+		server_ea_name = ea_name;
+		cifs_dbg(FYI, "%s: querying trusted xattr %s\n",
+			 __func__, name);
+		goto query_ea;
+
 	case XATTR_SECURITY:
 		rc = cifs_build_ea_name(handler->flags, name, ea_name,
 					sizeof(ea_name));
@@ -491,6 +521,13 @@ static const struct xattr_handler cifs_user_xattr_handler = {
 	.set = cifs_xattr_set,
 };
 
+static const struct xattr_handler cifs_trusted_xattr_handler = {
+	.prefix = XATTR_TRUSTED_PREFIX,
+	.flags = XATTR_TRUSTED,
+	.get = cifs_xattr_get,
+	.set = cifs_xattr_set,
+};
+
 static const struct xattr_handler cifs_security_xattr_handler = {
 	.prefix = XATTR_SECURITY_PREFIX,
 	.flags = XATTR_SECURITY,
@@ -582,6 +619,7 @@ static const struct xattr_handler smb3_ntsd_full_xattr_handler = {
 
 const struct xattr_handler * const cifs_xattr_handlers[] = {
 	&cifs_user_xattr_handler,
+	&cifs_trusted_xattr_handler,
 	&cifs_security_xattr_handler,
 	&cifs_os2_xattr_handler,
 	&cifs_cifs_acl_xattr_handler,
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 4/9] ksmbd: extract SMB EA backing xattr name mapping
  2026-07-17  3:39 [RFC PATCH v2 0/9] smb: support security and trusted xattrs over EAs Ze Tan
                   ` (2 preceding siblings ...)
  2026-07-17  3:39 ` [RFC PATCH v2 3/9] smb: client: support trusted xattrs " Ze Tan
@ 2026-07-17  3:39 ` Ze Tan
  2026-07-17  3:39 ` [RFC PATCH v2 5/9] ksmbd: extract SMB EA response name handling Ze Tan
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Ze Tan @ 2026-07-17  3:39 UTC (permalink / raw)
  To: sfrench, linkinjeon, pc, sprasad, tom, senozhatsky, chenxiaosong,
	linux-cifs
  Cc: linux-kernel, tanze

smb2_set_ea() directly adds the user prefix when it builds the backing
xattr name. This mixes name conversion with the set operation.

Extract ksmbd_map_ea_name_to_xattr() and keep the existing behavior
unchanged.

Signed-off-by: Ze Tan <tanze@kylinos.cn>
---
 fs/smb/server/smb2pdu.c | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index b73167785e87..dad3427a584e 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -2643,6 +2643,18 @@ static noinline int create_smb2_pipe(struct ksmbd_work *work)
 	return err;
 }
 
+static int ksmbd_map_ea_name_to_xattr(const char *ea_name,
+				      size_t ea_name_len, char *attr_name)
+{
+	if (ea_name_len > XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)
+		return -EINVAL;
+
+	memcpy(attr_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
+	memcpy(&attr_name[XATTR_USER_PREFIX_LEN], ea_name, ea_name_len);
+	attr_name[XATTR_USER_PREFIX_LEN + ea_name_len] = '\0';
+	return XATTR_USER_PREFIX_LEN + ea_name_len;
+}
+
 /**
  * smb2_set_ea() - handler for setting extended attributes using set
  *		info command
@@ -2658,7 +2670,7 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
 {
 	struct mnt_idmap *idmap = mnt_idmap(path->mnt);
 	char *attr_name = NULL, *value;
-	int rc = 0;
+	int rc = 0, attr_name_len;
 	unsigned int next = 0;
 
 	if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + 1 +
@@ -2679,24 +2691,21 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
 			    le16_to_cpu(eabuf->EaValueLength),
 			    le32_to_cpu(eabuf->NextEntryOffset));
 
-		if (eabuf->EaNameLength >
-		    (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) {
+		attr_name_len = ksmbd_map_ea_name_to_xattr(eabuf->name,
+							   eabuf->EaNameLength,
+							   attr_name);
+		if (attr_name_len < 0) {
 			rc = -EINVAL;
 			break;
 		}
 
-		memcpy(attr_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
-		memcpy(&attr_name[XATTR_USER_PREFIX_LEN], eabuf->name,
-		       eabuf->EaNameLength);
-		attr_name[XATTR_USER_PREFIX_LEN + eabuf->EaNameLength] = '\0';
 		value = (char *)&eabuf->name + eabuf->EaNameLength + 1;
 
 		if (!eabuf->EaValueLength) {
 			rc = ksmbd_vfs_casexattr_len(idmap,
 						     path->dentry,
 						     attr_name,
-						     XATTR_USER_PREFIX_LEN +
-						     eabuf->EaNameLength);
+						     attr_name_len);
 
 			/* delete the EA only when it exits */
 			if (rc > 0) {
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 5/9] ksmbd: extract SMB EA response name handling
  2026-07-17  3:39 [RFC PATCH v2 0/9] smb: support security and trusted xattrs over EAs Ze Tan
                   ` (3 preceding siblings ...)
  2026-07-17  3:39 ` [RFC PATCH v2 4/9] ksmbd: extract SMB EA backing xattr name mapping Ze Tan
@ 2026-07-17  3:39 ` Ze Tan
  2026-07-17  3:39 ` [RFC PATCH v2 6/9] ksmbd: support security.capability EAs Ze Tan
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Ze Tan @ 2026-07-17  3:39 UTC (permalink / raw)
  To: sfrench, linkinjeon, pc, sprasad, tom, senozhatsky, chenxiaosong,
	linux-cifs
  Cc: linux-kernel, tanze

smb2_get_ea() directly checks the user namespace, filters internal EAs,
and removes the user prefix.

Extract ksmbd_is_visible_ea_name() and keep the existing behavior
unchanged.

Signed-off-by: Ze Tan <tanze@kylinos.cn>
---
 fs/smb/server/smb2pdu.c | 53 ++++++++++++++++++++++-------------------
 1 file changed, 29 insertions(+), 24 deletions(-)

diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index dad3427a584e..f0422e9c6a3a 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -2655,6 +2655,27 @@ static int ksmbd_map_ea_name_to_xattr(const char *ea_name,
 	return XATTR_USER_PREFIX_LEN + ea_name_len;
 }
 
+static bool ksmbd_is_visible_ea_name(const char *name, const char **ea_name,
+				     size_t *ea_name_len)
+{
+	size_t name_len = strlen(name);
+
+	if (strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
+		return false;
+
+	*ea_name = name + XATTR_USER_PREFIX_LEN;
+	*ea_name_len = name_len - XATTR_USER_PREFIX_LEN;
+
+	if (!strncmp(*ea_name, STREAM_PREFIX, STREAM_PREFIX_LEN))
+		return false;
+
+	if (!strncmp(*ea_name, DOS_ATTRIBUTE_PREFIX,
+		     DOS_ATTRIBUTE_PREFIX_LEN))
+		return false;
+
+	return true;
+}
+
 /**
  * smb2_set_ea() - handler for setting extended attributes using set
  *		info command
@@ -5203,36 +5224,25 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
 	idx = 0;
 
 	while (idx < xattr_list_len) {
+		const char *ea_name;
+		size_t visible_name_len;
+
 		name = xattr_list + idx;
 		name_len = strlen(name);
 
 		ksmbd_debug(SMB, "%s, len %d\n", name, name_len);
 		idx += name_len + 1;
 
-		/*
-		 * CIFS does not support EA other than user.* namespace,
-		 * still keep the framework generic, to list other attrs
-		 * in future.
-		 */
-		if (strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
+		if (!ksmbd_is_visible_ea_name(name, &ea_name,
+					      &visible_name_len))
 			continue;
 
-		if (!strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX,
-			     STREAM_PREFIX_LEN))
-			continue;
+		name_len = visible_name_len;
 
 		if (req->InputBufferLength &&
-		    strncmp(&name[XATTR_USER_PREFIX_LEN], ea_req->name,
-			    ea_req->EaNameLength))
+		    strncmp(ea_name, ea_req->name, ea_req->EaNameLength))
 			continue;
 
-		if (!strncmp(&name[XATTR_USER_PREFIX_LEN],
-			     DOS_ATTRIBUTE_PREFIX, DOS_ATTRIBUTE_PREFIX_LEN))
-			continue;
-
-		if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
-			name_len -= XATTR_USER_PREFIX_LEN;
-
 		ptr = eainfo->name + name_len + 1;
 		buf_free_len -= (offsetof(struct smb2_ea_info, name) +
 				name_len + 1);
@@ -5257,12 +5267,7 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
 		ptr += value_len;
 		eainfo->Flags = 0;
 		eainfo->EaNameLength = name_len;
-
-		if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
-			memcpy(eainfo->name, &name[XATTR_USER_PREFIX_LEN],
-			       name_len);
-		else
-			memcpy(eainfo->name, name, name_len);
+		memcpy(eainfo->name, ea_name, name_len);
 
 		eainfo->name[name_len] = '\0';
 		eainfo->EaValueLength = cpu_to_le16(value_len);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 6/9] ksmbd: support security.capability EAs
  2026-07-17  3:39 [RFC PATCH v2 0/9] smb: support security and trusted xattrs over EAs Ze Tan
                   ` (4 preceding siblings ...)
  2026-07-17  3:39 ` [RFC PATCH v2 5/9] ksmbd: extract SMB EA response name handling Ze Tan
@ 2026-07-17  3:39 ` Ze Tan
  2026-07-20  6:57   ` Ralph Boehme
  2026-07-17  3:39 ` [RFC PATCH v2 7/9] ksmbd: support security.xfstests EAs Ze Tan
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Ze Tan @ 2026-07-17  3:39 UTC (permalink / raw)
  To: sfrench, linkinjeon, pc, sprasad, tom, senozhatsky, chenxiaosong,
	linux-cifs
  Cc: linux-kernel, tanze

generic/093 uses setcap and getcap to check that a write clears the file
capability. ksmbd adds the user prefix to every SMB EA name, so setcap
stores security.capability as user.security.capability and getcap cannot
read it as a file capability.

When SMB3 POSIX extensions are available, map security.capability to the
same backing xattr name. Use this mapping for set, get, and list
operations.

Signed-off-by: Ze Tan <tanze@kylinos.cn>
---
 fs/smb/server/smb2pdu.c | 77 +++++++++++++++++++++++++++++++----------
 1 file changed, 58 insertions(+), 19 deletions(-)

diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index f0422e9c6a3a..2159b45c80a6 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -2643,9 +2643,35 @@ static noinline int create_smb2_pipe(struct ksmbd_work *work)
 	return err;
 }
 
-static int ksmbd_map_ea_name_to_xattr(const char *ea_name,
-				      size_t ea_name_len, char *attr_name)
+static bool ksmbd_is_security_capability_ea_name(const char *name,
+						 size_t name_len)
 {
+	return name_len == sizeof(XATTR_NAME_CAPS) - 1 &&
+	       !strncmp(name, XATTR_NAME_CAPS, name_len);
+}
+
+static bool ksmbd_is_posix_ea_name(const char *name, size_t name_len)
+{
+	if (ksmbd_is_security_capability_ea_name(name, name_len))
+		return true;
+
+	return false;
+}
+
+static int ksmbd_map_ea_name_to_xattr(bool posix_extensions,
+				      const char *ea_name, size_t ea_name_len,
+				      char *attr_name)
+{
+	if (posix_extensions &&
+	    ksmbd_is_posix_ea_name(ea_name, ea_name_len)) {
+		if (ea_name_len > XATTR_NAME_MAX)
+			return -EINVAL;
+
+		memcpy(attr_name, ea_name, ea_name_len);
+		attr_name[ea_name_len] = '\0';
+		return ea_name_len;
+	}
+
 	if (ea_name_len > XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)
 		return -EINVAL;
 
@@ -2655,24 +2681,30 @@ static int ksmbd_map_ea_name_to_xattr(const char *ea_name,
 	return XATTR_USER_PREFIX_LEN + ea_name_len;
 }
 
-static bool ksmbd_is_visible_ea_name(const char *name, const char **ea_name,
-				     size_t *ea_name_len)
+static bool ksmbd_is_visible_ea_name(bool posix_extensions, const char *name,
+				     const char **ea_name, size_t *ea_name_len)
 {
 	size_t name_len = strlen(name);
 
-	if (strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
-		return false;
+	if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
+		*ea_name = name + XATTR_USER_PREFIX_LEN;
+		*ea_name_len = name_len - XATTR_USER_PREFIX_LEN;
+
+		if (!strncmp(*ea_name, STREAM_PREFIX, STREAM_PREFIX_LEN))
+			return false;
 
-	*ea_name = name + XATTR_USER_PREFIX_LEN;
-	*ea_name_len = name_len - XATTR_USER_PREFIX_LEN;
+		if (!strncmp(*ea_name, DOS_ATTRIBUTE_PREFIX,
+			     DOS_ATTRIBUTE_PREFIX_LEN))
+			return false;
 
-	if (!strncmp(*ea_name, STREAM_PREFIX, STREAM_PREFIX_LEN))
-		return false;
+		return true;
+	}
 
-	if (!strncmp(*ea_name, DOS_ATTRIBUTE_PREFIX,
-		     DOS_ATTRIBUTE_PREFIX_LEN))
+	if (!posix_extensions || !ksmbd_is_posix_ea_name(name, name_len))
 		return false;
 
+	*ea_name = name;
+	*ea_name_len = name_len;
 	return true;
 }
 
@@ -2683,11 +2715,13 @@ static bool ksmbd_is_visible_ea_name(const char *name, const char **ea_name,
  * @buf_len:	set info command buffer length
  * @path:	dentry path for get ea
  * @get_write:	get write access to a mount
+ * @posix_extensions:	client negotiated SMB3 POSIX extensions
  *
  * Return:	0 on success, otherwise error
  */
 static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
-		       const struct path *path, bool get_write)
+		       const struct path *path, bool get_write,
+		       bool posix_extensions)
 {
 	struct mnt_idmap *idmap = mnt_idmap(path->mnt);
 	char *attr_name = NULL, *value;
@@ -2712,7 +2746,8 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
 			    le16_to_cpu(eabuf->EaValueLength),
 			    le32_to_cpu(eabuf->NextEntryOffset));
 
-		attr_name_len = ksmbd_map_ea_name_to_xattr(eabuf->name,
+		attr_name_len = ksmbd_map_ea_name_to_xattr(posix_extensions,
+							   eabuf->name,
 							   eabuf->EaNameLength,
 							   attr_name);
 		if (attr_name_len < 0) {
@@ -3694,7 +3729,8 @@ int smb2_open(struct ksmbd_work *work)
 
 			rc = smb2_set_ea(&ea_buf->ea,
 					 le32_to_cpu(ea_buf->ccontext.DataLength),
-					 &path, false);
+					 &path, false,
+					 work->tcon->posix_extensions);
 			if (rc == -EOPNOTSUPP)
 				rc = 0;
 			else if (rc)
@@ -5180,7 +5216,7 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
 	}
 
 	path = &fp->filp->f_path;
-	/* single EA entry is requested with given user.* name */
+	/* single EA entry is requested with a client-visible EA name */
 	if (req->InputBufferLength) {
 		if (le32_to_cpu(req->InputBufferLength) <=
 		    sizeof(struct smb2_ea_info_req))
@@ -5233,14 +5269,16 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
 		ksmbd_debug(SMB, "%s, len %d\n", name, name_len);
 		idx += name_len + 1;
 
-		if (!ksmbd_is_visible_ea_name(name, &ea_name,
+		if (!ksmbd_is_visible_ea_name(work->tcon->posix_extensions, name,
+					      &ea_name,
 					      &visible_name_len))
 			continue;
 
 		name_len = visible_name_len;
 
 		if (req->InputBufferLength &&
-		    strncmp(ea_name, ea_req->name, ea_req->EaNameLength))
+		    (name_len != ea_req->EaNameLength ||
+		     strncmp(ea_name, ea_req->name, ea_req->EaNameLength)))
 			continue;
 
 		ptr = eainfo->name + name_len + 1;
@@ -7061,7 +7099,8 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
 			return -EMSGSIZE;
 
 		return smb2_set_ea((struct smb2_ea_info *)buffer,
-				   buf_len, &fp->filp->f_path, true);
+				   buf_len, &fp->filp->f_path, true,
+				   work->tcon->posix_extensions);
 	}
 	case FILE_POSITION_INFORMATION:
 	{
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 7/9] ksmbd: support security.xfstests EAs
  2026-07-17  3:39 [RFC PATCH v2 0/9] smb: support security and trusted xattrs over EAs Ze Tan
                   ` (5 preceding siblings ...)
  2026-07-17  3:39 ` [RFC PATCH v2 6/9] ksmbd: support security.capability EAs Ze Tan
@ 2026-07-17  3:39 ` Ze Tan
  2026-07-20  5:03   ` Namjae Jeon
  2026-07-17  3:39 ` [RFC PATCH v2 8/9] ksmbd: support trusted EAs Ze Tan
  2026-07-17  3:39 ` [RFC PATCH v2 9/9] ksmbd: avoid self oplock breaks for EA opens Ze Tan
  8 siblings, 1 reply; 21+ messages in thread
From: Ze Tan @ 2026-07-17  3:39 UTC (permalink / raw)
  To: sfrench, linkinjeon, pc, sprasad, tom, senozhatsky, chenxiaosong,
	linux-cifs
  Cc: linux-kernel, tanze

Before checking file capabilities, generic/093 calls _require_attrs
security. This helper runs "setfattr -n security.xfstests". ksmbd
recognizes only security.capability as a native security EA, so it stores
the attribute as user.security.xfstests.

Add security.xfstests as another exact security EA name. Use this name
directly for set, get, and list operations. Do not support other security
xattrs.

Signed-off-by: Ze Tan <tanze@kylinos.cn>
---
 fs/smb/server/smb2pdu.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index 2159b45c80a6..da3d5c217577 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -2650,11 +2650,21 @@ static bool ksmbd_is_security_capability_ea_name(const char *name,
 	       !strncmp(name, XATTR_NAME_CAPS, name_len);
 }
 
+static bool ksmbd_is_security_xfstests_ea_name(const char *name,
+					       size_t name_len)
+{
+	return name_len == sizeof(XATTR_SECURITY_PREFIX "xfstests") - 1 &&
+	       !strncmp(name, XATTR_SECURITY_PREFIX "xfstests", name_len);
+}
+
 static bool ksmbd_is_posix_ea_name(const char *name, size_t name_len)
 {
 	if (ksmbd_is_security_capability_ea_name(name, name_len))
 		return true;
 
+	if (ksmbd_is_security_xfstests_ea_name(name, name_len))
+		return true;
+
 	return false;
 }
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 8/9] ksmbd: support trusted EAs
  2026-07-17  3:39 [RFC PATCH v2 0/9] smb: support security and trusted xattrs over EAs Ze Tan
                   ` (6 preceding siblings ...)
  2026-07-17  3:39 ` [RFC PATCH v2 7/9] ksmbd: support security.xfstests EAs Ze Tan
@ 2026-07-17  3:39 ` Ze Tan
  2026-07-17  3:39 ` [RFC PATCH v2 9/9] ksmbd: avoid self oplock breaks for EA opens Ze Tan
  8 siblings, 0 replies; 21+ messages in thread
From: Ze Tan @ 2026-07-17  3:39 UTC (permalink / raw)
  To: sfrench, linkinjeon, pc, sprasad, tom, senozhatsky, chenxiaosong,
	linux-cifs
  Cc: linux-kernel, tanze

generic/093 uses "setfattr -n trusted.name" and getfattr to check that a
write does not clear the trusted xattr. ksmbd stores the attribute as
user.trusted.name on the backing filesystem.

Map trusted names to the trusted xattr namespace for set, get, and list
operations. Filter the internal POSIX ACL xattrs.

Signed-off-by: Ze Tan <tanze@kylinos.cn>
---
 fs/smb/server/smb2pdu.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index da3d5c217577..7b2baa317888 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -2643,6 +2643,19 @@ static noinline int create_smb2_pipe(struct ksmbd_work *work)
 	return err;
 }
 
+static bool ksmbd_is_internal_acl_ea_name(const char *name, size_t name_len)
+{
+	return (name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 &&
+		!strncmp(name, XATTR_NAME_POSIX_ACL_ACCESS, name_len)) ||
+	       (name_len == sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1 &&
+		!strncmp(name, XATTR_NAME_POSIX_ACL_DEFAULT, name_len)) ||
+	       (name_len == sizeof(XATTR_TRUSTED_PREFIX "SGI_ACL_FILE") - 1 &&
+		!strncmp(name, XATTR_TRUSTED_PREFIX "SGI_ACL_FILE", name_len)) ||
+	       (name_len == sizeof(XATTR_TRUSTED_PREFIX "SGI_ACL_DEFAULT") - 1 &&
+		!strncmp(name, XATTR_TRUSTED_PREFIX "SGI_ACL_DEFAULT",
+			 name_len));
+}
+
 static bool ksmbd_is_security_capability_ea_name(const char *name,
 						 size_t name_len)
 {
@@ -2665,6 +2678,18 @@ static bool ksmbd_is_posix_ea_name(const char *name, size_t name_len)
 	if (ksmbd_is_security_xfstests_ea_name(name, name_len))
 		return true;
 
+	/*
+	 * POSIX ACL xattrs are filesystem-internal ACL records, not
+	 * user-visible EAs.  XFS may also expose trusted.SGI_ACL_* aliases
+	 * through listxattr(), so filter those as well.
+	 */
+	if (ksmbd_is_internal_acl_ea_name(name, name_len))
+		return false;
+
+	if (name_len > XATTR_TRUSTED_PREFIX_LEN &&
+	    !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
+		return true;
+
 	return false;
 }
 
@@ -2672,6 +2697,9 @@ static int ksmbd_map_ea_name_to_xattr(bool posix_extensions,
 				      const char *ea_name, size_t ea_name_len,
 				      char *attr_name)
 {
+	if (ksmbd_is_internal_acl_ea_name(ea_name, ea_name_len))
+		return -EINVAL;
+
 	if (posix_extensions &&
 	    ksmbd_is_posix_ea_name(ea_name, ea_name_len)) {
 		if (ea_name_len > XATTR_NAME_MAX)
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 9/9] ksmbd: avoid self oplock breaks for EA opens
  2026-07-17  3:39 [RFC PATCH v2 0/9] smb: support security and trusted xattrs over EAs Ze Tan
                   ` (7 preceding siblings ...)
  2026-07-17  3:39 ` [RFC PATCH v2 8/9] ksmbd: support trusted EAs Ze Tan
@ 2026-07-17  3:39 ` Ze Tan
  2026-07-20  5:34   ` Namjae Jeon
  8 siblings, 1 reply; 21+ messages in thread
From: Ze Tan @ 2026-07-17  3:39 UTC (permalink / raw)
  To: sfrench, linkinjeon, pc, sprasad, tom, senozhatsky, chenxiaosong,
	linux-cifs
  Cc: linux-kernel, tanze

generic/093 writes to a file after setcap sets security.capability. The
CIFS client can reopen the file to query or update EAs while the same
session holds an oplock. ksmbd breaks this oplock and waits for the same
client, so the write can block.

Skip the oplock break for same-session EA or metadata opens. Keep the
normal break when another session holds an oplock.

Signed-off-by: Ze Tan <tanze@kylinos.cn>
---
 fs/smb/server/oplock.c | 49 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
index 3c55ae5d6a11..85f7c29fc2c4 100644
--- a/fs/smb/server/oplock.c
+++ b/fs/smb/server/oplock.c
@@ -1424,6 +1424,49 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
 	ksmbd_inode_put(p_ci);
 }
 
+static bool ksmbd_skip_session_ea_break(struct ksmbd_work *work,
+					struct ksmbd_file *fp,
+					int req_op_level,
+					struct lease_ctx_info *lctx)
+{
+	struct oplock_info *opinfo;
+	bool same_session = false;
+	bool foreign_session = false;
+	__le32 ea_meta_mask = FILE_READ_EA_LE | FILE_WRITE_EA_LE |
+			      FILE_READ_ATTRIBUTES_LE |
+			      FILE_WRITE_ATTRIBUTES_LE |
+			      FILE_READ_CONTROL_LE | FILE_SYNCHRONIZE_LE;
+
+	if (!work || !fp || lctx || req_op_level != SMB2_OPLOCK_LEVEL_NONE)
+		return false;
+
+	/*
+	 * Avoid self-deadlock when the same session reopens the file only
+	 * to read/write EAs or metadata, e.g. CIFS killpriv querying or
+	 * removing security.capability during buffered write.
+	 */
+	if (!(fp->daccess & (FILE_READ_EA_LE | FILE_WRITE_EA_LE)) ||
+	    (fp->daccess & ~ea_meta_mask))
+		return false;
+
+	down_read(&fp->f_ci->m_lock);
+	list_for_each_entry(opinfo, &fp->f_ci->m_op_list, op_entry) {
+		if (!opinfo->conn || opinfo->level == SMB2_OPLOCK_LEVEL_NONE)
+			continue;
+
+		if (opinfo->sess == work->sess)
+			same_session = true;
+		else
+			foreign_session = true;
+
+		if (same_session && foreign_session)
+			break;
+	}
+	up_read(&fp->f_ci->m_lock);
+
+	return same_session && !foreign_session;
+}
+
 /**
  * smb_grant_oplock() - handle oplock/lease request on file open
  * @work:		smb work
@@ -1529,6 +1572,12 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
 		goto err_out;
 	}
 
+	if (share_ret >= 0 &&
+	    ksmbd_skip_session_ea_break(work, fp, req_op_level, lctx)) {
+		opinfo_put(prev_opinfo);
+		goto set_lev;
+	}
+
 	if (prev_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH &&
 	    prev_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
 		opinfo_put(prev_opinfo);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC PATCH v2 7/9] ksmbd: support security.xfstests EAs
  2026-07-17  3:39 ` [RFC PATCH v2 7/9] ksmbd: support security.xfstests EAs Ze Tan
@ 2026-07-20  5:03   ` Namjae Jeon
  2026-07-20  6:33     ` tanze
  2026-07-20  6:36     ` tanze
  0 siblings, 2 replies; 21+ messages in thread
From: Namjae Jeon @ 2026-07-20  5:03 UTC (permalink / raw)
  To: Ze Tan
  Cc: sfrench, pc, sprasad, tom, senozhatsky, chenxiaosong, linux-cifs,
	linux-kernel

> diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
> index 2159b45c80a6..da3d5c217577 100644
> --- a/fs/smb/server/smb2pdu.c
> +++ b/fs/smb/server/smb2pdu.c
> @@ -2650,11 +2650,21 @@ static bool ksmbd_is_security_capability_ea_name(const char *name,
>                !strncmp(name, XATTR_NAME_CAPS, name_len);
>  }
>
> +static bool ksmbd_is_security_xfstests_ea_name(const char *name,
> +                                              size_t name_len)
> +{
> +       return name_len == sizeof(XATTR_SECURITY_PREFIX "xfstests") - 1 &&
> +              !strncmp(name, XATTR_SECURITY_PREFIX "xfstests", name_len);
Is it appropriate to special-case an xfstests-only xattr name in ksmbd?
Could the security namespace support be implemented using a general,
well-defined policy instead?
Thanks.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC PATCH v2 1/9] smb: client: support security.capability over EAs
  2026-07-17  3:39 ` [RFC PATCH v2 1/9] smb: client: support security.capability " Ze Tan
@ 2026-07-20  5:21   ` Namjae Jeon
  0 siblings, 0 replies; 21+ messages in thread
From: Namjae Jeon @ 2026-07-20  5:21 UTC (permalink / raw)
  To: Ze Tan
  Cc: sfrench, pc, sprasad, tom, senozhatsky, chenxiaosong, linux-cifs,
	linux-kernel

On Fri, Jul 17, 2026 at 12:40 PM Ze Tan <tanze@kylinos.cn> wrote:
>
> generic/093 uses setcap and getcap to check that a write clears the file
> capability. The CIFS client does not have a security xattr handler, so
> these commands cannot set or read security.capability through SMB EAs.
>
> Register a security xattr handler and build the complete EA name for
> SET_INFO and QUERY_INFO. Keep security.capability unchanged in EA lists.
> Reject other security xattrs.
>
> Signed-off-by: Ze Tan <tanze@kylinos.cn>
The client exposes these EA names through security.* regardless of
whether SMB3 POSIX extensions were
negotiated. Is that right?

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC PATCH v2 9/9] ksmbd: avoid self oplock breaks for EA opens
  2026-07-17  3:39 ` [RFC PATCH v2 9/9] ksmbd: avoid self oplock breaks for EA opens Ze Tan
@ 2026-07-20  5:34   ` Namjae Jeon
  2026-07-20  8:54     ` tanze
  0 siblings, 1 reply; 21+ messages in thread
From: Namjae Jeon @ 2026-07-20  5:34 UTC (permalink / raw)
  To: Ze Tan
  Cc: sfrench, pc, sprasad, tom, senozhatsky, chenxiaosong, linux-cifs,
	linux-kernel

On Fri, Jul 17, 2026 at 12:40 PM Ze Tan <tanze@kylinos.cn> wrote:
>
> generic/093 writes to a file after setcap sets security.capability. The
> CIFS client can reopen the file to query or update EAs while the same
> session holds an oplock. ksmbd breaks this oplock and waits for the same
> client, so the write can block.
>
> Skip the oplock break for same-session EA or metadata opens. Keep the
> normal break when another session holds an oplock.
A session can own multiple independent opens. Why is session identity
sufficient to conclude that an EA/metadata-only open may bypass the
existing exclusive or batch oplock break? Oplock state and break
notifications are associated with an individual open, rather
than the session as a whole. Could you point to the SMB specification text ?

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC PATCH v2 7/9] ksmbd: support security.xfstests EAs
  2026-07-20  5:03   ` Namjae Jeon
@ 2026-07-20  6:33     ` tanze
  2026-07-20  6:36     ` tanze
  1 sibling, 0 replies; 21+ messages in thread
From: tanze @ 2026-07-20  6:33 UTC (permalink / raw)
  To: Namjae Jeon
  Cc: sfrench, pc, sprasad, tom, senozhatsky, chenxiaosong, linux-cifs,
	linux-kernel

This is how the current version works, but I believe there is an issue 
with it. Three days ago, I sent a private email to you and Steve 
outlining my proposal for improvement, which leverages the SMB3 POSIX 
extensions to implement this feature. However, your email system blocks 
messages from me, so I was unable to forward the email to you successfully.

在 2026/7/20 13:03, Namjae Jeon 写道:
>> diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
>> index 2159b45c80a6..da3d5c217577 100644
>> --- a/fs/smb/server/smb2pdu.c
>> +++ b/fs/smb/server/smb2pdu.c
>> @@ -2650,11 +2650,21 @@ static bool ksmbd_is_security_capability_ea_name(const char *name,
>>                 !strncmp(name, XATTR_NAME_CAPS, name_len);
>>   }
>>
>> +static bool ksmbd_is_security_xfstests_ea_name(const char *name,
>> +                                              size_t name_len)
>> +{
>> +       return name_len == sizeof(XATTR_SECURITY_PREFIX "xfstests") - 1 &&
>> +              !strncmp(name, XATTR_SECURITY_PREFIX "xfstests", name_len);
> Is it appropriate to special-case an xfstests-only xattr name in ksmbd?
> Could the security namespace support be implemented using a general,
> well-defined policy instead?
> Thanks.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC PATCH v2 7/9] ksmbd: support security.xfstests EAs
  2026-07-20  5:03   ` Namjae Jeon
  2026-07-20  6:33     ` tanze
@ 2026-07-20  6:36     ` tanze
  1 sibling, 0 replies; 21+ messages in thread
From: tanze @ 2026-07-20  6:36 UTC (permalink / raw)
  To: Namjae Jeon
  Cc: sfrench, pc, sprasad, tom, senozhatsky, chenxiaosong, linux-cifs,
	linux-kernel

That’s what I came to think later. My plan is to place it under the 
security.* extended EA namespace, and we can add more entries if further 
requirements arise. I will push a revised code version in a couple of days.

在 2026/7/20 13:03, Namjae Jeon 写道:
> Is it appropriate to special-case an xfstests-only xattr name in ksmbd?
> Could the security namespace support be implemented using a general,
> well-defined policy instead?
> Thanks.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC PATCH v2 6/9] ksmbd: support security.capability EAs
  2026-07-17  3:39 ` [RFC PATCH v2 6/9] ksmbd: support security.capability EAs Ze Tan
@ 2026-07-20  6:57   ` Ralph Boehme
  2026-07-20 13:06     ` tanze
  0 siblings, 1 reply; 21+ messages in thread
From: Ralph Boehme @ 2026-07-20  6:57 UTC (permalink / raw)
  To: Ze Tan, sfrench, linkinjeon, pc, sprasad, tom, senozhatsky,
	chenxiaosong, linux-cifs
  Cc: linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 768 bytes --]

On 7/17/26 5:39 AM, Ze Tan wrote:
> +static bool ksmbd_is_posix_ea_name(const char *name, size_t name_len)
> +{
> +	if (ksmbd_is_security_capability_ea_name(name, name_len))
> +		return true;
> +
> +	return false;
> +}
> +
> +static int ksmbd_map_ea_name_to_xattr(bool posix_extensions,
> +				      const char *ea_name, size_t ea_name_len,
> +				      char *attr_name)
> +{
> +	if (posix_extensions &&
> +	    ksmbd_is_posix_ea_name(ea_name, ea_name_len)) {

why the check for allowed namespaces via ksmbd_is_posix_ea_name() at all 
and not just pass through whatever the client sends us, pass it down and 
let the xattr subsystem deal with it?

Still wrapping my head around this so I might be missing something 
obvious. :)

Thanks!
-slow

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC PATCH v2 9/9] ksmbd: avoid self oplock breaks for EA opens
  2026-07-20  5:34   ` Namjae Jeon
@ 2026-07-20  8:54     ` tanze
  0 siblings, 0 replies; 21+ messages in thread
From: tanze @ 2026-07-20  8:54 UTC (permalink / raw)
  To: Namjae Jeon
  Cc: sfrench, pc, sprasad, tom, senozhatsky, chenxiaosong, linux-cifs,
	linux-kernel

You are right, my handling here is flawed. The logic cannot rely solely 
on matching sessions, as a single SMB session can hold multiple 
independent file open handles.

I will remove the session-based special exception logic on the server 
side and rework the complete fix on the client side.


在 2026/7/20 13:34, Namjae Jeon 写道:
> On Fri, Jul 17, 2026 at 12:40 PM Ze Tan <tanze@kylinos.cn> wrote:
>> generic/093 writes to a file after setcap sets security.capability. The
>> CIFS client can reopen the file to query or update EAs while the same
>> session holds an oplock. ksmbd breaks this oplock and waits for the same
>> client, so the write can block.
>>
>> Skip the oplock break for same-session EA or metadata opens. Keep the
>> normal break when another session holds an oplock.
> A session can own multiple independent opens. Why is session identity
> sufficient to conclude that an EA/metadata-only open may bypass the
> existing exclusive or batch oplock break? Oplock state and break
> notifications are associated with an individual open, rather
> than the session as a whole. Could you point to the SMB specification text ?

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC PATCH v2 6/9] ksmbd: support security.capability EAs
  2026-07-20  6:57   ` Ralph Boehme
@ 2026-07-20 13:06     ` tanze
  2026-07-21 13:38       ` Ralph Boehme
  0 siblings, 1 reply; 21+ messages in thread
From: tanze @ 2026-07-20 13:06 UTC (permalink / raw)
  To: Ralph Boehme, sfrench, linkinjeon, pc, sprasad, tom, senozhatsky,
	chenxiaosong, linux-cifs
  Cc: linux-kernel

Thanks for your question. When the CIFS client accesses user.EA, the 
name transmitted over the SMB protocol is simply EA instead of user.EA. 
ksmbd then prepends user. to convert it back to user.EA. If we pass 
every attribute name directly to the VFS unmodified, other types of 
extended attributes will return -EOPNOTSUPP due to missing handlers.

The current workflow works as follows:

Client request                                 --user.EA
↓ CIFS client strips off the "user."
prefix SMB EA layer receives:          --EA
↓ ksmbd adds back the "user."
prefix Server filesystem layer:         --user.EA

After ksmbd finishes mapping to the underlying extended attribute name, 
filesystem compatibility checks, value validation and all related 
operations should be delegated uniformly to |vfs_setxattr()|. This 
mapping logic is not meant to duplicate the full set of xattr namespaces 
supported by the VFS. Instead, it filters which SMB extended attribute 
names get parsed as native Linux xattr names.

I will revise the patch to enable native namespace mapping only when 
both of the following two conditions are satisfied:

   1.The request is sent with POSIX extended attribute parameters;
   2. The mapped server-side user account is root or an account with 
administrative privileges.

Thanks!


在 2026/7/20 14:57, Ralph Boehme 写道:
> On 7/17/26 5:39 AM, Ze Tan wrote:
>> +static bool ksmbd_is_posix_ea_name(const char *name, size_t name_len)
>> +{
>> +    if (ksmbd_is_security_capability_ea_name(name, name_len))
>> +        return true;
>> +
>> +    return false;
>> +}
>> +
>> +static int ksmbd_map_ea_name_to_xattr(bool posix_extensions,
>> +                      const char *ea_name, size_t ea_name_len,
>> +                      char *attr_name)
>> +{
>> +    if (posix_extensions &&
>> +        ksmbd_is_posix_ea_name(ea_name, ea_name_len)) {
>
> why the check for allowed namespaces via ksmbd_is_posix_ea_name() at 
> all and not just pass through whatever the client sends us, pass it 
> down and let the xattr subsystem deal with it?
>
> Still wrapping my head around this so I might be missing something 
> obvious. :)
>
> Thanks!
> -slow

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC PATCH v2 6/9] ksmbd: support security.capability EAs
  2026-07-20 13:06     ` tanze
@ 2026-07-21 13:38       ` Ralph Boehme
  2026-07-21 16:41         ` Steve French
  0 siblings, 1 reply; 21+ messages in thread
From: Ralph Boehme @ 2026-07-21 13:38 UTC (permalink / raw)
  To: tanze, sfrench, linkinjeon, pc, sprasad, tom, senozhatsky,
	chenxiaosong, linux-cifs
  Cc: linux-kernel, Jeremy Allison, Stefan Metzmacher


[-- Attachment #1.1: Type: text/plain, Size: 3537 bytes --]

On 7/20/26 3:06 PM, tanze wrote:
> Thanks for your question. When the CIFS client accesses user.EA, the 
> name transmitted over the SMB protocol is simply EA instead of user.EA.
> ksmbd then prepends user. to convert it back to user.EA. If we pass 
> every attribute name directly to the VFS unmodified, other types of 
> extended attributes will return -EOPNOTSUPP due to missing handlers.

yup, but I guess that's exactly what we want.

If I get that right your proposal is

Client        Network       Server
-------------------------------------------------
user.foo      foo           user.foo
system.bar    system.bar    system.bar

This seems wrong (user namespace not prefixed, others prefixed).

What we might want to do instead is send the namespace over the wire in 
all cases, but in a separate protocol field (expressed by splitting the 
dotted string into two words seperated by a comma):

Client        Network        Server
=============================================================
Linux:                       Linux:
user.foo      user, foo      user.foo
system.bar    system, bar    system.bar

FreeBSD:                     Linux:
*1, foo       user, foo      user.foo
*2, bar       system, bar    system.bar

*1: EXTATTR_NAMESPACE_USER
*2: EXTATTR_NAMESPACE_SYSTEM

This way we have a clear way how implementations can map their namespace 
to the protocol, and server and client know exactly what to do.

Thoughts?
-slow

> 
> The current workflow works as follows:
> 
> Client request                                 --user.EA
> ↓ CIFS client strips off the "user."
> prefix SMB EA layer receives:          --EA
> ↓ ksmbd adds back the "user."
> prefix Server filesystem layer:         --user.EA
> 
> After ksmbd finishes mapping to the underlying extended attribute name, 
> filesystem compatibility checks, value validation and all related 
> operations should be delegated uniformly to |vfs_setxattr()|. This 
> mapping logic is not meant to duplicate the full set of xattr namespaces 
> supported by the VFS. Instead, it filters which SMB extended attribute 
> names get parsed as native Linux xattr names.
> 
> I will revise the patch to enable native namespace mapping only when 
> both of the following two conditions are satisfied:
> 
>    1.The request is sent with POSIX extended attribute parameters;
>    2. The mapped server-side user account is root or an account with 
> administrative privileges.
> 
> Thanks!
> 
> 
> 在 2026/7/20 14:57, Ralph Boehme 写道:
>> On 7/17/26 5:39 AM, Ze Tan wrote:
>>> +static bool ksmbd_is_posix_ea_name(const char *name, size_t name_len)
>>> +{
>>> +    if (ksmbd_is_security_capability_ea_name(name, name_len))
>>> +        return true;
>>> +
>>> +    return false;
>>> +}
>>> +
>>> +static int ksmbd_map_ea_name_to_xattr(bool posix_extensions,
>>> +                      const char *ea_name, size_t ea_name_len,
>>> +                      char *attr_name)
>>> +{
>>> +    if (posix_extensions &&
>>> +        ksmbd_is_posix_ea_name(ea_name, ea_name_len)) {
>>
>> why the check for allowed namespaces via ksmbd_is_posix_ea_name() at 
>> all and not just pass through whatever the client sends us, pass it 
>> down and let the xattr subsystem deal with it?
>>
>> Still wrapping my head around this so I might be missing something 
>> obvious. :)
>>
>> Thanks!
>> -slow


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC PATCH v2 6/9] ksmbd: support security.capability EAs
  2026-07-21 13:38       ` Ralph Boehme
@ 2026-07-21 16:41         ` Steve French
  2026-07-21 17:10           ` Ralph Boehme
  0 siblings, 1 reply; 21+ messages in thread
From: Steve French @ 2026-07-21 16:41 UTC (permalink / raw)
  To: Ralph Boehme
  Cc: tanze, sfrench, linkinjeon, pc, sprasad, tom, senozhatsky,
	chenxiaosong, linux-cifs, linux-kernel, Jeremy Allison,
	Stefan Metzmacher

On Tue, Jul 21, 2026 at 8:48 AM Ralph Boehme <slow@samba.org> wrote:
>
> On 7/20/26 3:06 PM, tanze wrote:
> > Thanks for your question. When the CIFS client accesses user.EA, the
> > name transmitted over the SMB protocol is simply EA instead of user.EA.
> > ksmbd then prepends user. to convert it back to user.EA. If we pass
> > every attribute name directly to the VFS unmodified, other types of
> > extended attributes will return -EOPNOTSUPP due to missing handlers.
>
> yup, but I guess that's exactly what we want.
>
> If I get that right your proposal is
>
> Client        Network       Server
> -------------------------------------------------
> user.foo      foo           user.foo
> system.bar    system.bar    system.bar
>
> This seems wrong (user namespace not prefixed, others prefixed).

This approach at least doesn't require changing the protocol. It
shouldn't regress existing servers and clients who are sending "foo"
across the network (without the prefix) for the most common EAs


> What we might want to do instead is send the namespace over the wire in
> all cases, but in a separate protocol field (expressed by splitting the
> dotted string into two words seperated by a comma):
>
> Client        Network        Server
> =============================================================
> Linux:                       Linux:
> user.foo      user, foo      user.foo
> system.bar    system, bar    system.bar
>
> FreeBSD:                     Linux:
> *1, foo       user, foo      user.foo
> *2, bar       system, bar    system.bar
>
> *1: EXTATTR_NAMESPACE_USER
> *2: EXTATTR_NAMESPACE_SYSTEM
>
> This way we have a clear way how implementations can map their namespace
> to the protocol, and server and client know exactly what to do.
>
> Thoughts?
> -slow
>
> >
> > The current workflow works as follows:
> >
> > Client request                                 --user.EA
> > ↓ CIFS client strips off the "user."
> > prefix SMB EA layer receives:          --EA
> > ↓ ksmbd adds back the "user."
> > prefix Server filesystem layer:         --user.EA
> >
> > After ksmbd finishes mapping to the underlying extended attribute name,
> > filesystem compatibility checks, value validation and all related
> > operations should be delegated uniformly to |vfs_setxattr()|. This
> > mapping logic is not meant to duplicate the full set of xattr namespaces
> > supported by the VFS. Instead, it filters which SMB extended attribute
> > names get parsed as native Linux xattr names.
> >
> > I will revise the patch to enable native namespace mapping only when
> > both of the following two conditions are satisfied:
> >
> >    1.The request is sent with POSIX extended attribute parameters;
> >    2. The mapped server-side user account is root or an account with
> > administrative privileges.
> >
> > Thanks!
> >
> >
> > 在 2026/7/20 14:57, Ralph Boehme 写道:
> >> On 7/17/26 5:39 AM, Ze Tan wrote:
> >>> +static bool ksmbd_is_posix_ea_name(const char *name, size_t name_len)
> >>> +{
> >>> +    if (ksmbd_is_security_capability_ea_name(name, name_len))
> >>> +        return true;
> >>> +
> >>> +    return false;
> >>> +}
> >>> +
> >>> +static int ksmbd_map_ea_name_to_xattr(bool posix_extensions,
> >>> +                      const char *ea_name, size_t ea_name_len,
> >>> +                      char *attr_name)
> >>> +{
> >>> +    if (posix_extensions &&
> >>> +        ksmbd_is_posix_ea_name(ea_name, ea_name_len)) {
> >>
> >> why the check for allowed namespaces via ksmbd_is_posix_ea_name() at
> >> all and not just pass through whatever the client sends us, pass it
> >> down and let the xattr subsystem deal with it?
> >>
> >> Still wrapping my head around this so I might be missing something
> >> obvious. :)
> >>
> >> Thanks!
> >> -slow
>


-- 
Thanks,

Steve

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [RFC PATCH v2 6/9] ksmbd: support security.capability EAs
  2026-07-21 16:41         ` Steve French
@ 2026-07-21 17:10           ` Ralph Boehme
  0 siblings, 0 replies; 21+ messages in thread
From: Ralph Boehme @ 2026-07-21 17:10 UTC (permalink / raw)
  To: Steve French
  Cc: tanze, sfrench, linkinjeon, pc, sprasad, tom, senozhatsky,
	chenxiaosong, linux-cifs, linux-kernel, Jeremy Allison,
	Stefan Metzmacher


[-- Attachment #1.1: Type: text/plain, Size: 1894 bytes --]

On 7/21/26 6:41 PM, Steve French wrote:
> On Tue, Jul 21, 2026 at 8:48 AM Ralph Boehme <slow@samba.org> wrote:
>>
>> On 7/20/26 3:06 PM, tanze wrote:
>>> Thanks for your question. When the CIFS client accesses user.EA, the
>>> name transmitted over the SMB protocol is simply EA instead of user.EA.
>>> ksmbd then prepends user. to convert it back to user.EA. If we pass
>>> every attribute name directly to the VFS unmodified, other types of
>>> extended attributes will return -EOPNOTSUPP due to missing handlers.
>>
>> yup, but I guess that's exactly what we want.
>>
>> If I get that right your proposal is
>>
>> Client        Network       Server
>> -------------------------------------------------
>> user.foo      foo           user.foo
>> system.bar    system.bar    system.bar
>>
>> This seems wrong (user namespace not prefixed, others prefixed).
> 
> This approach at least doesn't require changing the protocol.

By definition we're defining an SMB3 POSIX protocol here, so I think we 
should strive for a protocol that is consistent rather than encoding 
historic Linux-specific implementation details.

In the proposal above, user.* is treated differently from every other 
namespace:

user.foo    -> foo
system.bar  -> system.bar

That means the wire format no longer has a uniform representation of an 
extended attribute. Whether a namespace is transmitted depends on which 
namespace it is, which makes the protocol less self-describing and 
introduces a special case that every implementation has to know about.

This is horrible.

If the protocol instead carries namespace and attribute name as separate 
fields, every namespace is represented uniformly. Linux, FreeBSD, and 
any future implementation simply map their local namespace 
representation to the protocol, rather than the protocol inheriting 
Linux's conventions.

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2026-07-21 17:10 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-17  3:39 [RFC PATCH v2 0/9] smb: support security and trusted xattrs over EAs Ze Tan
2026-07-17  3:39 ` [RFC PATCH v2 1/9] smb: client: support security.capability " Ze Tan
2026-07-20  5:21   ` Namjae Jeon
2026-07-17  3:39 ` [RFC PATCH v2 2/9] smb: client: support security.xfstests " Ze Tan
2026-07-17  3:39 ` [RFC PATCH v2 3/9] smb: client: support trusted xattrs " Ze Tan
2026-07-17  3:39 ` [RFC PATCH v2 4/9] ksmbd: extract SMB EA backing xattr name mapping Ze Tan
2026-07-17  3:39 ` [RFC PATCH v2 5/9] ksmbd: extract SMB EA response name handling Ze Tan
2026-07-17  3:39 ` [RFC PATCH v2 6/9] ksmbd: support security.capability EAs Ze Tan
2026-07-20  6:57   ` Ralph Boehme
2026-07-20 13:06     ` tanze
2026-07-21 13:38       ` Ralph Boehme
2026-07-21 16:41         ` Steve French
2026-07-21 17:10           ` Ralph Boehme
2026-07-17  3:39 ` [RFC PATCH v2 7/9] ksmbd: support security.xfstests EAs Ze Tan
2026-07-20  5:03   ` Namjae Jeon
2026-07-20  6:33     ` tanze
2026-07-20  6:36     ` tanze
2026-07-17  3:39 ` [RFC PATCH v2 8/9] ksmbd: support trusted EAs Ze Tan
2026-07-17  3:39 ` [RFC PATCH v2 9/9] ksmbd: avoid self oplock breaks for EA opens Ze Tan
2026-07-20  5:34   ` Namjae Jeon
2026-07-20  8:54     ` tanze

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®