forked from mirrors/linux
		
	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>
			
			
This commit is contained in:
		
							parent
							
								
									267c068e5f
								
							
						
					
					
						commit
						a04a119808
					
				
					 10 changed files with 347 additions and 0 deletions
				
			
		
							
								
								
									
										70
									
								
								Documentation/userspace-api/lsm.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								Documentation/userspace-api/lsm.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,70 @@ | ||||||
|  | .. SPDX-License-Identifier: GPL-2.0 | ||||||
|  | .. Copyright (C) 2022 Casey Schaufler <casey@schaufler-ca.com> | ||||||
|  | .. Copyright (C) 2022 Intel Corporation | ||||||
|  | 
 | ||||||
|  | ===================================== | ||||||
|  | Linux Security Modules | ||||||
|  | ===================================== | ||||||
|  | 
 | ||||||
|  | :Author: Casey Schaufler | ||||||
|  | :Date: July 2023 | ||||||
|  | 
 | ||||||
|  | Linux security modules (LSM) provide a mechanism to implement | ||||||
|  | additional access controls to the Linux security policies. | ||||||
|  | 
 | ||||||
|  | The various security modules may support any of these attributes: | ||||||
|  | 
 | ||||||
|  | ``LSM_ATTR_CURRENT`` is the current, active security context of the | ||||||
|  | process. | ||||||
|  | The proc filesystem provides this value in ``/proc/self/attr/current``. | ||||||
|  | This is supported by the SELinux, Smack and AppArmor security modules. | ||||||
|  | Smack also provides this value in ``/proc/self/attr/smack/current``. | ||||||
|  | AppArmor also provides this value in ``/proc/self/attr/apparmor/current``. | ||||||
|  | 
 | ||||||
|  | ``LSM_ATTR_EXEC`` is the security context of the process at the time the | ||||||
|  | current image was executed. | ||||||
|  | The proc filesystem provides this value in ``/proc/self/attr/exec``. | ||||||
|  | This is supported by the SELinux and AppArmor security modules. | ||||||
|  | AppArmor also provides this value in ``/proc/self/attr/apparmor/exec``. | ||||||
|  | 
 | ||||||
|  | ``LSM_ATTR_FSCREATE`` is the security context of the process used when | ||||||
|  | creating file system objects. | ||||||
|  | The proc filesystem provides this value in ``/proc/self/attr/fscreate``. | ||||||
|  | This is supported by the SELinux security module. | ||||||
|  | 
 | ||||||
|  | ``LSM_ATTR_KEYCREATE`` is the security context of the process used when | ||||||
|  | creating key objects. | ||||||
|  | The proc filesystem provides this value in ``/proc/self/attr/keycreate``. | ||||||
|  | This is supported by the SELinux security module. | ||||||
|  | 
 | ||||||
|  | ``LSM_ATTR_PREV`` is the security context of the process at the time the | ||||||
|  | current security context was set. | ||||||
|  | The proc filesystem provides this value in ``/proc/self/attr/prev``. | ||||||
|  | This is supported by the SELinux and AppArmor security modules. | ||||||
|  | AppArmor also provides this value in ``/proc/self/attr/apparmor/prev``. | ||||||
|  | 
 | ||||||
|  | ``LSM_ATTR_SOCKCREATE`` is the security context of the process used when | ||||||
|  | creating socket objects. | ||||||
|  | The proc filesystem provides this value in ``/proc/self/attr/sockcreate``. | ||||||
|  | This is supported by the SELinux security module. | ||||||
|  | 
 | ||||||
|  | Kernel interface | ||||||
|  | ================ | ||||||
|  | 
 | ||||||
|  | Set a security attribute of the current process | ||||||
|  | ----------------------------------------------- | ||||||
|  | 
 | ||||||
|  | .. kernel-doc:: security/lsm_syscalls.c | ||||||
|  |     :identifiers: sys_lsm_set_self_attr | ||||||
|  | 
 | ||||||
|  | Get the specified security attributes of the current process | ||||||
|  | ------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  | .. kernel-doc:: security/lsm_syscalls.c | ||||||
|  |     :identifiers: sys_lsm_get_self_attr | ||||||
|  | 
 | ||||||
