[v3,5/9] LSM: lsm_get_self_attr syscall for LSM self attributes

Message ID 20221123201552.7865-6-casey@schaufler-ca.com
State New
Headers
Series LSM: Three basic syscalls |

Commit Message

Casey Schaufler Nov. 23, 2022, 8:15 p.m. UTC
  Create a system call lsm_get_self_attr() to provide the security
module maintained attributes of the current process. Historically
these attributes have been exposed to user space via entries in
procfs under /proc/self/attr.

Attributes are provided as a collection of lsm_ctx structures
which are placed into a user supplied buffer. Each structure
identifys the size of the attribute, and the attribute value.
The format of the attribute value is defined by the security
module, but will always be \0 terminated. The ctx_len value
will always be strlen(ctx)+1.

        ---------------------------
        | __u32 id                |
        ---------------------------
        | __u64 flags             |
        ---------------------------
        | __kernel_size_t ctx_len |
        ---------------------------
        | __u8 ctx[ctx_len]       |
        ---------------------------
        | __u32 id                |
        ---------------------------
        | __u64 flags             |
        ---------------------------
        | __kernel_size_t ctx_len |
        ---------------------------
        | __u8 ctx[ctx_len]       |
        ---------------------------

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 Documentation/userspace-api/lsm.rst |   9 ++
 include/linux/syscalls.h            |   3 +
 include/uapi/linux/lsm.h            |  21 ++++
 kernel/sys_ni.c                     |   3 +
 security/Makefile                   |   1 +
 security/lsm_syscalls.c             | 182 ++++++++++++++++++++++++++++
 6 files changed, 219 insertions(+)
 create mode 100644 security/lsm_syscalls.c
  

Comments

kernel test robot Nov. 25, 2022, 1:54 p.m. UTC | #1
Hi Casey,

I love your patch! Perhaps something to improve:

[auto build test WARNING on tip/perf/core]
[also build test WARNING on acme/perf/core shuah-kselftest/next shuah-kselftest/fixes linus/master v6.1-rc6]
[cannot apply to next-20221125]
[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/20221124-051600
patch link:    https://lore.kernel.org/r/20221123201552.7865-6-casey%40schaufler-ca.com
patch subject: [PATCH v3 5/9] LSM: lsm_get_self_attr syscall for LSM self attributes
config: arc-randconfig-r043-20221124
compiler: arc-elf-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/3ac4c5ad809a20ae21e121f48716bade40790d55
        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/20221124-051600
        git checkout 3ac4c5ad809a20ae21e121f48716bade40790d55
        # 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=arc SHELL=/bin/bash arch/arc/kernel/

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 >>):

   In file included from arch/arc/kernel/process.c:19:
