[v1,7/8] LSM: Create lsm_module_list system call

Message ID 20221025184519.13231-8-casey@schaufler-ca.com
State New
Headers
Series LSM: Two basic syscalls |

Commit Message

Casey Schaufler Oct. 25, 2022, 6:45 p.m. UTC
  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.

The calling application can use this list determine what LSM
specific actions it might take. That might include chosing an
output format, determining required privilege or bypassing
security module specific behavior.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 include/linux/syscalls.h |  1 +
 kernel/sys_ni.c          |  1 +
 security/lsm_syscalls.c  | 38 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 40 insertions(+)
  

Comments

Greg KH Oct. 26, 2022, 6:02 a.m. UTC | #1
On Tue, Oct 25, 2022 at 11:45:18AM -0700, 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.
> 
> The calling application can use this list determine what LSM
> specific actions it might take. That might include chosing an
> output format, determining required privilege or bypassing
> security module specific behavior.
> 
> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> ---
>  include/linux/syscalls.h |  1 +
>  kernel/sys_ni.c          |  1 +
>  security/lsm_syscalls.c  | 38 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 40 insertions(+)
> 
> diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
> index 2d9033e9e5a0..02bb82142e24 100644
> --- a/include/linux/syscalls.h
> +++ b/include/linux/syscalls.h
> @@ -1058,6 +1058,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);

Instead of "unsigned int", how about "u64" to make it portable
properly?

thanks,

greg k-h
  
kernel test robot Oct. 26, 2022, 12:07 p.m. UTC | #2
Hi Casey,

I love your patch! Yet something to improve:

[auto build test ERROR on kees/for-next/hardening]
[also build test ERROR on pcmoore-selinux/next acme/perf/core linus/master v6.1-rc2 next-20221026]
[cannot apply to tip/perf/core]
[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/20221026-034541
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
patch link:    https://lore.kernel.org/r/20221025184519.13231-8-casey%40schaufler-ca.com
patch subject: [PATCH v1 7/8] LSM: Create lsm_module_list system call
config: arm-randconfig-r031-20221025 (attached as .config)
compiler: clang version 16.0.0 (https://github.com/llvm/llvm-project 791a7ae1ba3efd6bca96338e10ffde557ba83920)
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
        # install arm cross compiling tool for clang build
        # apt-get install binutils-arm-linux-gnueabi
        # https://github.com/intel-lab-lkp/linux/commit/e4fdffbcada3e48a7f4049e4c872642a1fed8f04
        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/20221026-034541
        git checkout e4fdffbcada3e48a7f4049e4c872642a1fed8f04
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   In file included from security/lsm_syscalls.c:15:
   include/linux/syscalls.h:1060:42: warning: declaration of 'struct lsm_ctx' will not be visible outside of this function [-Wvisibility]
   asmlinkage long sys_lsm_self_attr(struct lsm_ctx *ctx, size_t *size, int flags);
                                            ^
   security/lsm_syscalls.c:47:1: error: conflicting types for 'sys_lsm_self_attr'
   SYSCALL_DEFINE3(lsm_self_attr,
   ^
   include/linux/syscalls.h:220:36: note: expanded from macro 'SYSCALL_DEFINE3'
   #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
                                      ^
   include/linux/syscalls.h:229:2: note: expanded from macro 'SYSCALL_DEFINEx'
           __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
           ^
   include/linux/syscalls.h:243:18: note: expanded from macro '__SYSCALL_DEFINEx'
           asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))       \
                           ^
   <scratch space>:65:1: note: expanded from here
   sys_lsm_self_attr
   ^
   include/linux/syscalls.h:1060:17: note: previous declaration is here
   asmlinkage long sys_lsm_self_attr(struct lsm_ctx *ctx, size_t *size, int flags);
                   ^
>> security/lsm_syscalls.c:171:1: error: conflicting types for 'sys_lsm_module_list'
   SYSCALL_DEFINE3(lsm_module_list,
   ^
   include/linux/syscalls.h:220:36: note: expanded from macro 'SYSCALL_DEFINE3'
   #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
                                      ^
   include/linux/syscalls.h:229:2: note: expanded from macro 'SYSCALL_DEFINEx'
           __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
           ^
   include/linux/syscalls.h:243:18: note: expanded from macro '__SYSCALL_DEFINEx'
           asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))       \
                           ^
   <scratch space>:104:1: note: expanded from here
   sys_lsm_module_list
   ^
   include/linux/syscalls.h:1061:17: note: previous declaration is here
   asmlinkage long sys_lsm_module_list(unsigned int *ids, size_t *size, int flags);
                   ^
   1 warning and 2 errors generated.


vim +/sys_lsm_module_list +171 security/lsm_syscalls.c

   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,
  
