summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-10-20 20:04:07 -1000
committerLinus Torvalds <torvalds@linux-foundation.org>2026-10-20 20:04:07 -1000
commita804c5742bff224d4cb4d25dd383554d598be32b (patch)
tree9ed21d8b340428f13f26485f2d0c5085445d8cdf /include
parent331eadd85f14bac85663c14c99228f6dedf64d87 (diff)
parent436485132d2367a50aa22dcc8a89faeee24a4cc9 (diff)
Merge tag 'lsm-pr-20261016' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm
Pull lsm updates from Paul Moore: - Add LSM hooks, object blobs, and audit records for namespaces Add the necessary bits to enable LSMs to enforce access controls on the management of various kernel namespaces. While this pull request does not contain any in-tree users of these hooks, the Landlock pull request for Linux v7.4 will include Landlock support and the next merge window will likely include SELinux support as well. Considering the development behind these hooks, I expect that BPF LSM developers will also be making use of the namespace hooks, if they haven't already. - Update the inode LSM hooks to include mount idmaps This allows LSMs to incorporate the mount ID mapping into their access control decisions. While there are no current in-tree users of this, it was requested by those developing BPF LSM programs and this pull request includes a BPF LSM selftest. - Preserve the full 32-bit ioctl command in LSM audit records Previously only the low 16 bits were logged, ignoring the direction and size information in the upper 16 bits. The pull request also includes a Landlock based selftest to verify the full 32-bit ioctl value. - Ensure we don't call security_backing_file_free() multiple times Thankfully we don't have a problem with the current code base, but we want to fix this behavior now before it becomes a problem. - Clarify that only the current task may access current->cred The current code is a bit misleading around safely accessing the cred field in a task struct. Through comment and code corrections, this pull request clarifies that only the task itself may access its cred field. - Add SLAB_NO_MERGE to the credential object cache Harden the credential cache by ensuring credential objects live on dedicated slab pages. - Make use of safe memory zero'ing in the LSM Rust bindings - Update the docs for the current behavior of /sys/kernel/security/lsm - Update the docs for CONFIG_LSM and the "lsm=" command line option - Remove unnecessary code * tag 'lsm-pr-20261016' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm: lsm: remove redundant NULL check in security_init() selftests/landlock: Check full ioctl commands in audit records lsm: Preserve full ioctl commands in audit records doc: fix LSM ordering description for /sys/kernel/security/lsm doc: describe CONFIG_LSM and lsm= as the selection mechanism selftests/bpf: verify mount idmaps reach inode hooks lsm: expose mount idmaps to inode hooks rust: lsm: replace `core::mem::zeroed` with `pin_init::zeroed` cred: prevent slab cache merging for cred_jar lsm: don't call security_backing_file_free() multiple times lsm: delete duplicate assignment in lsm_prepare() lsm: update the BUILD_BUG_ON() in audit_log_lsm_data() lsm: add LSM_AUDIT_DATA_NS for namespace audit records lsm: add LSM blob and hooks for namespaces ns: Free anonymous mount namespaces via ns_common_free() cred: clarify that task_struct::cred is only for the current task
Diffstat (limited to 'include')
-rw-r--r--include/linux/cred.h17
-rw-r--r--include/linux/lsm_audit.h7
-rw-r--r--include/linux/lsm_hook_defs.h26
-rw-r--r--include/linux/lsm_hooks.h1
-rw-r--r--include/linux/ns/ns_common_types.h3
-rw-r--r--include/linux/sched.h8
-rw-r--r--include/linux/security.h78
-rw-r--r--include/uapi/linux/nsfs.h1
8 files changed, 97 insertions, 44 deletions
diff --git a/include/linux/cred.h b/include/linux/cred.h
index 6ef1750c93e2..49c26af37349 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -180,12 +180,18 @@ static inline bool cap_ambient_invariant_ok(const struct cred *cred)
static inline const struct cred *override_creds(const struct cred *override_cred)
{
- return rcu_replace_pointer(current->cred, override_cred, 1);
+ const struct cred *old = current->cred;
+
+ current->cred = override_cred;
+ return old;
}
static inline const struct cred *revert_creds(const struct cred *revert_cred)
{
- return rcu_replace_pointer(current->cred, revert_cred, 1);
+ const struct cred *override_cred = current->cred;
+
+ current->cred = revert_cred;
+ return override_cred;
}
DEFINE_CLASS(override_creds,
@@ -293,11 +299,10 @@ DEFINE_FREE(put_cred, struct cred *, if (!IS_ERR_OR_NULL(_T)) put_cred(_T))
/**
* current_cred - Access the current task's subjective credentials
*
- * Access the subjective credentials of the current task. RCU-safe,
- * since nobody else can modify it.
+ * Access the subjective credentials of the current task.
+ * Nobody else can modify it.
*/
-#define current_cred() \
- rcu_dereference_protected(current->cred, 1)
+#define current_cred() (current->cred)
/**
* current_real_cred - Access the current task's objective credentials
diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index 584db296e43b..5cf0b4795065 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -44,7 +44,7 @@ struct lsm_network_audit {
struct lsm_ioctlop_audit {
struct path path;
- u16 cmd;
+ unsigned int cmd;
};
struct lsm_ibpkey_audit {
@@ -78,6 +78,7 @@ struct common_audit_data {
#define LSM_AUDIT_DATA_NOTIFICATION 16
#define LSM_AUDIT_DATA_ANONINODE 17
#define LSM_AUDIT_DATA_NLMSGTYPE 18
+#define LSM_AUDIT_DATA_NS 19
union {
struct path path;
struct dentry *dentry;
@@ -100,6 +101,10 @@ struct common_audit_data {
int reason;
const char *anonclass;
u16 nlmsg_type;
+ struct {
+ u32 ns_type;
+ u64 ns_id;
+ } ns;
} u;
/* this union contains LSM specific data */
union {
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 194084f60746..87d9d06710cb 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -120,26 +120,27 @@ LSM_HOOK(int, -EOPNOTSUPP, inode_init_security, struct inode *inode,
int *xattr_count)
LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode,
const struct qstr *name, const struct inode *context_inode)
-LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry,
- umode_t mode)
+LSM_HOOK(int, 0, inode_create, const struct mnt_idmap *idmap, struct inode *dir,
+ struct dentry *dentry, umode_t mode)
LSM_HOOK(void, LSM_RET_VOID, inode_post_create_tmpfile, const struct mnt_idmap *idmap,
struct inode *inode)
-LSM_HOOK(int, 0, inode_link, struct dentry *old_dentry, struct inode *dir,
- struct dentry *new_dentry)
+LSM_HOOK(int, 0, inode_link, const struct mnt_idmap *idmap,
+ struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
LSM_HOOK(int, 0, inode_unlink, struct inode *dir, struct dentry *dentry)
-LSM_HOOK(int, 0, inode_symlink, struct inode *dir, struct dentry *dentry,
- const char *old_name)
-LSM_HOOK(int, 0, inode_mkdir, struct inode *dir, struct dentry *dentry,
- umode_t mode)
+LSM_HOOK(int, 0, inode_symlink, const struct mnt_idmap *idmap, struct inode *dir,
+ struct dentry *dentry, const char *old_name)
+LSM_HOOK(int, 0, inode_mkdir, const struct mnt_idmap *idmap, struct inode *dir,
+ struct dentry *dentry, umode_t mode)
LSM_HOOK(int, 0, inode_rmdir, struct inode *dir, struct dentry *dentry)
-LSM_HOOK(int, 0, inode_mknod, struct inode *dir, struct dentry *dentry,
- umode_t mode, dev_t dev)
+LSM_HOOK(int, 0, inode_mknod, const struct mnt_idmap *idmap, struct inode *dir,
+ struct dentry *dentry, umode_t mode, dev_t dev)
LSM_HOOK(int, 0, inode_rename, struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
LSM_HOOK(int, 0, inode_readlink, struct dentry *dentry)
LSM_HOOK(int, 0, inode_follow_link, struct dentry *dentry, struct inode *inode,
bool rcu)
-LSM_HOOK(int, 0, inode_permission, struct inode *inode, int mask)
+LSM_HOOK(int, 0, inode_permission, const struct mnt_idmap *idmap,
+ struct inode *inode, int mask)
LSM_HOOK(int, 0, inode_setattr, const struct mnt_idmap *idmap, struct dentry *dentry,
struct iattr *attr)
LSM_HOOK(void, LSM_RET_VOID, inode_post_setattr, const struct mnt_idmap *idmap,
@@ -265,6 +266,9 @@ LSM_HOOK(int, -ENOSYS, task_prctl, int option, unsigned long arg2,
LSM_HOOK(void, LSM_RET_VOID, task_to_inode, struct task_struct *p,
struct inode *inode)
LSM_HOOK(int, 0, userns_create, const struct cred *cred)
+LSM_HOOK(int, 0, namespace_init, struct ns_common *ns)
+LSM_HOOK(void, LSM_RET_VOID, namespace_free, struct ns_common *ns)
+LSM_HOOK(int, 0, namespace_install, const struct nsset *nsset, struct ns_common *ns)
LSM_HOOK(int, 0, ipc_permission, struct kern_ipc_perm *ipcp, short flag)
LSM_HOOK(void, LSM_RET_VOID, ipc_getlsmprop, struct kern_ipc_perm *ipcp,
struct lsm_prop *prop)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index c4488c4a6d8a..13621e9e233e 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -112,6 +112,7 @@ struct lsm_blob_sizes {
unsigned int lbs_ipc;
unsigned int lbs_key;
unsigned int lbs_msg_msg;
+ unsigned int lbs_ns;
unsigned int lbs_perf_event;
unsigned int lbs_task;
unsigned int lbs_xattr_count; /* num xattr slots in new_xattrs array */
diff --git a/include/linux/ns/ns_common_types.h b/include/linux/ns/ns_common_types.h
index 6ed6b497831c..47a5cfe2326a 100644
--- a/include/linux/ns/ns_common_types.h
+++ b/include/linux/ns/ns_common_types.h
@@ -116,6 +116,9 @@ struct ns_common {
struct dentry *stashed;
const struct proc_ns_operations *ops;
unsigned int inum;
+#ifdef CONFIG_SECURITY
+ void *ns_security;
+#endif
struct ns_tree;
struct rcu_head ns_rcu;
};
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 93ab9b6bec3e..12a7e094a3e6 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1173,8 +1173,12 @@ struct task_struct {
/* Objective and real subjective task credentials (COW): */
const struct cred __rcu *real_cred;
- /* Effective (overridable) subjective task credentials (COW): */
- const struct cred __rcu *cred;
+ /*
+ * Effective (overridable) subjective task credentials (COW).
+ * Only accessible for the current task and during task creation/freeing.
+ * This pointer is not managed by RCU!
+ */
+ const struct cred *cred;
#ifdef CONFIG_KEYS
/* Cached requested key. */
diff --git a/include/linux/security.h b/include/linux/security.h
index c7691feb8f8e..40831fab5470 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -67,6 +67,7 @@ enum fs_value_type;
struct watch;
struct watch_notification;
struct lsm_ctx;
+struct nsset;
/* Default (no) options for the capable function */
#define CAP_OPT_NONE 0x0
@@ -80,6 +81,7 @@ struct lsm_ctx;
struct ctl_table;
struct audit_krule;
+struct ns_common;
struct user_namespace;
struct timezone;
@@ -404,24 +406,28 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
int security_inode_init_security_anon(struct inode *inode,
const struct qstr *name,
const struct inode *context_inode);
-int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode);
+int security_inode_create(const struct mnt_idmap *idmap, struct inode *dir,
+ struct dentry *dentry, umode_t mode);
void security_inode_post_create_tmpfile(const struct mnt_idmap *idmap,
struct inode *inode);
-int security_inode_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *new_dentry);
+int security_inode_link(const struct mnt_idmap *idmap, struct dentry *old_dentry,
+ struct inode *dir, struct dentry *new_dentry);
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
-int security_inode_symlink(struct inode *dir, struct dentry *dentry,
- const char *old_name);
-int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
+int security_inode_symlink(const struct mnt_idmap *idmap, struct inode *dir,
+ struct dentry *dentry, const char *old_name);
+int security_inode_mkdir(const struct mnt_idmap *idmap, struct inode *dir,
+ struct dentry *dentry, umode_t mode);
int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
-int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev);
+int security_inode_mknod(const struct mnt_idmap *idmap, struct inode *dir,
+ struct dentry *dentry, umode_t mode, dev_t dev);
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags);
int security_inode_readlink(struct dentry *dentry);
int security_inode_follow_link(struct dentry *dentry, struct inode *inode,
bool rcu);
-int security_inode_permission(struct inode *inode, int mask);
+int security_inode_permission(const struct mnt_idmap *idmap,
+ struct inode *inode, int mask);
int security_inode_setattr(const struct mnt_idmap *idmap,
struct dentry *dentry, struct iattr *attr);
void security_inode_post_setattr(const struct mnt_idmap *idmap, struct dentry *dentry,
@@ -540,6 +546,9 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5);
void security_task_to_inode(struct task_struct *p, struct inode *inode);
int security_create_user_ns(const struct cred *cred);
+int security_namespace_init(struct ns_common *ns);
+void security_namespace_free(struct ns_common *ns);
+int security_namespace_install(const struct nsset *nsset, struct ns_common *ns);
int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag);
void security_ipc_getlsmprop(struct kern_ipc_perm *ipcp, struct lsm_prop *prop);
int security_msg_msg_alloc(struct msg_msg *msg);
@@ -902,9 +911,10 @@ static inline int security_inode_init_security_anon(struct inode *inode,
return 0;
}
-static inline int security_inode_create(struct inode *dir,
- struct dentry *dentry,
- umode_t mode)
+static inline int security_inode_create(const struct mnt_idmap *idmap,
+ struct inode *dir,
+ struct dentry *dentry,
+ umode_t mode)
{
return 0;
}
@@ -913,9 +923,10 @@ static inline void
security_inode_post_create_tmpfile(const struct mnt_idmap *idmap, struct inode *inode)
{ }
-static inline int security_inode_link(struct dentry *old_dentry,
- struct inode *dir,
- struct dentry *new_dentry)
+static inline int security_inode_link(const struct mnt_idmap *idmap,
+ struct dentry *old_dentry,
+ struct inode *dir,
+ struct dentry *new_dentry)
{
return 0;
}
@@ -926,16 +937,18 @@ static inline int security_inode_unlink(struct inode *dir,
return 0;
}
-static inline int security_inode_symlink(struct inode *dir,
- struct dentry *dentry,
- const char *old_name)
+static inline int security_inode_symlink(const struct mnt_idmap *idmap,
+ struct inode *dir,
+ struct dentry *dentry,
+ const char *old_name)
{
return 0;
}
-static inline int security_inode_mkdir(struct inode *dir,
- struct dentry *dentry,
- int mode)
+static inline int security_inode_mkdir(const struct mnt_idmap *idmap,
+ struct inode *dir,
+ struct dentry *dentry,
+ int mode)
{
return 0;
}
@@ -946,9 +959,10 @@ static inline int security_inode_rmdir(struct inode *dir,
return 0;
}
-static inline int security_inode_mknod(struct inode *dir,
- struct dentry *dentry,
- int mode, dev_t dev)
+static inline int security_inode_mknod(const struct mnt_idmap *idmap,
+ struct inode *dir,
+ struct dentry *dentry,
+ int mode, dev_t dev)
{
return 0;
}
@@ -974,7 +988,8 @@ static inline int security_inode_follow_link(struct dentry *dentry,
return 0;
}
-static inline int security_inode_permission(struct inode *inode, int mask)
+static inline int security_inode_permission(const struct mnt_idmap *idmap,
+ struct inode *inode, int mask)
{
return 0;
}
@@ -1431,6 +1446,21 @@ static inline int security_create_user_ns(const struct cred *cred)
return 0;
}
+static inline int security_namespace_init(struct ns_common *ns)
+{
+ return 0;
+}
+
+static inline void security_namespace_free(struct ns_common *ns)
+{
+}
+
+static inline int security_namespace_install(const struct nsset *nsset,
+ struct ns_common *ns)
+{
+ return 0;
+}
+
static inline int security_ipc_permission(struct kern_ipc_perm *ipcp,
short flag)
{
diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h
index 007fed5971b4..e5909266ec3f 100644
--- a/include/uapi/linux/nsfs.h
+++ b/include/uapi/linux/nsfs.h
@@ -55,6 +55,7 @@ enum init_ns_ino {
MNT_NS_INIT_INO = 0xEFFFFFF8U,
#ifdef __KERNEL__
MNT_NS_ANON_INO = 0xEFFFFFF7U,
+ MNT_NS_INO_SPECIAL_MAX = MNT_NS_ANON_INO,
#endif
};