|  | Additional documentation | ||||||
|  | ======================== | ||||||
|  | 
 | ||||||
|  | * Documentation/security/lsm.rst | ||||||
|  | * Documentation/security/lsm-development.rst | ||||||
|  | @ -262,6 +262,10 @@ LSM_HOOK(int, 0, sem_semop, struct kern_ipc_perm *perm, struct sembuf *sops, | ||||||
| LSM_HOOK(int, 0, netlink_send, struct sock *sk, struct sk_buff *skb) | LSM_HOOK(int, 0, netlink_send, struct sock *sk, struct sk_buff *skb) | ||||||
| LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry, | LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry, | ||||||
| 	 struct inode *inode) | 	 struct inode *inode) | ||||||
|  | LSM_HOOK(int, -EOPNOTSUPP, getselfattr, unsigned int attr, | ||||||
|  | 	 struct lsm_ctx __user *ctx, size_t *size, u32 flags) | ||||||
|  | LSM_HOOK(int, -EOPNOTSUPP, setselfattr, unsigned int attr, | ||||||
|  | 	 struct lsm_ctx *ctx, size_t size, u32 flags) | ||||||
| LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name, | LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name, | ||||||
| 	 char **value) | 	 char **value) | ||||||
| LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size) | LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size) | ||||||
|  |  | ||||||
|  | @ -25,6 +25,7 @@ | ||||||
| #ifndef __LINUX_LSM_HOOKS_H | #ifndef __LINUX_LSM_HOOKS_H | ||||||
| #define __LINUX_LSM_HOOKS_H | #define __LINUX_LSM_HOOKS_H | ||||||
| 
 | 
 | ||||||
|  | #include <uapi/linux/lsm.h> | ||||||
| #include <linux/security.h> | #include <linux/security.h> | ||||||
| #include <linux/init.h> | #include <linux/init.h> | ||||||
| #include <linux/rculist.h> | #include <linux/rculist.h> | ||||||
|  |  | ||||||
|  | @ -60,6 +60,7 @@ struct fs_parameter; | ||||||
| enum fs_value_type; | enum fs_value_type; | ||||||
| struct watch; | struct watch; | ||||||
| struct watch_notification; | struct watch_notification; | ||||||
|  | struct lsm_ctx; | ||||||
| 
 | 
 | ||||||
| /* Default (no) options for the capable function */ | /* Default (no) options for the capable function */ | ||||||
| #define CAP_OPT_NONE 0x0 | #define CAP_OPT_NONE 0x0 | ||||||
|  | @ -472,6 +473,10 @@ int security_sem_semctl(struct kern_ipc_perm *sma, int cmd); | ||||||
| int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, | int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, | ||||||
| 			unsigned nsops, int alter); | 			unsigned nsops, int alter); | ||||||
| void security_d_instantiate(struct dentry *dentry, struct inode *inode); | void security_d_instantiate(struct dentry *dentry, struct inode *inode); | ||||||
|  | int security_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, | ||||||
|  | 			 size_t __user *size, u32 flags); | ||||||
|  | int security_setselfattr(unsigned int attr, struct lsm_ctx __user *ctx, | ||||||
|  | 			 size_t size, u32 flags); | ||||||
| int security_getprocattr(struct task_struct *p, int lsmid, const char *name, | int security_getprocattr(struct task_struct *p, int lsmid, const char *name, | ||||||
| 			 char **value); | 			 char **value); | ||||||
| int security_setprocattr(int lsmid, const char *name, void *value, size_t size); | int security_setprocattr(int lsmid, const char *name, void *value, size_t size); | ||||||
|  | @ -1338,6 +1343,20 @@ static inline void security_d_instantiate(struct dentry *dentry, | ||||||
| 					  struct inode *inode) | 					  struct inode *inode) | ||||||
| { } | { } | ||||||
| 
 | 
 | ||||||
