[PATCH 06/19] smack: fix bug: getxattr() returns invalid SMACK64EXEC/MMAP

Konstantin Andreev andreev at swemel.ru
Thu Jul 24 13:09:39 UTC 2025


The Smack inode_getsecurity hook, smack_inode_getsecurity(),
does not provide the values of the SMACK64EXEC and SMACK64MMAP
xattrs from the inode. Instead, it returns -EOPNOTSUPP
to signal that these xattrs are not handled.

Since [1], the -EOPNOTSUPP return value
from the inode_getsecurity LSM hook
has been interpreted by security_inode_getsecurity()
as a signal to "continue polling other LSMs".

As a result, security_inode_getsecurity() continues querying
other LSMs and eventually returns control to vfs_getxattr(),
which attempts to read these xattrs from disk
via __vfs_getxattr()

There are two issues here:

1) querying a Smack property from other LSMs
   is incorrect, as Smack does own these xattrs.

2) the on-disk xattrs may differ from the in-memory
   labels actually associated with the inode.

The SMACK64EXEC/MMAP xattr on disk may contain an invalid
label (e.g. foo/bar, see [2]), a forbidden one (*, @),
or even corrupted data.

Such values are treated somehow during inode instantiation
and may produce a valid Smack label or no label at all,
but, anyway, one that differs from the on-disk value

This change ensures that getxattr() returns the actual
in-memory label associated with the inode,
not the raw xattr from disk.

[1] 2016-05-31 Casey Schaufler
commit 2885c1e3e0c2 ("LSM: Fix for security_inode_getsecurity
                      and -EOPNOTSUPP")
Link: https://lore.kernel.org/lkml/d8a4d26e-46c8-975d-d075-a3848130981c@schaufler-ca.com/

[2] 2025-07 andreev
commit ("smack: fix bug: setting label-containing xattrs
         silently ignores input garbage")
Link: https://lore.kernel.org/linux-security-module/ae1100894499a1f6ce8e783727635388b3ac3af8.1753356770.git.andreev@swemel.ru/

Signed-off-by: Konstantin Andreev <andreev at swemel.ru>
---
 security/smack/smack_lsm.c | 36 +++++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 15 deletions(-)

diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 7a27c554ac56..052404e2fda6 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1649,17 +1649,20 @@ static int smack_inode_getsecurity(struct mnt_idmap *idmap,
 				   struct inode *inode, const char *name,
 				   void **buffer, bool alloc)
 {
-	struct smack_known *isp;
-	struct inode_smack *ispp;
-	size_t label_len;
-	char *label = NULL;
+	const struct smack_known *skp;
+	const struct inode_smack * const isp = smack_inode(inode);
+	const char *value = NULL;
+	int value_len;
 
 	if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
-		isp = smk_of_inode(inode);
+		skp = isp->smk_inode;
+	} else if (strcmp(name, XATTR_SMACK_EXEC) == 0) {
+		skp = isp->smk_task;
+	} else if (strcmp(name, XATTR_SMACK_MMAP) == 0) {
+		skp = isp->smk_mmap;
 	} else if (strcmp(name, XATTR_SMACK_TRANSMUTE) == 0) {
-		ispp = smack_inode(inode);
-		if (ispp->smk_flags & SMK_INODE_TRANSMUTE)
-			label = TRANS_TRUE;
+		if (isp->smk_flags & SMK_INODE_TRANSMUTE)
+			value = TRANS_TRUE;
 		else
 			return -ENODATA;
 	} else if (strcmp(name, XATTR_SMACK_IPIN) == 0 ||
@@ -1680,24 +1683,27 @@ static int smack_inode_getsecurity(struct mnt_idmap *idmap,
 		ssp = smack_sock(sk);
 
 		if (strcmp(name, XATTR_SMACK_IPIN) == 0)
-			isp = ssp->smk_in;
+			skp = ssp->smk_in;
 		else
-			isp = ssp->smk_out;
+			skp = ssp->smk_out;
 	} else
 		return -EOPNOTSUPP;
 
-	if (!label)
-		label = isp->smk_known;
+	if (!value) {
+		if (!skp)
+			return -ENODATA;
+		value = skp->smk_known;
+	}
 
-	label_len = strlen(label);
+	value_len = strlen(value);
 
 	if (alloc) {
-		*buffer = kstrdup(label, GFP_KERNEL);
+		*buffer = kmemdup(value, value_len, GFP_KERNEL);
 		if (*buffer == NULL)
 			return -ENOMEM;
 	}
 
-	return label_len;
+	return value_len;
 }
 
 
-- 
2.43.0




More information about the Linux-security-module-archive mailing list