[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