>> include/linux/syscalls.h:1060:46: warning: 'struct lsm_ctx' declared inside parameter list will not be visible outside of this definition or declaration
    1060 | asmlinkage long sys_lsm_get_self_attr(struct lsm_ctx *ctx, size_t *size,
         |                                              ^~~~~~~
--
   In file included from arch/arc/kernel/signal.c:51:
>> include/linux/syscalls.h:1060:46: warning: 'struct lsm_ctx' declared inside parameter list will not be visible outside of this definition or declaration
    1060 | asmlinkage long sys_lsm_get_self_attr(struct lsm_ctx *ctx, size_t *size,
         |                                              ^~~~~~~
   arch/arc/kernel/signal.c:401:6: warning: no previous prototype for 'do_signal' [-Wmissing-prototypes]
     401 | void do_signal(struct pt_regs *regs)
         |      ^~~~~~~~~
   arch/arc/kernel/signal.c:434:6: warning: no previous prototype for 'do_notify_resume' [-Wmissing-prototypes]
     434 | void do_notify_resume(struct pt_regs *regs)
         |      ^~~~~~~~~~~~~~~~
--
   In file included from arch/arc/kernel/sys.c:3:
>> include/linux/syscalls.h:1060:46: warning: 'struct lsm_ctx' declared inside parameter list will not be visible outside of this definition or declaration
    1060 | asmlinkage long sys_lsm_get_self_attr(struct lsm_ctx *ctx, size_t *size,
         |                                              ^~~~~~~
   arch/arc/kernel/sys.c:13:36: warning: initialized field overwritten [-Woverride-init]
      13 | #define __SYSCALL(nr, call) [nr] = (call),
         |                                    ^
   include/uapi/asm-generic/unistd.h:29:37: note: in expansion of macro '__SYSCALL'
      29 | #define __SC_COMP(_nr, _sys, _comp) __SYSCALL(_nr, _sys)
         |                                     ^~~~~~~~~
   include/uapi/asm-generic/unistd.h:34:1: note: in expansion of macro '__SC_COMP'
      34 | __SC_COMP(__NR_io_setup, sys_io_setup, compat_sys_io_setup)
         | ^~~~~~~~~
   arch/arc/kernel/sys.c:13:36: note: (near initialization for 'sys_call_table[0]')
      13 | #define __SYSCALL(nr, call) [nr] = (call),
         |                                    ^
   include/uapi/asm-generic/unistd.h:29:37: note: in expansion of macro '__SYSCALL'
      29 | #define __SC_COMP(_nr, _sys, _comp) __SYSCALL(_nr, _sys)
         |                                     ^~~~~~~~~
   include/uapi/asm-generic/unistd.h:34:1: note: in expansion of macro '__SC_COMP'
      34 | __SC_COMP(__NR_io_setup, sys_io_setup, compat_sys_io_setup)
         | ^~~~~~~~~
   arch/arc/kernel/sys.c:13:36: warning: initialized field overwritten [-Woverride-init]
      13 | #define __SYSCALL(nr, call) [nr] = (call),
         |                                    ^
   include/uapi/asm-generic/unistd.h:36:1: note: in expansion of macro '__SYSCALL'
      36 | __SYSCALL(__NR_io_destroy, sys_io_destroy)
         | ^~~~~~~~~
   arch/arc/kernel/sys.c:13:36: note: (near initialization for 'sys_call_table[1]')
      13 | #define __SYSCALL(nr, call) [nr] = (call),
         |                                    ^
   include/uapi/asm-generic/unistd.h:36:1: note: in expansion of macro '__SYSCALL'
      36 | __SYSCALL(__NR_io_destroy, sys_io_destroy)
         | ^~~~~~~~~
   arch/arc/kernel/sys.c:13:36: warning: initialized field overwritten [-Woverride-init]
      13 | #define __SYSCALL(nr, call) [nr] = (call),
         |                                    ^
   include/uapi/asm-generic/unistd.h:29:37: note: in expansion of macro '__SYSCALL'
      29 | #define __SC_COMP(_nr, _sys, _comp) __SYSCALL(_nr, _sys)
         |                                     ^~~~~~~~~
   include/uapi/asm-generic/unistd.h:38:1: note: in expansion of macro '__SC_COMP'
      38 | __SC_COMP(__NR_io_submit, sys_io_submit, compat_sys_io_submit)
         | ^~~~~~~~~
   arch/arc/kernel/sys.c:13:36: note: (near initialization for 'sys_call_table[2]')
      13 | #define __SYSCALL(nr, call) [nr] = (call),
         |                                    ^
   include/uapi/asm-generic/unistd.h:29:37: note: in expansion of macro '__SYSCALL'
      29 | #define __SC_COMP(_nr, _sys, _comp) __SYSCALL(_nr, _sys)
         |                                     ^~~~~~~~~
   include/uapi/asm-generic/unistd.h:38:1: note: in expansion of macro '__SC_COMP'
      38 | __SC_COMP(__NR_io_submit, sys_io_submit, compat_sys_io_submit)
         | ^~~~~~~~~
   arch/arc/kernel/sys.c:13:36: warning: initialized field overwritten [-Woverride-init]
      13 | #define __SYSCALL(nr, call) [nr] = (call),
         |                                    ^
   include/uapi/asm-generic/unistd.h:40:1: note: in expansion of macro '__SYSCALL'
      40 | __SYSCALL(__NR_io_cancel, sys_io_cancel)
         | ^~~~~~~~~
   arch/arc/kernel/sys.c:13:36: note: (near initialization for 'sys_call_table[3]')
      13 | #define __SYSCALL(nr, call) [nr] = (call),
         |                                    ^
   include/uapi/asm-generic/unistd.h:40:1: note: in expansion of macro '__SYSCALL'
      40 | __SYSCALL(__NR_io_cancel, sys_io_cancel)
         | ^~~~~~~~~
   arch/arc/kernel/sys.c:13:36: warning: initialized field overwritten [-Woverride-init]
      13 | #define __SYSCALL(nr, call) [nr] = (call),
         |                                    ^
   include/uapi/asm-generic/unistd.h:20:34: note: in expansion of macro '__SYSCALL'
      20 | #define __SC_3264(_nr, _32, _64) __SYSCALL(_nr, _32)
         |                                  ^~~~~~~~~
   include/uapi/asm-generic/unistd.h:43:1: note: in expansion of macro '__SC_3264'
      43 | __SC_3264(__NR_io_getevents, sys_io_getevents_time32, sys_io_getevents)
         | ^~~~~~~~~
   arch/arc/kernel/sys.c:13:36: note: (near initialization for 'sys_call_table[4]')
      13 | #define __SYSCALL(nr, call) [nr] = (call),
         |                                    ^
   include/uapi/asm-generic/unistd.h:20:34: note: in expansion of macro '__SYSCALL'
      20 | #define __SC_3264(_nr, _32, _64) __SYSCALL(_nr, _32)
         |                                  ^~~~~~~~~
   include/uapi/asm-generic/unistd.h:43:1: note: in expansion of macro '__SC_3264'
      43 | __SC_3264(__NR_io_getevents, sys_io_getevents_time32, sys_io_getevents)
         | ^~~~~~~~~
   arch/arc/kernel/sys.c:13:36: warning: initialized field overwritten [-Woverride-init]
      13 | #define __SYSCALL(nr, call) [nr] = (call),
         |                                    ^
   include/uapi/asm-generic/unistd.h:48:1: note: in expansion of macro '__SYSCALL'
      48 | __SYSCALL(__NR_setxattr, sys_setxattr)
         | ^~~~~~~~~
   arch/arc/kernel/sys.c:13:36: note: (near initialization for 'sys_call_table[5]')
      13 | #define __SYSCALL(nr, call) [nr] = (call),
         |                                    ^
   include/uapi/asm-generic/unistd.h:48:1: note: in expansion of macro '__SYSCALL'
      48 | __SYSCALL(__NR_setxattr, sys_setxattr)
         | ^~~~~~~~~
   arch/arc/kernel/sys.c:13:36: warning: initialized field overwritten [-Woverride-init]
      13 | #define __SYSCALL(nr, call) [nr] = (call),
         |                                    ^
   include/uapi/asm-generic/unistd.h:50:1: note: in expansion of macro '__SYSCALL'
      50 | __SYSCALL(__NR_lsetxattr, sys_lsetxattr)
         | ^~~~~~~~~
   arch/arc/kernel/sys.c:13:36: note: (near initialization for 'sys_call_table[6]')
      13 | #define __SYSCALL(nr, call) [nr] = (call),


vim +1060 include/linux/syscalls.h

   904	
   905	/* mm/, CONFIG_MMU only */
   906	asmlinkage long sys_swapon(const char __user *specialfile, int swap_flags);
   907	asmlinkage long sys_swapoff(const char __user *specialfile);
   908	asmlinkage long sys_mprotect(unsigned long start, size_t len,
   909					unsigned long prot);
   910	asmlinkage long sys_msync(unsigned long start, size_t len, int flags);
   911	asmlinkage long sys_mlock(unsigned long start, size_t len);
   912	asmlinkage long sys_munlock(unsigned long start, size_t len);
   913	asmlinkage long sys_mlockall(int flags);
   914	asmlinkage long sys_munlockall(void);
   915	asmlinkage long sys_mincore(unsigned long start, size_t len,
   916					unsigned char __user * vec);
   917	asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior);
   918	asmlinkage long sys_process_madvise(int pidfd, const struct iovec __user *vec,
   919				size_t vlen, int behavior, unsigned int flags);
   920	asmlinkage long sys_process_mrelease(int pidfd, unsigned int flags);
   921	asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
   922				unsigned long prot, unsigned long pgoff,
   923				unsigned long flags);
   924	asmlinkage long sys_mbind(unsigned long start, unsigned long len,
   925					unsigned long mode,
   926					const unsigned long __user *nmask,
   927					unsigned long maxnode,
   928					unsigned flags);
   929	asmlinkage long sys_get_mempolicy(int __user *policy,
   930					unsigned long __user *nmask,
   931					unsigned long maxnode,
   932					unsigned long addr, unsigned long flags);
   933	asmlinkage long sys_set_mempolicy(int mode, const unsigned long __user *nmask,
   934					unsigned long maxnode);
   935	asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
   936					const unsigned long __user *from,
   937					const unsigned long __user *to);
   938	asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
   939					const void __user * __user *pages,
   940					const int __user *nodes,
   941					int __user *status,
   942					int flags);
   943	
   944	asmlinkage long sys_rt_tgsigqueueinfo(pid_t tgid, pid_t  pid, int sig,
   945			siginfo_t __user *uinfo);
   946	asmlinkage long sys_perf_event_open(
   947			struct perf_event_attr __user *attr_uptr,
   948			pid_t pid, int cpu, int group_fd, unsigned long flags);
   949	asmlinkage long sys_accept4(int, struct sockaddr __user *, int __user *, int);
   950	asmlinkage long sys_recvmmsg(int fd, struct mmsghdr __user *msg,
   951				     unsigned int vlen, unsigned flags,
   952				     struct __kernel_timespec __user *timeout);
   953	asmlinkage long sys_recvmmsg_time32(int fd, struct mmsghdr __user *msg,
   954				     unsigned int vlen, unsigned flags,
   955				     struct old_timespec32 __user *timeout);
   956	
   957	asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr,
   958					int options, struct rusage __user *ru);
   959	asmlinkage long sys_prlimit64(pid_t pid, unsigned int resource,
   960					const struct rlimit64 __user *new_rlim,
   961					struct rlimit64 __user *old_rlim);
   962	asmlinkage long sys_fanotify_init(unsigned int flags, unsigned int event_f_flags);
   963	asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags,
   964					  u64 mask, int fd,
   965					  const char  __user *pathname);
   966	asmlinkage long sys_name_to_handle_at(int dfd, const char __user *name,
   967					      struct file_handle __user *handle,
   968					      int __user *mnt_id, int flag);
   969	asmlinkage long sys_open_by_handle_at(int mountdirfd,
   970					      struct file_handle __user *handle,
   971					      int flags);
   972	asmlinkage long sys_clock_adjtime(clockid_t which_clock,
   973					struct __kernel_timex __user *tx);
   974	asmlinkage long sys_clock_adjtime32(clockid_t which_clock,
   975					struct old_timex32 __user *tx);
   976	asmlinkage long sys_syncfs(int fd);
   977	asmlinkage long sys_setns(int fd, int nstype);
   978	asmlinkage long sys_pidfd_open(pid_t pid, unsigned int flags);
   979	asmlinkage long sys_sendmmsg(int fd, struct mmsghdr __user *msg,
   980				     unsigned int vlen, unsigned flags);
   981	asmlinkage long sys_process_vm_readv(pid_t pid,
   982					     const struct iovec __user *lvec,
   983					     unsigned long liovcnt,
   984					     const struct iovec __user *rvec,
   985					     unsigned long riovcnt,
   986					     unsigned long flags);
   987	asmlinkage long sys_process_vm_writev(pid_t pid,
   988					      const struct iovec __user *lvec,
   989					      unsigned long liovcnt,
   990					      const struct iovec __user *rvec,
   991					      unsigned long riovcnt,
   992					      unsigned long flags);
   993	asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
   994				 unsigned long idx1, unsigned long idx2);
   995	asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags);
   996	asmlinkage long sys_sched_setattr(pid_t pid,
   997						struct sched_attr __user *attr,
   998						unsigned int flags);
   999	asmlinkage long sys_sched_getattr(pid_t pid,
  1000						struct sched_attr __user *attr,
  1001						unsigned int size,
  1002						unsigned int flags);
  1003	asmlinkage long sys_renameat2(int olddfd, const char __user *oldname,
  1004				      int newdfd, const char __user *newname,
  1005				      unsigned int flags);
  1006	asmlinkage long sys_seccomp(unsigned int op, unsigned int flags,
  1007				    void __user *uargs);
  1008	asmlinkage long sys_getrandom(char __user *buf, size_t count,
  1009				      unsigned int flags);
  1010	asmlinkage long sys_memfd_create(const char __user *uname_ptr, unsigned int flags);
  1011	asmlinkage long sys_bpf(int cmd, union bpf_attr *attr, unsigned int size);
  1012	asmlinkage long sys_execveat(int dfd, const char __user *filename,
  1013				const char __user *const __user *argv,
  1014				const char __user *const __user *envp, int flags);
  1015	asmlinkage long sys_userfaultfd(int flags);
  1016	asmlinkage long sys_membarrier(int cmd, unsigned int flags, int cpu_id);
  1017	asmlinkage long sys_mlock2(unsigned long start, size_t len, int flags);
  1018	asmlinkage long sys_copy_file_range(int fd_in, loff_t __user *off_in,
  1019					    int fd_out, loff_t __user *off_out,
  1020					    size_t len, unsigned int flags);
  1021	asmlinkage long sys_preadv2(unsigned long fd, const struct iovec __user *vec,
  1022				    unsigned long vlen, unsigned long pos_l, unsigned long pos_h,
  1023				    rwf_t flags);
  1024	asmlinkage long sys_pwritev2(unsigned long fd, const struct iovec __user *vec,
  1025				    unsigned long vlen, unsigned long pos_l, unsigned long pos_h,
  1026				    rwf_t flags);
  1027	asmlinkage long sys_pkey_mprotect(unsigned long start, size_t len,
  1028					  unsigned long prot, int pkey);
  1029	asmlinkage long sys_pkey_alloc(unsigned long flags, unsigned long init_val);
  1030	asmlinkage long sys_pkey_free(int pkey);
  1031	asmlinkage long sys_statx(int dfd, const char __user *path, unsigned flags,
  1032				  unsigned mask, struct statx __user *buffer);
  1033	asmlinkage long sys_rseq(struct rseq __user *rseq, uint32_t rseq_len,
  1034				 int flags, uint32_t sig);
  1035	asmlinkage long sys_open_tree(int dfd, const char __user *path, unsigned flags);
  1036	asmlinkage long sys_move_mount(int from_dfd, const char __user *from_path,
  1037				       int to_dfd, const char __user *to_path,
  1038				       unsigned int ms_flags);
  1039	asmlinkage long sys_mount_setattr(int dfd, const char __user *path,
  1040					  unsigned int flags,
  1041					  struct mount_attr __user *uattr, size_t usize);
  1042	asmlinkage long sys_fsopen(const char __user *fs_name, unsigned int flags);
  1043	asmlinkage long sys_fsconfig(int fs_fd, unsigned int cmd, const char __user *key,
  1044				     const void __user *value, int aux);
  1045	asmlinkage long sys_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags);
  1046	asmlinkage long sys_fspick(int dfd, const char __user *path, unsigned int flags);
  1047	asmlinkage long sys_pidfd_send_signal(int pidfd, int sig,
  1048					       siginfo_t __user *info,
  1049					       unsigned int flags);
  1050	asmlinkage long sys_pidfd_getfd(int pidfd, int fd, unsigned int flags);
  1051	asmlinkage long sys_landlock_create_ruleset(const struct landlock_ruleset_attr __user *attr,
  1052			size_t size, __u32 flags);
  1053	asmlinkage long sys_landlock_add_rule(int ruleset_fd, enum landlock_rule_type rule_type,
  1054			const void __user *rule_attr, __u32 flags);
  1055	asmlinkage long sys_landlock_restrict_self(int ruleset_fd, __u32 flags);
  1056	asmlinkage long sys_memfd_secret(unsigned int flags);
  1057	asmlinkage long sys_set_mempolicy_home_node(unsigned long start, unsigned long len,
  1058						    unsigned long home_node,
  1059						    unsigned long flags);
> 1060	asmlinkage long sys_lsm_get_self_attr(struct lsm_ctx *ctx, size_t *size,
  1061					      int flags);
  1062
  
kernel test robot Dec. 4, 2022, 2:16 a.m. UTC | #2
Hi Casey,

I love your patch! Yet something to improve:

[auto build test ERROR on tip/perf/core]
[also build test ERROR on acme/perf/core shuah-kselftest/next shuah-kselftest/fixes linus/master v6.1-rc7]
[cannot apply to next-20221202]
[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/20221124-051600
patch link:    https://lore.kernel.org/r/20221123201552.7865-6-casey%40schaufler-ca.com
patch subject: [PATCH v3 5/9] LSM: lsm_get_self_attr syscall for LSM self attributes
config: openrisc-randconfig-m031-20221204
compiler: or1k-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/3ac4c5ad809a20ae21e121f48716bade40790d55
        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/20221124-051600
        git checkout 3ac4c5ad809a20ae21e121f48716bade40790d55
        # 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=openrisc 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:46: warning: 'struct lsm_ctx' declared inside parameter list will not be visible outside of this definition or declaration
    1060 | asmlinkage long sys_lsm_get_self_attr(struct lsm_ctx *ctx, size_t *size,
         |                                              ^~~~~~~
>> include/linux/syscalls.h:243:25: error: conflicting types for 'sys_lsm_get_self_attr'; have 'long int(struct lsm_ctx *, __kernel_size_t *, __u32)' {aka 'long int(struct lsm_ctx *, unsigned int *, unsigned int)'}
     243 |         asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))       \
         |                         ^~~
   include/linux/syscalls.h:229:9: note: in expansion of macro '__SYSCALL_DEFINEx'
     229 |         __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
         |         ^~~~~~~~~~~~~~~~~
   include/linux/syscalls.h:220:36: note: in expansion of macro 'SYSCALL_DEFINEx'
     220 | #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
         |                                    ^~~~~~~~~~~~~~~
   security/lsm_syscalls.c:61:1: note: in expansion of macro 'SYSCALL_DEFINE3'
      61 | SYSCALL_DEFINE3(lsm_get_self_attr,
         | ^~~~~~~~~~~~~~~
   include/linux/syscalls.h:1060:17: note: previous declaration of 'sys_lsm_get_self_attr' with type 'long int(struct lsm_ctx *, size_t *, int)' {aka 'long int(struct lsm_ctx *, unsigned int *, int)'}
    1060 | asmlinkage long sys_lsm_get_self_attr(struct lsm_ctx *ctx, size_t *size,
         |                 ^~~~~~~~~~~~~~~~~~~~~


vim +243 include/linux/syscalls.h

1bd21c6c21e848 Dominik Brodowski   2018-04-05  232  
e145242ea0df6b Dominik Brodowski   2018-04-09  233  /*
e145242ea0df6b Dominik Brodowski   2018-04-09  234   * The asmlinkage stub is aliased to a function named __se_sys_*() which
e145242ea0df6b Dominik Brodowski   2018-04-09  235   * sign-extends 32-bit ints to longs whenever needed. The actual work is
e145242ea0df6b Dominik Brodowski   2018-04-09  236   * done within __do_sys_*().
e145242ea0df6b Dominik Brodowski   2018-04-09  237   */
1bd21c6c21e848 Dominik Brodowski   2018-04-05  238  #ifndef __SYSCALL_DEFINEx
bed1ffca022cc8 Frederic Weisbecker 2009-03-13  239  #define __SYSCALL_DEFINEx(x, name, ...)					\
bee20031772af3 Arnd Bergmann       2018-06-19  240  	__diag_push();							\
bee20031772af3 Arnd Bergmann       2018-06-19  241  	__diag_ignore(GCC, 8, "-Wattribute-alias",			\
bee20031772af3 Arnd Bergmann       2018-06-19  242  		      "Type aliasing is used to sanitize syscall arguments");\
83460ec8dcac14 Andi Kleen          2013-11-12 @243  	asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))	\
e145242ea0df6b Dominik Brodowski   2018-04-09  244  		__attribute__((alias(__stringify(__se_sys##name))));	\
c9a211951c7c79 Howard McLauchlan   2018-03-21  245  	ALLOW_ERROR_INJECTION(sys##name, ERRNO);			\
e145242ea0df6b Dominik Brodowski   2018-04-09  246  	static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
e145242ea0df6b Dominik Brodowski   2018-04-09  247  	asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__));	\
e145242ea0df6b Dominik Brodowski   2018-04-09  248  	asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))	\
1a94bc34768e46 Heiko Carstens      2009-01-14  249  	{								\
e145242ea0df6b Dominik Brodowski   2018-04-09  250  		long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\
07fe6e00f6cca6 Al Viro             2013-01-21  251  		__MAP(x,__SC_TEST,__VA_ARGS__);				\
2cf0966683430b Al Viro             2013-01-21  252  		__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));	\
2cf0966683430b Al Viro             2013-01-21  253  		return ret;						\
1a94bc34768e46 Heiko Carstens      2009-01-14  254  	}								\
bee20031772af3 Arnd Bergmann       2018-06-19  255  	__diag_pop();							\
e145242ea0df6b Dominik Brodowski   2018-04-09  256  	static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
1bd21c6c21e848 Dominik Brodowski   2018-04-05  257  #endif /* __SYSCALL_DEFINEx */
1a94bc34768e46 Heiko Carstens      2009-01-14  258
  

Patch

diff --git a/Documentation/userspace-api/lsm.rst b/Documentation/userspace-api/lsm.rst
index 6ddf5506110b..98a0c191b499 100644
--- a/Documentation/userspace-api/lsm.rst
+++ b/Documentation/userspace-api/lsm.rst
@@ -48,6 +48,15 @@  creating socket objects.
 The proc filesystem provides this value in ``/proc/self/attr/sockcreate``.
 This is supported by the SELinux security module.
 
+Kernel interface
+================
+
+Get the security attributes of the current process
+--------------------------------------------------
+
+.. kernel-doc:: security/lsm_syscalls.c
+    :identifiers: sys_lsm_get_self_attr
+
 Additional documentation
 ========================
 
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index a34b0f9a9972..2f2434adec4a 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -71,6 +71,7 @@  struct clone_args;
 struct open_how;
 struct mount_attr;
 struct landlock_ruleset_attr;
+struct lsm_cxt;
 enum landlock_rule_type;
 
 #include <linux/types.h>
@@ -1056,6 +1057,8 @@  asmlinkage long sys_memfd_secret(unsigned int flags);
 asmlinkage long sys_set_mempolicy_home_node(unsigned long start, unsigned long len,
 					    unsigned long home_node,
 					    unsigned long flags);
+asmlinkage long sys_lsm_get_self_attr(struct lsm_ctx *ctx, size_t *size,
+				      int flags);
 
 /*
  * Architecture-specific system calls
diff --git a/include/uapi/linux/lsm.h b/include/uapi/linux/lsm.h
index 8e9124bf622c..a400ae056d22 100644
--- a/include/uapi/linux/lsm.h
+++ b/include/uapi/linux/lsm.h
@@ -9,6 +9,27 @@ 
 #ifndef _UAPI_LINUX_LSM_H
 #define _UAPI_LINUX_LSM_H
 
+#include <linux/types.h>
+#include <linux/unistd.h>
+
+/**
+ * struct lsm_ctx - LSM context
+ * @id: the LSM id number, see LSM_ID_XXX
+ * @flags: context specifier and LSM specific flags
+ * @ctx_len: the size of @ctx
+ * @ctx: the LSM context, a nul terminated string
+ *
+ * @ctx in a nul terminated string.
+ *	(strlen(@ctx) < @ctx_len) is always true.
+ *	(strlen(@ctx) == @ctx_len + 1) is not guaranteed.
+ */
+struct lsm_ctx {
+	__u32		id;
+	__u64		flags;
+	__kernel_size_t	ctx_len;
+	__u8		ctx[];
+};
+
 /*
  * ID values to identify security modules.
  * A system may use more than one security module.
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 860b2dcf3ac4..7b2513d5605d 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -262,6 +262,9 @@  COND_SYSCALL_COMPAT(recvmsg);
 /* mm/nommu.c, also with MMU */
 COND_SYSCALL(mremap);
 
+/* security/lsm_syscalls.c */
+COND_SYSCALL(lsm_get_self_attr);
+
 /* security/keys/keyctl.c */
 COND_SYSCALL(add_key);
 COND_SYSCALL(request_key);
diff --git a/security/Makefile b/security/Makefile
index 18121f8f85cd..59f238490665 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -7,6 +7,7 @@  obj-$(CONFIG_KEYS)			+= keys/
 
 # always enable default capabilities
 obj-y					+= commoncap.o
+obj-$(CONFIG_SECURITY) 			+= lsm_syscalls.o
 obj-$(CONFIG_MMU)			+= min_addr.o
 
 # Object file lists
diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c
new file mode 100644
index 000000000000..c109a0dc18fe
--- /dev/null
+++ b/security/lsm_syscalls.c
@@ -0,0 +1,182 @@ 
+// 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>
+
+struct attrs_used_map {
+	char *name;
+	int attrs_used;
+};
+
+static const struct attrs_used_map lsm_attr_names[] = {
+	{ .name = "current",	.attrs_used = LSM_ATTR_CURRENT, },
+	{ .name = "exec",	.attrs_used = LSM_ATTR_EXEC, },
+	{ .name = "fscreate",	.attrs_used = LSM_ATTR_FSCREATE, },
+	{ .name = "keycreate",	.attrs_used = LSM_ATTR_KEYCREATE, },
+	{ .name = "prev",	.attrs_used = LSM_ATTR_PREV, },
+	{ .name = "sockcreate",	.attrs_used = LSM_ATTR_SOCKCREATE, },
+};
+
+static int attr_used_index(u32 flags)
+{
+	int i;
+
+	if (flags == 0)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(lsm_attr_names); i++)
+		if ((lsm_attr_names[i].attrs_used & flags) == flags)
+			return i;
+
+	return -EINVAL;
+}
+
+/**
+ * sys_lsm_get_self_attr - Return current task's security module attributes
+ * @ctx: the LSM contexts
+ * @size: size of @ctx, updated on return
+ * @flags: which attribute to return
+ *
+ * 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_DEFINE3(lsm_get_self_attr,
+		struct lsm_ctx __user *, ctx,
+		__kernel_size_t __user *, size,
+		__u32, flags)
+{
+	int i;
+	int rc = 0;
+	int len;
+	int attr;
+	int count = 0;
+	void *curr;
+	char *cp;
+	char *np;
+	char **interum_ctx;
+	size_t total_size = 0;
+	struct lsm_ctx *ip;
+	struct lsm_ctx *interum;
+	struct lsm_ctx *final = NULL;
+
+	attr = attr_used_index(flags);
+	if (attr < 0)
+		return attr;
+
+	interum = kzalloc(ARRAY_SIZE(lsm_attr_names) * lsm_active_cnt *
+			  sizeof(*interum), GFP_KERNEL);
+	if (interum == NULL)
+		return -ENOMEM;
+	ip = interum;
+
+	interum_ctx = kzalloc(ARRAY_SIZE(lsm_attr_names) * lsm_active_cnt *
+			      sizeof(*interum_ctx), GFP_KERNEL);
+	if (interum_ctx == NULL) {
+		kfree(interum);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < lsm_active_cnt; i++) {
+		if ((lsm_idlist[i]->attrs_used &
+		     lsm_attr_names[attr].attrs_used) == 0)
+			continue;
+
+		len = security_getprocattr(current, lsm_idlist[i]->id,
+					   lsm_attr_names[attr].name,
+					   &cp);
+		if (len <= 0)
+			continue;
+
+		ip->id = lsm_idlist[i]->id;
+		ip->flags = lsm_attr_names[attr].attrs_used;
+		interum_ctx[count] = cp;
+
+		/*
+		 * A security module that returns a binary attribute
+		 * will need to identify itself to prevent string
+		 * processing.
+		 *
+		 * At least one security module adds a \n at the
+		 * end of a context to make it look nicer. Change
+		 * that to a \0 so that user space doesn't have to
+		 * work around it.
+		 *
+		 * Security modules have been inconsistent about
+		 * including the \0 terminator in the size. If it's
+		 * not there make space for it.
+		 *
+		 * The length returned will reflect the length of
+		 * the string provided by the security module, which
+		 * may not match what getprocattr returned.
+		 */
+		np = strnchr(cp, len, '\n');
+		if (np != NULL)
+			*np = '\0';
+		ip->ctx_len = strnlen(cp, len) + 1;
+		total_size += sizeof(*interum) + ip->ctx_len;
+		ip++;
+		count++;
+	}
+
+	if (count == 0)
+		goto free_out;
+
+	final = kzalloc(total_size, GFP_KERNEL);
+	if (final == NULL) {
+		rc = -ENOMEM;
+		goto free_out;
+	}
+
+	curr = final;
+	ip = interum;
+	for (i = 0; i < count; i++) {
+		memcpy(curr, ip, sizeof(*interum));
+		curr += sizeof(*interum);
+		if (ip->ctx_len > 1)
+			memcpy(curr, interum_ctx[i], ip->ctx_len - 1);
+		curr += ip->ctx_len;
+		ip++;
+	}
+
+	if (get_user(len, size)) {
+		rc = -EFAULT;
+		goto free_out;
+	}
+	if (total_size > len) {
+		rc = -ERANGE;
+		if (put_user(total_size, size) != 0)
+			rc = -EFAULT;
+		goto free_out;
+	}
+	if (copy_to_user(ctx, final, total_size) != 0 ||
+	    put_user(total_size, size) != 0)
+		rc = -EFAULT;
+	else
+		rc = count;
+
+free_out:
+	for (i = 0; i < count; i++)
+		kfree(interum_ctx[i]);
+	kfree(interum_ctx);
+	kfree(interum);
+	kfree(final);
+	return rc;
+}