Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

LSM: syscalls for current process attributes

Create a system call lsm_get_self_attr() to provide the security
module maintained attributes of the current process.
Create a system call lsm_set_self_attr() to set a security
module maintained attribute of the current process.
Historically these attributes have been exposed to user space via
entries in procfs under /proc/self/attr.

The attribute value is provided in a lsm_ctx structure. The structure
identifies the size of the attribute, and the attribute value. The format
of the attribute value is defined by the security module. A flags field
is included for LSM specific information. It is currently unused and must
be 0. The total size of the data, including the lsm_ctx structure and any
padding, is maintained as well.

struct lsm_ctx {
__u64 id;
__u64 flags;
__u64 len;
__u64 ctx_len;
__u8 ctx[];
};

Two new LSM hooks are used to interface with the LSMs.
security_getselfattr() collects the lsm_ctx values from the
LSMs that support the hook, accounting for space requirements.
security_setselfattr() identifies which LSM the attribute is
intended for and passes it along.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Reviewed-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>

authored by

Casey Schaufler and committed by
Paul Moore
a04a1198 267c068e

+347
+70
Documentation/userspace-api/lsm.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. Copyright (C) 2022 Casey Schaufler <casey@schaufler-ca.com> 3 + .. Copyright (C) 2022 Intel Corporation 4 + 5 + ===================================== 6 + Linux Security Modules 7 + ===================================== 8 + 9 + :Author: Casey Schaufler 10 + :Date: July 2023 11 + 12 + Linux security modules (LSM) provide a mechanism to implement 13 + additional access controls to the Linux security policies. 14 + 15 + The various security modules may support any of these attributes: 16 + 17 + ``LSM_ATTR_CURRENT`` is the current, active security context of the 18 + process. 19 + The proc filesystem provides this value in ``/proc/self/attr/current``. 20 + This is supported by the SELinux, Smack and AppArmor security modules. 21 + Smack also provides this value in ``/proc/self/attr/smack/current``. 22 + AppArmor also provides this value in ``/proc/self/attr/apparmor/current``. 23 + 24 + ``LSM_ATTR_EXEC`` is the security context of the process at the time the 25 + current image was executed. 26 + The proc filesystem provides this value in ``/proc/self/attr/exec``. 27 + This is supported by the SELinux and AppArmor security modules. 28 + AppArmor also provides this value in ``/proc/self/attr/apparmor/exec``. 29 + 30 + ``LSM_ATTR_FSCREATE`` is the security context of the process used when 31 + creating file system objects. 32 + The proc filesystem provides this value in ``/proc/self/attr/fscreate``. 33 + This is supported by the SELinux security module. 34 + 35 + ``LSM_ATTR_KEYCREATE`` is the security context of the process used when 36 + creating key objects. 37 + The proc filesystem provides this value in ``/proc/self/attr/keycreate``. 38 + This is supported by the SELinux security module. 39 + 40 + ``LSM_ATTR_PREV`` is the security context of the process at the time the 41 + current security context was set. 42 + The proc filesystem provides this value in ``/proc/self/attr/prev``. 43 + This is supported by the SELinux and AppArmor security modules. 44 + AppArmor also provides this value in ``/proc/self/attr/apparmor/prev``. 45 + 46 + ``LSM_ATTR_SOCKCREATE`` is the security context of the process used when 47 + creating socket objects. 48 + The proc filesystem provides this value in ``/proc/self/attr/sockcreate``. 49 + This is supported by the SELinux security module. 50 + 51 + Kernel interface 52 + ================ 53 + 54 + Set a security attribute of the current process 55 + ----------------------------------------------- 56 + 57 + .. kernel-doc:: security/lsm_syscalls.c 58 + :identifiers: sys_lsm_set_self_attr 59 + 60 + Get the specified security attributes of the current process 61 + ------------------------------------------------------------ 62 + 63 + .. kernel-doc:: security/lsm_syscalls.c 64 + :identifiers: sys_lsm_get_self_attr 65 + 66 + Additional documentation 67 + ======================== 68 + 69 + * Documentation/security/lsm.rst 70 + * Documentation/security/lsm-development.rst
+4
include/linux/lsm_hook_defs.h
··· 262 262 LSM_HOOK(int, 0, netlink_send, struct sock *sk, struct sk_buff *skb) 263 263 LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry, 264 264 struct inode *inode) 265 + LSM_HOOK(int, -EOPNOTSUPP, getselfattr, unsigned int attr, 266 + struct lsm_ctx __user *ctx, size_t *size, u32 flags) 267 + LSM_HOOK(int, -EOPNOTSUPP, setselfattr, unsigned int attr, 268 + struct lsm_ctx *ctx, size_t size, u32 flags) 265 269 LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name, 266 270 char **value) 267 271 LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size)
+1
include/linux/lsm_hooks.h
··· 25 25 #ifndef __LINUX_LSM_HOOKS_H 26 26 #define __LINUX_LSM_HOOKS_H 27 27 28 + #include <uapi/linux/lsm.h> 28 29 #include <linux/security.h> 29 30 #include <linux/init.h> 30 31 #include <linux/rculist.h>
+19
include/linux/security.h
··· 60 60 enum fs_value_type; 61 61 struct watch; 62 62 struct watch_notification; 63 + struct lsm_ctx; 63 64 64 65 /* Default (no) options for the capable function */ 65 66 #define CAP_OPT_NONE 0x0 ··· 473 472 int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, 474 473 unsigned nsops, int alter); 475 474 void security_d_instantiate(struct dentry *dentry, struct inode *inode); 475 + int security_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, 476 + size_t __user *size, u32 flags); 477 + int security_setselfattr(unsigned int attr, struct lsm_ctx __user *ctx, 478 + size_t size, u32 flags); 476 479 int security_getprocattr(struct task_struct *p, int lsmid, const char *name, 477 480 char **value); 478 481 int security_setprocattr(int lsmid, const char *name, void *value, size_t size); ··· 1342 1337 static inline void security_d_instantiate(struct dentry *dentry, 1343 1338 struct inode *inode) 1344 1339 { } 1340 + 1341 + static inline int security_getselfattr(unsigned int attr, 1342 + struct lsm_ctx __user *ctx, 1343 + size_t __user *size, u32 flags) 1344 + { 1345 + return -EOPNOTSUPP; 1346 + } 1347 + 1348 + static inline int security_setselfattr(unsigned int attr, 1349 + struct lsm_ctx __user *ctx, 1350 + size_t size, u32 flags) 1351 + { 1352 + return -EOPNOTSUPP; 1353 + } 1345 1354 1346 1355 static inline int security_getprocattr(struct task_struct *p, int lsmid, 1347 1356 const char *name, char **value)
+5
include/linux/syscalls.h
··· 71 71 struct open_how; 72 72 struct mount_attr; 73 73 struct landlock_ruleset_attr; 74 + struct lsm_ctx; 74 75 enum landlock_rule_type; 75 76 struct cachestat_range; 76 77 struct cachestat; ··· 950 949 struct cachestat_range __user *cstat_range, 951 950 struct cachestat __user *cstat, unsigned int flags); 952 951 asmlinkage long sys_map_shadow_stack(unsigned long addr, unsigned long size, unsigned int flags); 952 + asmlinkage long sys_lsm_get_self_attr(unsigned int attr, struct lsm_ctx *ctx, 953 + size_t *size, __u32 flags); 954 + asmlinkage long sys_lsm_set_self_attr(unsigned int attr, struct lsm_ctx *ctx, 955 + size_t size, __u32 flags); 953 956 954 957 /* 955 958 * Architecture-specific system calls
+36
include/uapi/linux/lsm.h
··· 9 9 #ifndef _UAPI_LINUX_LSM_H 10 10 #define _UAPI_LINUX_LSM_H 11 11 12 + #include <linux/types.h> 13 + #include <linux/unistd.h> 14 + 15 + /** 16 + * struct lsm_ctx - LSM context information 17 + * @id: the LSM id number, see LSM_ID_XXX 18 + * @flags: LSM specific flags 19 + * @len: length of the lsm_ctx struct, @ctx and any other data or padding 20 + * @ctx_len: the size of @ctx 21 + * @ctx: the LSM context value 22 + * 23 + * The @len field MUST be equal to the size of the lsm_ctx struct 24 + * plus any additional padding and/or data placed after @ctx. 25 + * 26 + * In all cases @ctx_len MUST be equal to the length of @ctx. 27 + * If @ctx is a string value it should be nul terminated with 28 + * @ctx_len equal to `strlen(@ctx) + 1`. Binary values are 29 + * supported. 30 + * 31 + * The @flags and @ctx fields SHOULD only be interpreted by the 32 + * LSM specified by @id; they MUST be set to zero/0 when not used. 33 + */ 34 + struct lsm_ctx { 35 + __u64 id; 36 + __u64 flags; 37 + __u64 len; 38 + __u64 ctx_len; 39 + __u8 ctx[]; 40 + }; 41 + 12 42 /* 13 43 * ID tokens to identify Linux Security Modules (LSMs) 14 44 * ··· 80 50 #define LSM_ATTR_KEYCREATE 103 81 51 #define LSM_ATTR_PREV 104 82 52 #define LSM_ATTR_SOCKCREATE 105 53 + 54 + /* 55 + * LSM_FLAG_XXX definitions identify special handling instructions 56 + * for the API. 57 + */ 58 + #define LSM_FLAG_SINGLE 0x0001 83 59 84 60 #endif /* _UAPI_LINUX_LSM_H */
+2
kernel/sys_ni.c
··· 171 171 COND_SYSCALL(landlock_restrict_self); 172 172 COND_SYSCALL(fadvise64_64); 173 173 COND_SYSCALL_COMPAT(fadvise64_64); 174 + COND_SYSCALL(lsm_get_self_attr); 175 + COND_SYSCALL(lsm_set_self_attr); 174 176 175 177 /* CONFIG_MMU only */ 176 178 COND_SYSCALL(swapon);
+1
security/Makefile
··· 7 7 8 8 # always enable default capabilities 9 9 obj-y += commoncap.o 10 + obj-$(CONFIG_SECURITY) += lsm_syscalls.o 10 11 obj-$(CONFIG_MMU) += min_addr.o 11 12 12 13 # Object file lists
+57
security/lsm_syscalls.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * System calls implementing the Linux Security Module API. 4 + * 5 + * Copyright (C) 2022 Casey Schaufler <casey@schaufler-ca.com> 6 + * Copyright (C) 2022 Intel Corporation 7 + */ 8 + 9 + #include <asm/current.h> 10 + #include <linux/compiler_types.h> 11 + #include <linux/err.h> 12 + #include <linux/errno.h> 13 + #include <linux/security.h> 14 + #include <linux/stddef.h> 15 + #include <linux/syscalls.h> 16 + #include <linux/types.h> 17 + #include <linux/lsm_hooks.h> 18 + #include <uapi/linux/lsm.h> 19 + 20 + /** 21 + * sys_lsm_set_self_attr - Set current task's security module attribute 22 + * @attr: which attribute to set 23 + * @ctx: the LSM contexts 24 + * @size: size of @ctx 25 + * @flags: reserved for future use 26 + * 27 + * Sets the calling task's LSM context. On success this function 28 + * returns 0. If the attribute specified cannot be set a negative 29 + * value indicating the reason for the error is returned. 30 + */ 31 + SYSCALL_DEFINE4(lsm_set_self_attr, unsigned int, attr, struct lsm_ctx __user *, 32 + ctx, size_t, size, u32, flags) 33 + { 34 + return security_setselfattr(attr, ctx, size, flags); 35 + } 36 + 37 + /** 38 + * sys_lsm_get_self_attr - Return current task's security module attributes 39 + * @attr: which attribute to return 40 + * @ctx: the user-space destination for the information, or NULL 41 + * @size: pointer to the size of space available to receive the data 42 + * @flags: special handling options. LSM_FLAG_SINGLE indicates that only 43 + * attributes associated with the LSM identified in the passed @ctx be 44 + * reported. 45 + * 46 + * Returns the calling task's LSM contexts. On success this 47 + * function returns the number of @ctx array elements. This value 48 + * may be zero if there are no LSM contexts assigned. If @size is 49 + * insufficient to contain the return data -E2BIG is returned and 50 + * @size is set to the minimum required size. In all other cases 51 + * a negative value indicating the error is returned. 52 + */ 53 + SYSCALL_DEFINE4(lsm_get_self_attr, unsigned int, attr, struct lsm_ctx __user *, 54 + ctx, size_t __user *, size, u32, flags) 55 + { 56 + return security_getselfattr(attr, ctx, size, flags); 57 + }
+152
security/security.c
··· 3837 3837 } 3838 3838 EXPORT_SYMBOL(security_d_instantiate); 3839 3839 3840 + /* 3841 + * Please keep this in sync with it's counterpart in security/lsm_syscalls.c 3842 + */ 3843 + 3844 + /** 3845 + * security_getselfattr - Read an LSM attribute of the current process. 3846 + * @attr: which attribute to return 3847 + * @uctx: the user-space destination for the information, or NULL 3848 + * @size: pointer to the size of space available to receive the data 3849 + * @flags: special handling options. LSM_FLAG_SINGLE indicates that only 3850 + * attributes associated with the LSM identified in the passed @ctx be 3851 + * reported. 3852 + * 3853 + * A NULL value for @uctx can be used to get both the number of attributes 3854 + * and the size of the data. 3855 + * 3856 + * Returns the number of attributes found on success, negative value 3857 + * on error. @size is reset to the total size of the data. 3858 + * If @size is insufficient to contain the data -E2BIG is returned. 3859 + */ 3860 + int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx, 3861 + size_t __user *size, u32 flags) 3862 + { 3863 + struct security_hook_list *hp; 3864 + struct lsm_ctx lctx = { .id = LSM_ID_UNDEF, }; 3865 + u8 __user *base = (u8 __user *)uctx; 3866 + size_t total = 0; 3867 + size_t entrysize; 3868 + size_t left; 3869 + bool toobig = false; 3870 + bool single = false; 3871 + int count = 0; 3872 + int rc; 3873 + 3874 + if (attr == LSM_ATTR_UNDEF) 3875 + return -EINVAL; 3876 + if (size == NULL) 3877 + return -EINVAL; 3878 + if (get_user(left, size)) 3879 + return -EFAULT; 3880 + 3881 + if (flags) { 3882 + /* 3883 + * Only flag supported is LSM_FLAG_SINGLE 3884 + */ 3885 + if (flags != LSM_FLAG_SINGLE) 3886 + return -EINVAL; 3887 + if (uctx && copy_from_user(&lctx, uctx, sizeof(lctx))) 3888 + return -EFAULT; 3889 + /* 3890 + * If the LSM ID isn't specified it is an error. 3891 + */ 3892 + if (lctx.id == LSM_ID_UNDEF) 3893 + return -EINVAL; 3894 + single = true; 3895 + } 3896 + 3897 + /* 3898 + * In the usual case gather all the data from the LSMs. 3899 + * In the single case only get the data from the LSM specified. 3900 + */ 3901 + hlist_for_each_entry(hp, &security_hook_heads.getselfattr, list) { 3902 + if (single && lctx.id != hp->lsmid->id) 3903 + continue; 3904 + entrysize = left; 3905 + if (base) 3906 + uctx = (struct lsm_ctx __user *)(base + total); 3907 + rc = hp->hook.getselfattr(attr, uctx, &entrysize, flags); 3908 + if (rc == -EOPNOTSUPP) { 3909 + rc = 0; 3910 + continue; 3911 + } 3912 + if (rc == -E2BIG) { 3913 + toobig = true; 3914 + left = 0; 3915 + } else if (rc < 0) 3916 + return rc; 3917 + else 3918 + left -= entrysize; 3919 + 3920 + total += entrysize; 3921 + count += rc; 3922 + if (single) 3923 + break; 3924 + } 3925 + if (put_user(total, size)) 3926 + return -EFAULT; 3927 + if (toobig) 3928 + return -E2BIG; 3929 + if (count == 0) 3930 + return LSM_RET_DEFAULT(getselfattr); 3931 + return count; 3932 + } 3933 + 3934 + /* 3935 + * Please keep this in sync with it's counterpart in security/lsm_syscalls.c 3936 + */ 3937 + 3938 + /** 3939 + * security_setselfattr - Set an LSM attribute on the current process. 3940 + * @attr: which attribute to set 3941 + * @uctx: the user-space source for the information 3942 + * @size: the size of the data 3943 + * @flags: reserved for future use, must be 0 3944 + * 3945 + * Set an LSM attribute for the current process. The LSM, attribute 3946 + * and new value are included in @uctx. 3947 + * 3948 + * Returns 0 on success, -EINVAL if the input is inconsistent, -EFAULT 3949 + * if the user buffer is inaccessible, E2BIG if size is too big, or an 3950 + * LSM specific failure. 3951 + */ 3952 + int security_setselfattr(unsigned int attr, struct lsm_ctx __user *uctx, 3953 + size_t size, u32 flags) 3954 + { 3955 + struct security_hook_list *hp; 3956 + struct lsm_ctx *lctx; 3957 + int rc = LSM_RET_DEFAULT(setselfattr); 3958 + 3959 + if (flags) 3960 + return -EINVAL; 3961 + if (size < sizeof(*lctx)) 3962 + return -EINVAL; 3963 + if (size > PAGE_SIZE) 3964 + return -E2BIG; 3965 + 3966 + lctx = kmalloc(size, GFP_KERNEL); 3967 + if (lctx == NULL) 3968 + return -ENOMEM; 3969 + 3970 + if (copy_from_user(lctx, uctx, size)) { 3971 + rc = -EFAULT; 3972 + goto free_out; 3973 + } 3974 + 3975 + if (size < lctx->len || size < lctx->ctx_len + sizeof(*lctx) || 3976 + lctx->len < lctx->ctx_len + sizeof(*lctx)) { 3977 + rc = -EINVAL; 3978 + goto free_out; 3979 + } 3980 + 3981 + hlist_for_each_entry(hp, &security_hook_heads.setselfattr, list) 3982 + if ((hp->lsmid->id) == lctx->id) { 3983 + rc = hp->hook.setselfattr(attr, lctx, size, flags); 3984 + break; 3985 + } 3986 + 3987 + free_out: 3988 + kfree(lctx); 3989 + return rc; 3990 + } 3991 + 3840 3992 /** 3841 3993 * security_getprocattr() - Read an attribute for a task 3842 3994 * @p: the task