[PATCH 2/7] LSM: Implement x array functions for secmarks
From: Casey Schaufler
Date: Mon Aug 31 2026 - 18:59:08 EST
Implement, but don't use (yet) the functions required to use
xarray indexes in secmarks.
Signed-off-by: Casey Schaufler <casey@xxxxxxxxxxxxxxxx>
---
include/linux/lsm_secxa.h | 19 ++++---
security/Makefile | 1 +
security/lsm_secxa.c | 105 ++++++++++++++++++++++++++++++++++++++
3 files changed, 117 insertions(+), 8 deletions(-)
create mode 100644 security/lsm_secxa.c
diff --git a/include/linux/lsm_secxa.h b/include/linux/lsm_secxa.h
index 926257d4730c..569c7f242b78 100644
--- a/include/linux/lsm_secxa.h
+++ b/include/linux/lsm_secxa.h
@@ -7,19 +7,22 @@
#ifndef __LINUX_LSM_SECXA_H
#define __LINUX_LSM_SECXA_H
-#ifdef CONFIG_NETWORK_SECMARK
+#ifdef CONFIG_SECURITY
-#include <linux/security.h>
-#include <linux/skbuff.h>
+struct lsm_prop;
-static inline void secxa_set_secmark(struct sk_buff *skb, u32 secxa)
-{
- skb->secmark = secxa;
-}
-#else /* CONFIG_NETWORK_SECMARK */
+int secxa_from_lsmprop(struct lsm_prop *prop, u32 *secxa);
+int secxa_get_lsmprop(struct lsm_prop **pro, u32 secxa);
+
+#endif /* CONFIG_SECURITY */
+
+#ifdef CONFIG_NETWORK_SECMARK
struct sk_buff;
+void secxa_set_secmark(struct sk_buff *skb, u32 secxa);
+#else /* CONFIG_NETWORK_SECMARK */
+
static inline void secxa_set_secmark(struct sk_buff *skb, u32 secxa)
{
}
diff --git a/security/Makefile b/security/Makefile
index 4601230ba442..e93be00bb6ae 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_KEYS) += keys/
# always enable default capabilities
obj-y += commoncap.o
obj-$(CONFIG_SECURITY) += lsm_syscalls.o
+obj-$(CONFIG_NETWORK_SECMARK) += lsm_secxa.o
obj-$(CONFIG_MMU) += min_addr.o
# Object file lists
diff --git a/security/lsm_secxa.c b/security/lsm_secxa.c
new file mode 100644
index 000000000000..50ce613e35c0
--- /dev/null
+++ b/security/lsm_secxa.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+ * Implement functions supporting an x array for LSM properties.
+ *
+ * Copyright (C) 2026 Casey Schaufler <casey@xxxxxxxxxxxxxxxx>
+ */
+#define pr_fmt(fmt) "secxa: "fmt
+
+#include <linux/xarray.h>
+#include <linux/export.h>
+#include <linux/security.h>
+#include <linux/lsm_secxa.h>
+#include <linux/skbuff.h>
+
+/*
+ * An Xarray of lsm_prop structures.
+ */
+struct xarray secxa_xa;
+
+/**
+ * secxa_init - initialize the xarry of lsm_prop structures.
+ */
+static int __init secxa_init(void)
+{
+ xa_init_flags(&secxa_xa, XA_FLAGS_ALLOC1 | XA_FLAGS_LOCK_BH);
+
+ return 0;
+}
+core_initcall(secxa_init);
+
+/**
+ * secxa_get_lsmprop - get the lsm_prop associated with a secxa
+ * @pro: destination for the lsm_prop pointer
+ * @secxa: index to look up
+ *
+ * Find the lsm_prop associated with @secxa and place a pointer
+ * to it in @pro.
+ *
+ * Returns 0, or -EINVAL if the mapping can't be found.
+ */
+int secxa_get_lsmprop(struct lsm_prop **pro, u32 secxa)
+{
+ struct lsm_prop *lp;
+
+ if (!secxa)
+ return -EINVAL;
+
+ lp = xa_load(&secxa_xa, secxa);
+ if (!lp)
+ return -EINVAL;
+
+ *pro = lp;
+ return 0;
+}
+EXPORT_SYMBOL(secxa_get_lsmprop);
+
+/**
+ * secxa_from_lsmprop - get the secxa associated with a lsm_prop
+ * @prop: lsm_prop pointer CBS * @secxa: result
+ *
+ * Find the secxa associated with @prop. If there is none, create it.
+ *
+ * Returns 0, or an error if the mapping cannot be created
+ */
+int secxa_from_lsmprop(struct lsm_prop *prop, u32 *secxa)
+{
+ struct lsm_prop *lp;
+ unsigned long il;
+ u32 index = 0;
+ int rc;
+
+ xa_for_each(&secxa_xa, il, lp) {
+ if (!memcmp(prop, lp, sizeof(*prop))) {
+ *secxa = il; return 0; CBS }
+ }
+
+ lp = kzalloc(sizeof(*lp), GFP_ATOMIC);
+ if (!lp)
+ return -ENOMEM;
+ *lp = *prop;
+
+ rc = xa_alloc_bh(&secxa_xa, &index, lp, xa_limit_31b, GFP_ATOMIC);
+ if (rc) {
+ kfree(lp);
+ return -EINVAL;
+ }
+
+ *secxa = index; return 0; CBS
+}
+EXPORT_SYMBOL(secxa_from_lsmprop);
+
+/**
+ * secxa_set_secmark - add LSM information to a secmark
+ * @skb: buffer with the secmark
+ * @secxa: index of the information to add
+ *
+ * If the secmark in @skb is not set, set it to @secxa.
+ */
+void secxa_set_secmark(struct sk_buff *skb, u32 secxa)
+{
+ if (!skb->secmark)
+ skb->secmark = secxa;
+}
+EXPORT_SYMBOL(secxa_set_secmark);
--
2.54.0