Message ID | 20220927203155.15060-1-casey@schaufler-ca.com (mailing list archive) |
---|---|
State | Handled Elsewhere |
Delegated to: | Paul Moore |
Headers | show |
Series | [v38,01/39] LSM: Identify modules by more than name | expand |
Hi Casey, I love your patch! Perhaps something to improve: [auto build test WARNING on linus/master] [also build test WARNING on v6.0-rc7] [cannot apply to pcmoore-audit/next pcmoore-selinux/next zohar-integrity/next-integrity next-20220927] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Casey-Schaufler/LSM-Identify-modules-by-more-than-name/20220928-045406 base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 46452d3786a82bd732ba73fb308ae5cbe4e1e591 config: s390-defconfig compiler: s390-linux-gcc (GCC) 12.1.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/6f957bc7939d85848cbe2a2a1c1007e344629ae0 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Casey-Schaufler/LSM-Identify-modules-by-more-than-name/20220928-045406 git checkout 6f957bc7939d85848cbe2a2a1c1007e344629ae0 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=s390 SHELL=/bin/bash If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): security/lsm_syscalls.c:51: warning: expecting prototype for lsm_self_attr(). Prototype was for sys_lsm_self_attr() instead >> security/lsm_syscalls.c:175: warning: expecting prototype for lsm_module_list(). Prototype was for sys_lsm_module_list() instead vim +175 security/lsm_syscalls.c 33 34 /** 35 * lsm_self_attr - Return current task's security module attributes 36 * @ctx: the LSM contexts 37 * @size: size of @ctx, updated on return 38 * @flags: reserved for future use, must be zero 39 * 40 * Returns the calling task's LSM contexts. On success this 41 * function returns the number of @ctx array elements. This value 42 * may be zero if there are no LSM contexts assigned. If @size is 43 * insufficient to contain the return data -E2BIG is returned and 44 * @size is set to the minimum required size. In all other cases 45 * a negative value indicating the error is returned. 46 */ 47 SYSCALL_DEFINE3(lsm_self_attr, 48 struct lsm_ctx __user *, ctx, 49 size_t __user *, size, 50 int, flags) > 51 { 52 struct lsm_ctx *final = NULL; 53 struct lsm_ctx *interum; 54 struct lsm_ctx *ip; 55 void *curr; 56 char **interum_ctx; 57 char *cp; 58 size_t total_size = 0; 59 int count = 0; 60 int attr; 61 int len; 62 int rc = 0; 63 int i; 64 65 interum = kzalloc(ARRAY_SIZE(lsm_attr_names) * lsm_id * 66 sizeof(*interum), GFP_KERNEL); 67 if (interum == NULL) 68 return -ENOMEM; 69 ip = interum; 70 71 interum_ctx = kzalloc(ARRAY_SIZE(lsm_attr_names) * lsm_id * 72 sizeof(*interum_ctx), GFP_KERNEL); 73 if (interum_ctx == NULL) { 74 kfree(interum); 75 return -ENOMEM; 76 } 77 78 for (attr = 0; attr < ARRAY_SIZE(lsm_attr_names); attr++) { 79 for (i = 0; i < lsm_id; i++) { 80 if ((lsm_idlist[i]->features & 81 lsm_attr_names[attr].feature) == 0) 82 continue; 83 84 len = security_getprocattr(current, lsm_idlist[i]->id, 85 lsm_attr_names[attr].name, 86 &cp); 87 if (len <= 0) 88 continue; 89 90 ip->id = lsm_idlist[i]->id; 91 ip->flags = lsm_attr_names[attr].feature; 92 /* space for terminating \0 is allocated below */ 93 ip->ctx_len = len + 1; 94 interum_ctx[count] = cp; 95 /* 96 * Security modules have been inconsistent about 97 * including the \0 terminator in the size. The 98 * context len has been adjusted to ensure there 99 * is one. 100 * At least one security module adds a \n at the 101 * end of a context to make it look nicer. Change 102 * that to a \0 so that user space doesn't have to 103 * work around it. Because of this meddling it is 104 * safe to assume that lsm_ctx.name is terminated 105 * and that strlen(lsm_ctx.name) < lsm.ctx_len. 106 */ 107 total_size += sizeof(*interum) + ip->ctx_len; 108 cp = strnchr(cp, len, '\n'); 109 if (cp != NULL) 110 *cp = '\0'; 111 ip++; 112 count++; 113 } 114 } 115 116 if (count == 0) 117 goto free_out; 118 119 final = kzalloc(total_size, GFP_KERNEL); 120 if (final == NULL) { 121 rc = -ENOMEM; 122 goto free_out; 123 } 124 125 curr = final; 126 ip = interum; 127 for (i = 0; i < count; i++) { 128 memcpy(curr, ip, sizeof(*interum)); 129 curr += sizeof(*interum); 130 memcpy(curr, interum_ctx[i], ip->ctx_len); 131 curr += ip->ctx_len; 132 ip++; 133 } 134 135 if (get_user(len, size)) { 136 rc = -EFAULT; 137 goto free_out; 138 } 139 if (total_size > len) { 140 rc = -ERANGE; 141 goto free_out; 142 } 143 if (copy_to_user(ctx, final, total_size) != 0 || 144 put_user(total_size, size) != 0) 145 rc = -EFAULT; 146 else 147 rc = count; 148 149 free_out: 150 for (i = 0; i < count; i++) 151 kfree(interum_ctx[i]); 152 kfree(interum_ctx); 153 kfree(interum); 154 kfree(final); 155 return rc; 156 } 157 158 /** 159 * lsm_module_list - Return a list of the active security modules 160 * @ids: the LSM module ids 161 * @size: size of @ids, updated on return 162 * @flags: reserved for future use, must be zero 163 * 164 * Returns a list of the active LSM ids. On success this function 165 * returns the number of @ids array elements. This value may be zero 166 * if there are no LSMs active. If @size is insufficient to contain 167 * the return data -E2BIG is returned and @size is set to the minimum 168 * required size. In all other cases a negative value indicating the 169 * error is returned. 170 */ 171 SYSCALL_DEFINE3(lsm_module_list, 172 unsigned int __user *, ids, 173 size_t __user *, size, 174 int, flags) > 175 {
On 27/09/2022 22:31, Casey Schaufler wrote: > Create a system call to report the list of Linux Security Modules > that are active on the system. The list is provided as an array > of LSM ID numbers. With lsm_self_attr(), this would look like a dir/file structure. Would it be useful for user space to list all the currently used LSMs instead of only retrieving information about a known (list of) LSM? What is the use case for this syscall? > > Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> > --- > arch/x86/entry/syscalls/syscall_64.tbl | 1 + > include/linux/syscalls.h | 1 + > include/uapi/asm-generic/unistd.h | 5 ++- > kernel/sys_ni.c | 1 + > security/lsm_syscalls.c | 50 ++++++++++++++++++++++++++ > 5 files changed, 57 insertions(+), 1 deletion(-) > > diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl > index 56d5c5202fd0..40b35e7069a7 100644 > --- a/arch/x86/entry/syscalls/syscall_64.tbl > +++ b/arch/x86/entry/syscalls/syscall_64.tbl > @@ -373,6 +373,7 @@ > 449 common futex_waitv sys_futex_waitv > 450 common set_mempolicy_home_node sys_set_mempolicy_home_node > 451 common lsm_self_attr sys_lsm_self_attr > +452 common lsm_module_list sys_lsm_module_list As for the other syscall, this should also be in the same dedicated "wire syscalls" patch. > > # > # Due to a historical design error, certain syscalls are numbered differently > diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h > index 7f87ef8be546..e2e2a9e93e8c 100644 > --- a/include/linux/syscalls.h > +++ b/include/linux/syscalls.h > @@ -1057,6 +1057,7 @@ asmlinkage long sys_set_mempolicy_home_node(unsigned long start, unsigned long l > unsigned long home_node, > unsigned long flags); > asmlinkage long sys_lsm_self_attr(struct lsm_ctx *ctx, size_t *size, int flags); > +asmlinkage long sys_lsm_module_list(unsigned int *ids, size_t *size, int flags); > > /* > * Architecture-specific system calls > diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h > index aa66718e1b48..090617a9a53a 100644 > --- a/include/uapi/asm-generic/unistd.h > +++ b/include/uapi/asm-generic/unistd.h > @@ -889,8 +889,11 @@ __SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node) > #define __NR_lsm_self_attr 451 > __SYSCALL(__NR_lsm_self_attr, sys_lsm_self_attr) > > +#define __NR_lsm_module_list 452 > +__SYSCALL(__NR_lsm_module_list, sys_lsm_module_list) > + > #undef __NR_syscalls > -#define __NR_syscalls 452 > +#define __NR_syscalls 453 Same here. > > /* > * 32 bit systems traditionally used different > diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c > index 0fdb0341251d..bde9e74a3473 100644 > --- a/kernel/sys_ni.c > +++ b/kernel/sys_ni.c > @@ -264,6 +264,7 @@ COND_SYSCALL(mremap); > > /* security/lsm_syscalls.c */ > COND_SYSCALL(lsm_self_attr); > +COND_SYSCALL(lsm_module_list); > > /* security/keys/keyctl.c */ > COND_SYSCALL(add_key); > diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c > index da0fab7065e2..41d9ef945ede 100644 > --- a/security/lsm_syscalls.c > +++ b/security/lsm_syscalls.c > @@ -154,3 +154,53 @@ SYSCALL_DEFINE3(lsm_self_attr, > kfree(final); > return rc; > } > + > +/** > + * lsm_module_list - Return a list of the active security modules > + * @ids: the LSM module ids > + * @size: size of @ids, updated on return > + * @flags: reserved for future use, must be zero > + * > + * Returns a list of the active LSM ids. On success this function > + * returns the number of @ids array elements. This value may be zero > + * if there are no LSMs active. 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_DEFINE3(lsm_module_list, > + unsigned int __user *, ids, > + size_t __user *, size, > + int, flags) > +{ > + unsigned int *interum; > + size_t total_size = lsm_id * sizeof(*interum); > + size_t usize; > + int rc; > + int i; > + > + if (get_user(usize, size)) > + return -EFAULT; > + > + if (usize < total_size) { > + if (put_user(total_size, size) != 0) > + return -EFAULT; > + return -E2BIG; > + } > + > + interum = kzalloc(total_size, GFP_KERNEL); > + if (interum == NULL) > + return -ENOMEM; > + > + for (i = 0; i < lsm_id; i++) > + interum[i] = lsm_idlist[i]->id; > + > + if (copy_to_user(ids, interum, total_size) != 0 || > + put_user(total_size, size) != 0) > + rc = -EFAULT; > + else > + rc = lsm_id; > + > + kfree(interum); > + return rc; > +}
On Tue, Sep 27, 2022 at 01:31:55PM -0700, Casey Schaufler wrote: > +SYSCALL_DEFINE3(lsm_module_list, > + unsigned int __user *, ids, > + size_t __user *, size, > + int, flags) Please make this unsigned int. > +{ > + unsigned int *interum; > + size_t total_size = lsm_id * sizeof(*interum); > + size_t usize; > + int rc; > + int i; Please test that flags == 0 so it can be used in the future: if (flags) return -EINVAL; > + > + if (get_user(usize, size)) > + return -EFAULT; > + > + if (usize < total_size) { > + if (put_user(total_size, size) != 0) > + return -EFAULT; > + return -E2BIG; > + } > + > + interum = kzalloc(total_size, GFP_KERNEL); > + if (interum == NULL) > + return -ENOMEM; > + > + for (i = 0; i < lsm_id; i++) > + interum[i] = lsm_idlist[i]->id; > + > + if (copy_to_user(ids, interum, total_size) != 0 || > + put_user(total_size, size) != 0) > + rc = -EFAULT; No need to repeat this, if it is written first. > + else > + rc = lsm_id; > + > + kfree(interum); > + return rc; No need for the alloc/free. Here's what I would imagine for the whole thing: if (flags) return -EINVAL; if (get_user(usize, size)) return -EFAULT; if (put_user(total_size, size) != 0) return -EFAULT; if (usize < total_size) return -E2BIG; for (i = 0; i < lsm_id; i++) if (put_user(lsm_idlist[i]->id, id++)) return -EFAULT; return lsm_id;
On 10/12/2022 2:19 PM, Mickaël Salaün wrote: > > On 27/09/2022 22:31, Casey Schaufler wrote: >> Create a system call to report the list of Linux Security Modules >> that are active on the system. The list is provided as an array >> of LSM ID numbers. > > With lsm_self_attr(), this would look like a dir/file structure. I'm not sure I understand what you mean by this. I think you're suggesting that lsm_module_list() shows the list of possibilities and lsm_self_attr() shows the data. That's roughly correct. Note that many security modules will never provide any data in lsm_self_attr(), and that others will only provide it when it has been explicitly set. > > Would it be useful for user space to list all the currently used LSMs > instead of only retrieving information about a known (list of) LSM? I believe so. User space tends to lag behind kernel features. ps(1) can report the "current" value for any LSM without knowing which module supplied the value today by using the /proc/self/attr/current interface. id(1) could do the same were it not unnecessarily coded to be SELinux specific. lsm_module_list(2), like the existing /sys/kernel/security/lsm interface, allows an application to know if it should address the modules it knows about. It also provides the LSM order, which could be significant to systemd, dbus, auditd or other sophisticated system services. > What is the use case for this syscall? 1. Identify if a specific LSM is in the list. Used by ps(1) to format the -Z output correctly Used by systemd(1) to determine which service start options to support Used by dbus to identify what policy to enforce at runtime 2. Identify the order of LSMs in the list. Will AppArmor data show up in /proc/self/attr/current, or will Smack data? > > >> >> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> >> --- >> arch/x86/entry/syscalls/syscall_64.tbl | 1 + >> include/linux/syscalls.h | 1 + >> include/uapi/asm-generic/unistd.h | 5 ++- >> kernel/sys_ni.c | 1 + >> security/lsm_syscalls.c | 50 ++++++++++++++++++++++++++ >> 5 files changed, 57 insertions(+), 1 deletion(-) >> >> diff --git a/arch/x86/entry/syscalls/syscall_64.tbl >> b/arch/x86/entry/syscalls/syscall_64.tbl >> index 56d5c5202fd0..40b35e7069a7 100644 >> --- a/arch/x86/entry/syscalls/syscall_64.tbl >> +++ b/arch/x86/entry/syscalls/syscall_64.tbl >> @@ -373,6 +373,7 @@ >> 449 common futex_waitv sys_futex_waitv >> 450 common set_mempolicy_home_node >> sys_set_mempolicy_home_node >> 451 common lsm_self_attr sys_lsm_self_attr >> +452 common lsm_module_list sys_lsm_module_list > > As for the other syscall, this should also be in the same dedicated > "wire syscalls" patch. > > >> # >> # Due to a historical design error, certain syscalls are numbered >> differently >> diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h >> index 7f87ef8be546..e2e2a9e93e8c 100644 >> --- a/include/linux/syscalls.h >> +++ b/include/linux/syscalls.h >> @@ -1057,6 +1057,7 @@ asmlinkage long >> sys_set_mempolicy_home_node(unsigned long start, unsigned long l >> unsigned long home_node, >> unsigned long flags); >> asmlinkage long sys_lsm_self_attr(struct lsm_ctx *ctx, size_t >> *size, int flags); >> +asmlinkage long sys_lsm_module_list(unsigned int *ids, size_t *size, >> int flags); >> /* >> * Architecture-specific system calls >> diff --git a/include/uapi/asm-generic/unistd.h >> b/include/uapi/asm-generic/unistd.h >> index aa66718e1b48..090617a9a53a 100644 >> --- a/include/uapi/asm-generic/unistd.h >> +++ b/include/uapi/asm-generic/unistd.h >> @@ -889,8 +889,11 @@ __SYSCALL(__NR_set_mempolicy_home_node, >> sys_set_mempolicy_home_node) >> #define __NR_lsm_self_attr 451 >> __SYSCALL(__NR_lsm_self_attr, sys_lsm_self_attr) >> +#define __NR_lsm_module_list 452 >> +__SYSCALL(__NR_lsm_module_list, sys_lsm_module_list) >> + >> #undef __NR_syscalls >> -#define __NR_syscalls 452 >> +#define __NR_syscalls 453 > > Same here. > > >> /* >> * 32 bit systems traditionally used different >> diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c >> index 0fdb0341251d..bde9e74a3473 100644 >> --- a/kernel/sys_ni.c >> +++ b/kernel/sys_ni.c >> @@ -264,6 +264,7 @@ COND_SYSCALL(mremap); >> /* security/lsm_syscalls.c */ >> COND_SYSCALL(lsm_self_attr); >> +COND_SYSCALL(lsm_module_list); >> /* security/keys/keyctl.c */ >> COND_SYSCALL(add_key); >> diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c >> index da0fab7065e2..41d9ef945ede 100644 >> --- a/security/lsm_syscalls.c >> +++ b/security/lsm_syscalls.c >> @@ -154,3 +154,53 @@ SYSCALL_DEFINE3(lsm_self_attr, >> kfree(final); >> return rc; >> } >> + >> +/** >> + * lsm_module_list - Return a list of the active security modules >> + * @ids: the LSM module ids >> + * @size: size of @ids, updated on return >> + * @flags: reserved for future use, must be zero >> + * >> + * Returns a list of the active LSM ids. On success this function >> + * returns the number of @ids array elements. This value may be zero >> + * if there are no LSMs active. 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_DEFINE3(lsm_module_list, >> + unsigned int __user *, ids, >> + size_t __user *, size, >> + int, flags) >> +{ >> + unsigned int *interum; >> + size_t total_size = lsm_id * sizeof(*interum); >> + size_t usize; >> + int rc; >> + int i; >> + >> + if (get_user(usize, size)) >> + return -EFAULT; >> + >> + if (usize < total_size) { >> + if (put_user(total_size, size) != 0) >> + return -EFAULT; >> + return -E2BIG; >> + } >> + >> + interum = kzalloc(total_size, GFP_KERNEL); >> + if (interum == NULL) >> + return -ENOMEM; >> + >> + for (i = 0; i < lsm_id; i++) >> + interum[i] = lsm_idlist[i]->id; >> + >> + if (copy_to_user(ids, interum, total_size) != 0 || >> + put_user(total_size, size) != 0) >> + rc = -EFAULT; >> + else >> + rc = lsm_id; >> + >> + kfree(interum); >> + return rc; >> +}
On 10/12/2022 3:04 PM, Kees Cook wrote: > On Tue, Sep 27, 2022 at 01:31:55PM -0700, Casey Schaufler wrote: >> +SYSCALL_DEFINE3(lsm_module_list, >> + unsigned int __user *, ids, >> + size_t __user *, size, >> + int, flags) > Please make this unsigned int. Sure. >> +{ >> + unsigned int *interum; >> + size_t total_size = lsm_id * sizeof(*interum); >> + size_t usize; >> + int rc; >> + int i; > Please test that flags == 0 so it can be used in the future: > > if (flags) > return -EINVAL; Yup. >> + >> + if (get_user(usize, size)) >> + return -EFAULT; >> + >> + if (usize < total_size) { >> + if (put_user(total_size, size) != 0) >> + return -EFAULT; >> + return -E2BIG; >> + } >> + >> + interum = kzalloc(total_size, GFP_KERNEL); >> + if (interum == NULL) >> + return -ENOMEM; >> + >> + for (i = 0; i < lsm_id; i++) >> + interum[i] = lsm_idlist[i]->id; >> + >> + if (copy_to_user(ids, interum, total_size) != 0 || >> + put_user(total_size, size) != 0) >> + rc = -EFAULT; > No need to repeat this, if it is written first. > >> + else >> + rc = lsm_id; >> + >> + kfree(interum); >> + return rc; > No need for the alloc/free. Here's what I would imagine for the whole > thing: A better approach. Thank you. > > if (flags) > return -EINVAL; > > if (get_user(usize, size)) > return -EFAULT; > > if (put_user(total_size, size) != 0) > return -EFAULT; > > if (usize < total_size) > return -E2BIG; > > for (i = 0; i < lsm_id; i++) > if (put_user(lsm_idlist[i]->id, id++)) > return -EFAULT; > > return lsm_id; >
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 56d5c5202fd0..40b35e7069a7 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -373,6 +373,7 @@ 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common lsm_self_attr sys_lsm_self_attr +452 common lsm_module_list sys_lsm_module_list # # Due to a historical design error, certain syscalls are numbered differently diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 7f87ef8be546..e2e2a9e93e8c 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -1057,6 +1057,7 @@ asmlinkage long sys_set_mempolicy_home_node(unsigned long start, unsigned long l unsigned long home_node, unsigned long flags); asmlinkage long sys_lsm_self_attr(struct lsm_ctx *ctx, size_t *size, int flags); +asmlinkage long sys_lsm_module_list(unsigned int *ids, size_t *size, int flags); /* * Architecture-specific system calls diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index aa66718e1b48..090617a9a53a 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -889,8 +889,11 @@ __SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node) #define __NR_lsm_self_attr 451 __SYSCALL(__NR_lsm_self_attr, sys_lsm_self_attr) +#define __NR_lsm_module_list 452 +__SYSCALL(__NR_lsm_module_list, sys_lsm_module_list) + #undef __NR_syscalls -#define __NR_syscalls 452 +#define __NR_syscalls 453 /* * 32 bit systems traditionally used different diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 0fdb0341251d..bde9e74a3473 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -264,6 +264,7 @@ COND_SYSCALL(mremap); /* security/lsm_syscalls.c */ COND_SYSCALL(lsm_self_attr); +COND_SYSCALL(lsm_module_list); /* security/keys/keyctl.c */ COND_SYSCALL(add_key); diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c index da0fab7065e2..41d9ef945ede 100644 --- a/security/lsm_syscalls.c +++ b/security/lsm_syscalls.c @@ -154,3 +154,53 @@ SYSCALL_DEFINE3(lsm_self_attr, kfree(final); return rc; } + +/** + * lsm_module_list - Return a list of the active security modules + * @ids: the LSM module ids + * @size: size of @ids, updated on return + * @flags: reserved for future use, must be zero + * + * Returns a list of the active LSM ids. On success this function + * returns the number of @ids array elements. This value may be zero + * if there are no LSMs active. 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_DEFINE3(lsm_module_list, + unsigned int __user *, ids, + size_t __user *, size, + int, flags) +{ + unsigned int *interum; + size_t total_size = lsm_id * sizeof(*interum); + size_t usize; + int rc; + int i; + + if (get_user(usize, size)) + return -EFAULT; + + if (usize < total_size) { + if (put_user(total_size, size) != 0) + return -EFAULT; + return -E2BIG; + } + + interum = kzalloc(total_size, GFP_KERNEL); + if (interum == NULL) + return -ENOMEM; + + for (i = 0; i < lsm_id; i++) + interum[i] = lsm_idlist[i]->id; + + if (copy_to_user(ids, interum, total_size) != 0 || + put_user(total_size, size) != 0) + rc = -EFAULT; + else + rc = lsm_id; + + kfree(interum); + return rc; +}
Create a system call to report the list of Linux Security Modules that are active on the system. The list is provided as an array of LSM ID numbers. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> --- arch/x86/entry/syscalls/syscall_64.tbl | 1 + include/linux/syscalls.h | 1 + include/uapi/asm-generic/unistd.h | 5 ++- kernel/sys_ni.c | 1 + security/lsm_syscalls.c | 50 ++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 1 deletion(-)