Paul Moore Nov. 9, 2022, 11:35 p.m. UTC | #3
On Tue, Oct 25, 2022 at 2:48 PM Casey Schaufler <casey@schaufler-ca.com> 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.
>
> The calling application can use this list determine what LSM
> specific actions it might take. That might include chosing an
> output format, determining required privilege or bypassing
> security module specific behavior.
>
> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> ---
>  include/linux/syscalls.h |  1 +
>  kernel/sys_ni.c          |  1 +
>  security/lsm_syscalls.c  | 38 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 40 insertions(+)

...

> diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c
> index da0fab7065e2..cd5db370b974 100644
> --- a/security/lsm_syscalls.c
> +++ b/security/lsm_syscalls.c
> @@ -154,3 +154,41 @@ 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.
> + */

Let's make a promise that for this syscall we will order the LSM IDs
in the array in the same order as which they are configured/executed.
I'm doubtful that only a *very* small number of applications will care
about this (if any), but this is something we can do so let's do it
now while we can.

> +SYSCALL_DEFINE3(lsm_module_list,
> +               unsigned int __user *, ids,
> +               size_t __user *, size,
> +               unsigned int, flags)

--
paul-moore.com
  
Casey Schaufler Nov. 10, 2022, 1:37 a.m. UTC | #4
On 11/9/2022 3:35 PM, Paul Moore wrote:
> On Tue, Oct 25, 2022 at 2:48 PM Casey Schaufler <casey@schaufler-ca.com> 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.
>>
>> The calling application can use this list determine what LSM
>> specific actions it might take. That might include chosing an
>> output format, determining required privilege or bypassing
>> security module specific behavior.
>>
>> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
>> ---
>>  include/linux/syscalls.h |  1 +
>>  kernel/sys_ni.c          |  1 +
>>  security/lsm_syscalls.c  | 38 ++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 40 insertions(+)
> ..
>
>> diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c
>> index da0fab7065e2..cd5db370b974 100644
>> --- a/security/lsm_syscalls.c
>> +++ b/security/lsm_syscalls.c
>> @@ -154,3 +154,41 @@ 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.
>> + */
> Let's make a promise that for this syscall we will order the LSM IDs
> in the array in the same order as which they are configured/executed.

Sure. Order registered, which can vary, as opposed to LSM ID order,
which cannot. That could be important to ensure that applications
that enforce the same policy as the kernel will hit the checks in
the same order as the kernel. That's how it is coded. It needs to
be documented. 

> I'm doubtful that only a *very* small number of applications will care
> about this (if any), but this is something we can do so let's do it
> now while we can.
>
>> +SYSCALL_DEFINE3(lsm_module_list,
>> +               unsigned int __user *, ids,
>> +               size_t __user *, size,
>> +               unsigned int, flags)
> --
> paul-moore.com
  
Paul Moore Nov. 10, 2022, 3:17 a.m. UTC | #5
On Wed, Nov 9, 2022 at 8:37 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
> On 11/9/2022 3:35 PM, Paul Moore wrote:
> > On Tue, Oct 25, 2022 at 2:48 PM Casey Schaufler <casey@schaufler-ca.com> 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.
> >>
> >> The calling application can use this list determine what LSM
> >> specific actions it might take. That might include chosing an
> >> output format, determining required privilege or bypassing
> >> security module specific behavior.
> >>
> >> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> >> ---
> >>  include/linux/syscalls.h |  1 +
> >>  kernel/sys_ni.c          |  1 +
> >>  security/lsm_syscalls.c  | 38 ++++++++++++++++++++++++++++++++++++++
> >>  3 files changed, 40 insertions(+)
> > ..
> >
> >> diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c
> >> index da0fab7065e2..cd5db370b974 100644
> >> --- a/security/lsm_syscalls.c
> >> +++ b/security/lsm_syscalls.c
> >> @@ -154,3 +154,41 @@ 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.
> >> + */
> > Let's make a promise that for this syscall we will order the LSM IDs
> > in the array in the same order as which they are configured/executed.
>
> Sure. Order registered, which can vary, as opposed to LSM ID order,
> which cannot. That could be important to ensure that applications
> that enforce the same policy as the kernel will hit the checks in
> the same order as the kernel. That's how it is coded. It needs to
> be documented.

Yep.  One of the big reasons for documenting it this way is to ensure
that we define the order as part of the API.
  

Patch

diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 2d9033e9e5a0..02bb82142e24 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1058,6 +1058,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/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..cd5db370b974 100644
--- a/security/lsm_syscalls.c
+++ b/security/lsm_syscalls.c
@@ -154,3 +154,41 @@  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,
+		unsigned int, flags)
+{
+	size_t total_size = lsm_id * sizeof(*ids);
+	size_t usize;
+	int i;
+
+	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, ids++))
+			return -EFAULT;
+
+	return lsm_id;
+}