[PATCH 17/19] smack: smack_inode_post_setxattr(): find label instead of import

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


Efforts were made in [1]
to ensure that smk_import_entry() can not fail
when called by smack_inode_post_setxattr():
label is imported in advance by smack_inode_setxattr().

However,

  - smk_import_entry() can still fail
    due to memory allocation

  - its use is misleading here,
    as no actual import is needed

Using smk_find_entry() instead of smk_import_entry()
should be sufficient for smack_inode_post_setxattr().

However, smk_find_entry() takes a \0-terminated string,
while we have a (non-\0-terminated string, length) tuple.

To resolve this, I added smk_find_label_rcu(),
which accepts such a tuple and
is otherwise identical to smk_find_entry().
It is now used in smack_inode_post_setxattr().

smack_inode_post_setxattr() can no longer fail.

[1] 2009-04-16 etienne.basset
commit defc433ba3bc ("Smack: check for SMACK xattr validity
                      in smack_inode_setxattr")

Signed-off-by: Konstantin Andreev <andreev at swemel.ru>
---
 security/smack/smack.h        |  2 ++
 security/smack/smack_access.c | 22 ++++++++++++++++++++--
 security/smack/smack_lsm.c    | 26 ++++++++++++--------------
 3 files changed, 34 insertions(+), 16 deletions(-)

diff --git a/security/smack/smack.h b/security/smack/smack.h
index 759343a6bbae..9abb11947fe9 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -294,6 +294,8 @@ struct smack_known *smk_import_valid_label(const char *label, int label_len,
 					   gfp_t gfp);
 void smk_insert_entry(struct smack_known *skp);
 struct smack_known *smk_find_entry(const char *);
+struct smack_known *smk_find_label_rcu(const char *string, size_t string_len);
+struct smack_known *smk_find_label(const char *string, size_t string_len);
 bool smack_privileged(int cap);
 bool smack_privileged_cred(int cap, const struct cred *cred);
 void smk_destroy_label_list(struct list_head *list);
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 09167be79122..390dc9642f9b 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -427,21 +427,39 @@ void smk_insert_entry(struct smack_known *skp)
  * matches the passed string or NULL if not found.
  */
 struct smack_known *smk_find_entry(const char *string)
+{
+	return smk_find_label_rcu(string, strlen(string));
+}
+
+struct smack_known *
+smk_find_label_rcu(const char *string, size_t string_len)
 {
 	unsigned int hash;
 	struct hlist_head *head;
 	struct smack_known *skp;
 
-	hash = full_name_hash(NULL, string, strlen(string));
+	hash = full_name_hash(NULL, string, string_len);
 	head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)];
 
 	hlist_for_each_entry_rcu(skp, head, smk_hashed)
-		if (strcmp(skp->smk_known, string) == 0)
+		if (strlen(skp->smk_known) == string_len &&
+		   strncmp(skp->smk_known, string, string_len) == 0)
 			return skp;
 
 	return NULL;
 }
 
+struct smack_known *
+smk_find_label(const char *string, size_t string_len)
+{
+	struct smack_known *skp;
+
+	rcu_read_lock();
+	skp = smk_find_label_rcu(string, string_len);
+	rcu_read_unlock();
+	return skp;
+}
+
 /**
  * smk_parse_label_len - calculate the length of the starting segment
  *                       in the string that constitutes a valid smack label
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 9271cd54bc43..5d3d72162444 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1484,7 +1484,7 @@ static int smack_inode_setxattr(struct mnt_idmap *idmap,
 static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
 				      const void *value, size_t size, int flags)
 {
-	struct smack_known *skp;
+	struct smack_known **skpp = NULL;
 	struct inode_smack *isp = smack_inode(d_backing_inode(dentry));
 
 	if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
@@ -1492,19 +1492,17 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
 		return;
 	}
 
-	if (strcmp(name, XATTR_NAME_SMACK) == 0) {
-		skp = smk_import_entry(value, size);
-		if (!IS_ERR(skp))
-			isp->smk_inode = skp;
-	} else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) {
-		skp = smk_import_entry(value, size);
-		if (!IS_ERR(skp))
-			isp->smk_task = skp;
-	} else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
-		skp = smk_import_entry(value, size);
-		if (!IS_ERR(skp))
-			isp->smk_mmap = skp;
-	}
+	if (strcmp(name, XATTR_NAME_SMACK) == 0)
+		skpp = &isp->smk_inode;
+	else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0)
+		skpp = &isp->smk_task;
+	else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0)
+		skpp = &isp->smk_mmap;
+	/*
+	 * Label has been imported by smack_inode_setxattr, just find it
+	 */
+	if (skpp)
+		*skpp = smk_find_label(value, size);
 
 	return;
 }
-- 
2.43.0




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