|  | static inline int security_getselfattr(unsigned int attr, | ||||||
|  | 				       struct lsm_ctx __user *ctx, | ||||||
|  | 				       size_t __user *size, u32 flags) | ||||||
|  | { | ||||||
|  | 	return -EOPNOTSUPP; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline int security_setselfattr(unsigned int attr, | ||||||
|  | 				       struct lsm_ctx __user *ctx, | ||||||
|  | 				       size_t size, u32 flags) | ||||||
|  | { | ||||||
|  | 	return -EOPNOTSUPP; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static inline int security_getprocattr(struct task_struct *p, int lsmid, | static inline int security_getprocattr(struct task_struct *p, int lsmid, | ||||||
| 				       const char *name, char **value) | 				       const char *name, char **value) | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -71,6 +71,7 @@ struct clone_args; | ||||||
| struct open_how; | struct open_how; | ||||||
| struct mount_attr; | struct mount_attr; | ||||||
| struct landlock_ruleset_attr; | struct landlock_ruleset_attr; | ||||||
|  | struct lsm_ctx; | ||||||
| enum landlock_rule_type; | enum landlock_rule_type; | ||||||
| struct cachestat_range; | struct cachestat_range; | ||||||
| struct cachestat; | struct cachestat; | ||||||
|  | @ -949,6 +950,10 @@ asmlinkage long sys_cachestat(unsigned int fd, | ||||||
| 		struct cachestat_range __user *cstat_range, | 		struct cachestat_range __user *cstat_range, | ||||||
| 		struct cachestat __user *cstat, unsigned int flags); | 		struct cachestat __user *cstat, unsigned int flags); | ||||||
| asmlinkage long sys_map_shadow_stack(unsigned long addr, unsigned long size, unsigned int flags); | asmlinkage long sys_map_shadow_stack(unsigned long addr, unsigned long size, unsigned int flags); | ||||||
|  | asmlinkage long sys_lsm_get_self_attr(unsigned int attr, struct lsm_ctx *ctx, | ||||||
|  | 				      size_t *size, __u32 flags); | ||||||
|  | asmlinkage long sys_lsm_set_self_attr(unsigned int attr, struct lsm_ctx *ctx, | ||||||
|  | 				      size_t size, __u32 flags); | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Architecture-specific system calls |  * Architecture-specific system calls | ||||||
|  |  | ||||||
|  | @ -9,6 +9,36 @@ | ||||||
| #ifndef _UAPI_LINUX_LSM_H | #ifndef _UAPI_LINUX_LSM_H | ||||||
| #define _UAPI_LINUX_LSM_H | #define _UAPI_LINUX_LSM_H | ||||||
| 
 | 
 | ||||||
|  | #include <linux/types.h> | ||||||
|  | #include <linux/unistd.h> | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * struct lsm_ctx - LSM context information | ||||||
|  |  * @id: the LSM id number, see LSM_ID_XXX | ||||||
|  |  * @flags: LSM specific flags | ||||||
|  |  * @len: length of the lsm_ctx struct, @ctx and any other data or padding | ||||||
|  |  * @ctx_len: the size of @ctx | ||||||
|  |  * @ctx: the LSM context value | ||||||
|  |  * | ||||||
|  |  * The @len field MUST be equal to the size of the lsm_ctx struct | ||||||
|  |  * plus any additional padding and/or data placed after @ctx. | ||||||
|  |  * | ||||||
|  |  * In all cases @ctx_len MUST be equal to the length of @ctx. | ||||||
|  |  * If @ctx is a string value it should be nul terminated with | ||||||
|  |  * @ctx_len equal to `strlen(@ctx) + 1`.  Binary values are | ||||||
|  |  * supported. | ||||||
|  |  * | ||||||
|  |  * The @flags and @ctx fields SHOULD only be interpreted by the | ||||||
|  |  * LSM specified by @id; they MUST be set to zero/0 when not used. | ||||||
|  |  */ | ||||||
|  | struct lsm_ctx { | ||||||
|  | 	__u64 id; | ||||||
|  | 	__u64 flags; | ||||||
|  | 	__u64 len; | ||||||
|  | 	__u64 ctx_len; | ||||||
|  | 	__u8 ctx[]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * ID tokens to identify Linux Security Modules (LSMs) |  * ID tokens to identify Linux Security Modules (LSMs) | ||||||
|  * |  * | ||||||
|  | @ -51,4 +81,10 @@ | ||||||
| #define LSM_ATTR_PREV		104 | #define LSM_ATTR_PREV		104 | ||||||
| #define LSM_ATTR_SOCKCREATE	105 | #define LSM_ATTR_SOCKCREATE	105 | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * LSM_FLAG_XXX definitions identify special handling instructions | ||||||
|  |  * for the API. | ||||||
|  |  */ | ||||||
|  | #define LSM_FLAG_SINGLE	0x0001 | ||||||
|  | 
 | ||||||
| #endif /* _UAPI_LINUX_LSM_H */ | #endif /* _UAPI_LINUX_LSM_H */ | ||||||
|  |  | ||||||
|  | @ -171,6 +171,8 @@ COND_SYSCALL(landlock_add_rule); | ||||||
| COND_SYSCALL(landlock_restrict_self); | COND_SYSCALL(landlock_restrict_self); | ||||||
| COND_SYSCALL(fadvise64_64); | COND_SYSCALL(fadvise64_64); | ||||||
| COND_SYSCALL_COMPAT(fadvise64_64); | COND_SYSCALL_COMPAT(fadvise64_64); | ||||||
|  | COND_SYSCALL(lsm_get_self_attr); | ||||||
|  | COND_SYSCALL(lsm_set_self_attr); | ||||||
| 
 | 
 | ||||||
| /* CONFIG_MMU only */ | /* CONFIG_MMU only */ | ||||||
| COND_SYSCALL(swapon); | COND_SYSCALL(swapon); | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ obj-$(CONFIG_KEYS)			+= keys/ | ||||||
| 
 | 
 | ||||||
| # always enable default capabilities
 | # always enable default capabilities
 | ||||||
| obj-y					+= commoncap.o | obj-y					+= commoncap.o | ||||||
|  | obj-$(CONFIG_SECURITY) 			+= lsm_syscalls.o | ||||||
| obj-$(CONFIG_MMU)			+= min_addr.o | obj-$(CONFIG_MMU)			+= min_addr.o | ||||||
| 
 | 
 | ||||||
| # Object file lists
 | # Object file lists
 | ||||||
|  |  | ||||||
							
								
								
									
										57
									
								
								security/lsm_syscalls.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								security/lsm_syscalls.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,57 @@ | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-only
 | ||||||
|  | /*
 | ||||||
|  |  * System calls implementing the Linux Security Module API. | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2022 Casey Schaufler <casey@schaufler-ca.com> | ||||||
|  |  *  Copyright (C) 2022 Intel Corporation | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <asm/current.h> | ||||||
|  | #include <linux/compiler_types.h> | ||||||
|  | #include <linux/err.h> | ||||||
|  | #include <linux/errno.h> | ||||||
|  | #include <linux/security.h> | ||||||
|  | #include <linux/stddef.h> | ||||||
|  | #include <linux/syscalls.h> | ||||||
|  | #include <linux/types.h> | ||||||
|  | #include <linux/lsm_hooks.h> | ||||||
|  | #include <uapi/linux/lsm.h> | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * sys_lsm_set_self_attr - Set current task's security module attribute | ||||||
|  |  * @attr: which attribute to set | ||||||
|  |  * @ctx: the LSM contexts | ||||||
|  |  * @size: size of @ctx | ||||||
|  |  * @flags: reserved for future use | ||||||
|  |  * | ||||||
|  |  * Sets the calling task's LSM context. On success this function | ||||||
|  |  * returns 0. If the attribute specified cannot be set a negative | ||||||
|  |  * value indicating the reason for the error is returned. | ||||||
|  |  */ | ||||||
|  | SYSCALL_DEFINE4(lsm_set_self_attr, unsigned int, attr, struct lsm_ctx __user *, | ||||||
|  | 		ctx, size_t, size, u32, flags) | ||||||
|  | { | ||||||
|  | 	return security_setselfattr(attr, ctx, size, flags); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * sys_lsm_get_self_attr - Return current task's security module attributes | ||||||
|  |  * @attr: which attribute to return | ||||||
|  |  * @ctx: the user-space destination for the information, or NULL | ||||||
|  |  * @size: pointer to the size of space available to receive the data | ||||||
|  |  * @flags: special handling options. LSM_FLAG_SINGLE indicates that only | ||||||
|  |  * attributes associated with the LSM identified in the passed @ctx be | ||||||
|  |  * reported. | ||||||
|  |  * | ||||||
|  |  * Returns the calling task's LSM contexts. On success this | ||||||
|  |  * function returns the number of @ctx array elements. This value | ||||||
|  |  * may be zero if there are no LSM contexts assigned. If @size is | ||||||
|  |  * insufficient to contain the return data -E2BIG is returned and | ||||||
|  |  * @size is set to the minimum required size. In all other cases | ||||||
|  |  * a negative value indicating the error is returned. | ||||||
|  |  */ | ||||||
|  | SYSCALL_DEFINE4(lsm_get_self_attr, unsigned int, attr, struct lsm_ctx __user *, | ||||||
|  | 		ctx, size_t __user *, size, u32, flags) | ||||||
|  | { | ||||||
|  | 	return security_getselfattr(attr, ctx, size, flags); | ||||||
|  | } | ||||||
|  | @ -3837,6 +3837,158 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode) | ||||||
| } | } | ||||||
| EXPORT_SYMBOL(security_d_instantiate); | EXPORT_SYMBOL(security_d_instantiate); | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Please keep this in sync with it's counterpart in security/lsm_syscalls.c | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * security_getselfattr - Read an LSM attribute of the current process. | ||||||
|  |  * @attr: which attribute to return | ||||||
|  |  * @uctx: the user-space destination for the information, or NULL | ||||||
|  |  * @size: pointer to the size of space available to receive the data | ||||||
|  |  * @flags: special handling options. LSM_FLAG_SINGLE indicates that only | ||||||
|  |  * attributes associated with the LSM identified in the passed @ctx be | ||||||
|  |  * reported. | ||||||
|  |  * | ||||||
|  |  * A NULL value for @uctx can be used to get both the number of attributes | ||||||
|  |  * and the size of the data. | ||||||
|  |  * | ||||||
|  |  * Returns the number of attributes found on success, negative value | ||||||
|  |  * on error. @size is reset to the total size of the data. | ||||||
|  |  * If @size is insufficient to contain the data -E2BIG is returned. | ||||||
|  |  */ | ||||||
|  | int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx, | ||||||
|  | 			 size_t __user *size, u32 flags) | ||||||
|  | { | ||||||
|  | 	struct security_hook_list *hp; | ||||||
|  | 	struct lsm_ctx lctx = { .id = LSM_ID_UNDEF, }; | ||||||
|  | 	u8 __user *base = (u8 __user *)uctx; | ||||||
|  | 	size_t total = 0; | ||||||
|  | 	size_t entrysize; | ||||||
|  | 	size_t left; | ||||||
|  | 	bool toobig = false; | ||||||
|  | 	bool single = false; | ||||||
|  | 	int count = 0; | ||||||
|  | 	int rc; | ||||||
|  | 
 | ||||||
|  | 	if (attr == LSM_ATTR_UNDEF) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	if (size == NULL) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	if (get_user(left, size)) | ||||||
|  | 		return -EFAULT; | ||||||
|  | 
 | ||||||
|  | 	if (flags) { | ||||||
|  | 		/*
 | ||||||
|  | 		 * Only flag supported is LSM_FLAG_SINGLE | ||||||
|  | 		 */ | ||||||
|  | 		if (flags != LSM_FLAG_SINGLE) | ||||||
|  | 			return -EINVAL; | ||||||
|  | 		if (uctx && copy_from_user(&lctx, uctx, sizeof(lctx))) | ||||||
|  | 			return -EFAULT; | ||||||
|  | 		/*
 | ||||||
|  | 		 * If the LSM ID isn't specified it is an error. | ||||||
|  | 		 */ | ||||||
|  | 		if (lctx.id == LSM_ID_UNDEF) | ||||||
|  | 			return -EINVAL; | ||||||
|  | 		single = true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * In the usual case gather all the data from the LSMs. | ||||||
|  | 	 * In the single case only get the data from the LSM specified. | ||||||
|  | 	 */ | ||||||
|  | 	hlist_for_each_entry(hp, &security_hook_heads.getselfattr, list) { | ||||||
|  | 		if (single && lctx.id != hp->lsmid->id) | ||||||
|  | 			continue; | ||||||
|  | 		entrysize = left; | ||||||
|  | 		if (base) | ||||||
|  | 			uctx = (struct lsm_ctx __user *)(base + total); | ||||||
|  | 		rc = hp->hook.getselfattr(attr, uctx, &entrysize, flags); | ||||||
|  | 		if (rc == -EOPNOTSUPP) { | ||||||
|  | 			rc = 0; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		if (rc == -E2BIG) { | ||||||
|  | 			toobig = true; | ||||||
|  | 			left = 0; | ||||||
|  | 		} else if (rc < 0) | ||||||
|  | 			return rc; | ||||||
|  | 		else | ||||||
|  | 			left -= entrysize; | ||||||
|  | 
 | ||||||
|  | 		total += entrysize; | ||||||
|  | 		count += rc; | ||||||
|  | 		if (single) | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | 	if (put_user(total, size)) | ||||||
|  | 		return -EFAULT; | ||||||
|  | 	if (toobig) | ||||||
|  | 		return -E2BIG; | ||||||
|  | 	if (count == 0) | ||||||
|  | 		return LSM_RET_DEFAULT(getselfattr); | ||||||
|  | 	return count; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Please keep this in sync with it's counterpart in security/lsm_syscalls.c | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * security_setselfattr - Set an LSM attribute on the current process. | ||||||
|  |  * @attr: which attribute to set | ||||||
|  |  * @uctx: the user-space source for the information | ||||||
|  |  * @size: the size of the data | ||||||
|  |  * @flags: reserved for future use, must be 0 | ||||||
|  |  * | ||||||
|  |  * Set an LSM attribute for the current process. The LSM, attribute | ||||||
|  |  * and new value are included in @uctx. | ||||||
|  |  * | ||||||
|  |  * Returns 0 on success, -EINVAL if the input is inconsistent, -EFAULT | ||||||
|  |  * if the user buffer is inaccessible, E2BIG if size is too big, or an | ||||||
|  |  * LSM specific failure. | ||||||
|  |  */ | ||||||
|  | int security_setselfattr(unsigned int attr, struct lsm_ctx __user *uctx, | ||||||
|  | 			 size_t size, u32 flags) | ||||||
|  | { | ||||||
|  | 	struct security_hook_list *hp; | ||||||
|  | 	struct lsm_ctx *lctx; | ||||||
|  | 	int rc = LSM_RET_DEFAULT(setselfattr); | ||||||
|  | 
 | ||||||
|  | 	if (flags) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	if (size < sizeof(*lctx)) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	if (size > PAGE_SIZE) | ||||||
|  | 		return -E2BIG; | ||||||
|  | 
 | ||||||
|  | 	lctx = kmalloc(size, GFP_KERNEL); | ||||||
|  | 	if (lctx == NULL) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	if (copy_from_user(lctx, uctx, size)) { | ||||||
|  | 		rc = -EFAULT; | ||||||
|  | 		goto free_out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (size < lctx->len || size < lctx->ctx_len + sizeof(*lctx) || | ||||||
|  | 	    lctx->len < lctx->ctx_len + sizeof(*lctx)) { | ||||||
|  | 		rc = -EINVAL; | ||||||
|  | 		goto free_out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	hlist_for_each_entry(hp, &security_hook_heads.setselfattr, list) | ||||||
|  | 		if ((hp->lsmid->id) == lctx->id) { | ||||||
|  | 			rc = hp->hook.setselfattr(attr, lctx, size, flags); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | free_out: | ||||||
|  | 	kfree(lctx); | ||||||
|  | 	return rc; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * security_getprocattr() - Read an attribute for a task |  * security_getprocattr() - Read an attribute for a task | ||||||
|  * @p: the task |  * @p: the task | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Casey Schaufler
						Casey Schaufler