diff options
| author | Paul Moore <paul@paul-moore.com> | 2026-10-16 17:01:58 -0400 |
|---|---|---|
| committer | Paul Moore <paul@paul-moore.com> | 2026-10-16 17:01:58 -0400 |
| commit | 436485132d2367a50aa22dcc8a89faeee24a4cc9 (patch) | |
| tree | f4c7cafad0ec42898880ea53ab0ecd2a7b147cde /security | |
| parent | fd73f4a6659897191fa0d40695fe370925dd3780 (diff) | |
| parent | 881f19c2ffbc73f351b257e09c71e6059939b770 (diff) | |
Automated merge of 'lsm/dev' into 'stable-7.4'
Manual merge fixup in ns_common_types.h:ns_common to work around a conflict
with the nsfs RCU grace period fix.
* lsm/dev:
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 'security')
| -rw-r--r-- | security/lsm_audit.c | 8 | ||||
| -rw-r--r-- | security/lsm_init.c | 9 | ||||
| -rw-r--r-- | security/security.c | 115 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 25 | ||||
| -rw-r--r-- | security/smack/smack_lsm.c | 9 |
5 files changed, 129 insertions, 37 deletions
diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 737f5a263a8f..955b2e7b2c8e 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c @@ -182,7 +182,7 @@ void audit_log_lsm_data(struct audit_buffer *ab, * start making this union too large! See struct lsm_network_audit * as an example of how to deal with large data. */ - BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2); + BUILD_BUG_ON(sizeof(a->u) > (sizeof(u64) * 2)); switch (a->type) { case LSM_AUDIT_DATA_NONE: @@ -231,7 +231,7 @@ void audit_log_lsm_data(struct audit_buffer *ab, audit_log_format(ab, " ino=%llu", inode->i_ino); } - audit_log_format(ab, " ioctlcmd=0x%hx", a->u.op->cmd); + audit_log_format(ab, " ioctlcmd=0x%x", a->u.op->cmd); break; } case LSM_AUDIT_DATA_DENTRY: { @@ -403,6 +403,10 @@ void audit_log_lsm_data(struct audit_buffer *ab, case LSM_AUDIT_DATA_NLMSGTYPE: audit_log_format(ab, " nl-msgtype=%hu", a->u.nlmsg_type); break; + case LSM_AUDIT_DATA_NS: + audit_log_format(ab, " namespace_type=0x%x namespace_id=%llu", + a->u.ns.ns_type, a->u.ns.ns_id); + break; } /* switch (a->type) */ } diff --git a/security/lsm_init.c b/security/lsm_init.c index a1ad641811de..8d5ecea99c46 100644 --- a/security/lsm_init.c +++ b/security/lsm_init.c @@ -290,7 +290,6 @@ static void __init lsm_prepare(struct lsm_info *lsm) return; /* Register the LSM blob sizes. */ - blobs = lsm->blobs; lsm_blob_size_update(&blobs->lbs_cred, &blob_sizes.lbs_cred); lsm_blob_size_update(&blobs->lbs_file, &blob_sizes.lbs_file); lsm_blob_size_update(&blobs->lbs_backing_file, @@ -303,6 +302,7 @@ static void __init lsm_prepare(struct lsm_info *lsm) lsm_blob_size_update(&blobs->lbs_ipc, &blob_sizes.lbs_ipc); lsm_blob_size_update(&blobs->lbs_key, &blob_sizes.lbs_key); lsm_blob_size_update(&blobs->lbs_msg_msg, &blob_sizes.lbs_msg_msg); + lsm_blob_size_update(&blobs->lbs_ns, &blob_sizes.lbs_ns); lsm_blob_size_update(&blobs->lbs_perf_event, &blob_sizes.lbs_perf_event); lsm_blob_size_update(&blobs->lbs_sock, &blob_sizes.lbs_sock); @@ -431,8 +431,7 @@ int __init security_init(void) } if (lsm_order_cmdline) { - if (lsm_order_legacy) - lsm_order_legacy = NULL; + lsm_order_legacy = NULL; lsm_order_parse(lsm_order_cmdline, "cmdline"); } else lsm_order_parse(lsm_order_builtin, "builtin"); @@ -450,6 +449,7 @@ int __init security_init(void) lsm_pr("blob(ipc) size %d\n", blob_sizes.lbs_ipc); lsm_pr("blob(key) size %d\n", blob_sizes.lbs_key); lsm_pr("blob(msg_msg)_size %d\n", blob_sizes.lbs_msg_msg); + lsm_pr("blob(ns) size %d\n", blob_sizes.lbs_ns); lsm_pr("blob(sock) size %d\n", blob_sizes.lbs_sock); lsm_pr("blob(superblock) size %d\n", blob_sizes.lbs_superblock); lsm_pr("blob(perf_event) size %d\n", blob_sizes.lbs_perf_event); @@ -476,8 +476,7 @@ int __init security_init(void) blob_sizes.lbs_inode, 0, SLAB_PANIC, NULL); - if (lsm_cred_alloc((struct cred *)unrcu_pointer(current->cred), - GFP_KERNEL)) + if (lsm_cred_alloc((struct cred *)current->cred, GFP_KERNEL)) panic("early LSM cred alloc failed\n"); if (lsm_task_alloc(current)) panic("early LSM task alloc failed\n"); diff --git a/security/security.c b/security/security.c index 2ee276ab15c5..7fa52d39a255 100644 --- a/security/security.c +++ b/security/security.c @@ -26,6 +26,7 @@ #include <linux/string.h> #include <linux/xattr.h> #include <linux/msg.h> +#include <linux/ns_common.h> #include <linux/overflow.h> #include <linux/perf_event.h> #include <linux/fs.h> @@ -382,6 +383,19 @@ static int lsm_superblock_alloc(struct super_block *sb) } /** + * lsm_ns_alloc - allocate a composite namespace blob + * @ns: the namespace that needs a blob + * + * Allocate the namespace blob for all the modules + * + * Returns 0, or -ENOMEM if memory can't be allocated. + */ +static int lsm_ns_alloc(struct ns_common *ns) +{ + return lsm_blob_alloc(&ns->ns_security, blob_sizes.lbs_ns, GFP_KERNEL); +} + +/** * lsm_fill_user_ctx - Fill a user space lsm_ctx structure * @uctx: a userspace LSM context to be filled * @uctx_len: available uctx size (input), used uctx size (output) @@ -1614,6 +1628,7 @@ int security_path_chroot(const struct path *path) /** * security_inode_create() - Check if creating a file is allowed + * @idmap: idmap of the mount * @dir: the parent directory * @dentry: the file being created * @mode: requested file mode @@ -1622,12 +1637,12 @@ int security_path_chroot(const struct path *path) * * Return: Returns 0 if permission is granted. */ -int security_inode_create(struct inode *dir, struct dentry *dentry, - umode_t mode) +int security_inode_create(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode) { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_create, dir, dentry, mode); + return call_int_hook(inode_create, idmap, dir, dentry, mode); } EXPORT_SYMBOL_GPL(security_inode_create); @@ -1648,6 +1663,7 @@ void security_inode_post_create_tmpfile(struct mnt_idmap *idmap, /** * security_inode_link() - Check if creating a hard link is allowed + * @idmap: idmap of the mount * @old_dentry: existing file * @dir: new parent directory * @new_dentry: new link @@ -1656,12 +1672,12 @@ void security_inode_post_create_tmpfile(struct mnt_idmap *idmap, * * Return: Returns 0 if permission is granted. */ -int security_inode_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry) +int security_inode_link(struct mnt_idmap *idmap, struct dentry *old_dentry, + struct inode *dir, struct dentry *new_dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)))) return 0; - return call_int_hook(inode_link, old_dentry, dir, new_dentry); + return call_int_hook(inode_link, idmap, old_dentry, dir, new_dentry); } /** @@ -1682,6 +1698,7 @@ int security_inode_unlink(struct inode *dir, struct dentry *dentry) /** * security_inode_symlink() - Check if creating a symbolic link is allowed + * @idmap: idmap of the mount * @dir: parent directory * @dentry: symbolic link * @old_name: existing filename @@ -1690,16 +1707,17 @@ int security_inode_unlink(struct inode *dir, struct dentry *dentry) * * Return: Returns 0 if permission is granted. */ -int security_inode_symlink(struct inode *dir, struct dentry *dentry, - const char *old_name) +int security_inode_symlink(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, const char *old_name) { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_symlink, dir, dentry, old_name); + return call_int_hook(inode_symlink, idmap, dir, dentry, old_name); } /** * security_inode_mkdir() - Check if creating a new directory is allowed + * @idmap: idmap of the mount * @dir: parent directory * @dentry: new directory * @mode: new directory mode @@ -1709,11 +1727,12 @@ int security_inode_symlink(struct inode *dir, struct dentry *dentry, * * Return: Returns 0 if permission is granted. */ -int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +int security_inode_mkdir(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode) { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_mkdir, dir, dentry, mode); + return call_int_hook(inode_mkdir, idmap, dir, dentry, mode); } EXPORT_SYMBOL_GPL(security_inode_mkdir); @@ -1735,6 +1754,7 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry) /** * security_inode_mknod() - Check if creating a special file is allowed + * @idmap: idmap of the mount * @dir: parent directory * @dentry: new file * @mode: new file mode @@ -1747,12 +1767,12 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry) * * Return: Returns 0 if permission is granted. */ -int security_inode_mknod(struct inode *dir, struct dentry *dentry, - umode_t mode, dev_t dev) +int security_inode_mknod(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode, dev_t dev) { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_mknod, dir, dentry, mode, dev); + return call_int_hook(inode_mknod, idmap, dir, dentry, mode, dev); } /** @@ -1823,6 +1843,7 @@ int security_inode_follow_link(struct dentry *dentry, struct inode *inode, /** * security_inode_permission() - Check if accessing an inode is allowed + * @idmap: idmap of the mount * @inode: inode * @mask: access mask * @@ -1835,11 +1856,12 @@ int security_inode_follow_link(struct dentry *dentry, struct inode *inode, * * Return: Returns 0 if permission is granted. */ -int security_inode_permission(struct inode *inode, int mask) +int security_inode_permission(struct mnt_idmap *idmap, struct inode *inode, + int mask) { if (unlikely(IS_PRIVATE(inode))) return 0; - return call_int_hook(inode_permission, inode, mask); + return call_int_hook(inode_permission, idmap, inode, mask); } /** @@ -2486,9 +2508,8 @@ void security_backing_file_free(struct file *backing_file) { void *blob = backing_file_security(backing_file); - call_void_hook(backing_file_free, backing_file); - if (blob) { + call_void_hook(backing_file_free, backing_file); backing_file_set_security(backing_file, NULL); kmem_cache_free(lsm_backing_file_cache, blob); } @@ -3358,6 +3379,64 @@ int security_create_user_ns(const struct cred *cred) } /** + * security_namespace_init() - Initialize LSM security data for a namespace + * @ns: the namespace being initialized + * + * Initialize the LSM security blob attached to the namespace. The namespace type + * is available via ns->ns_type, and the owning user namespace (if any) + * via ns->ops->owner(ns). + * + * Return: Returns 0 if successful, otherwise < 0 error code. + */ +int security_namespace_init(struct ns_common *ns) +{ + int rc; + + rc = lsm_ns_alloc(ns); + if (unlikely(rc)) + return rc; + + rc = call_int_hook(namespace_init, ns); + if (unlikely(rc)) + security_namespace_free(ns); + + return rc; +} + +/** + * security_namespace_free() - Release LSM security data from a namespace + * @ns: the namespace being freed + * + * Release security data attached to the namespace. Called before the + * namespace structure is freed. + */ +void security_namespace_free(struct ns_common *ns) +{ + if (!ns->ns_security) + return; + + call_void_hook(namespace_free, ns); + + kfree(ns->ns_security); + ns->ns_security = NULL; +} + +/** + * security_namespace_install() - Check permission to install a namespace + * @nsset: the target nsset being configured + * @ns: the namespace being installed + * + * Check permission before allowing a namespace to be installed into the + * process's set of namespaces via setns(2). + * + * Return: Returns 0 if permission is granted, otherwise < 0 error code. + */ +int security_namespace_install(const struct nsset *nsset, struct ns_common *ns) +{ + return call_int_hook(namespace_install, nsset, ns); +} + +/** * security_ipc_permission() - Check if sysv ipc access is allowed * @ipcp: ipc permission structure * @flag: requested permissions diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index e5e17f100aae..dd85351cbfc7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3074,12 +3074,14 @@ static int selinux_inode_init_security_anon(struct inode *inode, &ad); } -static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode) +static int selinux_inode_create(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode) { return may_create(dir, dentry, SECCLASS_FILE); } -static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) +static int selinux_inode_link(struct mnt_idmap *idmap, struct dentry *old_dentry, + struct inode *dir, struct dentry *new_dentry) { return may_link(dir, old_dentry, MAY_LINK); } @@ -3089,12 +3091,14 @@ static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) return may_link(dir, dentry, MAY_UNLINK); } -static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name) +static int selinux_inode_symlink(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, const char *name) { return may_create(dir, dentry, SECCLASS_LNK_FILE); } -static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask) +static int selinux_inode_mkdir(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mask) { return may_create(dir, dentry, SECCLASS_DIR); } @@ -3104,7 +3108,8 @@ static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry) return may_link(dir, dentry, MAY_RMDIR); } -static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) +static int selinux_inode_mknod(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode, dev_t dev) { return may_create(dir, dentry, inode_mode_to_security_class(mode)); } @@ -3236,13 +3241,15 @@ static inline void task_avdcache_update(struct task_security_struct *tsec, /** * selinux_inode_permission - Check if the current task can access an inode + * @idmap: idmap of the mount * @inode: the inode that is being accessed * @requested: the accesses being requested * * Check if the current task is allowed to access @inode according to * @requested. Returns 0 if allowed, negative values otherwise. */ -static int selinux_inode_permission(struct inode *inode, int requested) +static int selinux_inode_permission(struct mnt_idmap *idmap, + struct inode *inode, int requested) { int mask; u32 perms; @@ -3859,7 +3866,7 @@ static int selinux_backing_file_alloc(struct file *backing_file, * operation to an inode. */ static int ioctl_has_perm(const struct cred *cred, struct file *file, - u32 requested, u16 cmd) + u32 requested, unsigned int cmd) { struct common_audit_data ad; struct file_security_struct *fsec = selinux_file(file); @@ -3930,14 +3937,14 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, case FIOCLEX: case FIONCLEX: if (!selinux_policycap_ioctl_skip_cloexec()) - error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd); + error = ioctl_has_perm(cred, file, FILE__IOCTL, cmd); break; /* default case assumes that the command will go * to the file's ioctl() function. */ default: - error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd); + error = ioctl_has_perm(cred, file, FILE__IOCTL, cmd); } return error; } diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 8e88ac65fd7f..a45819d13c0d 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1089,14 +1089,15 @@ instant_inode: /** * smack_inode_link - Smack check on link + * @idmap: idmap of the mount * @old_dentry: the existing object * @dir: unused * @new_dentry: the new object * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry) +static int smack_inode_link(struct mnt_idmap *idmap, struct dentry *old_dentry, + struct inode *dir, struct dentry *new_dentry) { struct smack_known *isp; struct smk_audit_info ad; @@ -1226,6 +1227,7 @@ static int smack_inode_rename(struct inode *old_inode, /** * smack_inode_permission - Smack version of permission() + * @idmap: idmap of the mount * @inode: the inode in question * @mask: the access requested * @@ -1233,7 +1235,8 @@ static int smack_inode_rename(struct inode *old_inode, * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_permission(struct inode *inode, int mask) +static int smack_inode_permission(struct mnt_idmap *idmap, struct inode *inode, + int mask) { struct superblock_smack *sbsp = smack_superblock(inode->i_sb); struct smk_audit_info ad; |
