* [PATCH v3 28/34] safesetid: move initcalls to the LSM framework
From: Paul Moore @ 2025-08-14 22:50 UTC (permalink / raw)
To: linux-security-module, linux-integrity, selinux
Cc: John Johansen, Mimi Zohar, Roberto Sassu, Fan Wu,
Mickaël Salaün, Günther Noack, Kees Cook,
Micah Morton, Casey Schaufler, Tetsuo Handa, Nicolas Bouchinet,
Xiu Jianfeng
In-Reply-To: <20250814225159.275901-36-paul@paul-moore.com>
Reviewed-by: Kees Cook <kees@kernel.org>
Acked-by: Micah Morton <mortonm@chromium.org>
Signed-off-by: Paul Moore <paul@paul-moore.com>
---
security/safesetid/lsm.c | 1 +
security/safesetid/lsm.h | 2 ++
security/safesetid/securityfs.c | 3 +--
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/security/safesetid/lsm.c b/security/safesetid/lsm.c
index 9a7c68d4e642..d5fb949050dd 100644
--- a/security/safesetid/lsm.c
+++ b/security/safesetid/lsm.c
@@ -289,4 +289,5 @@ static int __init safesetid_security_init(void)
DEFINE_LSM(safesetid_security_init) = {
.id = &safesetid_lsmid,
.init = safesetid_security_init,
+ .initcall_fs = safesetid_init_securityfs,
};
diff --git a/security/safesetid/lsm.h b/security/safesetid/lsm.h
index d346f4849cea..bf5172e2c3f7 100644
--- a/security/safesetid/lsm.h
+++ b/security/safesetid/lsm.h
@@ -70,4 +70,6 @@ enum sid_policy_type _setid_policy_lookup(struct setid_ruleset *policy,
extern struct setid_ruleset __rcu *safesetid_setuid_rules;
extern struct setid_ruleset __rcu *safesetid_setgid_rules;
+int safesetid_init_securityfs(void);
+
#endif /* _SAFESETID_H */
diff --git a/security/safesetid/securityfs.c b/security/safesetid/securityfs.c
index 8e1ffd70b18a..ece259f75b0d 100644
--- a/security/safesetid/securityfs.c
+++ b/security/safesetid/securityfs.c
@@ -308,7 +308,7 @@ static const struct file_operations safesetid_gid_file_fops = {
.write = safesetid_gid_file_write,
};
-static int __init safesetid_init_securityfs(void)
+int __init safesetid_init_securityfs(void)
{
int ret;
struct dentry *policy_dir;
@@ -345,4 +345,3 @@ static int __init safesetid_init_securityfs(void)
securityfs_remove(policy_dir);
return ret;
}
-fs_initcall(safesetid_init_securityfs);
--
2.50.1
^ permalink raw reply related
* [PATCH v3 29/34] apparmor: move initcalls to the LSM framework
From: Paul Moore @ 2025-08-14 22:50 UTC (permalink / raw)
To: linux-security-module, linux-integrity, selinux
Cc: John Johansen, Mimi Zohar, Roberto Sassu, Fan Wu,
Mickaël Salaün, Günther Noack, Kees Cook,
Micah Morton, Casey Schaufler, Tetsuo Handa, Nicolas Bouchinet,
Xiu Jianfeng
In-Reply-To: <20250814225159.275901-36-paul@paul-moore.com>
Reviewed-by: Kees Cook <kees@kernel.org>
Signed-off-by: Paul Moore <paul@paul-moore.com>
---
security/apparmor/apparmorfs.c | 4 +---
security/apparmor/crypto.c | 3 +--
security/apparmor/include/apparmorfs.h | 2 ++
security/apparmor/include/crypto.h | 1 +
security/apparmor/lsm.c | 9 ++++++++-
5 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 391a586d0557..ee04c1ac9d6e 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -2649,7 +2649,7 @@ static const struct inode_operations policy_link_iops = {
*
* Returns: error on failure
*/
-static int __init aa_create_aafs(void)
+int __init aa_create_aafs(void)
{
struct dentry *dent;
int error;
@@ -2728,5 +2728,3 @@ static int __init aa_create_aafs(void)
AA_ERROR("Error creating AppArmor securityfs\n");
return error;
}
-
-fs_initcall(aa_create_aafs);
diff --git a/security/apparmor/crypto.c b/security/apparmor/crypto.c
index 227d47c14907..d8a7bde94d79 100644
--- a/security/apparmor/crypto.c
+++ b/security/apparmor/crypto.c
@@ -53,10 +53,9 @@ int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
return 0;
}
-static int __init init_profile_hash(void)
+int __init init_profile_hash(void)
{
if (apparmor_initialized)
aa_info_message("AppArmor sha256 policy hashing enabled");
return 0;
}
-late_initcall(init_profile_hash);
diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
index 1e94904f68d9..dd580594dfb7 100644
--- a/security/apparmor/include/apparmorfs.h
+++ b/security/apparmor/include/apparmorfs.h
@@ -104,6 +104,8 @@ enum aafs_prof_type {
#define prof_dir(X) ((X)->dents[AAFS_PROF_DIR])
#define prof_child_dir(X) ((X)->dents[AAFS_PROF_PROFS])
+int aa_create_aafs(void);
+
void __aa_bump_ns_revision(struct aa_ns *ns);
void __aafs_profile_rmdir(struct aa_profile *profile);
void __aafs_profile_migrate_dents(struct aa_profile *old,
diff --git a/security/apparmor/include/crypto.h b/security/apparmor/include/crypto.h
index 636a04e20d91..f3ffd388cc58 100644
--- a/security/apparmor/include/crypto.h
+++ b/security/apparmor/include/crypto.h
@@ -13,6 +13,7 @@
#include "policy.h"
#ifdef CONFIG_SECURITY_APPARMOR_HASH
+int init_profile_hash(void);
unsigned int aa_hash_size(void);
char *aa_calc_hash(void *data, size_t len);
int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 45b3a304d525..647c13e13e63 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -32,6 +32,7 @@
#include "include/audit.h"
#include "include/capability.h"
#include "include/cred.h"
+#include "include/crypto.h"
#include "include/file.h"
#include "include/ipc.h"
#include "include/net.h"
@@ -2426,7 +2427,6 @@ static int __init apparmor_nf_ip_init(void)
return 0;
}
-__initcall(apparmor_nf_ip_init);
#endif
static char nulldfa_src[] __aligned(8) = {
@@ -2557,4 +2557,11 @@ DEFINE_LSM(apparmor) = {
.enabled = &apparmor_enabled,
.blobs = &apparmor_blob_sizes,
.init = apparmor_init,
+ .initcall_fs = aa_create_aafs,
+#if defined(CONFIG_NETFILTER) && defined(CONFIG_NETWORK_SECMARK)
+ .initcall_device = apparmor_nf_ip_init,
+#endif
+#ifdef CONFIG_SECURITY_APPARMOR_HASH
+ .initcall_late = init_profile_hash,
+#endif
};
--
2.50.1
^ permalink raw reply related
* [PATCH v3 30/34] lockdown: move initcalls to the LSM framework
From: Paul Moore @ 2025-08-14 22:50 UTC (permalink / raw)
To: linux-security-module, linux-integrity, selinux
Cc: John Johansen, Mimi Zohar, Roberto Sassu, Fan Wu,
Mickaël Salaün, Günther Noack, Kees Cook,
Micah Morton, Casey Schaufler, Tetsuo Handa, Nicolas Bouchinet,
Xiu Jianfeng
In-Reply-To: <20250814225159.275901-36-paul@paul-moore.com>
Reviewed-by: Kees Cook <kees@kernel.org>
Acked-by: Xiu Jianfeng <xiujianfeng@huawei.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
---
security/lockdown/lockdown.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
index 4813f168ff93..8d46886d2cca 100644
--- a/security/lockdown/lockdown.c
+++ b/security/lockdown/lockdown.c
@@ -161,8 +161,6 @@ static int __init lockdown_secfs_init(void)
return PTR_ERR_OR_ZERO(dentry);
}
-core_initcall(lockdown_secfs_init);
-
#ifdef CONFIG_SECURITY_LOCKDOWN_LSM_EARLY
DEFINE_EARLY_LSM(lockdown) = {
#else
@@ -170,4 +168,5 @@ DEFINE_LSM(lockdown) = {
#endif
.id = &lockdown_lsmid,
.init = lockdown_lsm_init,
+ .initcall_core = lockdown_secfs_init,
};
--
2.50.1
^ permalink raw reply related
* [PATCH v3 31/34] ima,evm: move initcalls to the LSM framework
From: Paul Moore @ 2025-08-14 22:50 UTC (permalink / raw)
To: linux-security-module, linux-integrity, selinux
Cc: John Johansen, Mimi Zohar, Roberto Sassu, Fan Wu,
Mickaël Salaün, Günther Noack, Kees Cook,
Micah Morton, Casey Schaufler, Tetsuo Handa, Nicolas Bouchinet,
Xiu Jianfeng
In-Reply-To: <20250814225159.275901-36-paul@paul-moore.com>
This patch converts IMA and EVM to use the LSM frameworks's initcall
mechanism. There was a minor challenge in this conversion that wasn't
seen when converting the other LSMs brought about by the resource
sharing between the two related, yes independent IMA and EVM LSMs.
This was resolved by registering the same initcalls for each LSM and
including code in each registered initcall to ensure it only executes
once during each boot.
It is worth mentioning that this patch does not touch any of the
"platform certs" code that lives in the security/integrity/platform_certs
directory as the IMA/EVM maintainers have assured me that this code is
unrelated to IMA/EVM, despite the location, and will be moved to a more
relevant subsystem in the future.
Signed-off-by: Paul Moore <paul@paul-moore.com>
---
security/integrity/Makefile | 2 +-
security/integrity/evm/evm_main.c | 6 ++---
security/integrity/iint.c | 4 +--
security/integrity/ima/ima_main.c | 6 ++---
security/integrity/initcalls.c | 41 +++++++++++++++++++++++++++++++
security/integrity/initcalls.h | 28 +++++++++++++++++++++
6 files changed, 78 insertions(+), 9 deletions(-)
create mode 100644 security/integrity/initcalls.c
create mode 100644 security/integrity/initcalls.h
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 92b63039c654..6ea330ea88b1 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -5,7 +5,7 @@
obj-$(CONFIG_INTEGRITY) += integrity.o
-integrity-y := iint.o
+integrity-y := iint.o initcalls.o
integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index db8e324ed4e6..823573bcaa27 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -25,6 +25,7 @@
#include <crypto/hash.h>
#include <crypto/hash_info.h>
#include <crypto/utils.h>
+#include "../initcalls.h"
#include "evm.h"
int evm_initialized;
@@ -1112,7 +1113,7 @@ void __init evm_load_x509(void)
}
#endif
-static int __init init_evm(void)
+int __init init_evm(void)
{
int error;
struct list_head *pos, *q;
@@ -1179,6 +1180,5 @@ DEFINE_LSM(evm) = {
.init = init_evm_lsm,
.order = LSM_ORDER_LAST,
.blobs = &evm_blob_sizes,
+ .initcall_late = integrity_late_init,
};
-
-late_initcall(init_evm);
diff --git a/security/integrity/iint.c b/security/integrity/iint.c
index 068ac6c2ae1e..a4b88d67ff43 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -11,6 +11,7 @@
*/
#include <linux/security.h>
#include "integrity.h"
+#include "initcalls.h"
struct dentry *integrity_dir;
@@ -42,7 +43,7 @@ void __init integrity_load_keys(void)
evm_load_x509();
}
-static int __init integrity_fs_init(void)
+int __init integrity_fs_init(void)
{
integrity_dir = securityfs_create_dir("integrity", NULL);
if (IS_ERR(integrity_dir)) {
@@ -58,4 +59,3 @@ static int __init integrity_fs_init(void)
return 0;
}
-late_initcall(integrity_fs_init)
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index eade8e1e3cb1..06ae59cd77f4 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -28,6 +28,7 @@
#include <linux/iversion.h>
#include <linux/evm.h>
#include <linux/crash_dump.h>
+#include "../initcalls.h"
#include "ima.h"
@@ -1202,7 +1203,7 @@ static int ima_kernel_module_request(char *kmod_name)
#endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */
-static int __init init_ima(void)
+int __init init_ima(void)
{
int error;
@@ -1283,6 +1284,5 @@ DEFINE_LSM(ima) = {
.init = init_ima_lsm,
.order = LSM_ORDER_LAST,
.blobs = &ima_blob_sizes,
+ .initcall_late = integrity_late_init,
};
-
-late_initcall(init_ima); /* Start IMA after the TPM is available */
diff --git a/security/integrity/initcalls.c b/security/integrity/initcalls.c
new file mode 100644
index 000000000000..6afa411068f2
--- /dev/null
+++ b/security/integrity/initcalls.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * IMA/EVM initcalls
+ *
+ */
+
+#include <linux/init.h>
+
+#include "initcalls.h"
+
+/**
+ * integrity_late_init - late_initcalls for IMA/EVM
+ *
+ * This helper function wraps all of the late_initcalls for both IMA and EVM.
+ * It can be called multiple times, e.g. once from IMA and once from EVM,
+ * without problem as it maintains an internal static state variable which
+ * ensures that any setup/initialization is only done once.
+ */
+int __init integrity_late_init(void)
+{
+ int rc = 0, rc_tmp;
+ static bool setup = false;
+
+ if (setup)
+ return 0;
+ setup = true;
+
+ rc_tmp = integrity_fs_init();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+
+ rc_tmp = init_ima();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+
+ rc_tmp = init_evm();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+
+ return rc;
+}
diff --git a/security/integrity/initcalls.h b/security/integrity/initcalls.h
new file mode 100644
index 000000000000..b56e9c576505
--- /dev/null
+++ b/security/integrity/initcalls.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _INTEGRITY_INITCALLS_H
+#define _INTEGRITY_INITCALLS_H
+
+int integrity_fs_init(void);
+
+#ifdef CONFIG_IMA
+int init_ima(void);
+#else
+static inline int init_ima(void)
+{
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_EVM
+int init_evm(void);
+#else
+static inline int init_evm(void)
+{
+ return 0;
+}
+#endif
+
+int integrity_late_init(void);
+
+#endif
--
2.50.1
^ permalink raw reply related
* [PATCH v3 32/34] selinux: move initcalls to the LSM framework
From: Paul Moore @ 2025-08-14 22:50 UTC (permalink / raw)
To: linux-security-module, linux-integrity, selinux
Cc: John Johansen, Mimi Zohar, Roberto Sassu, Fan Wu,
Mickaël Salaün, Günther Noack, Kees Cook,
Micah Morton, Casey Schaufler, Tetsuo Handa, Nicolas Bouchinet,
Xiu Jianfeng
In-Reply-To: <20250814225159.275901-36-paul@paul-moore.com>
SELinux currently has a number of initcalls so we've created a new
function, selinux_initcall(), which wraps all of these initcalls so
that we have a single initcall function that can be registered with the
LSM framework.
Signed-off-by: Paul Moore <paul@paul-moore.com>
---
security/selinux/Makefile | 2 +-
security/selinux/hooks.c | 9 +++--
security/selinux/ibpkey.c | 5 ++-
security/selinux/include/audit.h | 9 +++++
security/selinux/include/initcalls.h | 19 ++++++++++
security/selinux/initcalls.c | 52 ++++++++++++++++++++++++++++
security/selinux/netif.c | 5 ++-
security/selinux/netlink.c | 5 ++-
security/selinux/netnode.c | 5 ++-
security/selinux/netport.c | 5 ++-
security/selinux/selinuxfs.c | 5 ++-
security/selinux/ss/services.c | 26 ++++----------
12 files changed, 107 insertions(+), 40 deletions(-)
create mode 100644 security/selinux/include/initcalls.h
create mode 100644 security/selinux/initcalls.c
diff --git a/security/selinux/Makefile b/security/selinux/Makefile
index 66e56e9011df..72d3baf7900c 100644
--- a/security/selinux/Makefile
+++ b/security/selinux/Makefile
@@ -15,7 +15,7 @@ ccflags-y := -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include
ccflags-$(CONFIG_SECURITY_SELINUX_DEBUG) += -DDEBUG
selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \
- netnode.o netport.o status.o \
+ netnode.o netport.o status.o initcalls.o \
ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \
ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/context.o
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index d94b1ff316ba..faa78d16e1b9 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -94,6 +94,7 @@
#include <linux/io_uring/cmd.h>
#include <uapi/linux/lsm.h>
+#include "initcalls.h"
#include "avc.h"
#include "objsec.h"
#include "netif.h"
@@ -7603,6 +7604,10 @@ static __init int selinux_init(void)
if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))
panic("SELinux: Unable to register AVC LSM notifier callback\n");
+ if (avc_add_callback(selinux_audit_rule_avc_callback,
+ AVC_CALLBACK_RESET))
+ panic("SELinux: Unable to register AVC audit callback\n");
+
if (selinux_enforcing_boot)
pr_debug("SELinux: Starting in enforcing mode\n");
else
@@ -7635,6 +7640,7 @@ DEFINE_LSM(selinux) = {
.enabled = &selinux_enabled_boot,
.blobs = &selinux_blob_sizes,
.init = selinux_init,
+ .initcall_device = selinux_initcall,
};
#if defined(CONFIG_NETFILTER)
@@ -7696,7 +7702,7 @@ static struct pernet_operations selinux_net_ops = {
.exit = selinux_nf_unregister,
};
-static int __init selinux_nf_ip_init(void)
+int __init selinux_nf_ip_init(void)
{
int err;
@@ -7711,5 +7717,4 @@ static int __init selinux_nf_ip_init(void)
return 0;
}
-__initcall(selinux_nf_ip_init);
#endif /* CONFIG_NETFILTER */
diff --git a/security/selinux/ibpkey.c b/security/selinux/ibpkey.c
index 470481cfe0e8..ea1d9b2c7d2b 100644
--- a/security/selinux/ibpkey.c
+++ b/security/selinux/ibpkey.c
@@ -23,6 +23,7 @@
#include <linux/list.h>
#include <linux/spinlock.h>
+#include "initcalls.h"
#include "ibpkey.h"
#include "objsec.h"
@@ -218,7 +219,7 @@ void sel_ib_pkey_flush(void)
spin_unlock_irqrestore(&sel_ib_pkey_lock, flags);
}
-static __init int sel_ib_pkey_init(void)
+int __init sel_ib_pkey_init(void)
{
int iter;
@@ -232,5 +233,3 @@ static __init int sel_ib_pkey_init(void)
return 0;
}
-
-subsys_initcall(sel_ib_pkey_init);
diff --git a/security/selinux/include/audit.h b/security/selinux/include/audit.h
index d5b0425055e4..85a531ac737b 100644
--- a/security/selinux/include/audit.h
+++ b/security/selinux/include/audit.h
@@ -15,6 +15,15 @@
#include <linux/audit.h>
#include <linux/types.h>
+/**
+ * selinux_audit_rule_avc_callback - update the audit LSM rules on AVC events.
+ * @event: the AVC event
+ *
+ * Update any audit LSM rules based on the AVC event specified in @event.
+ * Returns 0 on success, negative values otherwise.
+ */
+int selinux_audit_rule_avc_callback(u32 event);
+
/**
* selinux_audit_rule_init - alloc/init an selinux audit rule structure.
* @field: the field this rule refers to
diff --git a/security/selinux/include/initcalls.h b/security/selinux/include/initcalls.h
new file mode 100644
index 000000000000..6674cf489473
--- /dev/null
+++ b/security/selinux/include/initcalls.h
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SELinux initcalls
+ */
+
+#ifndef _SELINUX_INITCALLS_H
+#define _SELINUX_INITCALLS_H
+
+int init_sel_fs(void);
+int sel_netport_init(void);
+int sel_netnode_init(void);
+int sel_netif_init(void);
+int sel_netlink_init(void);
+int sel_ib_pkey_init(void);
+int selinux_nf_ip_init(void);
+
+int selinux_initcall(void);
+
+#endif
diff --git a/security/selinux/initcalls.c b/security/selinux/initcalls.c
new file mode 100644
index 000000000000..f6716a1d38c1
--- /dev/null
+++ b/security/selinux/initcalls.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SELinux initcalls
+ */
+
+#include <linux/init.h>
+
+#include "initcalls.h"
+
+/**
+ * selinux_initcall - Perform the SELinux initcalls
+ *
+ * Used as a device initcall in the SELinux LSM definition.
+ */
+int __init selinux_initcall(void)
+{
+ int rc = 0, rc_tmp = 0;
+
+ rc_tmp = init_sel_fs();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+
+ rc_tmp = sel_netport_init();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+
+ rc_tmp = sel_netnode_init();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+
+ rc_tmp = sel_netif_init();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+
+ rc_tmp = sel_netlink_init();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+
+#if defined(CONFIG_SECURITY_INFINIBAND)
+ rc_tmp = sel_ib_pkey_init();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+#endif
+
+#if defined(CONFIG_NETFILTER)
+ rc_tmp = selinux_nf_ip_init();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+#endif
+
+ return rc;
+}
diff --git a/security/selinux/netif.c b/security/selinux/netif.c
index 78afbecdbe57..e24b2cba28ea 100644
--- a/security/selinux/netif.c
+++ b/security/selinux/netif.c
@@ -22,6 +22,7 @@
#include <linux/rcupdate.h>
#include <net/net_namespace.h>
+#include "initcalls.h"
#include "security.h"
#include "objsec.h"
#include "netif.h"
@@ -265,7 +266,7 @@ static struct notifier_block sel_netif_netdev_notifier = {
.notifier_call = sel_netif_netdev_notifier_handler,
};
-static __init int sel_netif_init(void)
+int __init sel_netif_init(void)
{
int i;
@@ -280,5 +281,3 @@ static __init int sel_netif_init(void)
return 0;
}
-__initcall(sel_netif_init);
-
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c
index 1760aee712fd..eb40e4603475 100644
--- a/security/selinux/netlink.c
+++ b/security/selinux/netlink.c
@@ -17,6 +17,7 @@
#include <net/net_namespace.h>
#include <net/netlink.h>
+#include "initcalls.h"
#include "security.h"
static struct sock *selnl __ro_after_init;
@@ -105,7 +106,7 @@ void selnl_notify_policyload(u32 seqno)
selnl_notify(SELNL_MSG_POLICYLOAD, &seqno);
}
-static int __init selnl_init(void)
+int __init sel_netlink_init(void)
{
struct netlink_kernel_cfg cfg = {
.groups = SELNLGRP_MAX,
@@ -117,5 +118,3 @@ static int __init selnl_init(void)
panic("SELinux: Cannot create netlink socket.");
return 0;
}
-
-__initcall(selnl_init);
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
index 5d0ed08d46e5..9b3da5ce8d39 100644
--- a/security/selinux/netnode.c
+++ b/security/selinux/netnode.c
@@ -30,6 +30,7 @@
#include <net/ip.h>
#include <net/ipv6.h>
+#include "initcalls.h"
#include "netnode.h"
#include "objsec.h"
@@ -290,7 +291,7 @@ void sel_netnode_flush(void)
spin_unlock_bh(&sel_netnode_lock);
}
-static __init int sel_netnode_init(void)
+int __init sel_netnode_init(void)
{
int iter;
@@ -304,5 +305,3 @@ static __init int sel_netnode_init(void)
return 0;
}
-
-__initcall(sel_netnode_init);
diff --git a/security/selinux/netport.c b/security/selinux/netport.c
index 6fd7da4b3576..9e62f7285e81 100644
--- a/security/selinux/netport.c
+++ b/security/selinux/netport.c
@@ -29,6 +29,7 @@
#include <net/ip.h>
#include <net/ipv6.h>
+#include "initcalls.h"
#include "netport.h"
#include "objsec.h"
@@ -218,7 +219,7 @@ void sel_netport_flush(void)
spin_unlock_bh(&sel_netport_lock);
}
-static __init int sel_netport_init(void)
+int __init sel_netport_init(void)
{
int iter;
@@ -232,5 +233,3 @@ static __init int sel_netport_init(void)
return 0;
}
-
-__initcall(sel_netport_init);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 9aa1d03ab612..657e6ff65be7 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -35,6 +35,7 @@
/* selinuxfs pseudo filesystem for exporting the security policy API.
Based on the proc code and the fs/nfsd/nfsctl.c code. */
+#include "initcalls.h"
#include "flask.h"
#include "avc.h"
#include "avc_ss.h"
@@ -2130,7 +2131,7 @@ static struct file_system_type sel_fs_type = {
struct path selinux_null __ro_after_init;
-static int __init init_sel_fs(void)
+int __init init_sel_fs(void)
{
struct qstr null_name = QSTR_INIT(NULL_FILE_NAME,
sizeof(NULL_FILE_NAME)-1);
@@ -2174,5 +2175,3 @@ static int __init init_sel_fs(void)
return err;
}
-
-__initcall(init_sel_fs);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 713130bd43c4..13fc712d5923 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -3570,6 +3570,13 @@ struct selinux_audit_rule {
struct context au_ctxt;
};
+int selinux_audit_rule_avc_callback(u32 event)
+{
+ if (event == AVC_CALLBACK_RESET)
+ return audit_update_lsm_rules();
+ return 0;
+}
+
void selinux_audit_rule_free(void *vrule)
{
struct selinux_audit_rule *rule = vrule;
@@ -3820,25 +3827,6 @@ int selinux_audit_rule_match(struct lsm_prop *prop, u32 field, u32 op, void *vru
return match;
}
-static int aurule_avc_callback(u32 event)
-{
- if (event == AVC_CALLBACK_RESET)
- return audit_update_lsm_rules();
- return 0;
-}
-
-static int __init aurule_init(void)
-{
- int err;
-
- err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET);
- if (err)
- panic("avc_add_callback() failed, error %d\n", err);
-
- return err;
-}
-__initcall(aurule_init);
-
#ifdef CONFIG_NETLABEL
/**
* security_netlbl_cache_add - Add an entry to the NetLabel cache
--
2.50.1
^ permalink raw reply related
* [PATCH v3 33/34] lsm: consolidate all of the LSM framework initcalls
From: Paul Moore @ 2025-08-14 22:50 UTC (permalink / raw)
To: linux-security-module, linux-integrity, selinux
Cc: John Johansen, Mimi Zohar, Roberto Sassu, Fan Wu,
Mickaël Salaün, Günther Noack, Kees Cook,
Micah Morton, Casey Schaufler, Tetsuo Handa, Nicolas Bouchinet,
Xiu Jianfeng
In-Reply-To: <20250814225159.275901-36-paul@paul-moore.com>
The LSM framework itself registers a small number of initcalls, this
patch converts these initcalls into the new initcall mechanism.
Reviewed-by: Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
---
security/inode.c | 3 +--
security/lsm.h | 4 ++++
security/lsm_init.c | 14 ++++++++++++--
security/min_addr.c | 5 +++--
4 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/security/inode.c b/security/inode.c
index a5e7a073e672..21b1f9b4d396 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -384,7 +384,7 @@ static const struct file_operations lsm_ops = {
};
#endif
-static int __init securityfs_init(void)
+int __init securityfs_init(void)
{
int retval;
@@ -403,4 +403,3 @@ static int __init securityfs_init(void)
#endif
return 0;
}
-core_initcall(securityfs_init);
diff --git a/security/lsm.h b/security/lsm.h
index 8dc267977ae0..436219260376 100644
--- a/security/lsm.h
+++ b/security/lsm.h
@@ -35,4 +35,8 @@ extern struct kmem_cache *lsm_inode_cache;
int lsm_cred_alloc(struct cred *cred, gfp_t gfp);
int lsm_task_alloc(struct task_struct *task);
+/* LSM framework initializers */
+int securityfs_init(void);
+int min_addr_init(void);
+
#endif /* _LSM_H_ */
diff --git a/security/lsm_init.c b/security/lsm_init.c
index 697482a22a02..2bd705836df8 100644
--- a/security/lsm_init.c
+++ b/security/lsm_init.c
@@ -488,7 +488,12 @@ int __init security_init(void)
*/
static int __init security_initcall_pure(void)
{
- return lsm_initcall(pure);
+ int rc_adr, rc_lsm;
+
+ rc_adr = min_addr_init();
+ rc_lsm = lsm_initcall(pure);
+
+ return (rc_adr ? rc_adr : rc_lsm);
}
pure_initcall(security_initcall_pure);
@@ -506,7 +511,12 @@ early_initcall(security_initcall_early);
*/
static int __init security_initcall_core(void)
{
- return lsm_initcall(core);
+ int rc_sfs, rc_lsm;
+
+ rc_sfs = securityfs_init();
+ rc_lsm = lsm_initcall(core);
+
+ return (rc_sfs ? rc_sfs : rc_lsm);
}
core_initcall(security_initcall_core);
diff --git a/security/min_addr.c b/security/min_addr.c
index df1bc643d886..40714bdeefbe 100644
--- a/security/min_addr.c
+++ b/security/min_addr.c
@@ -4,6 +4,8 @@
#include <linux/security.h>
#include <linux/sysctl.h>
+#include "lsm.h"
+
/* amount of vm to protect from userspace access by both DAC and the LSM*/
unsigned long mmap_min_addr;
/* amount of vm to protect from userspace using CAP_SYS_RAWIO (DAC) */
@@ -54,11 +56,10 @@ static const struct ctl_table min_addr_sysctl_table[] = {
},
};
-static int __init init_mmap_min_addr(void)
+int __init min_addr_init(void)
{
register_sysctl_init("vm", min_addr_sysctl_table);
update_mmap_min_addr();
return 0;
}
-pure_initcall(init_mmap_min_addr);
--
2.50.1
^ permalink raw reply related
* [PATCH v3 34/34] lsm: add a LSM_STARTED_ALL notification event
From: Paul Moore @ 2025-08-14 22:50 UTC (permalink / raw)
To: linux-security-module, linux-integrity, selinux
Cc: John Johansen, Mimi Zohar, Roberto Sassu, Fan Wu,
Mickaël Salaün, Günther Noack, Kees Cook,
Micah Morton, Casey Schaufler, Tetsuo Handa, Nicolas Bouchinet,
Xiu Jianfeng
In-Reply-To: <20250814225159.275901-36-paul@paul-moore.com>
Add a new LSM notifier event, LSM_STARTED_ALL, which is fired once at
boot when all of the LSMs have been started.
Reviewed-by: Kees Cook <kees@kernel.org>
Reviewed-by: Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
---
include/linux/security.h | 1 +
security/lsm_init.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/include/linux/security.h b/include/linux/security.h
index 8560c50edd2e..c13f0a849024 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -85,6 +85,7 @@ struct timezone;
enum lsm_event {
LSM_POLICY_CHANGE,
+ LSM_STARTED_ALL,
};
struct dm_verity_digest {
diff --git a/security/lsm_init.c b/security/lsm_init.c
index 2bd705836df8..af4046c5c581 100644
--- a/security/lsm_init.c
+++ b/security/lsm_init.c
@@ -556,6 +556,7 @@ static int __init security_initcall_late(void)
rc = lsm_initcall(late);
lsm_pr_dbg("all enabled LSMs fully activated\n");
+ call_blocking_lsm_notifier(LSM_STARTED_ALL, NULL);
return rc;
}
--
2.50.1
^ permalink raw reply related
* Re: [PATCH] security: min_addr: use max() to improve code
From: Paul Moore @ 2025-08-15 2:17 UTC (permalink / raw)
To: Qianfeng Rong, James Morris, Serge E. Hallyn,
linux-security-module, linux-kernel
Cc: Qianfeng Rong
In-Reply-To: <20250814142653.283355-1-rongqianfeng@vivo.com>
On Aug 14, 2025 Qianfeng Rong <rongqianfeng@vivo.com> wrote:
>
> Use max() to reduce the code in update_mmap_min_addr() and improve its
> readability.
>
> Signed-off-by: Qianfeng Rong <rongqianfeng@vivo.com>
> ---
> security/min_addr.c | 5 +----
> 1 file changed, 1 insertion(+), 4 deletions(-)
>
> diff --git a/security/min_addr.c b/security/min_addr.c
> index df1bc643d886..50035bc9281c 100644
> --- a/security/min_addr.c
> +++ b/security/min_addr.c
> @@ -16,10 +16,7 @@ unsigned long dac_mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
> static void update_mmap_min_addr(void)
> {
> #ifdef CONFIG_LSM_MMAP_MIN_ADDR
> - if (dac_mmap_min_addr > CONFIG_LSM_MMAP_MIN_ADDR)
> - mmap_min_addr = dac_mmap_min_addr;
> - else
> - mmap_min_addr = CONFIG_LSM_MMAP_MIN_ADDR;
> + mmap_min_addr = max(dac_mmap_min_addr, CONFIG_LSM_MMAP_MIN_ADDR);
It seems like the umax() macro would be a better choice here, yes?
It might also be a good idea to explicitly include the
include/linux/minmax.h header in this file.
> #else
> mmap_min_addr = dac_mmap_min_addr;
> #endif
> --
> 2.34.1
--
paul-moore.com
^ permalink raw reply
* Re: [PATCH] security: min_addr: use max() to improve code
From: Qianfeng Rong @ 2025-08-15 3:39 UTC (permalink / raw)
To: Paul Moore, James Morris, Serge E. Hallyn, linux-security-module,
linux-kernel
In-Reply-To: <8ab2084cc35ddc9f2a4796ff7cd88954@paul-moore.com>
在 2025/8/15 10:17, Paul Moore 写道:
> On Aug 14, 2025 Qianfeng Rong <rongqianfeng@vivo.com> wrote:
>> Use max() to reduce the code in update_mmap_min_addr() and improve its
>> readability.
>>
>> Signed-off-by: Qianfeng Rong <rongqianfeng@vivo.com>
>> ---
>> security/min_addr.c | 5 +----
>> 1 file changed, 1 insertion(+), 4 deletions(-)
>>
>> diff --git a/security/min_addr.c b/security/min_addr.c
>> index df1bc643d886..50035bc9281c 100644
>> --- a/security/min_addr.c
>> +++ b/security/min_addr.c
>> @@ -16,10 +16,7 @@ unsigned long dac_mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
>> static void update_mmap_min_addr(void)
>> {
>> #ifdef CONFIG_LSM_MMAP_MIN_ADDR
>> - if (dac_mmap_min_addr > CONFIG_LSM_MMAP_MIN_ADDR)
>> - mmap_min_addr = dac_mmap_min_addr;
>> - else
>> - mmap_min_addr = CONFIG_LSM_MMAP_MIN_ADDR;
>> + mmap_min_addr = max(dac_mmap_min_addr, CONFIG_LSM_MMAP_MIN_ADDR);
> It seems like the umax() macro would be a better choice here, yes?
You are right, using umax() here makes the semantics clearer.
>
> It might also be a good idea to explicitly include the
> include/linux/minmax.h header in this file.
ok, Will do in the next version.
>
>> #else
>> mmap_min_addr = dac_mmap_min_addr;
>> #endif
>> --
>> 2.34.1
> --
> paul-moore.com
Best regards,
Qianfeng
^ permalink raw reply
* [PATCH v2] security: min_addr: use umax() to improve code
From: Qianfeng Rong @ 2025-08-15 3:56 UTC (permalink / raw)
To: Paul Moore, James Morris, Serge E. Hallyn, linux-security-module,
linux-kernel
Cc: Qianfeng Rong
Use umax() to reduce the code in update_mmap_min_addr() and improve its
readability.
Signed-off-by: Qianfeng Rong <rongqianfeng@vivo.com>
---
v2: Change max() to umax() and include <linux/minmax.h> explicitly.
---
security/min_addr.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/security/min_addr.c b/security/min_addr.c
index df1bc643d886..c55bb84b8632 100644
--- a/security/min_addr.c
+++ b/security/min_addr.c
@@ -3,6 +3,7 @@
#include <linux/mm.h>
#include <linux/security.h>
#include <linux/sysctl.h>
+#include <linux/minmax.h>
/* amount of vm to protect from userspace access by both DAC and the LSM*/
unsigned long mmap_min_addr;
@@ -16,10 +17,7 @@ unsigned long dac_mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
static void update_mmap_min_addr(void)
{
#ifdef CONFIG_LSM_MMAP_MIN_ADDR
- if (dac_mmap_min_addr > CONFIG_LSM_MMAP_MIN_ADDR)
- mmap_min_addr = dac_mmap_min_addr;
- else
- mmap_min_addr = CONFIG_LSM_MMAP_MIN_ADDR;
+ mmap_min_addr = umax(dac_mmap_min_addr, CONFIG_LSM_MMAP_MIN_ADDR);
#else
mmap_min_addr = dac_mmap_min_addr;
#endif
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v2] apparmor: Remove unused value
From: Akhilesh Patil @ 2025-08-15 4:10 UTC (permalink / raw)
To: Chandra Mohan Sundar
Cc: john.johansen, paul, jmorris, serge, apparmor,
linux-security-module, linux-kernel, shuah, linux-kernel-mentees
In-Reply-To: <20250814165403.616195-1-chandramohan.explore@gmail.com>
On Thu, Aug 14, 2025 at 10:24:01PM +0530, Chandra Mohan Sundar wrote:
> The value "new" is being assigned to NULL but that statement does not
> have effect since "new" is being overwritten in the subsequent
> fallback case.
>
> Remove the unused value. This issue was reported by coverity static
> analyzer.
Hi Chandra. Do you have Coverity ID for this issue ?
Regards,
Akhilesh
>
> Fixes: a9eb185be84e9 ("apparmor: fix x_table_lookup when stacking is not the first entry")
> Signed-off-by: Chandra Mohan Sundar <chandramohan.explore@gmail.com>
> ---
> Changes since v1:
> Fixed the commit message and Fixes tag message formatting.
>
> security/apparmor/domain.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
> index 267da82afb14..9c0c7fa8de46 100644
> --- a/security/apparmor/domain.c
> +++ b/security/apparmor/domain.c
> @@ -592,7 +592,6 @@ static struct aa_label *x_to_label(struct aa_profile *profile,
> if (!new || **lookupname != '&')
> break;
> stack = new;
> - new = NULL;
> fallthrough; /* to X_NAME */
> case AA_X_NAME:
> if (xindex & AA_X_CHILD)
> --
> 2.43.0
>
>
^ permalink raw reply
* Re: [PATCH v2] apparmor: Remove unused value
From: Chandra Mohan Sundar @ 2025-08-15 6:34 UTC (permalink / raw)
To: Akhilesh Patil
Cc: john.johansen, paul, jmorris, serge, apparmor,
linux-security-module, linux-kernel, shuah, linux-kernel-mentees
In-Reply-To: <aJ6zKriNeoM4B/km@bhairav-test.ee.iitb.ac.in>
On Fri, Aug 15, 2025 at 9:40 AM Akhilesh Patil <akhilesh@ee.iitb.ac.in> wrote:
>
> On Thu, Aug 14, 2025 at 10:24:01PM +0530, Chandra Mohan Sundar wrote:
> > The value "new" is being assigned to NULL but that statement does not
> > have effect since "new" is being overwritten in the subsequent
> > fallback case.
> >
> > Remove the unused value. This issue was reported by coverity static
> > analyzer.
>
> Hi Chandra. Do you have Coverity ID for this issue ?
>
Hi Akhilesh,
Sure. The Coverity id is 1662453 (
https://scan5.scan.coverity.com/#/project-view/65357/10063?selectedIssue=1662453
).
Thanks,
Chandra Mohan Sundar
^ permalink raw reply
* [syzbot ci] Re: Signed BPF programs
From: syzbot ci @ 2025-08-15 8:26 UTC (permalink / raw)
To: andrii, ast, bboscaccy, bpf, daniel, kpsingh, kys,
linux-security-module, paul
Cc: syzbot, syzkaller-bugs
In-Reply-To: <20250813205526.2992911-1-kpsingh@kernel.org>
syzbot ci has tested the following series
[v3] Signed BPF programs
https://lore.kernel.org/all/20250813205526.2992911-1-kpsingh@kernel.org
* [PATCH v3 01/12] bpf: Update the bpf_prog_calc_tag to use SHA256
* [PATCH v3 02/12] bpf: Implement exclusive map creation
* [PATCH v3 03/12] libbpf: Implement SHA256 internal helper
* [PATCH v3 04/12] libbpf: Support exclusive map creation
* [PATCH v3 05/12] selftests/bpf: Add tests for exclusive maps
* [PATCH v3 06/12] bpf: Return hashes of maps in BPF_OBJ_GET_INFO_BY_FD
* [PATCH v3 07/12] bpf: Move the signature kfuncs to helpers.c
* [PATCH v3 08/12] bpf: Implement signature verification for BPF programs
* [PATCH v3 09/12] libbpf: Update light skeleton for signing
* [PATCH v3 10/12] libbpf: Embed and verify the metadata hash in the loader
* [PATCH v3 11/12] bpftool: Add support for signing BPF programs
* [PATCH v3 12/12] selftests/bpf: Enable signature verification for some lskel tests
and found the following issue:
general protection fault in bpf_verify_pkcs7_signature
Full report is available here:
https://ci.syzbot.org/series/67d9a289-da5c-4051-8c3c-cc32b6ccd77d
***
general protection fault in bpf_verify_pkcs7_signature
tree: bpf-next
URL: https://kernel.googlesource.com/pub/scm/linux/kernel/git/bpf/bpf-next.git
base: 07866544e410e4c895a729971e4164861b41fad5
arch: amd64
compiler: Debian clang version 20.1.7 (++20250616065708+6146a88f6049-1~exp1~20250616065826.132), Debian LLD 20.1.7
config: https://ci.syzbot.org/builds/1e87aafb-11dc-48f1-a980-c91551ba52de/config
C repro: https://ci.syzbot.org/findings/0c329233-09a8-4e8b-9e6e-72f234dd85ab/c_repro
syz repro: https://ci.syzbot.org/findings/0c329233-09a8-4e8b-9e6e-72f234dd85ab/syz_repro
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] SMP KASAN PTI
KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
CPU: 1 UID: 0 PID: 6001 Comm: syz.0.17 Not tainted 6.17.0-rc1-syzkaller-00022-g07866544e410-dirty #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
RIP: 0010:bpf_verify_pkcs7_signature+0x31/0x190 kernel/bpf/helpers.c:3835
Code: 41 56 41 55 41 54 53 48 89 d3 49 89 f6 49 89 ff 48 bd 00 00 00 00 00 fc ff df e8 aa b0 e0 ff 4c 8d 63 08 4c 89 e0 48 c1 e8 03 <0f> b6 04 28 84 c0 0f 85 01 01 00 00 41 80 3c 24 00 74 3d 48 89 d8
RSP: 0018:ffffc90002f7fa08 EFLAGS: 00010202
RAX: 0000000000000001 RBX: 0000000000000000 RCX: ffff888020c51cc0
RDX: 0000000000000000 RSI: ffffc90002f7faa0 RDI: ffffc90002f7fac0
RBP: dffffc0000000000 R08: 0000000000000018 R09: ffffffff820b8a70
R10: ffffc90002f7fac0 R11: fffff520005eff5a R12: 0000000000000008
R13: 0000000000000010 R14: ffffc90002f7faa0 R15: ffffc90002f7fac0
FS: 00005555895fe500(0000) GS:ffff8881a3c1c000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000001b30b63fff CR3: 0000000028898000 CR4: 00000000000006f0
Call Trace:
<TASK>
bpf_prog_verify_signature+0x2da/0x3b0 kernel/bpf/syscall.c:2815
bpf_prog_load+0xcc4/0x19e0 kernel/bpf/syscall.c:2989
__sys_bpf+0x507/0x860 kernel/bpf/syscall.c:6116
__do_sys_bpf kernel/bpf/syscall.c:6226 [inline]
__se_sys_bpf kernel/bpf/syscall.c:6224 [inline]
__x64_sys_bpf+0x7c/0x90 kernel/bpf/syscall.c:6224
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f0a4558ebe9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fff940250b8 EFLAGS: 00000246 ORIG_RAX: 0000000000000141
RAX: ffffffffffffffda RBX: 00007f0a457b5fa0 RCX: 00007f0a4558ebe9
RDX: 00000000000000a8 RSI: 0000200000000140 RDI: 0000000000000005
RBP: 00007f0a45611e19 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f0a457b5fa0 R14: 00007f0a457b5fa0 R15: 0000000000000003
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:bpf_verify_pkcs7_signature+0x31/0x190 kernel/bpf/helpers.c:3835
Code: 41 56 41 55 41 54 53 48 89 d3 49 89 f6 49 89 ff 48 bd 00 00 00 00 00 fc ff df e8 aa b0 e0 ff 4c 8d 63 08 4c 89 e0 48 c1 e8 03 <0f> b6 04 28 84 c0 0f 85 01 01 00 00 41 80 3c 24 00 74 3d 48 89 d8
RSP: 0018:ffffc90002f7fa08 EFLAGS: 00010202
RAX: 0000000000000001 RBX: 0000000000000000 RCX: ffff888020c51cc0
RDX: 0000000000000000 RSI: ffffc90002f7faa0 RDI: ffffc90002f7fac0
RBP: dffffc0000000000 R08: 0000000000000018 R09: ffffffff820b8a70
R10: ffffc90002f7fac0 R11: fffff520005eff5a R12: 0000000000000008
R13: 0000000000000010 R14: ffffc90002f7faa0 R15: ffffc90002f7fac0
FS: 00005555895fe500(0000) GS:ffff8881a3c1c000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000001b30b63fff CR3: 0000000028898000 CR4: 00000000000006f0
----------------
Code disassembly (best guess):
0: 41 56 push %r14
2: 41 55 push %r13
4: 41 54 push %r12
6: 53 push %rbx
7: 48 89 d3 mov %rdx,%rbx
a: 49 89 f6 mov %rsi,%r14
d: 49 89 ff mov %rdi,%r15
10: 48 bd 00 00 00 00 00 movabs $0xdffffc0000000000,%rbp
17: fc ff df
1a: e8 aa b0 e0 ff call 0xffe0b0c9
1f: 4c 8d 63 08 lea 0x8(%rbx),%r12
23: 4c 89 e0 mov %r12,%rax
26: 48 c1 e8 03 shr $0x3,%rax
* 2a: 0f b6 04 28 movzbl (%rax,%rbp,1),%eax <-- trapping instruction
2e: 84 c0 test %al,%al
30: 0f 85 01 01 00 00 jne 0x137
36: 41 80 3c 24 00 cmpb $0x0,(%r12)
3b: 74 3d je 0x7a
3d: 48 89 d8 mov %rbx,%rax
***
If these findings have caused you to resend the series or submit a
separate fix, please add the following tag to your commit message:
Tested-by: syzbot@syzkaller.appspotmail.com
---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.
^ permalink raw reply
* Re: [PATCH] lockdown: avoid extra call to strlen() in lockdown_read()
From: Xiujianfeng @ 2025-08-15 12:28 UTC (permalink / raw)
To: Dmitry Antipov, Nicolas Bouchinet, Paul Moore, James Morris,
Serge E . Hallyn
Cc: linux-security-module@vger.kernel.org
Hi Dmitry,
> Since s*printf() family of functions returns the number of characters emitted,
> avoid redundant call to strlen() in lockdown_read() and prefer
> snprintf() over sprintf() for an extra protection against buffer overflow.
>
> Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
> ---
> security/lockdown/lockdown.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
> index cf83afa1d879..10537d7c4437 100644
> --- a/security/lockdown/lockdown.c
> +++ b/security/lockdown/lockdown.c
> @@ -106,9 +106,13 @@ static ssize_t lockdown_read(struct file *filp, char
> __user *buf, size_t count,
> const char *label = lockdown_reasons[level];
>
> if (kernel_locked_down == level)
> - offset += sprintf(temp+offset, "[%s] ", label);
> + offset += snprintf(temp + offset,
> + sizeof(temp) - offset,
> + "[%s] ", label);
> else
> - offset += sprintf(temp+offset, "%s ", label);
> + offset += snprintf(temp + offset,
> + sizeof(temp) - offset,
> + "%s ", label);
> }
> }
>
> @@ -116,7 +120,7 @@ static ssize_t lockdown_read(struct file *filp, char
> __user *buf, size_t count,
> if (offset > 0)
> temp[offset-1] = '\n';
>
> - return simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
> + return simple_read_from_buffer(buf, count, ppos, temp, offset);
Thanks for your patch.
Since the current `lockdown_levels` array is static and has only three members,
and the total number of characters of these three reasons is far from exceeding 80,
there seems to be no risk of buffer overflow for now.
About the change to strlen, I think lockdown_read() is not on the hot path, the impact
is minimal.
So I prefer to leave them as is, thanks.
Best regards,
Xiu
> }
>
> static ssize_t lockdown_write(struct file *file, const char __user *buf,
> --
> 2.50.1
^ permalink raw reply
* [PATCH] kselftest/landlock : fixed typo errors
From: hariconscious @ 2025-08-15 16:51 UTC (permalink / raw)
To: mic, gnoack, shuah, linux-security-module, linux-kselftest,
linux-kernel
Cc: HariKrishna
From: HariKrishna <hariconscious@gmail.com>
fixed typo errors
Signed-off-by: HariKrishna <hariconscious@gmail.com>
---
tools/testing/selftests/landlock/net_test.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/landlock/net_test.c b/tools/testing/selftests/landlock/net_test.c
index 2a45208551e6..2dc0eca25ed3 100644
--- a/tools/testing/selftests/landlock/net_test.c
+++ b/tools/testing/selftests/landlock/net_test.c
@@ -1587,7 +1587,7 @@ TEST_F(ipv4_tcp, port_endianness)
&bind_connect_host_endian_p1, 0));
enforce_ruleset(_metadata, ruleset_fd);
- /* No restriction for big endinan CPU. */
+ /* No restriction for big endian CPU. */
test_bind_and_connect(_metadata, &self->srv0, false, little_endian);
/* No restriction for any CPU. */
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v3 11/34] lsm: get rid of the lsm_names list and do some cleanup
From: Casey Schaufler @ 2025-08-15 17:00 UTC (permalink / raw)
To: Paul Moore, linux-security-module, linux-integrity, selinux
Cc: John Johansen, Mimi Zohar, Roberto Sassu, Fan Wu,
Mickaël Salaün, Günther Noack, Kees Cook,
Micah Morton, Tetsuo Handa, Nicolas Bouchinet, Xiu Jianfeng,
Casey Schaufler
In-Reply-To: <20250814225159.275901-47-paul@paul-moore.com>
On 8/14/2025 3:50 PM, Paul Moore wrote:
> The LSM currently has a lot of code to maintain a list of the currently
> active LSMs in a human readable string, with the only user being the
> "/sys/kernel/security/lsm" code. Let's drop all of that code and
> generate the string on first use and then cache it for subsequent use.
>
> Signed-off-by: Paul Moore <paul@paul-moore.com>
Reviewed-by: Casey Schaufler <casey@schaufler-ca.com>
> ---
> include/linux/lsm_hooks.h | 1 -
> security/inode.c | 59 +++++++++++++++++++++++++++++++++++++--
> security/lsm_init.c | 49 --------------------------------
> 3 files changed, 57 insertions(+), 52 deletions(-)
>
> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index 7343dd60b1d5..65a8227bece7 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -172,7 +172,6 @@ struct lsm_info {
>
>
> /* DO NOT tamper with these variables outside of the LSM framework */
> -extern char *lsm_names;
> extern struct lsm_static_calls_table static_calls_table __ro_after_init;
>
> /**
> diff --git a/security/inode.c b/security/inode.c
> index 43382ef8896e..a5e7a073e672 100644
> --- a/security/inode.c
> +++ b/security/inode.c
> @@ -22,6 +22,8 @@
> #include <linux/lsm_hooks.h>
> #include <linux/magic.h>
>
> +#include "lsm.h"
> +
> static struct vfsmount *mount;
> static int mount_count;
>
> @@ -315,12 +317,65 @@ void securityfs_remove(struct dentry *dentry)
> EXPORT_SYMBOL_GPL(securityfs_remove);
>
> #ifdef CONFIG_SECURITY
> +#include <linux/spinlock.h>
> +
> static struct dentry *lsm_dentry;
> +
> +/* NOTE: we never free the string below once it is set. */
> +static DEFINE_SPINLOCK(lsm_read_lock);
> +static char *lsm_read_str = NULL;
> +static ssize_t lsm_read_len = 0;
> +
> static ssize_t lsm_read(struct file *filp, char __user *buf, size_t count,
> loff_t *ppos)
> {
> - return simple_read_from_buffer(buf, count, ppos, lsm_names,
> - strlen(lsm_names));
> + int i;
> + char *str;
> + ssize_t len;
> +
> +restart:
> +
> + rcu_read_lock();
> + if (!lsm_read_str) {
> + /* we need to generate the string and try again */
> + rcu_read_unlock();
> + goto generate_string;
> + }
> + len = simple_read_from_buffer(buf, count, ppos,
> + rcu_dereference(lsm_read_str),
> + lsm_read_len);
> + rcu_read_unlock();
> + return len;
> +
> +generate_string:
> +
> + for (i = 0; i < lsm_active_cnt; i++)
> + /* the '+ 1' accounts for either a comma or a NUL */
> + len += strlen(lsm_idlist[i]->name) + 1;
> +
> + str = kmalloc(len, GFP_KERNEL);
> + if (!str)
> + return -ENOMEM;
> + str[0] = '\0';
> +
> + for (i = 0; i < lsm_active_cnt; i++) {
> + if (i > 0)
> + strcat(str, ",");
> + strcat(str, lsm_idlist[i]->name);
> + }
> +
> + spin_lock(&lsm_read_lock);
> + if (lsm_read_str) {
> + /* we raced and lost */
> + spin_unlock(&lsm_read_lock);
> + kfree(str);
> + goto restart;
> + }
> + lsm_read_str = str;
> + lsm_read_len = len - 1;
> + spin_unlock(&lsm_read_lock);
> +
> + goto restart;
> }
>
> static const struct file_operations lsm_ops = {
> diff --git a/security/lsm_init.c b/security/lsm_init.c
> index 9e495a36a332..87e2147016b3 100644
> --- a/security/lsm_init.c
> +++ b/security/lsm_init.c
> @@ -10,8 +10,6 @@
>
> #include "lsm.h"
>
> -char *lsm_names;
> -
> /* Pointers to LSM sections defined in include/asm-generic/vmlinux.lds.h */
> extern struct lsm_info __start_lsm_info[], __end_lsm_info[];
> extern struct lsm_info __start_early_lsm_info[], __end_early_lsm_info[];
> @@ -371,42 +369,6 @@ static void __init lsm_init_ordered(void)
> }
> }
>
> -static bool match_last_lsm(const char *list, const char *lsm)
> -{
> - const char *last;
> -
> - if (WARN_ON(!list || !lsm))
> - return false;
> - last = strrchr(list, ',');
> - if (last)
> - /* Pass the comma, strcmp() will check for '\0' */
> - last++;
> - else
> - last = list;
> - return !strcmp(last, lsm);
> -}
> -
> -static int lsm_append(const char *new, char **result)
> -{
> - char *cp;
> -
> - if (*result == NULL) {
> - *result = kstrdup(new, GFP_KERNEL);
> - if (*result == NULL)
> - return -ENOMEM;
> - } else {
> - /* Check if it is the last registered name */
> - if (match_last_lsm(*result, new))
> - return 0;
> - cp = kasprintf(GFP_KERNEL, "%s,%s", *result, new);
> - if (cp == NULL)
> - return -ENOMEM;
> - kfree(*result);
> - *result = cp;
> - }
> - return 0;
> -}
> -
> static void __init lsm_static_call_init(struct security_hook_list *hl)
> {
> struct lsm_static_call *scall = hl->scalls;
> @@ -443,15 +405,6 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
> hooks[i].lsmid = lsmid;
> lsm_static_call_init(&hooks[i]);
> }
> -
> - /*
> - * Don't try to append during early_security_init(), we'll come back
> - * and fix this up afterwards.
> - */
> - if (slab_is_available()) {
> - if (lsm_append(lsmid->name, &lsm_names) < 0)
> - panic("%s - Cannot get early memory.\n", __func__);
> - }
> }
>
> int __init early_security_init(void)
> @@ -488,8 +441,6 @@ int __init security_init(void)
> lsm_early_for_each_raw(lsm) {
> init_debug(" early started: %s (%s)\n", lsm->id->name,
> is_enabled(lsm) ? "enabled" : "disabled");
> - if (lsm->enabled)
> - lsm_append(lsm->id->name, &lsm_names);
> }
>
> /* Load LSMs in specified order. */
^ permalink raw reply
* Re: [PATCH v3 17/34] lsm: cleanup initialize_lsm() and rename to lsm_init_single()
From: Casey Schaufler @ 2025-08-15 17:05 UTC (permalink / raw)
To: Paul Moore, linux-security-module, linux-integrity, selinux
Cc: John Johansen, Mimi Zohar, Roberto Sassu, Fan Wu,
Mickaël Salaün, Günther Noack, Kees Cook,
Micah Morton, Tetsuo Handa, Nicolas Bouchinet, Xiu Jianfeng,
Casey Schaufler
In-Reply-To: <20250814225159.275901-53-paul@paul-moore.com>
On 8/14/2025 3:50 PM, Paul Moore wrote:
> Rename initialize_lsm() to be more consistent with the rest of the LSM
> initialization changes and rework the function itself to better fit
> with the "exit on fail" coding pattern.
>
> Reviewed-by: Kees Cook <kees@kernel.org>
> Reviewed-by: John Johansen <john.johansen@canonical.com>
> Signed-off-by: Paul Moore <paul@paul-moore.com>
Reviewed-by: Casey Schaufler <casey@schaufler-ca.com>
> ---
> security/lsm_init.c | 25 +++++++++++++++----------
> 1 file changed, 15 insertions(+), 10 deletions(-)
>
> diff --git a/security/lsm_init.c b/security/lsm_init.c
> index 5249aa044d9d..1f64222925c1 100644
> --- a/security/lsm_init.c
> +++ b/security/lsm_init.c
> @@ -169,6 +169,7 @@ static void __init lsm_order_append(struct lsm_info *lsm, const char *src)
> lsm_is_enabled(lsm) ? "enabled" : "disabled");
> }
>
> +
> /**
> * lsm_blob_size_update - Update the LSM blob size and offset information
> * @sz_req: the requested additional blob size
> @@ -225,16 +226,20 @@ static void __init lsm_prepare(struct lsm_info *lsm)
> lsm_blob_size_update(&blobs->lbs_bpf_token, &blob_sizes.lbs_bpf_token);
> }
>
> -/* Initialize a given LSM, if it is enabled. */
> -static void __init initialize_lsm(struct lsm_info *lsm)
> +/**
> + * lsm_init_single - Initialize a given LSM
> + * @lsm: LSM definition
> + */
> +static void __init lsm_init_single(struct lsm_info *lsm)
> {
> - if (lsm_is_enabled(lsm)) {
> - int ret;
> + int ret;
>
> - init_debug("initializing %s\n", lsm->id->name);
> - ret = lsm->init();
> - WARN(ret, "%s failed to initialize: %d\n", lsm->id->name, ret);
> - }
> + if (!lsm_is_enabled(lsm))
> + return;
> +
> + init_debug("initializing %s\n", lsm->id->name);
> + ret = lsm->init();
> + WARN(ret, "%s failed to initialize: %d\n", lsm->id->name, ret);
> }
>
> /**
> @@ -379,7 +384,7 @@ static void __init lsm_init_ordered(void)
> panic("%s: early task alloc failed.\n", __func__);
>
> lsm_order_for_each(lsm) {
> - initialize_lsm(*lsm);
> + lsm_init_single(*lsm);
> }
> }
>
> @@ -429,7 +434,7 @@ int __init early_security_init(void)
> lsm_enabled_set(lsm, true);
> lsm_order_append(lsm, "early");
> lsm_prepare(lsm);
> - initialize_lsm(lsm);
> + lsm_init_single(lsm);
> }
>
> return 0;
^ permalink raw reply
* Re: [PATCH v3 bpf-next 1/4] kernfs: remove iattr_mutex
From: Jan Kiszka @ 2025-08-16 5:52 UTC (permalink / raw)
To: Christian Brauner, André Draszik
Cc: Song Liu, bpf, linux-fsdevel, linux-kernel, linux-security-module,
kernel-team, andrii, eddyz87, ast, daniel, martin.lau, viro, jack,
kpsingh, mattbobrowski, amir73il, gregkh, tj, daan.j.demeyer,
Will McVicker, Peter Griffin, Tudor Ambarus, kernel-team
In-Reply-To: <20250702-hochmoderne-abklatsch-af9c605b57b2@brauner>
On 02.07.25 14:17, Christian Brauner wrote:
> On Wed, Jul 02, 2025 at 11:47:58AM +0100, André Draszik wrote:
>> Hi,
>>
>> On Sun, 2025-06-22 at 23:38 -0700, Song Liu wrote:
>>> From: Christian Brauner <brauner@kernel.org>
>>>
>>> All allocations of struct kernfs_iattrs are serialized through a global
>>> mutex. Simply do a racy allocation and let the first one win. I bet most
>>> callers are under inode->i_rwsem anyway and it wouldn't be needed but
>>> let's not require that.
>>>
>>> Signed-off-by: Christian Brauner <brauner@kernel.org>
>>> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>>> Acked-by: Tejun Heo <tj@kernel.org>
>>> Signed-off-by: Song Liu <song@kernel.org>
>>
>> On next-20250701, ls -lA gives errors on /sys:
>>
>> $ ls -lA /sys/
>> ls: /sys/: No data available
>> ls: /sys/kernel: No data available
>> ls: /sys/power: No data available
>> ls: /sys/class: No data available
>> ls: /sys/devices: No data available
>> ls: /sys/dev: No data available
>> ls: /sys/hypervisor: No data available
>> ls: /sys/fs: No data available
>> ls: /sys/bus: No data available
>> ls: /sys/firmware: No data available
>> ls: /sys/block: No data available
>> ls: /sys/module: No data available
>> total 0
>> drwxr-xr-x 2 root root 0 Jan 1 1970 block
>> drwxr-xr-x 52 root root 0 Jan 1 1970 bus
>> drwxr-xr-x 88 root root 0 Jan 1 1970 class
>> drwxr-xr-x 4 root root 0 Jan 1 1970 dev
>> drwxr-xr-x 11 root root 0 Jan 1 1970 devices
>> drwxr-xr-x 3 root root 0 Jan 1 1970 firmware
>> drwxr-xr-x 10 root root 0 Jan 1 1970 fs
>> drwxr-xr-x 2 root root 0 Jul 2 09:43 hypervisor
>> drwxr-xr-x 14 root root 0 Jan 1 1970 kernel
>> drwxr-xr-x 251 root root 0 Jan 1 1970 module
>> drwxr-xr-x 3 root root 0 Jul 2 09:43 power
>>
>>
>> and my bisect is pointing to this commit. Simply reverting it also fixes
>> the errors.
>>
>>
>> Do you have any suggestions?
>
> Yes, apparently the xattr selftest don't cover sysfs/kernfs. The issue
> is that the commit changed listxattr() to skip allocation of the xattr
> header and instead just returned ENODATA. We should just allocate like
> before tested just now:
>
> user1@localhost:~$ sudo ls -al /sys/kernel/
> total 0
> drwxr-xr-x 17 root root 0 Jul 2 13:41 .
> dr-xr-xr-x 12 root root 0 Jul 2 13:41 ..
> -r--r--r-- 1 root root 4096 Jul 2 13:41 address_bits
> drwxr-xr-x 3 root root 0 Jul 2 13:41 boot_params
> drwxr-xr-x 2 root root 0 Jul 2 13:41 btf
> drwxr-xr-x 2 root root 0 Jul 2 13:41 cgroup
> drwxr-xr-x 2 root root 0 Jul 2 13:41 config
> -r--r--r-- 1 root root 4096 Jul 2 13:41 cpu_byteorder
> -r--r--r-- 1 root root 4096 Jul 2 13:41 crash_elfcorehdr_size
> drwx------ 34 root root 0 Jul 2 13:41 debug
> -r--r--r-- 1 root root 4096 Jul 2 13:41 fscaps
> -r--r--r-- 1 root root 4096 Jul 2 13:41 hardlockup_count
> drwxr-xr-x 2 root root 0 Jul 2 13:41 iommu_groups
> drwxr-xr-x 344 root root 0 Jul 2 13:41 irq
> -r--r--r-- 1 root root 4096 Jul 2 13:41 kexec_crash_loaded
> -rw-r--r-- 1 root root 4096 Jul 2 13:41 kexec_crash_size
> -r--r--r-- 1 root root 4096 Jul 2 13:41 kexec_loaded
> drwxr-xr-x 9 root root 0 Jul 2 13:41 mm
> -r--r--r-- 1 root root 84 Jul 2 13:41 notes
> -r--r--r-- 1 root root 4096 Jul 2 13:41 oops_count
> -rw-r--r-- 1 root root 4096 Jul 2 13:41 profiling
> -rw-r--r-- 1 root root 4096 Jul 2 13:41 rcu_expedited
> -rw-r--r-- 1 root root 4096 Jul 2 13:41 rcu_normal
> -r--r--r-- 1 root root 4096 Jul 2 13:41 rcu_stall_count
> drwxr-xr-x 2 root root 0 Jul 2 13:41 reboot
> drwxr-xr-x 2 root root 0 Jul 2 13:41 sched_ext
> drwxr-xr-x 4 root root 0 Jul 2 13:41 security
> drwxr-xr-x 190 root root 0 Jul 2 13:41 slab
> -r--r--r-- 1 root root 4096 Jul 2 13:41 softlockup_count
> drwxr-xr-x 2 root root 0 Jul 2 13:41 software_nodes
> drwxr-xr-x 4 root root 0 Jul 2 13:41 sunrpc
> drwxr-xr-x 6 root root 0 Jul 2 13:41 tracing
> -r--r--r-- 1 root root 4096 Jul 2 13:41 uevent_seqnum
> -r--r--r-- 1 root root 4096 Jul 2 13:41 vmcoreinfo
> -r--r--r-- 1 root root 4096 Jul 2 13:41 warn_count
>
> I'm folding:
>
> diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
> index 3c293a5a21b1..457f91c412d4 100644
> --- a/fs/kernfs/inode.c
> +++ b/fs/kernfs/inode.c
> @@ -142,9 +142,9 @@ ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
> struct kernfs_node *kn = kernfs_dentry_node(dentry);
> struct kernfs_iattrs *attrs;
>
> - attrs = kernfs_iattrs_noalloc(kn);
> + attrs = kernfs_iattrs(kn);
> if (!attrs)
> - return -ENODATA;
> + return -ENOMEM;
>
> return simple_xattr_list(d_inode(dentry), &attrs->xattrs, buf, size);
> }
>
> which brings it back to the old behavior.
>
...but it looks like v3 was merged as-is in the end, without this fixup.
Is there some separate patch in the pipeline, or was this forgotten?
> I'm also adding a selftest for this behavior. Patch appended.
Jan
--
Siemens AG, Foundational Technologies
Linux Expert Center
^ permalink raw reply
* [PATCH v5 3/5] Audit: Add record for multiple task security contexts
From: Casey Schaufler @ 2025-08-16 16:41 UTC (permalink / raw)
To: casey, paul, eparis, linux-security-module, audit
Cc: jmorris, serge, keescook, john.johansen, penguin-kernel,
stephen.smalley.work, linux-kernel, selinux
In-Reply-To: <20250816164140.6045-1-casey@schaufler-ca.com>
Replace the single skb pointer in an audit_buffer with a list of
skb pointers. Add the audit_stamp information to the audit_buffer as
there's no guarantee that there will be an audit_context containing
the stamp associated with the event. At audit_log_end() time create
auxiliary records as have been added to the list. Functions are
created to manage the skb list in the audit_buffer.
Create a new audit record AUDIT_MAC_TASK_CONTEXTS.
An example of the MAC_TASK_CONTEXTS record is:
type=MAC_TASK_CONTEXTS
msg=audit(1600880931.832:113)
subj_apparmor=unconfined
subj_smack=_
When an audit event includes a AUDIT_MAC_TASK_CONTEXTS record the
"subj=" field in other records in the event will be "subj=?".
An AUDIT_MAC_TASK_CONTEXTS record is supplied when the system has
multiple security modules that may make access decisions based on a
subject security context.
Refactor audit_log_task_context(), creating a new audit_log_subj_ctx().
This is used in netlabel auditing to provide multiple subject security
contexts as necessary.
Suggested-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/audit.h | 16 +++
include/uapi/linux/audit.h | 1 +
kernel/audit.c | 207 +++++++++++++++++++++++++++++------
net/netlabel/netlabel_user.c | 9 +-
security/apparmor/lsm.c | 3 +
security/lsm.h | 4 -
security/lsm_init.c | 5 -
security/security.c | 3 -
security/selinux/hooks.c | 3 +
security/smack/smack_lsm.c | 3 +
10 files changed, 202 insertions(+), 52 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 0050ef288ab3..fb54c1119947 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -37,6 +37,8 @@ struct audit_watch;
struct audit_tree;
struct sk_buff;
struct kern_ipc_perm;
+struct lsm_id;
+struct lsm_prop;
struct audit_krule {
u32 pflags;
@@ -147,6 +149,9 @@ extern unsigned compat_signal_class[];
#define AUDIT_TTY_ENABLE BIT(0)
#define AUDIT_TTY_LOG_PASSWD BIT(1)
+/* bit values for audit_cfg_lsm */
+#define AUDIT_CFG_LSM_SECCTX_SUBJECT BIT(0)
+
struct filename;
#define AUDIT_OFF 0
@@ -185,6 +190,7 @@ extern void audit_log_path_denied(int type,
const char *operation);
extern void audit_log_lost(const char *message);
+extern int audit_log_subj_ctx(struct audit_buffer *ab, struct lsm_prop *prop);
extern int audit_log_task_context(struct audit_buffer *ab);
extern void audit_log_task_info(struct audit_buffer *ab);
@@ -210,6 +216,8 @@ extern u32 audit_enabled;
extern int audit_signal_info(int sig, struct task_struct *t);
+extern void audit_cfg_lsm(const struct lsm_id *lsmid, int flags);
+
#else /* CONFIG_AUDIT */
static inline __printf(4, 5)
void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
@@ -245,6 +253,11 @@ static inline void audit_log_key(struct audit_buffer *ab, char *key)
{ }
static inline void audit_log_path_denied(int type, const char *operation)
{ }
+static inline int audit_log_subj_ctx(struct audit_buffer *ab,
+ struct lsm_prop *prop)
+{
+ return 0;
+}
static inline int audit_log_task_context(struct audit_buffer *ab)
{
return 0;
@@ -269,6 +282,9 @@ static inline int audit_signal_info(int sig, struct task_struct *t)
return 0;
}
+static inline void audit_cfg_lsm(const struct lsm_id *lsmid, int flags)
+{ }
+
#endif /* CONFIG_AUDIT */
#ifdef CONFIG_AUDIT_COMPAT_GENERIC
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 9a4ecc9f6dc5..8cad2f307719 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -148,6 +148,7 @@
#define AUDIT_IPE_POLICY_LOAD 1422 /* IPE policy load */
#define AUDIT_LANDLOCK_ACCESS 1423 /* Landlock denial */
#define AUDIT_LANDLOCK_DOMAIN 1424 /* Landlock domain status */
+#define AUDIT_MAC_TASK_CONTEXTS 1425 /* Multiple LSM task contexts */
#define AUDIT_FIRST_KERN_ANOM_MSG 1700
#define AUDIT_LAST_KERN_ANOM_MSG 1799
diff --git a/kernel/audit.c b/kernel/audit.c
index 226c8ae00d04..c7dea6bfacdd 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -54,6 +54,7 @@
#include <net/netlink.h>
#include <linux/skbuff.h>
#include <linux/security.h>
+#include <linux/lsm_hooks.h>
#include <linux/freezer.h>
#include <linux/pid_namespace.h>
#include <net/netns/generic.h>
@@ -81,6 +82,11 @@ static u32 audit_failure = AUDIT_FAIL_PRINTK;
/* private audit network namespace index */
static unsigned int audit_net_id;
+/* Number of modules that provide a security context.
+ List of lsms that provide a security context */
+static u32 audit_subj_secctx_cnt;
+static const struct lsm_id *audit_subj_lsms[MAX_LSM_COUNT];
+
/**
* struct audit_net - audit private network namespace data
* @sk: communication socket
@@ -195,8 +201,10 @@ static struct audit_ctl_mutex {
* to place it on a transmit queue. Multiple audit_buffers can be in
* use simultaneously. */
struct audit_buffer {
- struct sk_buff *skb; /* formatted skb ready to send */
+ struct sk_buff *skb; /* the skb for audit_log functions */
+ struct sk_buff_head skb_list; /* formatted skbs, ready to send */
struct audit_context *ctx; /* NULL or associated context */
+ struct audit_stamp stamp; /* audit stamp for these records */
gfp_t gfp_mask;
};
@@ -278,6 +286,27 @@ static pid_t auditd_pid_vnr(void)
return pid;
}
+/**
+ * audit_cfg_lsm - Identify a security module as providing a secctx.
+ * @lsmid: LSM identity
+ * @flags: which contexts are provided
+ *
+ * Description:
+ * Increments the count of the security modules providing a secctx.
+ * If the LSM id is already in the list leave it alone.
+ */
+void audit_cfg_lsm(const struct lsm_id *lsmid, int flags)
+{
+ int i;
+
+ if (flags & AUDIT_CFG_LSM_SECCTX_SUBJECT) {
+ for (i = 0 ; i < audit_subj_secctx_cnt; i++)
+ if (audit_subj_lsms[i] == lsmid)
+ return;
+ audit_subj_lsms[audit_subj_secctx_cnt++] = lsmid;
+ }
+}
+
/**
* audit_get_sk - Return the audit socket for the given network namespace
* @net: the destination network namespace
@@ -1776,10 +1805,13 @@ __setup("audit_backlog_limit=", audit_backlog_limit_set);
static void audit_buffer_free(struct audit_buffer *ab)
{
+ struct sk_buff *skb;
+
if (!ab)
return;
- kfree_skb(ab->skb);
+ while ((skb = skb_dequeue(&ab->skb_list)))
+ kfree_skb(skb);
kmem_cache_free(audit_buffer_cache, ab);
}
@@ -1795,6 +1827,10 @@ static struct audit_buffer *audit_buffer_alloc(struct audit_context *ctx,
ab->skb = nlmsg_new(AUDIT_BUFSIZ, gfp_mask);
if (!ab->skb)
goto err;
+
+ skb_queue_head_init(&ab->skb_list);
+ skb_queue_tail(&ab->skb_list, ab->skb);
+
if (!nlmsg_put(ab->skb, 0, 0, type, 0, 0))
goto err;
@@ -1860,7 +1896,6 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
int type)
{
struct audit_buffer *ab;
- struct audit_stamp stamp;
if (audit_initialized != AUDIT_INITIALIZED)
return NULL;
@@ -1915,14 +1950,14 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
return NULL;
}
- audit_get_stamp(ab->ctx, &stamp);
+ audit_get_stamp(ab->ctx, &ab->stamp);
/* cancel dummy context to enable supporting records */
if (ctx)
ctx->dummy = 0;
audit_log_format(ab, "audit(%llu.%03lu:%u): ",
- (unsigned long long)stamp.ctime.tv_sec,
- stamp.ctime.tv_nsec/1000000,
- stamp.serial);
+ (unsigned long long)ab->stamp.ctime.tv_sec,
+ ab->stamp.ctime.tv_nsec/1000000,
+ ab->stamp.serial);
return ab;
}
@@ -2178,31 +2213,128 @@ void audit_log_key(struct audit_buffer *ab, char *key)
audit_log_format(ab, "(null)");
}
-int audit_log_task_context(struct audit_buffer *ab)
+/**
+ * audit_buffer_aux_new - Add an aux record buffer to the skb list
+ * @ab: audit_buffer
+ * @type: message type
+ *
+ * Aux records are allocated and added to the skb list of
+ * the "main" record. The ab->skb is reset to point to the
+ * aux record on its creation. When the aux record in complete
+ * ab->skb has to be reset to point to the "main" record.
+ * This allows the audit_log_ functions to be ignorant of
+ * which kind of record it is logging to. It also avoids adding
+ * special data for aux records.
+ *
+ * On success ab->skb will point to the new aux record.
+ * Returns 0 on success, -ENOMEM should allocation fail.
+ */
+static int audit_buffer_aux_new(struct audit_buffer *ab, int type)
+{
+ WARN_ON(ab->skb != skb_peek(&ab->skb_list));
+
+ ab->skb = nlmsg_new(AUDIT_BUFSIZ, ab->gfp_mask);
+ if (!ab->skb)
+ goto err;
+ if (!nlmsg_put(ab->skb, 0, 0, type, 0, 0))
+ goto err;
+ skb_queue_tail(&ab->skb_list, ab->skb);
+
+ audit_log_format(ab, "audit(%llu.%03lu:%u): ",
+ (unsigned long long)ab->stamp.ctime.tv_sec,
+ ab->stamp.ctime.tv_nsec/1000000,
+ ab->stamp.serial);
+
+ return 0;
+
+err:
+ kfree_skb(ab->skb);
+ ab->skb = skb_peek(&ab->skb_list);
+ return -ENOMEM;
+}
+
+/**
+ * audit_buffer_aux_end - Switch back to the "main" record from an aux record
+ * @ab: audit_buffer
+ *
+ * Restores the "main" audit record to ab->skb.
+ */
+static void audit_buffer_aux_end(struct audit_buffer *ab)
+{
+ ab->skb = skb_peek(&ab->skb_list);
+}
+
+/**
+ * audit_log_subj_ctx - Add LSM subject information
+ * @ab: audit_buffer
+ * @prop: LSM subject properties.
+ *
+ * Add a subj= field and, if necessary, a AUDIT_MAC_TASK_CONTEXTS record.
+ */
+int audit_log_subj_ctx(struct audit_buffer *ab, struct lsm_prop *prop)
{
- struct lsm_prop prop;
struct lsm_context ctx;
+ char *space = "";
int error;
+ int i;
- security_current_getlsmprop_subj(&prop);
- if (!lsmprop_is_set(&prop))
+ security_current_getlsmprop_subj(prop);
+ if (!lsmprop_is_set(prop))
return 0;
- error = security_lsmprop_to_secctx(&prop, &ctx, LSM_ID_UNDEF);
- if (error < 0) {
- if (error != -EINVAL)
- goto error_path;
+ if (audit_subj_secctx_cnt < 2) {
+ error = security_lsmprop_to_secctx(prop, &ctx, LSM_ID_UNDEF);
+ if (error < 0) {
+ if (error != -EINVAL)
+ goto error_path;
+ return 0;
+ }
+ audit_log_format(ab, " subj=%s", ctx.context);
+ security_release_secctx(&ctx);
return 0;
}
-
- audit_log_format(ab, " subj=%s", ctx.context);
- security_release_secctx(&ctx);
+ /* Multiple LSMs provide contexts. Include an aux record. */
+ audit_log_format(ab, " subj=?");
+ error = audit_buffer_aux_new(ab, AUDIT_MAC_TASK_CONTEXTS);
+ if (error)
+ goto error_path;
+
+ for (i = 0; i < audit_subj_secctx_cnt; i++) {
+ error = security_lsmprop_to_secctx(prop, &ctx,
+ audit_subj_lsms[i]->id);
+ if (error < 0) {
+ /*
+ * Don't print anything. An LSM like BPF could
+ * claim to support contexts, but only do so under
+ * certain conditions.
+ */
+ if (error == -EOPNOTSUPP)
+ continue;
+ if (error != -EINVAL)
+ audit_panic("error in audit_log_task_context");
+ } else {
+ audit_log_format(ab, "%ssubj_%s=%s", space,
+ audit_subj_lsms[i]->name, ctx.context);
+ space = " ";
+ security_release_secctx(&ctx);
+ }
+ }
+ audit_buffer_aux_end(ab);
return 0;
error_path:
- audit_panic("error in audit_log_task_context");
+ audit_panic("error in audit_log_subj_ctx");
return error;
}
+EXPORT_SYMBOL(audit_log_subj_ctx);
+
+int audit_log_task_context(struct audit_buffer *ab)
+{
+ struct lsm_prop prop;
+
+ security_current_getlsmprop_subj(&prop);
+ return audit_log_subj_ctx(ab, &prop);
+}
EXPORT_SYMBOL(audit_log_task_context);
void audit_log_d_path_exe(struct audit_buffer *ab,
@@ -2411,6 +2543,26 @@ int audit_signal_info(int sig, struct task_struct *t)
return audit_signal_info_syscall(t);
}
+/**
+ * __audit_log_end - enqueue one audit record
+ * @skb: the buffer to send
+ */
+static void __audit_log_end(struct sk_buff *skb)
+{
+ struct nlmsghdr *nlh;
+
+ if (audit_rate_check()) {
+ /* setup the netlink header, see the comments in
+ * kauditd_send_multicast_skb() for length quirks */
+ nlh = nlmsg_hdr(skb);
+ nlh->nlmsg_len = skb->len - NLMSG_HDRLEN;
+
+ /* queue the netlink packet */
+ skb_queue_tail(&audit_queue, skb);
+ } else
+ audit_log_lost("rate limit exceeded");
+}
+
/**
* audit_log_end - end one audit record
* @ab: the audit_buffer
@@ -2423,25 +2575,16 @@ int audit_signal_info(int sig, struct task_struct *t)
void audit_log_end(struct audit_buffer *ab)
{
struct sk_buff *skb;
- struct nlmsghdr *nlh;
if (!ab)
return;
- if (audit_rate_check()) {
- skb = ab->skb;
- ab->skb = NULL;
+ while ((skb = skb_dequeue(&ab->skb_list)))
+ __audit_log_end(skb);
- /* setup the netlink header, see the comments in
- * kauditd_send_multicast_skb() for length quirks */
- nlh = nlmsg_hdr(skb);
- nlh->nlmsg_len = skb->len - NLMSG_HDRLEN;
-
- /* queue the netlink packet and poke the kauditd thread */
- skb_queue_tail(&audit_queue, skb);
+ /* poke the kauditd thread */
+ if (audit_rate_check())
wake_up_interruptible(&kauditd_wait);
- } else
- audit_log_lost("rate limit exceeded");
audit_buffer_free(ab);
}
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 6d6545297ee3..0da652844dd6 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -84,7 +84,6 @@ struct audit_buffer *netlbl_audit_start_common(int type,
struct netlbl_audit *audit_info)
{
struct audit_buffer *audit_buf;
- struct lsm_context ctx;
if (audit_enabled == AUDIT_OFF)
return NULL;
@@ -96,13 +95,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
audit_log_format(audit_buf, "netlabel: auid=%u ses=%u",
from_kuid(&init_user_ns, audit_info->loginuid),
audit_info->sessionid);
-
- if (lsmprop_is_set(&audit_info->prop) &&
- security_lsmprop_to_secctx(&audit_info->prop, &ctx,
- LSM_ID_UNDEF) > 0) {
- audit_log_format(audit_buf, " subj=%s", ctx.context);
- security_release_secctx(&ctx);
- }
+ audit_log_subj_ctx(audit_buf, &audit_info->prop);
return audit_buf;
}
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index db8592bed189..a74825eebba0 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -2251,6 +2251,9 @@ static int __init apparmor_init(void)
security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks),
&apparmor_lsmid);
+ /* Inform the audit system that secctx is used */
+ audit_cfg_lsm(&apparmor_lsmid, AUDIT_CFG_LSM_SECCTX_SUBJECT);
+
/* Report that AppArmor successfully initialized */
apparmor_initialized = 1;
if (aa_g_profile_mode == APPARMOR_COMPLAIN)
diff --git a/security/lsm.h b/security/lsm.h
index d1d54540da98..c432dc0c5e30 100644
--- a/security/lsm.h
+++ b/security/lsm.h
@@ -24,10 +24,6 @@ extern bool lsm_debug;
extern unsigned int lsm_count;
extern const struct lsm_id *lsm_idlist[];
-/* LSM property configuration */
-extern unsigned int lsm_count_prop_subj;
-extern unsigned int lsm_count_prop_obj;
-
/* LSM blob configuration */
extern struct lsm_blob_sizes blob_sizes;
diff --git a/security/lsm_init.c b/security/lsm_init.c
index c2ef4db055db..54166688efff 100644
--- a/security/lsm_init.c
+++ b/security/lsm_init.c
@@ -190,11 +190,6 @@ static void __init lsm_order_append(struct lsm_info *lsm, const char *src)
lsm_order[lsm_count] = lsm;
lsm_idlist[lsm_count++] = lsm->id;
- if (lsm->id->flags & LSM_ID_FLG_PROP_SUBJ)
- lsm_count_prop_subj++;
- if (lsm->id->flags & LSM_ID_FLG_PROP_OBJ)
- lsm_count_prop_obj++;
-
lsm_pr_dbg("enabling LSM %s:%s\n", src, lsm->id->name);
}
diff --git a/security/security.c b/security/security.c
index 2cc832dc8a45..678b261e91de 100644
--- a/security/security.c
+++ b/security/security.c
@@ -78,9 +78,6 @@ bool lsm_debug __ro_after_init;
unsigned int lsm_count __ro_after_init;
const struct lsm_id *lsm_idlist[MAX_LSM_COUNT];
-unsigned int lsm_count_prop_subj __ro_after_init;
-unsigned int lsm_count_prop_obj __ro_after_init;
-
struct lsm_blob_sizes blob_sizes;
struct kmem_cache *lsm_file_cache;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b00c2627286a..81b66b4d9695 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -7594,6 +7594,9 @@ static __init int selinux_init(void)
/* Set the security state for the initial task. */
cred_init_security();
+ /* Inform the audit system that secctx is used */
+ audit_cfg_lsm(&selinux_lsmid, AUDIT_CFG_LSM_SECCTX_SUBJECT);
+
default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
if (!default_noexec)
pr_notice("SELinux: virtual memory is executable by default\n");
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 46ef5ece991c..9a76821b7191 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -5268,6 +5268,9 @@ static __init int smack_init(void)
/* initialize the smack_known_list */
init_smack_known_list();
+ /* Inform the audit system that secctx is used */
+ audit_cfg_lsm(&smack_lsmid, AUDIT_CFG_LSM_SECCTX_SUBJECT);
+
return 0;
}
--
2.50.1
^ permalink raw reply related
* [PATCH v5 2/5] LSM: security_lsmblob_to_secctx module selection
From: Casey Schaufler @ 2025-08-16 16:41 UTC (permalink / raw)
To: casey, paul, eparis, linux-security-module, audit
Cc: jmorris, serge, keescook, john.johansen, penguin-kernel,
stephen.smalley.work, linux-kernel, selinux
In-Reply-To: <20250816164140.6045-1-casey@schaufler-ca.com>
Add a parameter lsmid to security_lsmblob_to_secctx() to identify which
of the security modules that may be active should provide the security
context. If the value of lsmid is LSM_ID_UNDEF the first LSM providing
a hook is used. security_secid_to_secctx() is unchanged, and will
always report the first LSM providing a hook.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/security.h | 6 ++++--
kernel/audit.c | 4 ++--
kernel/auditsc.c | 8 +++++---
net/netlabel/netlabel_user.c | 3 ++-
security/security.c | 18 ++++++++++++++++--
5 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/include/linux/security.h b/include/linux/security.h
index c032ec4e95ff..5fbe38521938 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -564,7 +564,8 @@ int security_getprocattr(struct task_struct *p, int lsmid, const char *name,
int security_setprocattr(int lsmid, const char *name, void *value, size_t size);
int security_ismaclabel(const char *name);
int security_secid_to_secctx(u32 secid, struct lsm_context *cp);
-int security_lsmprop_to_secctx(struct lsm_prop *prop, struct lsm_context *cp);
+int security_lsmprop_to_secctx(struct lsm_prop *prop, struct lsm_context *cp,
+ int lsmid);
int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
void security_release_secctx(struct lsm_context *cp);
void security_inode_invalidate_secctx(struct inode *inode);
@@ -1536,7 +1537,8 @@ static inline int security_secid_to_secctx(u32 secid, struct lsm_context *cp)
}
static inline int security_lsmprop_to_secctx(struct lsm_prop *prop,
- struct lsm_context *cp)
+ struct lsm_context *cp,
+ int lsmid)
{
return -EOPNOTSUPP;
}
diff --git a/kernel/audit.c b/kernel/audit.c
index 547967cb4266..226c8ae00d04 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1473,7 +1473,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
case AUDIT_SIGNAL_INFO:
if (lsmprop_is_set(&audit_sig_lsm)) {
err = security_lsmprop_to_secctx(&audit_sig_lsm,
- &lsmctx);
+ &lsmctx, LSM_ID_UNDEF);
if (err < 0)
return err;
}
@@ -2188,7 +2188,7 @@ int audit_log_task_context(struct audit_buffer *ab)
if (!lsmprop_is_set(&prop))
return 0;
- error = security_lsmprop_to_secctx(&prop, &ctx);
+ error = security_lsmprop_to_secctx(&prop, &ctx, LSM_ID_UNDEF);
if (error < 0) {
if (error != -EINVAL)
goto error_path;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 528b6d2f5cb0..322d4e27f28e 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1109,7 +1109,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
from_kuid(&init_user_ns, auid),
from_kuid(&init_user_ns, uid), sessionid);
if (lsmprop_is_set(prop)) {
- if (security_lsmprop_to_secctx(prop, &ctx) < 0) {
+ if (security_lsmprop_to_secctx(prop, &ctx, LSM_ID_UNDEF) < 0) {
audit_log_format(ab, " obj=(none)");
rc = 1;
} else {
@@ -1395,7 +1395,8 @@ static void show_special(struct audit_context *context, int *call_panic)
struct lsm_context lsmctx;
if (security_lsmprop_to_secctx(&context->ipc.oprop,
- &lsmctx) < 0) {
+ &lsmctx,
+ LSM_ID_UNDEF) < 0) {
*call_panic = 1;
} else {
audit_log_format(ab, " obj=%s", lsmctx.context);
@@ -1560,7 +1561,8 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
if (lsmprop_is_set(&n->oprop)) {
struct lsm_context ctx;
- if (security_lsmprop_to_secctx(&n->oprop, &ctx) < 0) {
+ if (security_lsmprop_to_secctx(&n->oprop, &ctx,
+ LSM_ID_UNDEF) < 0) {
if (call_panic)
*call_panic = 2;
} else {
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 0d04d23aafe7..6d6545297ee3 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -98,7 +98,8 @@ struct audit_buffer *netlbl_audit_start_common(int type,
audit_info->sessionid);
if (lsmprop_is_set(&audit_info->prop) &&
- security_lsmprop_to_secctx(&audit_info->prop, &ctx) > 0) {
+ security_lsmprop_to_secctx(&audit_info->prop, &ctx,
+ LSM_ID_UNDEF) > 0) {
audit_log_format(audit_buf, " subj=%s", ctx.context);
security_release_secctx(&ctx);
}
diff --git a/security/security.c b/security/security.c
index 8a4e0f70e49d..2cc832dc8a45 100644
--- a/security/security.c
+++ b/security/security.c
@@ -3774,17 +3774,31 @@ EXPORT_SYMBOL(security_secid_to_secctx);
* security_lsmprop_to_secctx() - Convert a lsm_prop to a secctx
* @prop: lsm specific information
* @cp: the LSM context
+ * @lsmid: which security module to report
*
* Convert a @prop entry to security context. If @cp is NULL the
* length of the result will be returned. This does mean that the
* length could change between calls to check the length and the
* next call which actually allocates and returns the @cp.
*
+ * @lsmid identifies which LSM should supply the context.
+ * A value of LSM_ID_UNDEF indicates that the first LSM suppling
+ * the hook should be used. This is used in cases where the
+ * ID of the supplying LSM is unambiguous.
+ *
* Return: Return length of data on success, error on failure.
*/
-int security_lsmprop_to_secctx(struct lsm_prop *prop, struct lsm_context *cp)
+int security_lsmprop_to_secctx(struct lsm_prop *prop, struct lsm_context *cp,
+ int lsmid)
{
- return call_int_hook(lsmprop_to_secctx, prop, cp);
+ struct lsm_static_call *scall;
+
+ lsm_for_each_hook(scall, lsmprop_to_secctx) {
+ if (lsmid != LSM_ID_UNDEF && lsmid != scall->hl->lsmid->id)
+ continue;
+ return scall->hl->hook.lsmprop_to_secctx(prop, cp);
+ }
+ return LSM_RET_DEFAULT(lsmprop_to_secctx);
}
EXPORT_SYMBOL(security_lsmprop_to_secctx);
--
2.50.1
^ permalink raw reply related
* [PATCH v5 4/5] Audit: Fix indentation in audit_log_exit
From: Casey Schaufler @ 2025-08-16 16:41 UTC (permalink / raw)
To: casey, paul, eparis, linux-security-module, audit
Cc: jmorris, serge, keescook, john.johansen, penguin-kernel,
stephen.smalley.work, linux-kernel, selinux
In-Reply-To: <20250816164140.6045-1-casey@schaufler-ca.com>
Fix two indentation errors in audit_log_exit().
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
kernel/auditsc.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 322d4e27f28e..84173d234d4a 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1780,15 +1780,16 @@ static void audit_log_exit(void)
axs->target_sessionid[i],
&axs->target_ref[i],
axs->target_comm[i]))
- call_panic = 1;
+ call_panic = 1;
}
if (context->target_pid &&
audit_log_pid_context(context, context->target_pid,
context->target_auid, context->target_uid,
context->target_sessionid,
- &context->target_ref, context->target_comm))
- call_panic = 1;
+ &context->target_ref,
+ context->target_comm))
+ call_panic = 1;
if (context->pwd.dentry && context->pwd.mnt) {
ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
--
2.50.1
^ permalink raw reply related
* [PATCH v5 1/5] Audit: Create audit_stamp structure
From: Casey Schaufler @ 2025-08-16 16:41 UTC (permalink / raw)
To: casey, paul, eparis, linux-security-module, audit
Cc: jmorris, serge, keescook, john.johansen, penguin-kernel,
stephen.smalley.work, linux-kernel, selinux
In-Reply-To: <20250816164140.6045-1-casey@schaufler-ca.com>
Replace the timestamp and serial number pair used in audit records
with a structure containing the two elements.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
kernel/audit.c | 17 +++++++++--------
kernel/audit.h | 13 +++++++++----
kernel/auditsc.c | 22 +++++++++-------------
3 files changed, 27 insertions(+), 25 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 61b5744d0bb6..547967cb4266 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1833,11 +1833,11 @@ unsigned int audit_serial(void)
}
static inline void audit_get_stamp(struct audit_context *ctx,
- struct timespec64 *t, unsigned int *serial)
+ struct audit_stamp *stamp)
{
- if (!ctx || !auditsc_get_stamp(ctx, t, serial)) {
- ktime_get_coarse_real_ts64(t);
- *serial = audit_serial();
+ if (!ctx || !auditsc_get_stamp(ctx, stamp)) {
+ ktime_get_coarse_real_ts64(&stamp->ctime);
+ stamp->serial = audit_serial();
}
}
@@ -1860,8 +1860,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
int type)
{
struct audit_buffer *ab;
- struct timespec64 t;
- unsigned int serial;
+ struct audit_stamp stamp;
if (audit_initialized != AUDIT_INITIALIZED)
return NULL;
@@ -1916,12 +1915,14 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
return NULL;
}
- audit_get_stamp(ab->ctx, &t, &serial);
+ audit_get_stamp(ab->ctx, &stamp);
/* cancel dummy context to enable supporting records */
if (ctx)
ctx->dummy = 0;
audit_log_format(ab, "audit(%llu.%03lu:%u): ",
- (unsigned long long)t.tv_sec, t.tv_nsec/1000000, serial);
+ (unsigned long long)stamp.ctime.tv_sec,
+ stamp.ctime.tv_nsec/1000000,
+ stamp.serial);
return ab;
}
diff --git a/kernel/audit.h b/kernel/audit.h
index 0211cb307d30..4d6dd2588f9b 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -99,6 +99,12 @@ struct audit_proctitle {
char *value; /* the cmdline field */
};
+/* A timestamp/serial pair to identify an event */
+struct audit_stamp {
+ struct timespec64 ctime; /* time of syscall entry */
+ unsigned int serial; /* serial number for record */
+};
+
/* The per-task audit context. */
struct audit_context {
int dummy; /* must be the first element */
@@ -108,10 +114,9 @@ struct audit_context {
AUDIT_CTX_URING, /* in use by io_uring */
} context;
enum audit_state state, current_state;
- unsigned int serial; /* serial number for record */
+ struct audit_stamp stamp; /* event identifier */
int major; /* syscall number */
int uring_op; /* uring operation */
- struct timespec64 ctime; /* time of syscall entry */
unsigned long argv[4]; /* syscall arguments */
long return_code;/* syscall return code */
u64 prio;
@@ -263,7 +268,7 @@ extern void audit_put_tty(struct tty_struct *tty);
extern unsigned int audit_serial(void);
#ifdef CONFIG_AUDITSYSCALL
extern int auditsc_get_stamp(struct audit_context *ctx,
- struct timespec64 *t, unsigned int *serial);
+ struct audit_stamp *stamp);
extern void audit_put_watch(struct audit_watch *watch);
extern void audit_get_watch(struct audit_watch *watch);
@@ -304,7 +309,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,
struct audit_context *ctx);
extern struct list_head *audit_killed_trees(void);
#else /* CONFIG_AUDITSYSCALL */
-#define auditsc_get_stamp(c, t, s) 0
+#define auditsc_get_stamp(c, s) 0
#define audit_put_watch(w) do { } while (0)
#define audit_get_watch(w) do { } while (0)
#define audit_to_watch(k, p, l, o) (-EINVAL)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 78fd876a5473..528b6d2f5cb0 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -994,10 +994,10 @@ static void audit_reset_context(struct audit_context *ctx)
*/
ctx->current_state = ctx->state;
- ctx->serial = 0;
+ ctx->stamp.serial = 0;
+ ctx->stamp.ctime = (struct timespec64){ .tv_sec = 0, .tv_nsec = 0 };
ctx->major = 0;
ctx->uring_op = 0;
- ctx->ctime = (struct timespec64){ .tv_sec = 0, .tv_nsec = 0 };
memset(ctx->argv, 0, sizeof(ctx->argv));
ctx->return_code = 0;
ctx->prio = (ctx->state == AUDIT_STATE_RECORD ? ~0ULL : 0);
@@ -1917,7 +1917,7 @@ void __audit_uring_entry(u8 op)
ctx->context = AUDIT_CTX_URING;
ctx->current_state = ctx->state;
- ktime_get_coarse_real_ts64(&ctx->ctime);
+ ktime_get_coarse_real_ts64(&ctx->stamp.ctime);
}
/**
@@ -2039,7 +2039,7 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2,
context->argv[3] = a4;
context->context = AUDIT_CTX_SYSCALL;
context->current_state = state;
- ktime_get_coarse_real_ts64(&context->ctime);
+ ktime_get_coarse_real_ts64(&context->stamp.ctime);
}
/**
@@ -2508,21 +2508,17 @@ EXPORT_SYMBOL_GPL(__audit_inode_child);
/**
* auditsc_get_stamp - get local copies of audit_context values
* @ctx: audit_context for the task
- * @t: timespec64 to store time recorded in the audit_context
- * @serial: serial value that is recorded in the audit_context
+ * @stamp: timestamp to record
*
* Also sets the context as auditable.
*/
-int auditsc_get_stamp(struct audit_context *ctx,
- struct timespec64 *t, unsigned int *serial)
+int auditsc_get_stamp(struct audit_context *ctx, struct audit_stamp *stamp)
{
if (ctx->context == AUDIT_CTX_UNUSED)
return 0;
- if (!ctx->serial)
- ctx->serial = audit_serial();
- t->tv_sec = ctx->ctime.tv_sec;
- t->tv_nsec = ctx->ctime.tv_nsec;
- *serial = ctx->serial;
+ if (!ctx->stamp.serial)
+ ctx->stamp.serial = audit_serial();
+ *stamp = ctx->stamp;
if (!ctx->prio) {
ctx->prio = 1;
ctx->current_state = AUDIT_STATE_RECORD;
--
2.50.1
^ permalink raw reply related
* [PATCH v5 0/5] Audit: Records for multiple security contexts
From: Casey Schaufler @ 2025-08-16 16:41 UTC (permalink / raw)
To: casey, paul, eparis, linux-security-module, audit
Cc: jmorris, serge, keescook, john.johansen, penguin-kernel,
stephen.smalley.work, linux-kernel, selinux
In-Reply-To: <20250816164140.6045-1-casey.ref@schaufler-ca.com>
The Linux audit system includes LSM based security "context" information
in its events. Historically, only one LSM that uses security contexts can
be active on a system. One of the few obsticles to allowing multiple LSM
support is the inability to report more than one security context in an
audit event. This patchset provides a mechanism to provide supplimental
records containing more than one security context for subjects and
objects.
The mechanism for reporting multiple security contexts inspired
considerable discussion. It would have been possible to add multiple
contexts to existing records using sophisticated formatting. This would
have significant backward compatibility issues, and require additional
parsing in user space code. Adding new records for an event that contain
the contexts is more in keeping with the way audit events have been
constructed in the past.
Only audit events associated with system calls have required multiple
records prior to this. Mechanism has been added allowing any event
to be composed of multiple records. This should make it easier to
add information to existing audit events without breaking backward
compatability.
v5:
Comment on the LSM_ID_UNDEF behavior in security_secid_to_secctx().
Change some names to better reflect their purpose.
Move alignment changes into a separate patch.
v4:
Use LSM_ID_UNDEF when checking for valid LSM IDs in
security_lsmprop_to_secctx().
Fix the object record to include only those for LSMs that use them.
Squash the two patches dealing with subject contexts.
Base the patches on Paul Moore's LSM initialization patchset.
https://lore.kernel.org/all/20250409185019.238841-31-paul@paul-moore.com/
v3:
Rework how security modules identify that they provide security
contexts to the audit system. Maintain a list within the audit
system of the security modules that provide security contexts.
Revert the separate counts of subject and object contexts.
v2:
Maintain separate counts for LSMs using subject contexts and object
contexts. AppArmor uses the former but not the latter.
Correct error handling in object record creation.
https://github.com/cschaufler/lsm-stacking#audit-6.16-rc4-v5
Casey Schaufler (5):
Audit: Create audit_stamp structure
LSM: security_lsmblob_to_secctx module selection
Audit: Add record for multiple task security contexts
Audit: Fix indentation in audit_log_exit
Audit: Add record for multiple object contexts
include/linux/audit.h | 23 +++
include/linux/security.h | 6 +-
include/uapi/linux/audit.h | 2 +
kernel/audit.c | 274 ++++++++++++++++++++++++++++++-----
kernel/audit.h | 13 +-
kernel/auditsc.c | 65 +++------
net/netlabel/netlabel_user.c | 8 +-
security/apparmor/lsm.c | 3 +
security/lsm.h | 4 -
security/lsm_init.c | 5 -
security/security.c | 21 ++-
security/selinux/hooks.c | 5 +
security/smack/smack_lsm.c | 5 +
13 files changed, 325 insertions(+), 109 deletions(-)
--
2.50.1
^ permalink raw reply
* [PATCH v5 5/5] Audit: Add record for multiple object contexts
From: Casey Schaufler @ 2025-08-16 16:41 UTC (permalink / raw)
To: casey, paul, eparis, linux-security-module, audit
Cc: jmorris, serge, keescook, john.johansen, penguin-kernel,
stephen.smalley.work, linux-kernel, selinux
In-Reply-To: <20250816164140.6045-1-casey@schaufler-ca.com>
Create a new audit record AUDIT_MAC_OBJ_CONTEXTS.
An example of the MAC_OBJ_CONTEXTS record is:
type=MAC_OBJ_CONTEXTS
msg=audit(1601152467.009:1050):
obj_selinux=unconfined_u:object_r:user_home_t:s0
When an audit event includes a AUDIT_MAC_OBJ_CONTEXTS record
the "obj=" field in other records in the event will be "obj=?".
An AUDIT_MAC_OBJ_CONTEXTS record is supplied when the system has
multiple security modules that may make access decisions based
on an object security context.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/audit.h | 7 +++++
include/uapi/linux/audit.h | 1 +
kernel/audit.c | 58 +++++++++++++++++++++++++++++++++++++-
kernel/auditsc.c | 38 +++++--------------------
security/selinux/hooks.c | 4 ++-
security/smack/smack_lsm.c | 4 ++-
6 files changed, 78 insertions(+), 34 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index fb54c1119947..56944fbc1e58 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -151,6 +151,7 @@ extern unsigned compat_signal_class[];
/* bit values for audit_cfg_lsm */
#define AUDIT_CFG_LSM_SECCTX_SUBJECT BIT(0)
+#define AUDIT_CFG_LSM_SECCTX_OBJECT BIT(1)
struct filename;
@@ -191,6 +192,7 @@ extern void audit_log_path_denied(int type,
extern void audit_log_lost(const char *message);
extern int audit_log_subj_ctx(struct audit_buffer *ab, struct lsm_prop *prop);
+extern int audit_log_obj_ctx(struct audit_buffer *ab, struct lsm_prop *prop);
extern int audit_log_task_context(struct audit_buffer *ab);
extern void audit_log_task_info(struct audit_buffer *ab);
@@ -258,6 +260,11 @@ static inline int audit_log_subj_ctx(struct audit_buffer *ab,
{
return 0;
}
+static inline int audit_log_obj_ctx(struct audit_buffer *ab,
+ struct lsm_prop *prop)
+{
+ return 0;
+}
static inline int audit_log_task_context(struct audit_buffer *ab)
{
return 0;
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 8cad2f307719..14a1c1fe013a 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -149,6 +149,7 @@
#define AUDIT_LANDLOCK_ACCESS 1423 /* Landlock denial */
#define AUDIT_LANDLOCK_DOMAIN 1424 /* Landlock domain status */
#define AUDIT_MAC_TASK_CONTEXTS 1425 /* Multiple LSM task contexts */
+#define AUDIT_MAC_OBJ_CONTEXTS 1426 /* Multiple LSM objext contexts */
#define AUDIT_FIRST_KERN_ANOM_MSG 1700
#define AUDIT_LAST_KERN_ANOM_MSG 1799
diff --git a/kernel/audit.c b/kernel/audit.c
index c7dea6bfacdd..63c69db43172 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -85,7 +85,9 @@ static unsigned int audit_net_id;
/* Number of modules that provide a security context.
List of lsms that provide a security context */
static u32 audit_subj_secctx_cnt;
+static u32 audit_obj_secctx_cnt;
static const struct lsm_id *audit_subj_lsms[MAX_LSM_COUNT];
+static const struct lsm_id *audit_obj_lsms[MAX_LSM_COUNT];
/**
* struct audit_net - audit private network namespace data
@@ -305,6 +307,12 @@ void audit_cfg_lsm(const struct lsm_id *lsmid, int flags)
return;
audit_subj_lsms[audit_subj_secctx_cnt++] = lsmid;
}
+ if (flags & AUDIT_CFG_LSM_SECCTX_OBJECT) {
+ for (i = 0 ; i < audit_obj_secctx_cnt; i++)
+ if (audit_obj_lsms[i] == lsmid)
+ return;
+ audit_obj_lsms[audit_obj_secctx_cnt++] = lsmid;
+ }
}
/**
@@ -1142,7 +1150,6 @@ static int is_audit_feature_set(int i)
return af.features & AUDIT_FEATURE_TO_MASK(i);
}
-
static int audit_get_feature(struct sk_buff *skb)
{
u32 seq;
@@ -2337,6 +2344,55 @@ int audit_log_task_context(struct audit_buffer *ab)
}
EXPORT_SYMBOL(audit_log_task_context);
+int audit_log_obj_ctx(struct audit_buffer *ab, struct lsm_prop *prop)
+{
+ int i;
+ int rc;
+ int error = 0;
+ char *space = "";
+ struct lsm_context ctx;
+
+ if (audit_obj_secctx_cnt < 2) {
+ error = security_lsmprop_to_secctx(prop, &ctx, LSM_ID_UNDEF);
+ if (error < 0) {
+ if (error != -EINVAL)
+ goto error_path;
+ return error;
+ }
+ audit_log_format(ab, " obj=%s", ctx.context);
+ security_release_secctx(&ctx);
+ return 0;
+ }
+ audit_log_format(ab, " obj=?");
+ error = audit_buffer_aux_new(ab, AUDIT_MAC_OBJ_CONTEXTS);
+ if (error)
+ goto error_path;
+
+ for (i = 0; i < audit_obj_secctx_cnt; i++) {
+ rc = security_lsmprop_to_secctx(prop, &ctx,
+ audit_obj_lsms[i]->id);
+ if (rc < 0) {
+ audit_log_format(ab, "%sobj_%s=?", space,
+ audit_obj_lsms[i]->name);
+ if (rc != -EINVAL)
+ audit_panic("error in audit_log_obj_ctx");
+ error = rc;
+ } else {
+ audit_log_format(ab, "%sobj_%s=%s", space,
+ audit_obj_lsms[i]->name, ctx.context);
+ security_release_secctx(&ctx);
+ }
+ space = " ";
+ }
+
+ audit_buffer_aux_end(ab);
+ return error;
+
+error_path:
+ audit_panic("error in audit_log_obj_ctx");
+ return error;
+}
+
void audit_log_d_path_exe(struct audit_buffer *ab,
struct mm_struct *mm)
{
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 84173d234d4a..0c28fa33d099 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1098,7 +1098,6 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
char *comm)
{
struct audit_buffer *ab;
- struct lsm_context ctx;
int rc = 0;
ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
@@ -1108,15 +1107,9 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid,
from_kuid(&init_user_ns, auid),
from_kuid(&init_user_ns, uid), sessionid);
- if (lsmprop_is_set(prop)) {
- if (security_lsmprop_to_secctx(prop, &ctx, LSM_ID_UNDEF) < 0) {
- audit_log_format(ab, " obj=(none)");
- rc = 1;
- } else {
- audit_log_format(ab, " obj=%s", ctx.context);
- security_release_secctx(&ctx);
- }
- }
+ if (lsmprop_is_set(prop) && audit_log_obj_ctx(ab, prop))
+ rc = 1;
+
audit_log_format(ab, " ocomm=");
audit_log_untrustedstring(ab, comm);
audit_log_end(ab);
@@ -1392,16 +1385,8 @@ static void show_special(struct audit_context *context, int *call_panic)
from_kgid(&init_user_ns, context->ipc.gid),
context->ipc.mode);
if (lsmprop_is_set(&context->ipc.oprop)) {
- struct lsm_context lsmctx;
-
- if (security_lsmprop_to_secctx(&context->ipc.oprop,
- &lsmctx,
- LSM_ID_UNDEF) < 0) {
+ if (audit_log_obj_ctx(ab, &context->ipc.oprop))
*call_panic = 1;
- } else {
- audit_log_format(ab, " obj=%s", lsmctx.context);
- security_release_secctx(&lsmctx);
- }
}
if (context->ipc.has_perm) {
audit_log_end(ab);
@@ -1558,18 +1543,9 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
from_kgid(&init_user_ns, n->gid),
MAJOR(n->rdev),
MINOR(n->rdev));
- if (lsmprop_is_set(&n->oprop)) {
- struct lsm_context ctx;
-
- if (security_lsmprop_to_secctx(&n->oprop, &ctx,
- LSM_ID_UNDEF) < 0) {
- if (call_panic)
- *call_panic = 2;
- } else {
- audit_log_format(ab, " obj=%s", ctx.context);
- security_release_secctx(&ctx);
- }
- }
+ if (lsmprop_is_set(&n->oprop) &&
+ audit_log_obj_ctx(ab, &n->oprop))
+ *call_panic = 2;
/* log the audit_names record type */
switch (n->type) {
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 81b66b4d9695..11cd452c970b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -7595,7 +7595,9 @@ static __init int selinux_init(void)
cred_init_security();
/* Inform the audit system that secctx is used */
- audit_cfg_lsm(&selinux_lsmid, AUDIT_CFG_LSM_SECCTX_SUBJECT);
+ audit_cfg_lsm(&selinux_lsmid,
+ AUDIT_CFG_LSM_SECCTX_SUBJECT |
+ AUDIT_CFG_LSM_SECCTX_OBJECT);
default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
if (!default_noexec)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 9a76821b7191..5fe4b53fa40b 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -5269,7 +5269,9 @@ static __init int smack_init(void)
init_smack_known_list();
/* Inform the audit system that secctx is used */
- audit_cfg_lsm(&smack_lsmid, AUDIT_CFG_LSM_SECCTX_SUBJECT);
+ audit_cfg_lsm(&smack_lsmid,
+ AUDIT_CFG_LSM_SECCTX_SUBJECT |
+ AUDIT_CFG_LSM_SECCTX_OBJECT);
return 0;
}
--
2.50.1
^ permalink raw reply related
* Re: [PATCH v5 0/5] Audit: Records for multiple security contexts
From: Casey Schaufler @ 2025-08-16 17:27 UTC (permalink / raw)
To: paul, eparis, linux-security-module, audit
Cc: jmorris, serge, keescook, john.johansen, penguin-kernel,
stephen.smalley.work, linux-kernel, selinux
In-Reply-To: <20250816164140.6045-1-casey@schaufler-ca.com>
Opps. script error. Please disregard.
On 8/16/2025 9:41 AM, Casey Schaufler wrote:
> The Linux audit system includes LSM based security "context" information
> in its events. Historically, only one LSM that uses security contexts can
> be active on a system. One of the few obsticles to allowing multiple LSM
> support is the inability to report more than one security context in an
> audit event. This patchset provides a mechanism to provide supplimental
> records containing more than one security context for subjects and
> objects.
>
> The mechanism for reporting multiple security contexts inspired
> considerable discussion. It would have been possible to add multiple
> contexts to existing records using sophisticated formatting. This would
> have significant backward compatibility issues, and require additional
> parsing in user space code. Adding new records for an event that contain
> the contexts is more in keeping with the way audit events have been
> constructed in the past.
>
> Only audit events associated with system calls have required multiple
> records prior to this. Mechanism has been added allowing any event
> to be composed of multiple records. This should make it easier to
> add information to existing audit events without breaking backward
> compatability.
>
> v5:
> Comment on the LSM_ID_UNDEF behavior in security_secid_to_secctx().
> Change some names to better reflect their purpose.
> Move alignment changes into a separate patch.
> v4:
> Use LSM_ID_UNDEF when checking for valid LSM IDs in
> security_lsmprop_to_secctx().
> Fix the object record to include only those for LSMs that use them.
> Squash the two patches dealing with subject contexts.
> Base the patches on Paul Moore's LSM initialization patchset.
> https://lore.kernel.org/all/20250409185019.238841-31-paul@paul-moore.com/
> v3:
> Rework how security modules identify that they provide security
> contexts to the audit system. Maintain a list within the audit
> system of the security modules that provide security contexts.
> Revert the separate counts of subject and object contexts.
> v2:
> Maintain separate counts for LSMs using subject contexts and object
> contexts. AppArmor uses the former but not the latter.
> Correct error handling in object record creation.
>
> https://github.com/cschaufler/lsm-stacking#audit-6.16-rc4-v5
>
> Casey Schaufler (5):
> Audit: Create audit_stamp structure
> LSM: security_lsmblob_to_secctx module selection
> Audit: Add record for multiple task security contexts
> Audit: Fix indentation in audit_log_exit
> Audit: Add record for multiple object contexts
>
> include/linux/audit.h | 23 +++
> include/linux/security.h | 6 +-
> include/uapi/linux/audit.h | 2 +
> kernel/audit.c | 274 ++++++++++++++++++++++++++++++-----
> kernel/audit.h | 13 +-
> kernel/auditsc.c | 65 +++------
> net/netlabel/netlabel_user.c | 8 +-
> security/apparmor/lsm.c | 3 +
> security/lsm.h | 4 -
> security/lsm_init.c | 5 -
> security/security.c | 21 ++-
> security/selinux/hooks.c | 5 +
> security/smack/smack_lsm.c | 5 +
> 13 files changed, 325 insertions(+), 109 deletions(-)
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox