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

Merge tag 'lsm-pr-20240105' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm

Pull security module updates from Paul Moore:

- Add three new syscalls: lsm_list_modules(), lsm_get_self_attr(), and
lsm_set_self_attr().

The first syscall simply lists the LSMs enabled, while the second and
third get and set the current process' LSM attributes. Yes, these
syscalls may provide similar functionality to what can be found under
/proc or /sys, but they were designed to support multiple,
simultaneaous (stacked) LSMs from the start as opposed to the current
/proc based solutions which were created at a time when only one LSM
was allowed to be active at a given time.

We have spent considerable time discussing ways to extend the
existing /proc interfaces to support multiple, simultaneaous LSMs and
even our best ideas have been far too ugly to support as a kernel
API; after +20 years in the kernel, I felt the LSM layer had
established itself enough to justify a handful of syscalls.

Support amongst the individual LSM developers has been nearly
unanimous, with a single objection coming from Tetsuo (TOMOYO) as he
is worried that the LSM_ID_XXX token concept will make it more
difficult for out-of-tree LSMs to survive. Several members of the LSM
community have demonstrated the ability for out-of-tree LSMs to
continue to exist by picking high/unused LSM_ID values as well as
pointing out that many kernel APIs rely on integer identifiers, e.g.
syscalls (!), but unfortunately Tetsuo's objections remain.

My personal opinion is that while I have no interest in penalizing
out-of-tree LSMs, I'm not going to penalize in-tree development to
support out-of-tree development, and I view this as a necessary step
forward to support the push for expanded LSM stacking and reduce our
reliance on /proc and /sys which has occassionally been problematic
for some container users. Finally, we have included the linux-api
folks on (all?) recent revisions of the patchset and addressed all of
their concerns.

- Add a new security_file_ioctl_compat() LSM hook to handle the 32-bit
ioctls on 64-bit systems problem.

This patch includes support for all of the existing LSMs which
provide ioctl hooks, although it turns out only SELinux actually
cares about the individual ioctls. It is worth noting that while
Casey (Smack) and Tetsuo (TOMOYO) did not give explicit ACKs to this
patch, they did both indicate they are okay with the changes.

- Fix a potential memory leak in the CALIPSO code when IPv6 is disabled
at boot.

While it's good that we are fixing this, I doubt this is something
users are seeing in the wild as you need to both disable IPv6 and
then attempt to configure IPv6 labeled networking via
NetLabel/CALIPSO; that just doesn't make much sense.

Normally this would go through netdev, but Jakub asked me to take
this patch and of all the trees I maintain, the LSM tree seemed like
the best fit.

- Update the LSM MAINTAINERS entry with additional information about
our process docs, patchwork, bug reporting, etc.

I also noticed that the Lockdown LSM is missing a dedicated
MAINTAINERS entry so I've added that to the pull request. I've been
working with one of the major Lockdown authors/contributors to see if
they are willing to step up and assume a Lockdown maintainer role;
hopefully that will happen soon, but in the meantime I'll continue to
look after it.

- Add a handful of mailmap entries for Serge Hallyn and myself.

* tag 'lsm-pr-20240105' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm: (27 commits)
lsm: new security_file_ioctl_compat() hook
lsm: Add a __counted_by() annotation to lsm_ctx.ctx
calipso: fix memory leak in netlbl_calipso_add_pass()
selftests: remove the LSM_ID_IMA check in lsm/lsm_list_modules_test
MAINTAINERS: add an entry for the lockdown LSM
MAINTAINERS: update the LSM entry
mailmap: add entries for Serge Hallyn's dead accounts
mailmap: update/replace my old email addresses
lsm: mark the lsm_id variables are marked as static
lsm: convert security_setselfattr() to use memdup_user()
lsm: align based on pointer length in lsm_fill_user_ctx()
lsm: consolidate buffer size handling into lsm_fill_user_ctx()
lsm: correct error codes in security_getselfattr()
lsm: cleanup the size counters in security_getselfattr()
lsm: don't yet account for IMA in LSM_CONFIG_COUNT calculation
lsm: drop LSM_ID_IMA
LSM: selftests for Linux Security Module syscalls
SELinux: Add selfattr hooks
AppArmor: Add selfattr hooks
Smack: implement setselfattr and getselfattr hooks
...

+1784 -122
+4
.mailmap
··· 478 478 Paul E. McKenney <paulmck@kernel.org> <paulmck@us.ibm.com> 479 479 Paul Mackerras <paulus@ozlabs.org> <paulus@samba.org> 480 480 Paul Mackerras <paulus@ozlabs.org> <paulus@au1.ibm.com> 481 + Paul Moore <paul@paul-moore.com> <paul.moore@hp.com> 482 + Paul Moore <paul@paul-moore.com> <pmoore@redhat.com> 481 483 Pavankumar Kondeti <quic_pkondeti@quicinc.com> <pkondeti@codeaurora.org> 482 484 Peter A Jonsson <pj@ludd.ltu.se> 483 485 Peter Oruba <peter.oruba@amd.com> ··· 544 542 Sebastian Reichel <sre@kernel.org> <sre@debian.org> 545 543 Sedat Dilek <sedat.dilek@gmail.com> <sedat.dilek@credativ.de> 546 544 Senthilkumar N L <quic_snlakshm@quicinc.com> <snlakshm@codeaurora.org> 545 + Serge Hallyn <sergeh@kernel.org> <serge.hallyn@canonical.com> 546 + Serge Hallyn <sergeh@kernel.org> <serue@us.ibm.com> 547 547 Seth Forshee <sforshee@kernel.org> <seth.forshee@canonical.com> 548 548 Shannon Nelson <shannon.nelson@amd.com> <snelson@pensando.io> 549 549 Shannon Nelson <shannon.nelson@amd.com> <shannon.nelson@intel.com>
+1
Documentation/userspace-api/index.rst
··· 33 33 sysfs-platform_profile 34 34 vduse 35 35 futex2 36 + lsm 36 37 37 38 .. only:: subproject and html 38 39
+73
Documentation/userspace-api/lsm.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. Copyright (C) 2022 Casey Schaufler <casey@schaufler-ca.com> 3 + .. Copyright (C) 2022 Intel Corporation 4 + 5 + ===================================== 6 + Linux Security Modules 7 + ===================================== 8 + 9 + :Author: Casey Schaufler 10 + :Date: July 2023 11 + 12 + Linux security modules (LSM) provide a mechanism to implement 13 + additional access controls to the Linux security policies. 14 + 15 + The various security modules may support any of these attributes: 16 + 17 + ``LSM_ATTR_CURRENT`` is the current, active security context of the 18 + process. 19 + The proc filesystem provides this value in ``/proc/self/attr/current``. 20 + This is supported by the SELinux, Smack and AppArmor security modules. 21 + Smack also provides this value in ``/proc/self/attr/smack/current``. 22 + AppArmor also provides this value in ``/proc/self/attr/apparmor/current``. 23 + 24 + ``LSM_ATTR_EXEC`` is the security context of the process at the time the 25 + current image was executed. 26 + The proc filesystem provides this value in ``/proc/self/attr/exec``. 27 + This is supported by the SELinux and AppArmor security modules. 28 + AppArmor also provides this value in ``/proc/self/attr/apparmor/exec``. 29 + 30 + ``LSM_ATTR_FSCREATE`` is the security context of the process used when 31 + creating file system objects. 32 + The proc filesystem provides this value in ``/proc/self/attr/fscreate``. 33 + This is supported by the SELinux security module. 34 + 35 + ``LSM_ATTR_KEYCREATE`` is the security context of the process used when 36 + creating key objects. 37 + The proc filesystem provides this value in ``/proc/self/attr/keycreate``. 38 + This is supported by the SELinux security module. 39 + 40 + ``LSM_ATTR_PREV`` is the security context of the process at the time the 41 + current security context was set. 42 + The proc filesystem provides this value in ``/proc/self/attr/prev``. 43 + This is supported by the SELinux and AppArmor security modules. 44 + AppArmor also provides this value in ``/proc/self/attr/apparmor/prev``. 45 + 46 + ``LSM_ATTR_SOCKCREATE`` is the security context of the process used when 47 + creating socket objects. 48 + The proc filesystem provides this value in ``/proc/self/attr/sockcreate``. 49 + This is supported by the SELinux security module. 50 + 51 + Kernel interface 52 + ================ 53 + 54 + Set a security attribute of the current process 55 + ----------------------------------------------- 56 + 57 + .. kernel-doc:: security/lsm_syscalls.c 58 + :identifiers: sys_lsm_set_self_attr 59 + 60 + Get the specified security attributes of the current process 61 + ------------------------------------------------------------ 62 + 63 + .. kernel-doc:: security/lsm_syscalls.c 64 + :identifiers: sys_lsm_get_self_attr 65 + 66 + .. kernel-doc:: security/lsm_syscalls.c 67 + :identifiers: sys_lsm_list_modules 68 + 69 + Additional documentation 70 + ======================== 71 + 72 + * Documentation/security/lsm.rst 73 + * Documentation/security/lsm-development.rst
+14 -3
MAINTAINERS
··· 12417 12417 F: Documentation/admin-guide/LSM/LoadPin.rst 12418 12418 F: security/loadpin/ 12419 12419 12420 + LOCKDOWN SECURITY MODULE 12421 + L: linux-security-module@vger.kernel.org 12422 + S: Odd Fixes 12423 + T: git https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm.git 12424 + F: security/lockdown/ 12425 + 12420 12426 LOCKING PRIMITIVES 12421 12427 M: Peter Zijlstra <peterz@infradead.org> 12422 12428 M: Ingo Molnar <mingo@redhat.com> ··· 19461 19455 M: Paul Moore <paul@paul-moore.com> 19462 19456 M: James Morris <jmorris@namei.org> 19463 19457 M: "Serge E. Hallyn" <serge@hallyn.com> 19464 - L: linux-security-module@vger.kernel.org (suggested Cc:) 19458 + L: linux-security-module@vger.kernel.org 19465 19459 S: Supported 19466 - W: http://kernsec.org/ 19467 - T: git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm.git 19460 + Q: https://patchwork.kernel.org/project/linux-security-module/list 19461 + B: mailto:linux-security-module@vger.kernel.org 19462 + P: https://github.com/LinuxSecurityModule/kernel/blob/main/README.md 19463 + T: git https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm.git 19464 + F: include/uapi/linux/lsm.h 19468 19465 F: security/ 19466 + F: tools/testing/selftests/lsm/ 19469 19467 X: security/selinux/ 19468 + K: \bsecurity_[a-z_0-9]\+\b 19470 19469 19471 19470 SELINUX SECURITY MODULE 19472 19471 M: Paul Moore <paul@paul-moore.com>
+3
arch/alpha/kernel/syscalls/syscall.tbl
··· 498 498 566 common futex_requeue sys_futex_requeue 499 499 567 common statmount sys_statmount 500 500 568 common listmount sys_listmount 501 + 569 common lsm_get_self_attr sys_lsm_get_self_attr 502 + 570 common lsm_set_self_attr sys_lsm_set_self_attr 503 + 571 common lsm_list_modules sys_lsm_list_modules
+3
arch/arm/tools/syscall.tbl
··· 472 472 456 common futex_requeue sys_futex_requeue 473 473 457 common statmount sys_statmount 474 474 458 common listmount sys_listmount 475 + 459 common lsm_get_self_attr sys_lsm_get_self_attr 476 + 460 common lsm_set_self_attr sys_lsm_set_self_attr 477 + 461 common lsm_list_modules sys_lsm_list_modules
+1 -1
arch/arm64/include/asm/unistd.h
··· 39 39 #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5) 40 40 #define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800) 41 41 42 - #define __NR_compat_syscalls 459 42 + #define __NR_compat_syscalls 462 43 43 #endif 44 44 45 45 #define __ARCH_WANT_SYS_CLONE
+6
arch/arm64/include/asm/unistd32.h
··· 923 923 __SYSCALL(__NR_statmount, sys_statmount) 924 924 #define __NR_listmount 458 925 925 __SYSCALL(__NR_listmount, sys_listmount) 926 + #define __NR_lsm_get_self_attr 459 927 + __SYSCALL(__NR_lsm_get_self_attr, sys_lsm_get_self_attr) 928 + #define __NR_lsm_set_self_attr 460 929 + __SYSCALL(__NR_lsm_set_self_attr, sys_lsm_set_self_attr) 930 + #define __NR_lsm_list_modules 461 931 + __SYSCALL(__NR_lsm_list_modules, sys_lsm_list_modules) 926 932 927 933 /* 928 934 * Please add new compat syscalls above this comment and update
+3
arch/m68k/kernel/syscalls/syscall.tbl
··· 458 458 456 common futex_requeue sys_futex_requeue 459 459 457 common statmount sys_statmount 460 460 458 common listmount sys_listmount 461 + 459 common lsm_get_self_attr sys_lsm_get_self_attr 462 + 460 common lsm_set_self_attr sys_lsm_set_self_attr 463 + 461 common lsm_list_modules sys_lsm_list_modules
+3
arch/microblaze/kernel/syscalls/syscall.tbl
··· 464 464 456 common futex_requeue sys_futex_requeue 465 465 457 common statmount sys_statmount 466 466 458 common listmount sys_listmount 467 + 459 common lsm_get_self_attr sys_lsm_get_self_attr 468 + 460 common lsm_set_self_attr sys_lsm_set_self_attr 469 + 461 common lsm_list_modules sys_lsm_list_modules
+3
arch/mips/kernel/syscalls/syscall_n32.tbl
··· 397 397 456 n32 futex_requeue sys_futex_requeue 398 398 457 n32 statmount sys_statmount 399 399 458 n32 listmount sys_listmount 400 + 459 n32 lsm_get_self_attr sys_lsm_get_self_attr 401 + 460 n32 lsm_set_self_attr sys_lsm_set_self_attr 402 + 461 n32 lsm_list_modules sys_lsm_list_modules
+3
arch/mips/kernel/syscalls/syscall_n64.tbl
··· 373 373 456 n64 futex_requeue sys_futex_requeue 374 374 457 n64 statmount sys_statmount 375 375 458 n64 listmount sys_listmount 376 + 459 n64 lsm_get_self_attr sys_lsm_get_self_attr 377 + 460 n64 lsm_set_self_attr sys_lsm_set_self_attr 378 + 461 n64 lsm_list_modules sys_lsm_list_modules
+3
arch/mips/kernel/syscalls/syscall_o32.tbl
··· 446 446 456 o32 futex_requeue sys_futex_requeue 447 447 457 o32 statmount sys_statmount 448 448 458 o32 listmount sys_listmount 449 + 459 o32 lsm_get_self_attr sys_lsm_get_self_attr 450 + 460 o32 lsm_set_self_attr sys_lsm_set_self_attr 451 + 461 o32 lsm_list_modules sys_lsm_list_modules
+3
arch/parisc/kernel/syscalls/syscall.tbl
··· 457 457 456 common futex_requeue sys_futex_requeue 458 458 457 common statmount sys_statmount 459 459 458 common listmount sys_listmount 460 + 459 common lsm_get_self_attr sys_lsm_get_self_attr 461 + 460 common lsm_set_self_attr sys_lsm_set_self_attr 462 + 461 common lsm_list_modules sys_lsm_list_modules
+3
arch/powerpc/kernel/syscalls/syscall.tbl
··· 545 545 456 common futex_requeue sys_futex_requeue 546 546 457 common statmount sys_statmount 547 547 458 common listmount sys_listmount 548 + 459 common lsm_get_self_attr sys_lsm_get_self_attr 549 + 460 common lsm_set_self_attr sys_lsm_set_self_attr 550 + 461 common lsm_list_modules sys_lsm_list_modules
+3
arch/s390/kernel/syscalls/syscall.tbl
··· 461 461 456 common futex_requeue sys_futex_requeue sys_futex_requeue 462 462 457 common statmount sys_statmount sys_statmount 463 463 458 common listmount sys_listmount sys_listmount 464 + 459 common lsm_get_self_attr sys_lsm_get_self_attr sys_lsm_get_self_attr 465 + 460 common lsm_set_self_attr sys_lsm_set_self_attr sys_lsm_set_self_attr 466 + 461 common lsm_list_modules sys_lsm_list_modules sys_lsm_list_modules
+3
arch/sh/kernel/syscalls/syscall.tbl
··· 461 461 456 common futex_requeue sys_futex_requeue 462 462 457 common statmount sys_statmount 463 463 458 common listmount sys_listmount 464 + 459 common lsm_get_self_attr sys_lsm_get_self_attr 465 + 460 common lsm_set_self_attr sys_lsm_set_self_attr 466 + 461 common lsm_list_modules sys_lsm_list_modules
+3
arch/sparc/kernel/syscalls/syscall.tbl
··· 504 504 456 common futex_requeue sys_futex_requeue 505 505 457 common statmount sys_statmount 506 506 458 common listmount sys_listmount 507 + 459 common lsm_get_self_attr sys_lsm_get_self_attr 508 + 460 common lsm_set_self_attr sys_lsm_set_self_attr 509 + 461 common lsm_list_modules sys_lsm_list_modules
+3
arch/x86/entry/syscalls/syscall_32.tbl
··· 463 463 456 i386 futex_requeue sys_futex_requeue 464 464 457 i386 statmount sys_statmount 465 465 458 i386 listmount sys_listmount 466 + 459 i386 lsm_get_self_attr sys_lsm_get_self_attr 467 + 460 i386 lsm_set_self_attr sys_lsm_set_self_attr 468 + 461 i386 lsm_list_modules sys_lsm_list_modules
+3
arch/x86/entry/syscalls/syscall_64.tbl
··· 380 380 456 common futex_requeue sys_futex_requeue 381 381 457 common statmount sys_statmount 382 382 458 common listmount sys_listmount 383 + 459 common lsm_get_self_attr sys_lsm_get_self_attr 384 + 460 common lsm_set_self_attr sys_lsm_set_self_attr 385 + 461 common lsm_list_modules sys_lsm_list_modules 383 386 384 387 # 385 388 # Due to a historical design error, certain syscalls are numbered differently
+3
arch/xtensa/kernel/syscalls/syscall.tbl
··· 429 429 456 common futex_requeue sys_futex_requeue 430 430 457 common statmount sys_statmount 431 431 458 common listmount sys_listmount 432 + 459 common lsm_get_self_attr sys_lsm_get_self_attr 433 + 460 common lsm_set_self_attr sys_lsm_set_self_attr 434 + 461 common lsm_list_modules sys_lsm_list_modules
+1 -2
fs/ioctl.c
··· 920 920 if (!f.file) 921 921 return -EBADF; 922 922 923 - /* RED-PEN how should LSM module know it's handling 32bit? */ 924 - error = security_file_ioctl(f.file, cmd, arg); 923 + error = security_file_ioctl_compat(f.file, cmd, arg); 925 924 if (error) 926 925 goto out; 927 926
+15 -14
fs/proc/base.c
··· 97 97 #include <linux/resctrl.h> 98 98 #include <linux/cn_proc.h> 99 99 #include <linux/ksm.h> 100 + #include <uapi/linux/lsm.h> 100 101 #include <trace/events/oom.h> 101 102 #include "internal.h" 102 103 #include "fd.h" ··· 147 146 NOD(NAME, (S_IFREG|(MODE)), \ 148 147 NULL, &proc_single_file_operations, \ 149 148 { .proc_show = show } ) 150 - #define ATTR(LSM, NAME, MODE) \ 149 + #define ATTR(LSMID, NAME, MODE) \ 151 150 NOD(NAME, (S_IFREG|(MODE)), \ 152 151 NULL, &proc_pid_attr_operations, \ 153 - { .lsm = LSM }) 152 + { .lsmid = LSMID }) 154 153 155 154 /* 156 155 * Count the number of hardlinks for the pid_entry table, excluding the . ··· 2727 2726 if (!task) 2728 2727 return -ESRCH; 2729 2728 2730 - length = security_getprocattr(task, PROC_I(inode)->op.lsm, 2729 + length = security_getprocattr(task, PROC_I(inode)->op.lsmid, 2731 2730 file->f_path.dentry->d_name.name, 2732 2731 &p); 2733 2732 put_task_struct(task); ··· 2785 2784 if (rv < 0) 2786 2785 goto out_free; 2787 2786 2788 - rv = security_setprocattr(PROC_I(inode)->op.lsm, 2787 + rv = security_setprocattr(PROC_I(inode)->op.lsmid, 2789 2788 file->f_path.dentry->d_name.name, page, 2790 2789 count); 2791 2790 mutex_unlock(&current->signal->cred_guard_mutex); ··· 2834 2833 2835 2834 #ifdef CONFIG_SECURITY_SMACK 2836 2835 static const struct pid_entry smack_attr_dir_stuff[] = { 2837 - ATTR("smack", "current", 0666), 2836 + ATTR(LSM_ID_SMACK, "current", 0666), 2838 2837 }; 2839 2838 LSM_DIR_OPS(smack); 2840 2839 #endif 2841 2840 2842 2841 #ifdef CONFIG_SECURITY_APPARMOR 2843 2842 static const struct pid_entry apparmor_attr_dir_stuff[] = { 2844 - ATTR("apparmor", "current", 0666), 2845 - ATTR("apparmor", "prev", 0444), 2846 - ATTR("apparmor", "exec", 0666), 2843 + ATTR(LSM_ID_APPARMOR, "current", 0666), 2844 + ATTR(LSM_ID_APPARMOR, "prev", 0444), 2845 + ATTR(LSM_ID_APPARMOR, "exec", 0666), 2847 2846 }; 2848 2847 LSM_DIR_OPS(apparmor); 2849 2848 #endif 2850 2849 2851 2850 static const struct pid_entry attr_dir_stuff[] = { 2852 - ATTR(NULL, "current", 0666), 2853 - ATTR(NULL, "prev", 0444), 2854 - ATTR(NULL, "exec", 0666), 2855 - ATTR(NULL, "fscreate", 0666), 2856 - ATTR(NULL, "keycreate", 0666), 2857 - ATTR(NULL, "sockcreate", 0666), 2851 + ATTR(LSM_ID_UNDEF, "current", 0666), 2852 + ATTR(LSM_ID_UNDEF, "prev", 0444), 2853 + ATTR(LSM_ID_UNDEF, "exec", 0666), 2854 + ATTR(LSM_ID_UNDEF, "fscreate", 0666), 2855 + ATTR(LSM_ID_UNDEF, "keycreate", 0666), 2856 + ATTR(LSM_ID_UNDEF, "sockcreate", 0666), 2858 2857 #ifdef CONFIG_SECURITY_SMACK 2859 2858 DIR("smack", 0555, 2860 2859 proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
+1 -1
fs/proc/internal.h
··· 92 92 int (*proc_show)(struct seq_file *m, 93 93 struct pid_namespace *ns, struct pid *pid, 94 94 struct task_struct *task); 95 - const char *lsm; 95 + int lsmid; 96 96 }; 97 97 98 98 struct proc_inode {
+6
include/linux/lsm_hook_defs.h
··· 171 171 LSM_HOOK(void, LSM_RET_VOID, file_free_security, struct file *file) 172 172 LSM_HOOK(int, 0, file_ioctl, struct file *file, unsigned int cmd, 173 173 unsigned long arg) 174 + LSM_HOOK(int, 0, file_ioctl_compat, struct file *file, unsigned int cmd, 175 + unsigned long arg) 174 176 LSM_HOOK(int, 0, mmap_addr, unsigned long addr) 175 177 LSM_HOOK(int, 0, mmap_file, struct file *file, unsigned long reqprot, 176 178 unsigned long prot, unsigned long flags) ··· 264 262 LSM_HOOK(int, 0, netlink_send, struct sock *sk, struct sk_buff *skb) 265 263 LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry, 266 264 struct inode *inode) 265 + LSM_HOOK(int, -EOPNOTSUPP, getselfattr, unsigned int attr, 266 + struct lsm_ctx __user *ctx, size_t *size, u32 flags) 267 + LSM_HOOK(int, -EOPNOTSUPP, setselfattr, unsigned int attr, 268 + struct lsm_ctx *ctx, size_t size, u32 flags) 267 269 LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name, 268 270 char **value) 269 271 LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size)
+15 -2
include/linux/lsm_hooks.h
··· 25 25 #ifndef __LINUX_LSM_HOOKS_H 26 26 #define __LINUX_LSM_HOOKS_H 27 27 28 + #include <uapi/linux/lsm.h> 28 29 #include <linux/security.h> 29 30 #include <linux/init.h> 30 31 #include <linux/rculist.h> ··· 43 42 #undef LSM_HOOK 44 43 } __randomize_layout; 45 44 45 + /** 46 + * struct lsm_id - Identify a Linux Security Module. 47 + * @lsm: name of the LSM, must be approved by the LSM maintainers 48 + * @id: LSM ID number from uapi/linux/lsm.h 49 + * 50 + * Contains the information that identifies the LSM. 51 + */ 52 + struct lsm_id { 53 + const char *name; 54 + u64 id; 55 + }; 56 + 46 57 /* 47 58 * Security module hook list structure. 48 59 * For use with generic list macros for common operations. ··· 63 50 struct hlist_node list; 64 51 struct hlist_head *head; 65 52 union security_list_options hook; 66 - const char *lsm; 53 + const struct lsm_id *lsmid; 67 54 } __randomize_layout; 68 55 69 56 /* ··· 117 104 extern char *lsm_names; 118 105 119 106 extern void security_add_hooks(struct security_hook_list *hooks, int count, 120 - const char *lsm); 107 + const struct lsm_id *lsmid); 121 108 122 109 #define LSM_FLAG_LEGACY_MAJOR BIT(0) 123 110 #define LSM_FLAG_EXCLUSIVE BIT(1)
+50 -6
include/linux/security.h
··· 32 32 #include <linux/string.h> 33 33 #include <linux/mm.h> 34 34 #include <linux/sockptr.h> 35 + #include <uapi/linux/lsm.h> 35 36 36 37 struct linux_binprm; 37 38 struct cred; ··· 61 60 enum fs_value_type; 62 61 struct watch; 63 62 struct watch_notification; 63 + struct lsm_ctx; 64 64 65 65 /* Default (no) options for the capable function */ 66 66 #define CAP_OPT_NONE 0x0 ··· 140 138 }; 141 139 142 140 extern const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1]; 141 + extern u32 lsm_active_cnt; 142 + extern const struct lsm_id *lsm_idlist[]; 143 143 144 144 /* These functions are in security/commoncap.c */ 145 145 extern int cap_capable(const struct cred *cred, struct user_namespace *ns, ··· 265 261 /* prototypes */ 266 262 extern int security_init(void); 267 263 extern int early_security_init(void); 264 + extern u64 lsm_name_to_attr(const char *name); 268 265 269 266 /* Security operations */ 270 267 int security_binder_set_context_mgr(const struct cred *mgr); ··· 394 389 int security_file_alloc(struct file *file); 395 390 void security_file_free(struct file *file); 396 391 int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 392 + int security_file_ioctl_compat(struct file *file, unsigned int cmd, 393 + unsigned long arg); 397 394 int security_mmap_file(struct file *file, unsigned long prot, 398 395 unsigned long flags); 399 396 int security_mmap_addr(unsigned long addr); ··· 477 470 int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, 478 471 unsigned nsops, int alter); 479 472 void security_d_instantiate(struct dentry *dentry, struct inode *inode); 480 - int security_getprocattr(struct task_struct *p, const char *lsm, const char *name, 473 + int security_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, 474 + size_t __user *size, u32 flags); 475 + int security_setselfattr(unsigned int attr, struct lsm_ctx __user *ctx, 476 + size_t size, u32 flags); 477 + int security_getprocattr(struct task_struct *p, int lsmid, const char *name, 481 478 char **value); 482 - int security_setprocattr(const char *lsm, const char *name, void *value, 483 - size_t size); 479 + int security_setprocattr(int lsmid, const char *name, void *value, size_t size); 484 480 int security_netlink_send(struct sock *sk, struct sk_buff *skb); 485 481 int security_ismaclabel(const char *name); 486 482 int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); ··· 494 484 int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); 495 485 int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); 496 486 int security_locked_down(enum lockdown_reason what); 487 + int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, size_t *uctx_len, 488 + void *val, size_t val_len, u64 id, u64 flags); 497 489 #else /* CONFIG_SECURITY */ 498 490 499 491 static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data) ··· 511 499 static inline int unregister_blocking_lsm_notifier(struct notifier_block *nb) 512 500 { 513 501 return 0; 502 + } 503 + 504 + static inline u64 lsm_name_to_attr(const char *name) 505 + { 506 + return LSM_ATTR_UNDEF; 514 507 } 515 508 516 509 static inline void security_free_mnt_opts(void **mnt_opts) ··· 1004 987 return 0; 1005 988 } 1006 989 990 + static inline int security_file_ioctl_compat(struct file *file, 991 + unsigned int cmd, 992 + unsigned long arg) 993 + { 994 + return 0; 995 + } 996 + 1007 997 static inline int security_mmap_file(struct file *file, unsigned long prot, 1008 998 unsigned long flags) 1009 999 { ··· 1361 1337 struct inode *inode) 1362 1338 { } 1363 1339 1364 - static inline int security_getprocattr(struct task_struct *p, const char *lsm, 1340 + static inline int security_getselfattr(unsigned int attr, 1341 + struct lsm_ctx __user *ctx, 1342 + size_t __user *size, u32 flags) 1343 + { 1344 + return -EOPNOTSUPP; 1345 + } 1346 + 1347 + static inline int security_setselfattr(unsigned int attr, 1348 + struct lsm_ctx __user *ctx, 1349 + size_t size, u32 flags) 1350 + { 1351 + return -EOPNOTSUPP; 1352 + } 1353 + 1354 + static inline int security_getprocattr(struct task_struct *p, int lsmid, 1365 1355 const char *name, char **value) 1366 1356 { 1367 1357 return -EINVAL; 1368 1358 } 1369 1359 1370 - static inline int security_setprocattr(const char *lsm, char *name, 1371 - void *value, size_t size) 1360 + static inline int security_setprocattr(int lsmid, char *name, void *value, 1361 + size_t size) 1372 1362 { 1373 1363 return -EINVAL; 1374 1364 } ··· 1432 1394 static inline int security_locked_down(enum lockdown_reason what) 1433 1395 { 1434 1396 return 0; 1397 + } 1398 + static inline int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, 1399 + size_t *uctx_len, void *val, size_t val_len, 1400 + u64 id, u64 flags) 1401 + { 1402 + return -EOPNOTSUPP; 1435 1403 } 1436 1404 #endif /* CONFIG_SECURITY */ 1437 1405
+6
include/linux/syscalls.h
··· 71 71 struct open_how; 72 72 struct mount_attr; 73 73 struct landlock_ruleset_attr; 74 + struct lsm_ctx; 74 75 enum landlock_rule_type; 75 76 struct cachestat_range; 76 77 struct cachestat; ··· 958 957 struct cachestat_range __user *cstat_range, 959 958 struct cachestat __user *cstat, unsigned int flags); 960 959 asmlinkage long sys_map_shadow_stack(unsigned long addr, unsigned long size, unsigned int flags); 960 + asmlinkage long sys_lsm_get_self_attr(unsigned int attr, struct lsm_ctx *ctx, 961 + size_t *size, __u32 flags); 962 + asmlinkage long sys_lsm_set_self_attr(unsigned int attr, struct lsm_ctx *ctx, 963 + size_t size, __u32 flags); 964 + asmlinkage long sys_lsm_list_modules(u64 *ids, size_t *size, u32 flags); 961 965 962 966 /* 963 967 * Architecture-specific system calls
+8 -1
include/uapi/asm-generic/unistd.h
··· 835 835 #define __NR_listmount 458 836 836 __SYSCALL(__NR_listmount, sys_listmount) 837 837 838 + #define __NR_lsm_get_self_attr 459 839 + __SYSCALL(__NR_lsm_get_self_attr, sys_lsm_get_self_attr) 840 + #define __NR_lsm_set_self_attr 460 841 + __SYSCALL(__NR_lsm_set_self_attr, sys_lsm_set_self_attr) 842 + #define __NR_lsm_list_modules 461 843 + __SYSCALL(__NR_lsm_list_modules, sys_lsm_list_modules) 844 + 838 845 #undef __NR_syscalls 839 - #define __NR_syscalls 459 846 + #define __NR_syscalls 462 840 847 841 848 /* 842 849 * 32 bit systems traditionally used different
+90
include/uapi/linux/lsm.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 + /* 3 + * Linux Security Modules (LSM) - User space API 4 + * 5 + * Copyright (C) 2022 Casey Schaufler <casey@schaufler-ca.com> 6 + * Copyright (C) 2022 Intel Corporation 7 + */ 8 + 9 + #ifndef _UAPI_LINUX_LSM_H 10 + #define _UAPI_LINUX_LSM_H 11 + 12 + #include <linux/stddef.h> 13 + #include <linux/types.h> 14 + #include <linux/unistd.h> 15 + 16 + /** 17 + * struct lsm_ctx - LSM context information 18 + * @id: the LSM id number, see LSM_ID_XXX 19 + * @flags: LSM specific flags 20 + * @len: length of the lsm_ctx struct, @ctx and any other data or padding 21 + * @ctx_len: the size of @ctx 22 + * @ctx: the LSM context value 23 + * 24 + * The @len field MUST be equal to the size of the lsm_ctx struct 25 + * plus any additional padding and/or data placed after @ctx. 26 + * 27 + * In all cases @ctx_len MUST be equal to the length of @ctx. 28 + * If @ctx is a string value it should be nul terminated with 29 + * @ctx_len equal to `strlen(@ctx) + 1`. Binary values are 30 + * supported. 31 + * 32 + * The @flags and @ctx fields SHOULD only be interpreted by the 33 + * LSM specified by @id; they MUST be set to zero/0 when not used. 34 + */ 35 + struct lsm_ctx { 36 + __u64 id; 37 + __u64 flags; 38 + __u64 len; 39 + __u64 ctx_len; 40 + __u8 ctx[] __counted_by(ctx_len); 41 + }; 42 + 43 + /* 44 + * ID tokens to identify Linux Security Modules (LSMs) 45 + * 46 + * These token values are used to uniquely identify specific LSMs 47 + * in the kernel as well as in the kernel's LSM userspace API. 48 + * 49 + * A value of zero/0 is considered undefined and should not be used 50 + * outside the kernel. Values 1-99 are reserved for potential 51 + * future use. 52 + */ 53 + #define LSM_ID_UNDEF 0 54 + #define LSM_ID_CAPABILITY 100 55 + #define LSM_ID_SELINUX 101 56 + #define LSM_ID_SMACK 102 57 + #define LSM_ID_TOMOYO 103 58 + #define LSM_ID_APPARMOR 104 59 + #define LSM_ID_YAMA 105 60 + #define LSM_ID_LOADPIN 106 61 + #define LSM_ID_SAFESETID 107 62 + #define LSM_ID_LOCKDOWN 108 63 + #define LSM_ID_BPF 109 64 + #define LSM_ID_LANDLOCK 110 65 + 66 + /* 67 + * LSM_ATTR_XXX definitions identify different LSM attributes 68 + * which are used in the kernel's LSM userspace API. Support 69 + * for these attributes vary across the different LSMs. None 70 + * are required. 71 + * 72 + * A value of zero/0 is considered undefined and should not be used 73 + * outside the kernel. Values 1-99 are reserved for potential 74 + * future use. 75 + */ 76 + #define LSM_ATTR_UNDEF 0 77 + #define LSM_ATTR_CURRENT 100 78 + #define LSM_ATTR_EXEC 101 79 + #define LSM_ATTR_FSCREATE 102 80 + #define LSM_ATTR_KEYCREATE 103 81 + #define LSM_ATTR_PREV 104 82 + #define LSM_ATTR_SOCKCREATE 105 83 + 84 + /* 85 + * LSM_FLAG_XXX definitions identify special handling instructions 86 + * for the API. 87 + */ 88 + #define LSM_FLAG_SINGLE 0x0001 89 + 90 + #endif /* _UAPI_LINUX_LSM_H */
+3
kernel/sys_ni.c
··· 171 171 COND_SYSCALL(landlock_restrict_self); 172 172 COND_SYSCALL(fadvise64_64); 173 173 COND_SYSCALL_COMPAT(fadvise64_64); 174 + COND_SYSCALL(lsm_get_self_attr); 175 + COND_SYSCALL(lsm_set_self_attr); 176 + COND_SYSCALL(lsm_list_modules); 174 177 175 178 /* CONFIG_MMU only */ 176 179 COND_SYSCALL(swapon);
+26 -23
net/netlabel/netlabel_calipso.c
··· 54 54 [NLBL_CALIPSO_A_MTYPE] = { .type = NLA_U32 }, 55 55 }; 56 56 57 + static const struct netlbl_calipso_ops *calipso_ops; 58 + 59 + /** 60 + * netlbl_calipso_ops_register - Register the CALIPSO operations 61 + * @ops: ops to register 62 + * 63 + * Description: 64 + * Register the CALIPSO packet engine operations. 65 + * 66 + */ 67 + const struct netlbl_calipso_ops * 68 + netlbl_calipso_ops_register(const struct netlbl_calipso_ops *ops) 69 + { 70 + return xchg(&calipso_ops, ops); 71 + } 72 + EXPORT_SYMBOL(netlbl_calipso_ops_register); 73 + 74 + static const struct netlbl_calipso_ops *netlbl_calipso_ops_get(void) 75 + { 76 + return READ_ONCE(calipso_ops); 77 + } 78 + 57 79 /* NetLabel Command Handlers 58 80 */ 59 81 /** ··· 118 96 * 119 97 */ 120 98 static int netlbl_calipso_add(struct sk_buff *skb, struct genl_info *info) 121 - 122 99 { 123 100 int ret_val = -EINVAL; 124 101 struct netlbl_audit audit_info; 102 + const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get(); 125 103 126 104 if (!info->attrs[NLBL_CALIPSO_A_DOI] || 127 105 !info->attrs[NLBL_CALIPSO_A_MTYPE]) 128 106 return -EINVAL; 107 + 108 + if (!ops) 109 + return -EOPNOTSUPP; 129 110 130 111 netlbl_netlink_auditinfo(&audit_info); 131 112 switch (nla_get_u32(info->attrs[NLBL_CALIPSO_A_MTYPE])) { ··· 386 361 int __init netlbl_calipso_genl_init(void) 387 362 { 388 363 return genl_register_family(&netlbl_calipso_gnl_family); 389 - } 390 - 391 - static const struct netlbl_calipso_ops *calipso_ops; 392 - 393 - /** 394 - * netlbl_calipso_ops_register - Register the CALIPSO operations 395 - * @ops: ops to register 396 - * 397 - * Description: 398 - * Register the CALIPSO packet engine operations. 399 - * 400 - */ 401 - const struct netlbl_calipso_ops * 402 - netlbl_calipso_ops_register(const struct netlbl_calipso_ops *ops) 403 - { 404 - return xchg(&calipso_ops, ops); 405 - } 406 - EXPORT_SYMBOL(netlbl_calipso_ops_register); 407 - 408 - static const struct netlbl_calipso_ops *netlbl_calipso_ops_get(void) 409 - { 410 - return READ_ONCE(calipso_ops); 411 364 } 412 365 413 366 /**
+1
security/Makefile
··· 7 7 8 8 # always enable default capabilities 9 9 obj-y += commoncap.o 10 + obj-$(CONFIG_SECURITY) += lsm_syscalls.o 10 11 obj-$(CONFIG_MMU) += min_addr.o 11 12 12 13 # Object file lists
+1 -1
security/apparmor/include/procattr.h
··· 11 11 #ifndef __AA_PROCATTR_H 12 12 #define __AA_PROCATTR_H 13 13 14 - int aa_getprocattr(struct aa_label *label, char **string); 14 + int aa_getprocattr(struct aa_label *label, char **string, bool newline); 15 15 int aa_setprocattr_changehat(char *args, size_t size, int flags); 16 16 17 17 #endif /* __AA_PROCATTR_H */
+83 -7
security/apparmor/lsm.c
··· 24 24 #include <linux/zstd.h> 25 25 #include <net/sock.h> 26 26 #include <uapi/linux/mount.h> 27 + #include <uapi/linux/lsm.h> 27 28 28 29 #include "include/apparmor.h" 29 30 #include "include/apparmorfs.h" ··· 776 775 return error; 777 776 } 778 777 778 + static int apparmor_getselfattr(unsigned int attr, struct lsm_ctx __user *lx, 779 + size_t *size, u32 flags) 780 + { 781 + int error = -ENOENT; 782 + struct aa_task_ctx *ctx = task_ctx(current); 783 + struct aa_label *label = NULL; 784 + char *value; 785 + 786 + switch (attr) { 787 + case LSM_ATTR_CURRENT: 788 + label = aa_get_newest_label(cred_label(current_cred())); 789 + break; 790 + case LSM_ATTR_PREV: 791 + if (ctx->previous) 792 + label = aa_get_newest_label(ctx->previous); 793 + break; 794 + case LSM_ATTR_EXEC: 795 + if (ctx->onexec) 796 + label = aa_get_newest_label(ctx->onexec); 797 + break; 798 + default: 799 + error = -EOPNOTSUPP; 800 + break; 801 + } 802 + 803 + if (label) { 804 + error = aa_getprocattr(label, &value, false); 805 + if (error > 0) 806 + error = lsm_fill_user_ctx(lx, size, value, error, 807 + LSM_ID_APPARMOR, 0); 808 + kfree(value); 809 + } 810 + 811 + aa_put_label(label); 812 + 813 + if (error < 0) 814 + return error; 815 + return 1; 816 + } 817 + 779 818 static int apparmor_getprocattr(struct task_struct *task, const char *name, 780 819 char **value) 781 820 { ··· 835 794 error = -EINVAL; 836 795 837 796 if (label) 838 - error = aa_getprocattr(label, value); 797 + error = aa_getprocattr(label, value, true); 839 798 840 799 aa_put_label(label); 841 800 put_cred(cred); ··· 843 802 return error; 844 803 } 845 804 846 - static int apparmor_setprocattr(const char *name, void *value, 847 - size_t size) 805 + static int do_setattr(u64 attr, void *value, size_t size) 848 806 { 849 807 char *command, *largs = NULL, *args = value; 850 808 size_t arg_size; ··· 874 834 goto out; 875 835 876 836 arg_size = size - (args - (largs ? largs : (char *) value)); 877 - if (strcmp(name, "current") == 0) { 837 + if (attr == LSM_ATTR_CURRENT) { 878 838 if (strcmp(command, "changehat") == 0) { 879 839 error = aa_setprocattr_changehat(args, arg_size, 880 840 AA_CHANGE_NOFLAGS); ··· 889 849 error = aa_change_profile(args, AA_CHANGE_STACK); 890 850 } else 891 851 goto fail; 892 - } else if (strcmp(name, "exec") == 0) { 852 + } else if (attr == LSM_ATTR_EXEC) { 893 853 if (strcmp(command, "exec") == 0) 894 854 error = aa_change_profile(args, AA_CHANGE_ONEXEC); 895 855 else if (strcmp(command, "stack") == 0) ··· 909 869 910 870 fail: 911 871 ad.subj_label = begin_current_label_crit_section(); 912 - ad.info = name; 872 + if (attr == LSM_ATTR_CURRENT) 873 + ad.info = "current"; 874 + else if (attr == LSM_ATTR_EXEC) 875 + ad.info = "exec"; 876 + else 877 + ad.info = "invalid"; 913 878 ad.error = error = -EINVAL; 914 879 aa_audit_msg(AUDIT_APPARMOR_DENIED, &ad, NULL); 915 880 end_current_label_crit_section(ad.subj_label); 916 881 goto out; 882 + } 883 + 884 + static int apparmor_setselfattr(unsigned int attr, struct lsm_ctx *ctx, 885 + size_t size, u32 flags) 886 + { 887 + int rc; 888 + 889 + if (attr != LSM_ATTR_CURRENT && attr != LSM_ATTR_EXEC) 890 + return -EOPNOTSUPP; 891 + 892 + rc = do_setattr(attr, ctx->ctx, ctx->ctx_len); 893 + if (rc > 0) 894 + return 0; 895 + return rc; 896 + } 897 + 898 + static int apparmor_setprocattr(const char *name, void *value, 899 + size_t size) 900 + { 901 + int attr = lsm_name_to_attr(name); 902 + 903 + if (attr) 904 + return do_setattr(attr, value, size); 905 + return -EINVAL; 917 906 } 918 907 919 908 /** ··· 1454 1385 .lbs_task = sizeof(struct aa_task_ctx), 1455 1386 }; 1456 1387 1388 + static const struct lsm_id apparmor_lsmid = { 1389 + .name = "apparmor", 1390 + .id = LSM_ID_APPARMOR, 1391 + }; 1392 + 1457 1393 static struct security_hook_list apparmor_hooks[] __ro_after_init = { 1458 1394 LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), 1459 1395 LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), ··· 1492 1418 LSM_HOOK_INIT(file_lock, apparmor_file_lock), 1493 1419 LSM_HOOK_INIT(file_truncate, apparmor_file_truncate), 1494 1420 1421 + LSM_HOOK_INIT(getselfattr, apparmor_getselfattr), 1422 + LSM_HOOK_INIT(setselfattr, apparmor_setselfattr), 1495 1423 LSM_HOOK_INIT(getprocattr, apparmor_getprocattr), 1496 1424 LSM_HOOK_INIT(setprocattr, apparmor_setprocattr), 1497 1425 ··· 2278 2202 goto buffers_out; 2279 2203 } 2280 2204 security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks), 2281 - "apparmor"); 2205 + &apparmor_lsmid); 2282 2206 2283 2207 /* Report that AppArmor successfully initialized */ 2284 2208 apparmor_initialized = 1;
+6 -4
security/apparmor/procattr.c
··· 20 20 * aa_getprocattr - Return the label information for @label 21 21 * @label: the label to print label info about (NOT NULL) 22 22 * @string: Returns - string containing the label info (NOT NULL) 23 + * @newline: indicates that a newline should be added 23 24 * 24 25 * Requires: label != NULL && string != NULL 25 26 * ··· 28 27 * 29 28 * Returns: size of string placed in @string else error code on failure 30 29 */ 31 - int aa_getprocattr(struct aa_label *label, char **string) 30 + int aa_getprocattr(struct aa_label *label, char **string, bool newline) 32 31 { 33 32 struct aa_ns *ns = labels_ns(label); 34 33 struct aa_ns *current_ns = aa_get_current_ns(); ··· 58 57 return len; 59 58 } 60 59 61 - (*string)[len] = '\n'; 62 - (*string)[len + 1] = 0; 60 + if (newline) 61 + (*string)[len++] = '\n'; 62 + (*string)[len] = 0; 63 63 64 64 aa_put_ns(current_ns); 65 - return len + 1; 65 + return len; 66 66 } 67 67 68 68 /**
+8 -1
security/bpf/hooks.c
··· 5 5 */ 6 6 #include <linux/lsm_hooks.h> 7 7 #include <linux/bpf_lsm.h> 8 + #include <uapi/linux/lsm.h> 8 9 9 10 static struct security_hook_list bpf_lsm_hooks[] __ro_after_init = { 10 11 #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ ··· 16 15 LSM_HOOK_INIT(task_free, bpf_task_storage_free), 17 16 }; 18 17 18 + static const struct lsm_id bpf_lsmid = { 19 + .name = "bpf", 20 + .id = LSM_ID_BPF, 21 + }; 22 + 19 23 static int __init bpf_lsm_init(void) 20 24 { 21 - security_add_hooks(bpf_lsm_hooks, ARRAY_SIZE(bpf_lsm_hooks), "bpf"); 25 + security_add_hooks(bpf_lsm_hooks, ARRAY_SIZE(bpf_lsm_hooks), 26 + &bpf_lsmid); 22 27 pr_info("LSM support for eBPF active\n"); 23 28 return 0; 24 29 }
+7 -1
security/commoncap.c
··· 25 25 #include <linux/binfmts.h> 26 26 #include <linux/personality.h> 27 27 #include <linux/mnt_idmapping.h> 28 + #include <uapi/linux/lsm.h> 28 29 29 30 /* 30 31 * If a non-root user executes a setuid-root binary in ··· 1441 1440 1442 1441 #ifdef CONFIG_SECURITY 1443 1442 1443 + static const struct lsm_id capability_lsmid = { 1444 + .name = "capability", 1445 + .id = LSM_ID_CAPABILITY, 1446 + }; 1447 + 1444 1448 static struct security_hook_list capability_hooks[] __ro_after_init = { 1445 1449 LSM_HOOK_INIT(capable, cap_capable), 1446 1450 LSM_HOOK_INIT(settime, cap_settime), ··· 1470 1464 static int __init capability_init(void) 1471 1465 { 1472 1466 security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks), 1473 - "capability"); 1467 + &capability_lsmid); 1474 1468 return 0; 1475 1469 } 1476 1470
+1 -1
security/landlock/cred.c
··· 42 42 __init void landlock_add_cred_hooks(void) 43 43 { 44 44 security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks), 45 - LANDLOCK_NAME); 45 + &landlock_lsmid); 46 46 }
+1 -1
security/landlock/fs.c
··· 1223 1223 __init void landlock_add_fs_hooks(void) 1224 1224 { 1225 1225 security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks), 1226 - LANDLOCK_NAME); 1226 + &landlock_lsmid); 1227 1227 }
+1 -1
security/landlock/net.c
··· 196 196 __init void landlock_add_net_hooks(void) 197 197 { 198 198 security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks), 199 - LANDLOCK_NAME); 199 + &landlock_lsmid); 200 200 }
+1 -1
security/landlock/ptrace.c
··· 116 116 __init void landlock_add_ptrace_hooks(void) 117 117 { 118 118 security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks), 119 - LANDLOCK_NAME); 119 + &landlock_lsmid); 120 120 }
+6
security/landlock/setup.c
··· 8 8 9 9 #include <linux/init.h> 10 10 #include <linux/lsm_hooks.h> 11 + #include <uapi/linux/lsm.h> 11 12 12 13 #include "common.h" 13 14 #include "cred.h" ··· 24 23 .lbs_file = sizeof(struct landlock_file_security), 25 24 .lbs_inode = sizeof(struct landlock_inode_security), 26 25 .lbs_superblock = sizeof(struct landlock_superblock_security), 26 + }; 27 + 28 + const struct lsm_id landlock_lsmid = { 29 + .name = LANDLOCK_NAME, 30 + .id = LSM_ID_LANDLOCK, 27 31 }; 28 32 29 33 static int __init landlock_init(void)
+1
security/landlock/setup.h
··· 14 14 extern bool landlock_initialized; 15 15 16 16 extern struct lsm_blob_sizes landlock_blob_sizes; 17 + extern const struct lsm_id landlock_lsmid; 17 18 18 19 #endif /* _SECURITY_LANDLOCK_SETUP_H */
+8 -1
security/loadpin/loadpin.c
··· 20 20 #include <linux/string_helpers.h> 21 21 #include <linux/dm-verity-loadpin.h> 22 22 #include <uapi/linux/loadpin.h> 23 + #include <uapi/linux/lsm.h> 23 24 24 25 #define VERITY_DIGEST_FILE_HEADER "# LOADPIN_TRUSTED_VERITY_ROOT_DIGESTS" 25 26 ··· 209 208 return loadpin_check(NULL, (enum kernel_read_file_id) id); 210 209 } 211 210 211 + static const struct lsm_id loadpin_lsmid = { 212 + .name = "loadpin", 213 + .id = LSM_ID_LOADPIN, 214 + }; 215 + 212 216 static struct security_hook_list loadpin_hooks[] __ro_after_init = { 213 217 LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security), 214 218 LSM_HOOK_INIT(kernel_read_file, loadpin_read_file), ··· 265 259 if (!register_sysctl("kernel/loadpin", loadpin_sysctl_table)) 266 260 pr_notice("sysctl registration failed!\n"); 267 261 #endif 268 - security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin"); 262 + security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), 263 + &loadpin_lsmid); 269 264 270 265 return 0; 271 266 }
+7 -1
security/lockdown/lockdown.c
··· 13 13 #include <linux/security.h> 14 14 #include <linux/export.h> 15 15 #include <linux/lsm_hooks.h> 16 + #include <uapi/linux/lsm.h> 16 17 17 18 static enum lockdown_reason kernel_locked_down; 18 19 ··· 76 75 LSM_HOOK_INIT(locked_down, lockdown_is_locked_down), 77 76 }; 78 77 78 + const struct lsm_id lockdown_lsmid = { 79 + .name = "lockdown", 80 + .id = LSM_ID_LOCKDOWN, 81 + }; 82 + 79 83 static int __init lockdown_lsm_init(void) 80 84 { 81 85 #if defined(CONFIG_LOCK_DOWN_KERNEL_FORCE_INTEGRITY) ··· 89 83 lock_kernel_down("Kernel configuration", LOCKDOWN_CONFIDENTIALITY_MAX); 90 84 #endif 91 85 security_add_hooks(lockdown_hooks, ARRAY_SIZE(lockdown_hooks), 92 - "lockdown"); 86 + &lockdown_lsmid); 93 87 return 0; 94 88 } 95 89
+120
security/lsm_syscalls.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * System calls implementing the Linux Security Module API. 4 + * 5 + * Copyright (C) 2022 Casey Schaufler <casey@schaufler-ca.com> 6 + * Copyright (C) 2022 Intel Corporation 7 + */ 8 + 9 + #include <asm/current.h> 10 + #include <linux/compiler_types.h> 11 + #include <linux/err.h> 12 + #include <linux/errno.h> 13 + #include <linux/security.h> 14 + #include <linux/stddef.h> 15 + #include <linux/syscalls.h> 16 + #include <linux/types.h> 17 + #include <linux/lsm_hooks.h> 18 + #include <uapi/linux/lsm.h> 19 + 20 + /** 21 + * lsm_name_to_attr - map an LSM attribute name to its ID 22 + * @name: name of the attribute 23 + * 24 + * Returns the LSM attribute value associated with @name, or 0 if 25 + * there is no mapping. 26 + */ 27 + u64 lsm_name_to_attr(const char *name) 28 + { 29 + if (!strcmp(name, "current")) 30 + return LSM_ATTR_CURRENT; 31 + if (!strcmp(name, "exec")) 32 + return LSM_ATTR_EXEC; 33 + if (!strcmp(name, "fscreate")) 34 + return LSM_ATTR_FSCREATE; 35 + if (!strcmp(name, "keycreate")) 36 + return LSM_ATTR_KEYCREATE; 37 + if (!strcmp(name, "prev")) 38 + return LSM_ATTR_PREV; 39 + if (!strcmp(name, "sockcreate")) 40 + return LSM_ATTR_SOCKCREATE; 41 + return LSM_ATTR_UNDEF; 42 + } 43 + 44 + /** 45 + * sys_lsm_set_self_attr - Set current task's security module attribute 46 + * @attr: which attribute to set 47 + * @ctx: the LSM contexts 48 + * @size: size of @ctx 49 + * @flags: reserved for future use 50 + * 51 + * Sets the calling task's LSM context. On success this function 52 + * returns 0. If the attribute specified cannot be set a negative 53 + * value indicating the reason for the error is returned. 54 + */ 55 + SYSCALL_DEFINE4(lsm_set_self_attr, unsigned int, attr, struct lsm_ctx __user *, 56 + ctx, size_t, size, u32, flags) 57 + { 58 + return security_setselfattr(attr, ctx, size, flags); 59 + } 60 + 61 + /** 62 + * sys_lsm_get_self_attr - Return current task's security module attributes 63 + * @attr: which attribute to return 64 + * @ctx: the user-space destination for the information, or NULL 65 + * @size: pointer to the size of space available to receive the data 66 + * @flags: special handling options. LSM_FLAG_SINGLE indicates that only 67 + * attributes associated with the LSM identified in the passed @ctx be 68 + * reported. 69 + * 70 + * Returns the calling task's LSM contexts. On success this 71 + * function returns the number of @ctx array elements. This value 72 + * may be zero if there are no LSM contexts assigned. If @size is 73 + * insufficient to contain the return data -E2BIG is returned and 74 + * @size is set to the minimum required size. In all other cases 75 + * a negative value indicating the error is returned. 76 + */ 77 + SYSCALL_DEFINE4(lsm_get_self_attr, unsigned int, attr, struct lsm_ctx __user *, 78 + ctx, size_t __user *, size, u32, flags) 79 + { 80 + return security_getselfattr(attr, ctx, size, flags); 81 + } 82 + 83 + /** 84 + * sys_lsm_list_modules - Return a list of the active security modules 85 + * @ids: the LSM module ids 86 + * @size: pointer to size of @ids, updated on return 87 + * @flags: reserved for future use, must be zero 88 + * 89 + * Returns a list of the active LSM ids. On success this function 90 + * returns the number of @ids array elements. This value may be zero 91 + * if there are no LSMs active. If @size is insufficient to contain 92 + * the return data -E2BIG is returned and @size is set to the minimum 93 + * required size. In all other cases a negative value indicating the 94 + * error is returned. 95 + */ 96 + SYSCALL_DEFINE3(lsm_list_modules, u64 __user *, ids, size_t __user *, size, 97 + u32, flags) 98 + { 99 + size_t total_size = lsm_active_cnt * sizeof(*ids); 100 + size_t usize; 101 + int i; 102 + 103 + if (flags) 104 + return -EINVAL; 105 + 106 + if (get_user(usize, size)) 107 + return -EFAULT; 108 + 109 + if (put_user(total_size, size) != 0) 110 + return -EFAULT; 111 + 112 + if (usize < total_size) 113 + return -E2BIG; 114 + 115 + for (i = 0; i < lsm_active_cnt; i++) 116 + if (put_user(lsm_idlist[i]->id, ids++)) 117 + return -EFAULT; 118 + 119 + return lsm_active_cnt; 120 + }
+8 -1
security/safesetid/lsm.c
··· 19 19 #include <linux/ptrace.h> 20 20 #include <linux/sched/task_stack.h> 21 21 #include <linux/security.h> 22 + #include <uapi/linux/lsm.h> 22 23 #include "lsm.h" 23 24 24 25 /* Flag indicating whether initialization completed */ ··· 262 261 return 0; 263 262 } 264 263 264 + static const struct lsm_id safesetid_lsmid = { 265 + .name = "safesetid", 266 + .id = LSM_ID_SAFESETID, 267 + }; 268 + 265 269 static struct security_hook_list safesetid_security_hooks[] = { 266 270 LSM_HOOK_INIT(task_fix_setuid, safesetid_task_fix_setuid), 267 271 LSM_HOOK_INIT(task_fix_setgid, safesetid_task_fix_setgid), ··· 277 271 static int __init safesetid_security_init(void) 278 272 { 279 273 security_add_hooks(safesetid_security_hooks, 280 - ARRAY_SIZE(safesetid_security_hooks), "safesetid"); 274 + ARRAY_SIZE(safesetid_security_hooks), 275 + &safesetid_lsmid); 281 276 282 277 /* Report that SafeSetID successfully initialized */ 283 278 safesetid_initialized = 1;
+261 -12
security/security.c
··· 35 35 #define LSM_COUNT (__end_lsm_info - __start_lsm_info) 36 36 37 37 /* 38 + * How many LSMs are built into the kernel as determined at 39 + * build time. Used to determine fixed array sizes. 40 + * The capability module is accounted for by CONFIG_SECURITY 41 + */ 42 + #define LSM_CONFIG_COUNT ( \ 43 + (IS_ENABLED(CONFIG_SECURITY) ? 1 : 0) + \ 44 + (IS_ENABLED(CONFIG_SECURITY_SELINUX) ? 1 : 0) + \ 45 + (IS_ENABLED(CONFIG_SECURITY_SMACK) ? 1 : 0) + \ 46 + (IS_ENABLED(CONFIG_SECURITY_TOMOYO) ? 1 : 0) + \ 47 + (IS_ENABLED(CONFIG_SECURITY_APPARMOR) ? 1 : 0) + \ 48 + (IS_ENABLED(CONFIG_SECURITY_YAMA) ? 1 : 0) + \ 49 + (IS_ENABLED(CONFIG_SECURITY_LOADPIN) ? 1 : 0) + \ 50 + (IS_ENABLED(CONFIG_SECURITY_SAFESETID) ? 1 : 0) + \ 51 + (IS_ENABLED(CONFIG_SECURITY_LOCKDOWN_LSM) ? 1 : 0) + \ 52 + (IS_ENABLED(CONFIG_BPF_LSM) ? 1 : 0) + \ 53 + (IS_ENABLED(CONFIG_SECURITY_LANDLOCK) ? 1 : 0)) 54 + 55 + /* 38 56 * These are descriptions of the reasons that can be passed to the 39 57 * security_locked_down() LSM hook. Placing this array here allows 40 58 * all security modules to use the same descriptions for auditing ··· 262 244 WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret); 263 245 } 264 246 } 247 + 248 + /* 249 + * Current index to use while initializing the lsm id list. 250 + */ 251 + u32 lsm_active_cnt __ro_after_init; 252 + const struct lsm_id *lsm_idlist[LSM_CONFIG_COUNT]; 265 253 266 254 /* Populate ordered LSMs list from comma-separated LSM name list. */ 267 255 static void __init ordered_lsm_parse(const char *order, const char *origin) ··· 537 513 * security_add_hooks - Add a modules hooks to the hook lists. 538 514 * @hooks: the hooks to add 539 515 * @count: the number of hooks to add 540 - * @lsm: the name of the security module 516 + * @lsmid: the identification information for the security module 541 517 * 542 518 * Each LSM has to register its hooks with the infrastructure. 543 519 */ 544 520 void __init security_add_hooks(struct security_hook_list *hooks, int count, 545 - const char *lsm) 521 + const struct lsm_id *lsmid) 546 522 { 547 523 int i; 548 524 525 + /* 526 + * A security module may call security_add_hooks() more 527 + * than once during initialization, and LSM initialization 528 + * is serialized. Landlock is one such case. 529 + * Look at the previous entry, if there is one, for duplication. 530 + */ 531 + if (lsm_active_cnt == 0 || lsm_idlist[lsm_active_cnt - 1] != lsmid) { 532 + if (lsm_active_cnt >= LSM_CONFIG_COUNT) 533 + panic("%s Too many LSMs registered.\n", __func__); 534 + lsm_idlist[lsm_active_cnt++] = lsmid; 535 + } 536 + 549 537 for (i = 0; i < count; i++) { 550 - hooks[i].lsm = lsm; 538 + hooks[i].lsmid = lsmid; 551 539 hlist_add_tail_rcu(&hooks[i].list, hooks[i].head); 552 540 } 553 541 ··· 568 532 * and fix this up afterwards. 569 533 */ 570 534 if (slab_is_available()) { 571 - if (lsm_append(lsm, &lsm_names) < 0) 535 + if (lsm_append(lsmid->name, &lsm_names) < 0) 572 536 panic("%s - Cannot get early memory.\n", __func__); 573 537 } 574 538 } ··· 768 732 if (sb->s_security == NULL) 769 733 return -ENOMEM; 770 734 return 0; 735 + } 736 + 737 + /** 738 + * lsm_fill_user_ctx - Fill a user space lsm_ctx structure 739 + * @uctx: a userspace LSM context to be filled 740 + * @uctx_len: available uctx size (input), used uctx size (output) 741 + * @val: the new LSM context value 742 + * @val_len: the size of the new LSM context value 743 + * @id: LSM id 744 + * @flags: LSM defined flags 745 + * 746 + * Fill all of the fields in a userspace lsm_ctx structure. 747 + * 748 + * Returns 0 on success, -E2BIG if userspace buffer is not large enough, 749 + * -EFAULT on a copyout error, -ENOMEM if memory can't be allocated. 750 + */ 751 + int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, size_t *uctx_len, 752 + void *val, size_t val_len, 753 + u64 id, u64 flags) 754 + { 755 + struct lsm_ctx *nctx = NULL; 756 + size_t nctx_len; 757 + int rc = 0; 758 + 759 + nctx_len = ALIGN(struct_size(nctx, ctx, val_len), sizeof(void *)); 760 + if (nctx_len > *uctx_len) { 761 + rc = -E2BIG; 762 + goto out; 763 + } 764 + 765 + nctx = kzalloc(nctx_len, GFP_KERNEL); 766 + if (nctx == NULL) { 767 + rc = -ENOMEM; 768 + goto out; 769 + } 770 + nctx->id = id; 771 + nctx->flags = flags; 772 + nctx->len = nctx_len; 773 + nctx->ctx_len = val_len; 774 + memcpy(nctx->ctx, val, val_len); 775 + 776 + if (copy_to_user(uctx, nctx, nctx_len)) 777 + rc = -EFAULT; 778 + 779 + out: 780 + kfree(nctx); 781 + *uctx_len = nctx_len; 782 + return rc; 771 783 } 772 784 773 785 /* ··· 2726 2642 } 2727 2643 EXPORT_SYMBOL_GPL(security_file_ioctl); 2728 2644 2645 + /** 2646 + * security_file_ioctl_compat() - Check if an ioctl is allowed in compat mode 2647 + * @file: associated file 2648 + * @cmd: ioctl cmd 2649 + * @arg: ioctl arguments 2650 + * 2651 + * Compat version of security_file_ioctl() that correctly handles 32-bit 2652 + * processes running on 64-bit kernels. 2653 + * 2654 + * Return: Returns 0 if permission is granted. 2655 + */ 2656 + int security_file_ioctl_compat(struct file *file, unsigned int cmd, 2657 + unsigned long arg) 2658 + { 2659 + return call_int_hook(file_ioctl_compat, 0, file, cmd, arg); 2660 + } 2661 + EXPORT_SYMBOL_GPL(security_file_ioctl_compat); 2662 + 2729 2663 static inline unsigned long mmap_prot(struct file *file, unsigned long prot) 2730 2664 { 2731 2665 /* ··· 3896 3794 } 3897 3795 EXPORT_SYMBOL(security_d_instantiate); 3898 3796 3797 + /* 3798 + * Please keep this in sync with it's counterpart in security/lsm_syscalls.c 3799 + */ 3800 + 3801 + /** 3802 + * security_getselfattr - Read an LSM attribute of the current process. 3803 + * @attr: which attribute to return 3804 + * @uctx: the user-space destination for the information, or NULL 3805 + * @size: pointer to the size of space available to receive the data 3806 + * @flags: special handling options. LSM_FLAG_SINGLE indicates that only 3807 + * attributes associated with the LSM identified in the passed @ctx be 3808 + * reported. 3809 + * 3810 + * A NULL value for @uctx can be used to get both the number of attributes 3811 + * and the size of the data. 3812 + * 3813 + * Returns the number of attributes found on success, negative value 3814 + * on error. @size is reset to the total size of the data. 3815 + * If @size is insufficient to contain the data -E2BIG is returned. 3816 + */ 3817 + int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx, 3818 + size_t __user *size, u32 flags) 3819 + { 3820 + struct security_hook_list *hp; 3821 + struct lsm_ctx lctx = { .id = LSM_ID_UNDEF, }; 3822 + u8 __user *base = (u8 __user *)uctx; 3823 + size_t total = 0; 3824 + size_t entrysize; 3825 + size_t left; 3826 + bool toobig = false; 3827 + bool single = false; 3828 + int count = 0; 3829 + int rc; 3830 + 3831 + if (attr == LSM_ATTR_UNDEF) 3832 + return -EINVAL; 3833 + if (size == NULL) 3834 + return -EINVAL; 3835 + if (get_user(left, size)) 3836 + return -EFAULT; 3837 + 3838 + if (flags) { 3839 + /* 3840 + * Only flag supported is LSM_FLAG_SINGLE 3841 + */ 3842 + if (flags != LSM_FLAG_SINGLE || !uctx) 3843 + return -EINVAL; 3844 + if (copy_from_user(&lctx, uctx, sizeof(lctx))) 3845 + return -EFAULT; 3846 + /* 3847 + * If the LSM ID isn't specified it is an error. 3848 + */ 3849 + if (lctx.id == LSM_ID_UNDEF) 3850 + return -EINVAL; 3851 + single = true; 3852 + } 3853 + 3854 + /* 3855 + * In the usual case gather all the data from the LSMs. 3856 + * In the single case only get the data from the LSM specified. 3857 + */ 3858 + hlist_for_each_entry(hp, &security_hook_heads.getselfattr, list) { 3859 + if (single && lctx.id != hp->lsmid->id) 3860 + continue; 3861 + entrysize = left; 3862 + if (base) 3863 + uctx = (struct lsm_ctx __user *)(base + total); 3864 + rc = hp->hook.getselfattr(attr, uctx, &entrysize, flags); 3865 + if (rc == -EOPNOTSUPP) { 3866 + rc = 0; 3867 + continue; 3868 + } 3869 + if (rc == -E2BIG) { 3870 + rc = 0; 3871 + left = 0; 3872 + toobig = true; 3873 + } else if (rc < 0) 3874 + return rc; 3875 + else 3876 + left -= entrysize; 3877 + 3878 + total += entrysize; 3879 + count += rc; 3880 + if (single) 3881 + break; 3882 + } 3883 + if (put_user(total, size)) 3884 + return -EFAULT; 3885 + if (toobig) 3886 + return -E2BIG; 3887 + if (count == 0) 3888 + return LSM_RET_DEFAULT(getselfattr); 3889 + return count; 3890 + } 3891 + 3892 + /* 3893 + * Please keep this in sync with it's counterpart in security/lsm_syscalls.c 3894 + */ 3895 + 3896 + /** 3897 + * security_setselfattr - Set an LSM attribute on the current process. 3898 + * @attr: which attribute to set 3899 + * @uctx: the user-space source for the information 3900 + * @size: the size of the data 3901 + * @flags: reserved for future use, must be 0 3902 + * 3903 + * Set an LSM attribute for the current process. The LSM, attribute 3904 + * and new value are included in @uctx. 3905 + * 3906 + * Returns 0 on success, -EINVAL if the input is inconsistent, -EFAULT 3907 + * if the user buffer is inaccessible, E2BIG if size is too big, or an 3908 + * LSM specific failure. 3909 + */ 3910 + int security_setselfattr(unsigned int attr, struct lsm_ctx __user *uctx, 3911 + size_t size, u32 flags) 3912 + { 3913 + struct security_hook_list *hp; 3914 + struct lsm_ctx *lctx; 3915 + int rc = LSM_RET_DEFAULT(setselfattr); 3916 + 3917 + if (flags) 3918 + return -EINVAL; 3919 + if (size < sizeof(*lctx)) 3920 + return -EINVAL; 3921 + if (size > PAGE_SIZE) 3922 + return -E2BIG; 3923 + 3924 + lctx = memdup_user(uctx, size); 3925 + if (IS_ERR(lctx)) 3926 + return PTR_ERR(lctx); 3927 + 3928 + if (size < lctx->len || size < lctx->ctx_len + sizeof(*lctx) || 3929 + lctx->len < lctx->ctx_len + sizeof(*lctx)) { 3930 + rc = -EINVAL; 3931 + goto free_out; 3932 + } 3933 + 3934 + hlist_for_each_entry(hp, &security_hook_heads.setselfattr, list) 3935 + if ((hp->lsmid->id) == lctx->id) { 3936 + rc = hp->hook.setselfattr(attr, lctx, size, flags); 3937 + break; 3938 + } 3939 + 3940 + free_out: 3941 + kfree(lctx); 3942 + return rc; 3943 + } 3944 + 3899 3945 /** 3900 3946 * security_getprocattr() - Read an attribute for a task 3901 3947 * @p: the task 3902 - * @lsm: LSM name 3948 + * @lsmid: LSM identification 3903 3949 * @name: attribute name 3904 3950 * @value: attribute value 3905 3951 * ··· 4055 3805 * 4056 3806 * Return: Returns the length of @value on success, a negative value otherwise. 4057 3807 */ 4058 - int security_getprocattr(struct task_struct *p, const char *lsm, 4059 - const char *name, char **value) 3808 + int security_getprocattr(struct task_struct *p, int lsmid, const char *name, 3809 + char **value) 4060 3810 { 4061 3811 struct security_hook_list *hp; 4062 3812 4063 3813 hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) { 4064 - if (lsm != NULL && strcmp(lsm, hp->lsm)) 3814 + if (lsmid != 0 && lsmid != hp->lsmid->id) 4065 3815 continue; 4066 3816 return hp->hook.getprocattr(p, name, value); 4067 3817 } ··· 4070 3820 4071 3821 /** 4072 3822 * security_setprocattr() - Set an attribute for a task 4073 - * @lsm: LSM name 3823 + * @lsmid: LSM identification 4074 3824 * @name: attribute name 4075 3825 * @value: attribute value 4076 3826 * @size: attribute value size ··· 4080 3830 * 4081 3831 * Return: Returns bytes written on success, a negative value otherwise. 4082 3832 */ 4083 - int security_setprocattr(const char *lsm, const char *name, void *value, 4084 - size_t size) 3833 + int security_setprocattr(int lsmid, const char *name, void *value, size_t size) 4085 3834 { 4086 3835 struct security_hook_list *hp; 4087 3836 4088 3837 hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) { 4089 - if (lsm != NULL && strcmp(lsm, hp->lsm)) 3838 + if (lsmid != 0 && lsmid != hp->lsmid->id) 4090 3839 continue; 4091 3840 return hp->hook.setprocattr(name, value, size); 4092 3841 }
+145 -28
security/selinux/hooks.c
··· 92 92 #include <linux/fsnotify.h> 93 93 #include <linux/fanotify.h> 94 94 #include <linux/io_uring.h> 95 + #include <uapi/linux/lsm.h> 95 96 96 97 #include "avc.h" 97 98 #include "objsec.h" ··· 3739 3738 return error; 3740 3739 } 3741 3740 3741 + static int selinux_file_ioctl_compat(struct file *file, unsigned int cmd, 3742 + unsigned long arg) 3743 + { 3744 + /* 3745 + * If we are in a 64-bit kernel running 32-bit userspace, we need to 3746 + * make sure we don't compare 32-bit flags to 64-bit flags. 3747 + */ 3748 + switch (cmd) { 3749 + case FS_IOC32_GETFLAGS: 3750 + cmd = FS_IOC_GETFLAGS; 3751 + break; 3752 + case FS_IOC32_SETFLAGS: 3753 + cmd = FS_IOC_SETFLAGS; 3754 + break; 3755 + case FS_IOC32_GETVERSION: 3756 + cmd = FS_IOC_GETVERSION; 3757 + break; 3758 + case FS_IOC32_SETVERSION: 3759 + cmd = FS_IOC_SETVERSION; 3760 + break; 3761 + default: 3762 + break; 3763 + } 3764 + 3765 + return selinux_file_ioctl(file, cmd, arg); 3766 + } 3767 + 3742 3768 static int default_noexec __ro_after_init; 3743 3769 3744 3770 static int file_map_prot_check(struct file *file, unsigned long prot, int shared) ··· 6341 6313 inode_doinit_with_dentry(inode, dentry); 6342 6314 } 6343 6315 6344 - static int selinux_getprocattr(struct task_struct *p, 6345 - const char *name, char **value) 6316 + static int selinux_lsm_getattr(unsigned int attr, struct task_struct *p, 6317 + char **value) 6346 6318 { 6347 6319 const struct task_security_struct *__tsec; 6348 6320 u32 sid; ··· 6359 6331 goto bad; 6360 6332 } 6361 6333 6362 - if (!strcmp(name, "current")) 6334 + switch (attr) { 6335 + case LSM_ATTR_CURRENT: 6363 6336 sid = __tsec->sid; 6364 - else if (!strcmp(name, "prev")) 6337 + break; 6338 + case LSM_ATTR_PREV: 6365 6339 sid = __tsec->osid; 6366 - else if (!strcmp(name, "exec")) 6340 + break; 6341 + case LSM_ATTR_EXEC: 6367 6342 sid = __tsec->exec_sid; 6368 - else if (!strcmp(name, "fscreate")) 6343 + break; 6344 + case LSM_ATTR_FSCREATE: 6369 6345 sid = __tsec->create_sid; 6370 - else if (!strcmp(name, "keycreate")) 6346 + break; 6347 + case LSM_ATTR_KEYCREATE: 6371 6348 sid = __tsec->keycreate_sid; 6372 - else if (!strcmp(name, "sockcreate")) 6349 + break; 6350 + case LSM_ATTR_SOCKCREATE: 6373 6351 sid = __tsec->sockcreate_sid; 6374 - else { 6375 - error = -EINVAL; 6352 + break; 6353 + default: 6354 + error = -EOPNOTSUPP; 6376 6355 goto bad; 6377 6356 } 6378 6357 rcu_read_unlock(); ··· 6397 6362 return error; 6398 6363 } 6399 6364 6400 - static int selinux_setprocattr(const char *name, void *value, size_t size) 6365 + static int selinux_lsm_setattr(u64 attr, void *value, size_t size) 6401 6366 { 6402 6367 struct task_security_struct *tsec; 6403 6368 struct cred *new; ··· 6408 6373 /* 6409 6374 * Basic control over ability to set these attributes at all. 6410 6375 */ 6411 - if (!strcmp(name, "exec")) 6376 + switch (attr) { 6377 + case LSM_ATTR_EXEC: 6412 6378 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, 6413 6379 PROCESS__SETEXEC, NULL); 6414 - else if (!strcmp(name, "fscreate")) 6380 + break; 6381 + case LSM_ATTR_FSCREATE: 6415 6382 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, 6416 6383 PROCESS__SETFSCREATE, NULL); 6417 - else if (!strcmp(name, "keycreate")) 6384 + break; 6385 + case LSM_ATTR_KEYCREATE: 6418 6386 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, 6419 6387 PROCESS__SETKEYCREATE, NULL); 6420 - else if (!strcmp(name, "sockcreate")) 6388 + break; 6389 + case LSM_ATTR_SOCKCREATE: 6421 6390 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, 6422 6391 PROCESS__SETSOCKCREATE, NULL); 6423 - else if (!strcmp(name, "current")) 6392 + break; 6393 + case LSM_ATTR_CURRENT: 6424 6394 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, 6425 6395 PROCESS__SETCURRENT, NULL); 6426 - else 6427 - error = -EINVAL; 6396 + break; 6397 + default: 6398 + error = -EOPNOTSUPP; 6399 + break; 6400 + } 6428 6401 if (error) 6429 6402 return error; 6430 6403 ··· 6444 6401 } 6445 6402 error = security_context_to_sid(value, size, 6446 6403 &sid, GFP_KERNEL); 6447 - if (error == -EINVAL && !strcmp(name, "fscreate")) { 6404 + if (error == -EINVAL && attr == LSM_ATTR_FSCREATE) { 6448 6405 if (!has_cap_mac_admin(true)) { 6449 6406 struct audit_buffer *ab; 6450 6407 size_t audit_size; 6451 6408 6452 - /* We strip a nul only if it is at the end, otherwise the 6453 - * context contains a nul and we should audit that */ 6409 + /* We strip a nul only if it is at the end, 6410 + * otherwise the context contains a nul and 6411 + * we should audit that */ 6454 6412 if (str[size - 1] == '\0') 6455 6413 audit_size = size - 1; 6456 6414 else ··· 6462 6418 if (!ab) 6463 6419 return error; 6464 6420 audit_log_format(ab, "op=fscreate invalid_context="); 6465 - audit_log_n_untrustedstring(ab, value, audit_size); 6421 + audit_log_n_untrustedstring(ab, value, 6422 + audit_size); 6466 6423 audit_log_end(ab); 6467 6424 6468 6425 return error; ··· 6486 6441 checks and may_create for the file creation checks. The 6487 6442 operation will then fail if the context is not permitted. */ 6488 6443 tsec = selinux_cred(new); 6489 - if (!strcmp(name, "exec")) { 6444 + if (attr == LSM_ATTR_EXEC) { 6490 6445 tsec->exec_sid = sid; 6491 - } else if (!strcmp(name, "fscreate")) { 6446 + } else if (attr == LSM_ATTR_FSCREATE) { 6492 6447 tsec->create_sid = sid; 6493 - } else if (!strcmp(name, "keycreate")) { 6448 + } else if (attr == LSM_ATTR_KEYCREATE) { 6494 6449 if (sid) { 6495 6450 error = avc_has_perm(mysid, sid, 6496 6451 SECCLASS_KEY, KEY__CREATE, NULL); ··· 6498 6453 goto abort_change; 6499 6454 } 6500 6455 tsec->keycreate_sid = sid; 6501 - } else if (!strcmp(name, "sockcreate")) { 6456 + } else if (attr == LSM_ATTR_SOCKCREATE) { 6502 6457 tsec->sockcreate_sid = sid; 6503 - } else if (!strcmp(name, "current")) { 6458 + } else if (attr == LSM_ATTR_CURRENT) { 6504 6459 error = -EINVAL; 6505 6460 if (sid == 0) 6506 6461 goto abort_change; ··· 6539 6494 abort_change: 6540 6495 abort_creds(new); 6541 6496 return error; 6497 + } 6498 + 6499 + /** 6500 + * selinux_getselfattr - Get SELinux current task attributes 6501 + * @attr: the requested attribute 6502 + * @ctx: buffer to receive the result 6503 + * @size: buffer size (input), buffer size used (output) 6504 + * @flags: unused 6505 + * 6506 + * Fill the passed user space @ctx with the details of the requested 6507 + * attribute. 6508 + * 6509 + * Returns the number of attributes on success, an error code otherwise. 6510 + * There will only ever be one attribute. 6511 + */ 6512 + static int selinux_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, 6513 + size_t *size, u32 flags) 6514 + { 6515 + int rc; 6516 + char *val; 6517 + int val_len; 6518 + 6519 + val_len = selinux_lsm_getattr(attr, current, &val); 6520 + if (val_len < 0) 6521 + return val_len; 6522 + rc = lsm_fill_user_ctx(ctx, size, val, val_len, LSM_ID_SELINUX, 0); 6523 + kfree(val); 6524 + return (!rc ? 1 : rc); 6525 + } 6526 + 6527 + static int selinux_setselfattr(unsigned int attr, struct lsm_ctx *ctx, 6528 + size_t size, u32 flags) 6529 + { 6530 + int rc; 6531 + 6532 + rc = selinux_lsm_setattr(attr, ctx->ctx, ctx->ctx_len); 6533 + if (rc > 0) 6534 + return 0; 6535 + return rc; 6536 + } 6537 + 6538 + static int selinux_getprocattr(struct task_struct *p, 6539 + const char *name, char **value) 6540 + { 6541 + unsigned int attr = lsm_name_to_attr(name); 6542 + int rc; 6543 + 6544 + if (attr) { 6545 + rc = selinux_lsm_getattr(attr, p, value); 6546 + if (rc != -EOPNOTSUPP) 6547 + return rc; 6548 + } 6549 + 6550 + return -EINVAL; 6551 + } 6552 + 6553 + static int selinux_setprocattr(const char *name, void *value, size_t size) 6554 + { 6555 + int attr = lsm_name_to_attr(name); 6556 + 6557 + if (attr) 6558 + return selinux_lsm_setattr(attr, value, size); 6559 + return -EINVAL; 6542 6560 } 6543 6561 6544 6562 static int selinux_ismaclabel(const char *name) ··· 7086 6978 } 7087 6979 #endif /* CONFIG_IO_URING */ 7088 6980 6981 + static const struct lsm_id selinux_lsmid = { 6982 + .name = "selinux", 6983 + .id = LSM_ID_SELINUX, 6984 + }; 6985 + 7089 6986 /* 7090 6987 * IMPORTANT NOTE: When adding new hooks, please be careful to keep this order: 7091 6988 * 1. any hooks that don't belong to (2.) or (3.) below, ··· 7177 7064 LSM_HOOK_INIT(file_permission, selinux_file_permission), 7178 7065 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security), 7179 7066 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl), 7067 + LSM_HOOK_INIT(file_ioctl_compat, selinux_file_ioctl_compat), 7180 7068 LSM_HOOK_INIT(mmap_file, selinux_mmap_file), 7181 7069 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr), 7182 7070 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect), ··· 7233 7119 7234 7120 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate), 7235 7121 7122 + LSM_HOOK_INIT(getselfattr, selinux_getselfattr), 7123 + LSM_HOOK_INIT(setselfattr, selinux_setselfattr), 7236 7124 LSM_HOOK_INIT(getprocattr, selinux_getprocattr), 7237 7125 LSM_HOOK_INIT(setprocattr, selinux_setprocattr), 7238 7126 ··· 7414 7298 7415 7299 hashtab_cache_init(); 7416 7300 7417 - security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux"); 7301 + security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), 7302 + &selinux_lsmid); 7418 7303 7419 7304 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET)) 7420 7305 panic("SELinux: Unable to register AVC netcache callback\n");
+87 -6
security/smack/smack_lsm.c
··· 43 43 #include <linux/fs_parser.h> 44 44 #include <linux/watch_queue.h> 45 45 #include <linux/io_uring.h> 46 + #include <uapi/linux/lsm.h> 46 47 #include "smack.h" 47 48 48 49 #define TRANS_TRUE "TRUE" ··· 3627 3626 } 3628 3627 3629 3628 /** 3629 + * smack_getselfattr - Smack current process attribute 3630 + * @attr: which attribute to fetch 3631 + * @ctx: buffer to receive the result 3632 + * @size: available size in, actual size out 3633 + * @flags: unused 3634 + * 3635 + * Fill the passed user space @ctx with the details of the requested 3636 + * attribute. 3637 + * 3638 + * Returns the number of attributes on success, an error code otherwise. 3639 + * There will only ever be one attribute. 3640 + */ 3641 + static int smack_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, 3642 + size_t *size, u32 flags) 3643 + { 3644 + int rc; 3645 + struct smack_known *skp; 3646 + 3647 + if (attr != LSM_ATTR_CURRENT) 3648 + return -EOPNOTSUPP; 3649 + 3650 + skp = smk_of_current(); 3651 + rc = lsm_fill_user_ctx(ctx, size, 3652 + skp->smk_known, strlen(skp->smk_known) + 1, 3653 + LSM_ID_SMACK, 0); 3654 + return (!rc ? 1 : rc); 3655 + } 3656 + 3657 + /** 3630 3658 * smack_getprocattr - Smack process attribute access 3631 3659 * @p: the object task 3632 3660 * @name: the name of the attribute in /proc/.../attr ··· 3684 3654 } 3685 3655 3686 3656 /** 3687 - * smack_setprocattr - Smack process attribute setting 3688 - * @name: the name of the attribute in /proc/.../attr 3657 + * do_setattr - Smack process attribute setting 3658 + * @attr: the ID of the attribute 3689 3659 * @value: the value to set 3690 3660 * @size: the size of the value 3691 3661 * ··· 3694 3664 * 3695 3665 * Returns the length of the smack label or an error code 3696 3666 */ 3697 - static int smack_setprocattr(const char *name, void *value, size_t size) 3667 + static int do_setattr(u64 attr, void *value, size_t size) 3698 3668 { 3699 3669 struct task_smack *tsp = smack_cred(current_cred()); 3700 3670 struct cred *new; ··· 3708 3678 if (value == NULL || size == 0 || size >= SMK_LONGLABEL) 3709 3679 return -EINVAL; 3710 3680 3711 - if (strcmp(name, "current") != 0) 3712 - return -EINVAL; 3681 + if (attr != LSM_ATTR_CURRENT) 3682 + return -EOPNOTSUPP; 3713 3683 3714 3684 skp = smk_import_entry(value, size); 3715 3685 if (IS_ERR(skp)) ··· 3746 3716 3747 3717 commit_creds(new); 3748 3718 return size; 3719 + } 3720 + 3721 + /** 3722 + * smack_setselfattr - Set a Smack process attribute 3723 + * @attr: which attribute to set 3724 + * @ctx: buffer containing the data 3725 + * @size: size of @ctx 3726 + * @flags: unused 3727 + * 3728 + * Fill the passed user space @ctx with the details of the requested 3729 + * attribute. 3730 + * 3731 + * Returns 0 on success, an error code otherwise. 3732 + */ 3733 + static int smack_setselfattr(unsigned int attr, struct lsm_ctx *ctx, 3734 + size_t size, u32 flags) 3735 + { 3736 + int rc; 3737 + 3738 + rc = do_setattr(attr, ctx->ctx, ctx->ctx_len); 3739 + if (rc > 0) 3740 + return 0; 3741 + return rc; 3742 + } 3743 + 3744 + /** 3745 + * smack_setprocattr - Smack process attribute setting 3746 + * @name: the name of the attribute in /proc/.../attr 3747 + * @value: the value to set 3748 + * @size: the size of the value 3749 + * 3750 + * Sets the Smack value of the task. Only setting self 3751 + * is permitted and only with privilege 3752 + * 3753 + * Returns the length of the smack label or an error code 3754 + */ 3755 + static int smack_setprocattr(const char *name, void *value, size_t size) 3756 + { 3757 + int attr = lsm_name_to_attr(name); 3758 + 3759 + if (attr != LSM_ATTR_UNDEF) 3760 + return do_setattr(attr, value, size); 3761 + return -EINVAL; 3749 3762 } 3750 3763 3751 3764 /** ··· 5006 4933 .lbs_xattr_count = SMACK_INODE_INIT_XATTRS, 5007 4934 }; 5008 4935 4936 + static const struct lsm_id smack_lsmid = { 4937 + .name = "smack", 4938 + .id = LSM_ID_SMACK, 4939 + }; 4940 + 5009 4941 static struct security_hook_list smack_hooks[] __ro_after_init = { 5010 4942 LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), 5011 4943 LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), ··· 5051 4973 5052 4974 LSM_HOOK_INIT(file_alloc_security, smack_file_alloc_security), 5053 4975 LSM_HOOK_INIT(file_ioctl, smack_file_ioctl), 4976 + LSM_HOOK_INIT(file_ioctl_compat, smack_file_ioctl), 5054 4977 LSM_HOOK_INIT(file_lock, smack_file_lock), 5055 4978 LSM_HOOK_INIT(file_fcntl, smack_file_fcntl), 5056 4979 LSM_HOOK_INIT(mmap_file, smack_mmap_file), ··· 5106 5027 5107 5028 LSM_HOOK_INIT(d_instantiate, smack_d_instantiate), 5108 5029 5030 + LSM_HOOK_INIT(getselfattr, smack_getselfattr), 5031 + LSM_HOOK_INIT(setselfattr, smack_setselfattr), 5109 5032 LSM_HOOK_INIT(getprocattr, smack_getprocattr), 5110 5033 LSM_HOOK_INIT(setprocattr, smack_setprocattr), 5111 5034 ··· 5221 5140 /* 5222 5141 * Register with LSM 5223 5142 */ 5224 - security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), "smack"); 5143 + security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), &smack_lsmid); 5225 5144 smack_enabled = 1; 5226 5145 5227 5146 pr_info("Smack: Initializing.\n");
+9 -1
security/tomoyo/tomoyo.c
··· 6 6 */ 7 7 8 8 #include <linux/lsm_hooks.h> 9 + #include <uapi/linux/lsm.h> 9 10 #include "common.h" 10 11 11 12 /** ··· 543 542 } 544 543 } 545 544 545 + static const struct lsm_id tomoyo_lsmid = { 546 + .name = "tomoyo", 547 + .id = LSM_ID_TOMOYO, 548 + }; 549 + 546 550 /* 547 551 * tomoyo_security_ops is a "struct security_operations" which is used for 548 552 * registering TOMOYO. ··· 574 568 LSM_HOOK_INIT(path_rename, tomoyo_path_rename), 575 569 LSM_HOOK_INIT(inode_getattr, tomoyo_inode_getattr), 576 570 LSM_HOOK_INIT(file_ioctl, tomoyo_file_ioctl), 571 + LSM_HOOK_INIT(file_ioctl_compat, tomoyo_file_ioctl), 577 572 LSM_HOOK_INIT(path_chmod, tomoyo_path_chmod), 578 573 LSM_HOOK_INIT(path_chown, tomoyo_path_chown), 579 574 LSM_HOOK_INIT(path_chroot, tomoyo_path_chroot), ··· 602 595 struct tomoyo_task *s = tomoyo_task(current); 603 596 604 597 /* register ourselves with the security framework */ 605 - security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo"); 598 + security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), 599 + &tomoyo_lsmid); 606 600 pr_info("TOMOYO Linux initialized\n"); 607 601 s->domain_info = &tomoyo_kernel_domain; 608 602 atomic_inc(&tomoyo_kernel_domain.users);
+7 -1
security/yama/yama_lsm.c
··· 18 18 #include <linux/task_work.h> 19 19 #include <linux/sched.h> 20 20 #include <linux/spinlock.h> 21 + #include <uapi/linux/lsm.h> 21 22 22 23 #define YAMA_SCOPE_DISABLED 0 23 24 #define YAMA_SCOPE_RELATIONAL 1 ··· 422 421 return rc; 423 422 } 424 423 424 + static const struct lsm_id yama_lsmid = { 425 + .name = "yama", 426 + .id = LSM_ID_YAMA, 427 + }; 428 + 425 429 static struct security_hook_list yama_hooks[] __ro_after_init = { 426 430 LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check), 427 431 LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme), ··· 477 471 static int __init yama_init(void) 478 472 { 479 473 pr_info("Yama: becoming mindful.\n"); 480 - security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), "yama"); 474 + security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), &yama_lsmid); 481 475 yama_init_sysctl(); 482 476 return 0; 483 477 }
+5
tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
··· 371 371 454 n64 futex_wake sys_futex_wake 372 372 455 n64 futex_wait sys_futex_wait 373 373 456 n64 futex_requeue sys_futex_requeue 374 + 457 n64 statmount sys_statmount 375 + 458 n64 listmount sys_listmount 376 + 459 n64 lsm_get_self_attr sys_lsm_get_self_attr 377 + 460 n64 lsm_set_self_attr sys_lsm_set_self_attr 378 + 461 n64 lsm_list_modules sys_lsm_list_modules
+5
tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
··· 543 543 454 common futex_wake sys_futex_wake 544 544 455 common futex_wait sys_futex_wait 545 545 456 common futex_requeue sys_futex_requeue 546 + 457 common statmount sys_statmount 547 + 458 common listmount sys_listmount 548 + 459 common lsm_get_self_attr sys_lsm_get_self_attr 549 + 460 common lsm_set_self_attr sys_lsm_set_self_attr 550 + 461 common lsm_list_modules sys_lsm_list_modules
+5
tools/perf/arch/s390/entry/syscalls/syscall.tbl
··· 459 459 454 common futex_wake sys_futex_wake sys_futex_wake 460 460 455 common futex_wait sys_futex_wait sys_futex_wait 461 461 456 common futex_requeue sys_futex_requeue sys_futex_requeue 462 + 457 common statmount sys_statmount sys_statmount 463 + 458 common listmount sys_listmount sys_listmount 464 + 459 common lsm_get_self_attr sys_lsm_get_self_attr sys_lsm_get_self_attr 465 + 460 common lsm_set_self_attr sys_lsm_set_self_attr sys_lsm_set_self_attr 466 + 461 common lsm_list_modules sys_lsm_list_modules sys_lsm_list_modules
+5
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
··· 378 378 454 common futex_wake sys_futex_wake 379 379 455 common futex_wait sys_futex_wait 380 380 456 common futex_requeue sys_futex_requeue 381 + 457 common statmount sys_statmount 382 + 458 common listmount sys_listmount 383 + 459 common lsm_get_self_attr sys_lsm_get_self_attr 384 + 460 common lsm_set_self_attr sys_lsm_set_self_attr 385 + 461 common lsm_list_modules sys_lsm_list_modules 381 386 382 387 # 383 388 # Due to a historical design error, certain syscalls are numbered differently
+1
tools/testing/selftests/Makefile
··· 45 45 TARGETS += lib 46 46 TARGETS += livepatch 47 47 TARGETS += lkdtm 48 + TARGETS += lsm 48 49 TARGETS += membarrier 49 50 TARGETS += memfd 50 51 TARGETS += memory-hotplug
+1
tools/testing/selftests/lsm/.gitignore
··· 1 + /*_test
+17
tools/testing/selftests/lsm/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # 3 + # First run: make -C ../../../.. headers_install 4 + 5 + CFLAGS += -Wall -O2 $(KHDR_INCLUDES) 6 + LOCAL_HDRS += common.h 7 + 8 + TEST_GEN_PROGS := lsm_get_self_attr_test lsm_list_modules_test \ 9 + lsm_set_self_attr_test 10 + 11 + include ../lib.mk 12 + 13 + $(OUTPUT)/lsm_get_self_attr_test: lsm_get_self_attr_test.c common.c 14 + $(OUTPUT)/lsm_set_self_attr_test: lsm_set_self_attr_test.c common.c 15 + $(OUTPUT)/lsm_list_modules_test: lsm_list_modules_test.c common.c 16 + 17 + EXTRA_CLEAN = $(OUTPUT)/common.o
+89
tools/testing/selftests/lsm/common.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Linux Security Module infrastructure tests 4 + * 5 + * Copyright © 2023 Casey Schaufler <casey@schaufler-ca.com> 6 + */ 7 + 8 + #define _GNU_SOURCE 9 + #include <linux/lsm.h> 10 + #include <fcntl.h> 11 + #include <string.h> 12 + #include <stdio.h> 13 + #include <stdlib.h> 14 + #include <unistd.h> 15 + #include <sys/types.h> 16 + #include "common.h" 17 + 18 + #define PROCATTR "/proc/self/attr/" 19 + 20 + int read_proc_attr(const char *attr, char *value, size_t size) 21 + { 22 + int fd; 23 + int len; 24 + char *path; 25 + 26 + len = strlen(PROCATTR) + strlen(attr) + 1; 27 + path = calloc(len, 1); 28 + if (path == NULL) 29 + return -1; 30 + sprintf(path, "%s%s", PROCATTR, attr); 31 + 32 + fd = open(path, O_RDONLY); 33 + free(path); 34 + 35 + if (fd < 0) 36 + return -1; 37 + len = read(fd, value, size); 38 + 39 + close(fd); 40 + 41 + /* Ensure value is terminated */ 42 + if (len <= 0 || len == size) 43 + return -1; 44 + value[len] = '\0'; 45 + 46 + path = strchr(value, '\n'); 47 + if (path) 48 + *path = '\0'; 49 + 50 + return 0; 51 + } 52 + 53 + int read_sysfs_lsms(char *lsms, size_t size) 54 + { 55 + FILE *fp; 56 + size_t red; 57 + 58 + fp = fopen("/sys/kernel/security/lsm", "r"); 59 + if (fp == NULL) 60 + return -1; 61 + red = fread(lsms, 1, size, fp); 62 + fclose(fp); 63 + 64 + if (red <= 0 || red == size) 65 + return -1; 66 + lsms[red] = '\0'; 67 + return 0; 68 + } 69 + 70 + int attr_lsm_count(void) 71 + { 72 + char *names = calloc(sysconf(_SC_PAGESIZE), 1); 73 + int count = 0; 74 + 75 + if (!names) 76 + return 0; 77 + 78 + if (read_sysfs_lsms(names, sysconf(_SC_PAGESIZE))) 79 + return 0; 80 + 81 + if (strstr(names, "selinux")) 82 + count++; 83 + if (strstr(names, "smack")) 84 + count++; 85 + if (strstr(names, "apparmor")) 86 + count++; 87 + 88 + return count; 89 + }
+33
tools/testing/selftests/lsm/common.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Linux Security Module infrastructure tests 4 + * 5 + * Copyright © 2023 Casey Schaufler <casey@schaufler-ca.com> 6 + */ 7 + 8 + #ifndef lsm_get_self_attr 9 + static inline int lsm_get_self_attr(unsigned int attr, struct lsm_ctx *ctx, 10 + size_t *size, __u32 flags) 11 + { 12 + return syscall(__NR_lsm_get_self_attr, attr, ctx, size, flags); 13 + } 14 + #endif 15 + 16 + #ifndef lsm_set_self_attr 17 + static inline int lsm_set_self_attr(unsigned int attr, struct lsm_ctx *ctx, 18 + size_t size, __u32 flags) 19 + { 20 + return syscall(__NR_lsm_set_self_attr, attr, ctx, size, flags); 21 + } 22 + #endif 23 + 24 + #ifndef lsm_list_modules 25 + static inline int lsm_list_modules(__u64 *ids, size_t *size, __u32 flags) 26 + { 27 + return syscall(__NR_lsm_list_modules, ids, size, flags); 28 + } 29 + #endif 30 + 31 + extern int read_proc_attr(const char *attr, char *value, size_t size); 32 + extern int read_sysfs_lsms(char *lsms, size_t size); 33 + int attr_lsm_count(void);
+3
tools/testing/selftests/lsm/config
··· 1 + CONFIG_SYSFS=y 2 + CONFIG_SECURITY=y 3 + CONFIG_SECURITYFS=y
+275
tools/testing/selftests/lsm/lsm_get_self_attr_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Linux Security Module infrastructure tests 4 + * Tests for the lsm_get_self_attr system call 5 + * 6 + * Copyright © 2022 Casey Schaufler <casey@schaufler-ca.com> 7 + */ 8 + 9 + #define _GNU_SOURCE 10 + #include <linux/lsm.h> 11 + #include <fcntl.h> 12 + #include <string.h> 13 + #include <stdio.h> 14 + #include <unistd.h> 15 + #include <sys/types.h> 16 + #include "../kselftest_harness.h" 17 + #include "common.h" 18 + 19 + static struct lsm_ctx *next_ctx(struct lsm_ctx *ctxp) 20 + { 21 + void *vp; 22 + 23 + vp = (void *)ctxp + sizeof(*ctxp) + ctxp->ctx_len; 24 + return (struct lsm_ctx *)vp; 25 + } 26 + 27 + TEST(size_null_lsm_get_self_attr) 28 + { 29 + const long page_size = sysconf(_SC_PAGESIZE); 30 + struct lsm_ctx *ctx = calloc(page_size, 1); 31 + 32 + ASSERT_NE(NULL, ctx); 33 + errno = 0; 34 + ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, NULL, 0)); 35 + ASSERT_EQ(EINVAL, errno); 36 + 37 + free(ctx); 38 + } 39 + 40 + TEST(ctx_null_lsm_get_self_attr) 41 + { 42 + const long page_size = sysconf(_SC_PAGESIZE); 43 + size_t size = page_size; 44 + int rc; 45 + 46 + rc = lsm_get_self_attr(LSM_ATTR_CURRENT, NULL, &size, 0); 47 + 48 + if (attr_lsm_count()) { 49 + ASSERT_NE(-1, rc); 50 + ASSERT_NE(1, size); 51 + } else { 52 + ASSERT_EQ(-1, rc); 53 + } 54 + } 55 + 56 + TEST(size_too_small_lsm_get_self_attr) 57 + { 58 + const long page_size = sysconf(_SC_PAGESIZE); 59 + struct lsm_ctx *ctx = calloc(page_size, 1); 60 + size_t size = 1; 61 + 62 + ASSERT_NE(NULL, ctx); 63 + errno = 0; 64 + ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, 0)); 65 + if (attr_lsm_count()) { 66 + ASSERT_EQ(E2BIG, errno); 67 + } else { 68 + ASSERT_EQ(EOPNOTSUPP, errno); 69 + } 70 + ASSERT_NE(1, size); 71 + 72 + free(ctx); 73 + } 74 + 75 + TEST(flags_zero_lsm_get_self_attr) 76 + { 77 + const long page_size = sysconf(_SC_PAGESIZE); 78 + struct lsm_ctx *ctx = calloc(page_size, 1); 79 + __u64 *syscall_lsms = calloc(page_size, 1); 80 + size_t size; 81 + int lsmcount; 82 + int i; 83 + 84 + ASSERT_NE(NULL, ctx); 85 + errno = 0; 86 + size = page_size; 87 + ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, 88 + LSM_FLAG_SINGLE)); 89 + ASSERT_EQ(EINVAL, errno); 90 + ASSERT_EQ(page_size, size); 91 + 92 + lsmcount = syscall(__NR_lsm_list_modules, syscall_lsms, &size, 0); 93 + ASSERT_LE(1, lsmcount); 94 + ASSERT_NE(NULL, syscall_lsms); 95 + 96 + for (i = 0; i < lsmcount; i++) { 97 + errno = 0; 98 + size = page_size; 99 + ctx->id = syscall_lsms[i]; 100 + 101 + if (syscall_lsms[i] == LSM_ID_SELINUX || 102 + syscall_lsms[i] == LSM_ID_SMACK || 103 + syscall_lsms[i] == LSM_ID_APPARMOR) { 104 + ASSERT_EQ(1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, 105 + &size, LSM_FLAG_SINGLE)); 106 + } else { 107 + ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, 108 + &size, 109 + LSM_FLAG_SINGLE)); 110 + } 111 + } 112 + 113 + free(ctx); 114 + } 115 + 116 + TEST(flags_overset_lsm_get_self_attr) 117 + { 118 + const long page_size = sysconf(_SC_PAGESIZE); 119 + struct lsm_ctx *ctx = calloc(page_size, 1); 120 + size_t size; 121 + 122 + ASSERT_NE(NULL, ctx); 123 + 124 + errno = 0; 125 + size = page_size; 126 + ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT | LSM_ATTR_PREV, ctx, 127 + &size, 0)); 128 + ASSERT_EQ(EOPNOTSUPP, errno); 129 + 130 + errno = 0; 131 + size = page_size; 132 + ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, 133 + LSM_FLAG_SINGLE | 134 + (LSM_FLAG_SINGLE << 1))); 135 + ASSERT_EQ(EINVAL, errno); 136 + 137 + free(ctx); 138 + } 139 + 140 + TEST(basic_lsm_get_self_attr) 141 + { 142 + const long page_size = sysconf(_SC_PAGESIZE); 143 + size_t size = page_size; 144 + struct lsm_ctx *ctx = calloc(page_size, 1); 145 + struct lsm_ctx *tctx = NULL; 146 + __u64 *syscall_lsms = calloc(page_size, 1); 147 + char *attr = calloc(page_size, 1); 148 + int cnt_current = 0; 149 + int cnt_exec = 0; 150 + int cnt_fscreate = 0; 151 + int cnt_keycreate = 0; 152 + int cnt_prev = 0; 153 + int cnt_sockcreate = 0; 154 + int lsmcount; 155 + int count; 156 + int i; 157 + 158 + ASSERT_NE(NULL, ctx); 159 + ASSERT_NE(NULL, syscall_lsms); 160 + 161 + lsmcount = syscall(__NR_lsm_list_modules, syscall_lsms, &size, 0); 162 + ASSERT_LE(1, lsmcount); 163 + 164 + for (i = 0; i < lsmcount; i++) { 165 + switch (syscall_lsms[i]) { 166 + case LSM_ID_SELINUX: 167 + cnt_current++; 168 + cnt_exec++; 169 + cnt_fscreate++; 170 + cnt_keycreate++; 171 + cnt_prev++; 172 + cnt_sockcreate++; 173 + break; 174 + case LSM_ID_SMACK: 175 + cnt_current++; 176 + break; 177 + case LSM_ID_APPARMOR: 178 + cnt_current++; 179 + cnt_exec++; 180 + cnt_prev++; 181 + break; 182 + default: 183 + break; 184 + } 185 + } 186 + 187 + if (cnt_current) { 188 + size = page_size; 189 + count = lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, 0); 190 + ASSERT_EQ(cnt_current, count); 191 + tctx = ctx; 192 + ASSERT_EQ(0, read_proc_attr("current", attr, page_size)); 193 + ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); 194 + for (i = 1; i < count; i++) { 195 + tctx = next_ctx(tctx); 196 + ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); 197 + } 198 + } 199 + if (cnt_exec) { 200 + size = page_size; 201 + count = lsm_get_self_attr(LSM_ATTR_EXEC, ctx, &size, 0); 202 + ASSERT_GE(cnt_exec, count); 203 + if (count > 0) { 204 + tctx = ctx; 205 + if (read_proc_attr("exec", attr, page_size) == 0) 206 + ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); 207 + } 208 + for (i = 1; i < count; i++) { 209 + tctx = next_ctx(tctx); 210 + ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); 211 + } 212 + } 213 + if (cnt_fscreate) { 214 + size = page_size; 215 + count = lsm_get_self_attr(LSM_ATTR_FSCREATE, ctx, &size, 0); 216 + ASSERT_GE(cnt_fscreate, count); 217 + if (count > 0) { 218 + tctx = ctx; 219 + if (read_proc_attr("fscreate", attr, page_size) == 0) 220 + ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); 221 + } 222 + for (i = 1; i < count; i++) { 223 + tctx = next_ctx(tctx); 224 + ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); 225 + } 226 + } 227 + if (cnt_keycreate) { 228 + size = page_size; 229 + count = lsm_get_self_attr(LSM_ATTR_KEYCREATE, ctx, &size, 0); 230 + ASSERT_GE(cnt_keycreate, count); 231 + if (count > 0) { 232 + tctx = ctx; 233 + if (read_proc_attr("keycreate", attr, page_size) == 0) 234 + ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); 235 + } 236 + for (i = 1; i < count; i++) { 237 + tctx = next_ctx(tctx); 238 + ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); 239 + } 240 + } 241 + if (cnt_prev) { 242 + size = page_size; 243 + count = lsm_get_self_attr(LSM_ATTR_PREV, ctx, &size, 0); 244 + ASSERT_GE(cnt_prev, count); 245 + if (count > 0) { 246 + tctx = ctx; 247 + ASSERT_EQ(0, read_proc_attr("prev", attr, page_size)); 248 + ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); 249 + for (i = 1; i < count; i++) { 250 + tctx = next_ctx(tctx); 251 + ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); 252 + } 253 + } 254 + } 255 + if (cnt_sockcreate) { 256 + size = page_size; 257 + count = lsm_get_self_attr(LSM_ATTR_SOCKCREATE, ctx, &size, 0); 258 + ASSERT_GE(cnt_sockcreate, count); 259 + if (count > 0) { 260 + tctx = ctx; 261 + if (read_proc_attr("sockcreate", attr, page_size) == 0) 262 + ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); 263 + } 264 + for (i = 1; i < count; i++) { 265 + tctx = next_ctx(tctx); 266 + ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); 267 + } 268 + } 269 + 270 + free(ctx); 271 + free(attr); 272 + free(syscall_lsms); 273 + } 274 + 275 + TEST_HARNESS_MAIN
+137
tools/testing/selftests/lsm/lsm_list_modules_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Linux Security Module infrastructure tests 4 + * Tests for the lsm_list_modules system call 5 + * 6 + * Copyright © 2022 Casey Schaufler <casey@schaufler-ca.com> 7 + */ 8 + 9 + #define _GNU_SOURCE 10 + #include <linux/lsm.h> 11 + #include <string.h> 12 + #include <stdio.h> 13 + #include <unistd.h> 14 + #include <sys/types.h> 15 + #include "../kselftest_harness.h" 16 + #include "common.h" 17 + 18 + TEST(size_null_lsm_list_modules) 19 + { 20 + const long page_size = sysconf(_SC_PAGESIZE); 21 + __u64 *syscall_lsms = calloc(page_size, 1); 22 + 23 + ASSERT_NE(NULL, syscall_lsms); 24 + errno = 0; 25 + ASSERT_EQ(-1, lsm_list_modules(syscall_lsms, NULL, 0)); 26 + ASSERT_EQ(EFAULT, errno); 27 + 28 + free(syscall_lsms); 29 + } 30 + 31 + TEST(ids_null_lsm_list_modules) 32 + { 33 + const long page_size = sysconf(_SC_PAGESIZE); 34 + size_t size = page_size; 35 + 36 + errno = 0; 37 + ASSERT_EQ(-1, lsm_list_modules(NULL, &size, 0)); 38 + ASSERT_EQ(EFAULT, errno); 39 + ASSERT_NE(1, size); 40 + } 41 + 42 + TEST(size_too_small_lsm_list_modules) 43 + { 44 + const long page_size = sysconf(_SC_PAGESIZE); 45 + __u64 *syscall_lsms = calloc(page_size, 1); 46 + size_t size = 1; 47 + 48 + ASSERT_NE(NULL, syscall_lsms); 49 + errno = 0; 50 + ASSERT_EQ(-1, lsm_list_modules(syscall_lsms, &size, 0)); 51 + ASSERT_EQ(E2BIG, errno); 52 + ASSERT_NE(1, size); 53 + 54 + free(syscall_lsms); 55 + } 56 + 57 + TEST(flags_set_lsm_list_modules) 58 + { 59 + const long page_size = sysconf(_SC_PAGESIZE); 60 + __u64 *syscall_lsms = calloc(page_size, 1); 61 + size_t size = page_size; 62 + 63 + ASSERT_NE(NULL, syscall_lsms); 64 + errno = 0; 65 + ASSERT_EQ(-1, lsm_list_modules(syscall_lsms, &size, 7)); 66 + ASSERT_EQ(EINVAL, errno); 67 + ASSERT_EQ(page_size, size); 68 + 69 + free(syscall_lsms); 70 + } 71 + 72 + TEST(correct_lsm_list_modules) 73 + { 74 + const long page_size = sysconf(_SC_PAGESIZE); 75 + size_t size = page_size; 76 + __u64 *syscall_lsms = calloc(page_size, 1); 77 + char *sysfs_lsms = calloc(page_size, 1); 78 + char *name; 79 + char *cp; 80 + int count; 81 + int i; 82 + 83 + ASSERT_NE(NULL, sysfs_lsms); 84 + ASSERT_NE(NULL, syscall_lsms); 85 + ASSERT_EQ(0, read_sysfs_lsms(sysfs_lsms, page_size)); 86 + 87 + count = lsm_list_modules(syscall_lsms, &size, 0); 88 + ASSERT_LE(1, count); 89 + cp = sysfs_lsms; 90 + for (i = 0; i < count; i++) { 91 + switch (syscall_lsms[i]) { 92 + case LSM_ID_CAPABILITY: 93 + name = "capability"; 94 + break; 95 + case LSM_ID_SELINUX: 96 + name = "selinux"; 97 + break; 98 + case LSM_ID_SMACK: 99 + name = "smack"; 100 + break; 101 + case LSM_ID_TOMOYO: 102 + name = "tomoyo"; 103 + break; 104 + case LSM_ID_APPARMOR: 105 + name = "apparmor"; 106 + break; 107 + case LSM_ID_YAMA: 108 + name = "yama"; 109 + break; 110 + case LSM_ID_LOADPIN: 111 + name = "loadpin"; 112 + break; 113 + case LSM_ID_SAFESETID: 114 + name = "safesetid"; 115 + break; 116 + case LSM_ID_LOCKDOWN: 117 + name = "lockdown"; 118 + break; 119 + case LSM_ID_BPF: 120 + name = "bpf"; 121 + break; 122 + case LSM_ID_LANDLOCK: 123 + name = "landlock"; 124 + break; 125 + default: 126 + name = "INVALID"; 127 + break; 128 + } 129 + ASSERT_EQ(0, strncmp(cp, name, strlen(name))); 130 + cp += strlen(name) + 1; 131 + } 132 + 133 + free(sysfs_lsms); 134 + free(syscall_lsms); 135 + } 136 + 137 + TEST_HARNESS_MAIN
+74
tools/testing/selftests/lsm/lsm_set_self_attr_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Linux Security Module infrastructure tests 4 + * Tests for the lsm_set_self_attr system call 5 + * 6 + * Copyright © 2022 Casey Schaufler <casey@schaufler-ca.com> 7 + */ 8 + 9 + #define _GNU_SOURCE 10 + #include <linux/lsm.h> 11 + #include <string.h> 12 + #include <stdio.h> 13 + #include <unistd.h> 14 + #include <sys/types.h> 15 + #include "../kselftest_harness.h" 16 + #include "common.h" 17 + 18 + TEST(ctx_null_lsm_set_self_attr) 19 + { 20 + ASSERT_EQ(-1, lsm_set_self_attr(LSM_ATTR_CURRENT, NULL, 21 + sizeof(struct lsm_ctx), 0)); 22 + } 23 + 24 + TEST(size_too_small_lsm_set_self_attr) 25 + { 26 + const long page_size = sysconf(_SC_PAGESIZE); 27 + struct lsm_ctx *ctx = calloc(page_size, 1); 28 + size_t size = page_size; 29 + 30 + ASSERT_NE(NULL, ctx); 31 + if (attr_lsm_count()) { 32 + ASSERT_LE(1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, 33 + 0)); 34 + } 35 + ASSERT_EQ(-1, lsm_set_self_attr(LSM_ATTR_CURRENT, ctx, 1, 0)); 36 + 37 + free(ctx); 38 + } 39 + 40 + TEST(flags_zero_lsm_set_self_attr) 41 + { 42 + const long page_size = sysconf(_SC_PAGESIZE); 43 + struct lsm_ctx *ctx = calloc(page_size, 1); 44 + size_t size = page_size; 45 + 46 + ASSERT_NE(NULL, ctx); 47 + if (attr_lsm_count()) { 48 + ASSERT_LE(1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, 49 + 0)); 50 + } 51 + ASSERT_EQ(-1, lsm_set_self_attr(LSM_ATTR_CURRENT, ctx, size, 1)); 52 + 53 + free(ctx); 54 + } 55 + 56 + TEST(flags_overset_lsm_set_self_attr) 57 + { 58 + const long page_size = sysconf(_SC_PAGESIZE); 59 + char *ctx = calloc(page_size, 1); 60 + size_t size = page_size; 61 + struct lsm_ctx *tctx = (struct lsm_ctx *)ctx; 62 + 63 + ASSERT_NE(NULL, ctx); 64 + if (attr_lsm_count()) { 65 + ASSERT_LE(1, lsm_get_self_attr(LSM_ATTR_CURRENT, tctx, &size, 66 + 0)); 67 + } 68 + ASSERT_EQ(-1, lsm_set_self_attr(LSM_ATTR_CURRENT | LSM_ATTR_PREV, tctx, 69 + size, 0)); 70 + 71 + free(ctx); 72 + } 73 + 74 + TEST_HARNESS_MAIN