History

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 ...

Linus Torvalds committed 2 years ago

Commit 063a7ce2 parents 9f9310b f1bb47a66 files · +1784 −122Browse files

Unified · Split

66 files
  1. .mailmap +4 −0
  2. Documentation/userspace-api/index.rst +1 −0
  3. Documentation/userspace-api/lsm.rst +73 −0
  4. MAINTAINERS +14 −3
  5. arch/alpha/kernel/syscalls/syscall.tbl +3 −0
  6. arch/arm/tools/syscall.tbl +3 −0
  7. arch/arm64/include/asm/unistd.h +1 −1
  8. arch/arm64/include/asm/unistd32.h +6 −0
  9. arch/m68k/kernel/syscalls/syscall.tbl +3 −0
  10. arch/microblaze/kernel/syscalls/syscall.tbl +3 −0
  11. arch/mips/kernel/syscalls/syscall_n32.tbl +3 −0
  12. arch/mips/kernel/syscalls/syscall_n64.tbl +3 −0
  13. arch/mips/kernel/syscalls/syscall_o32.tbl +3 −0
  14. arch/parisc/kernel/syscalls/syscall.tbl +3 −0
  15. arch/powerpc/kernel/syscalls/syscall.tbl +3 −0
  16. arch/s390/kernel/syscalls/syscall.tbl +3 −0
  17. arch/sh/kernel/syscalls/syscall.tbl +3 −0
  18. arch/sparc/kernel/syscalls/syscall.tbl +3 −0
  19. arch/x86/entry/syscalls/syscall_32.tbl +3 −0
  20. arch/x86/entry/syscalls/syscall_64.tbl +3 −0
  21. arch/xtensa/kernel/syscalls/syscall.tbl +3 −0
  22. fs/ioctl.c +1 −2
  23. fs/proc/base.c +15 −14
  24. fs/proc/internal.h +1 −1
  25. include/linux/lsm_hook_defs.h +6 −0
  26. include/linux/lsm_hooks.h +15 −2
  27. include/linux/security.h +50 −6
  28. include/linux/syscalls.h +6 −0
  29. include/uapi/asm-generic/unistd.h +8 −1
  30. include/uapi/linux/lsm.h +90 −0
  31. kernel/sys_ni.c +3 −0
  32. net/netlabel/netlabel_calipso.c +26 −23
  33. security/Makefile +1 −0
  34. security/apparmor/include/procattr.h +1 −1
  35. security/apparmor/lsm.c +83 −7
  36. security/apparmor/procattr.c +6 −4
  37. security/bpf/hooks.c +8 −1
  38. security/commoncap.c +7 −1
  39. security/landlock/cred.c +1 −1
  40. security/landlock/fs.c +1 −1
  41. security/landlock/net.c +1 −1
  42. security/landlock/ptrace.c +1 −1
  43. security/landlock/setup.c +6 −0
  44. security/landlock/setup.h +1 −0
  45. security/loadpin/loadpin.c +8 −1
  46. security/lockdown/lockdown.c +7 −1
  47. security/lsm_syscalls.c +120 −0
  48. security/safesetid/lsm.c +8 −1
  49. security/security.c +261 −12
  50. security/selinux/hooks.c +145 −28
  51. security/smack/smack_lsm.c +87 −6
  52. security/tomoyo/tomoyo.c +9 −1
  53. security/yama/yama_lsm.c +7 −1
  54. tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl +5 −0
  55. tools/perf/arch/powerpc/entry/syscalls/syscall.tbl +5 −0
  56. tools/perf/arch/s390/entry/syscalls/syscall.tbl +5 −0
  57. tools/perf/arch/x86/entry/syscalls/syscall_64.tbl +5 −0
  58. tools/testing/selftests/Makefile +1 −0
  59. tools/testing/selftests/lsm/.gitignore +1 −0
  60. tools/testing/selftests/lsm/Makefile +17 −0
  61. tools/testing/selftests/lsm/common.c +89 −0
  62. tools/testing/selftests/lsm/common.h +33 −0
  63. tools/testing/selftests/lsm/config +3 −0
  64. tools/testing/selftests/lsm/lsm_get_self_attr_test.c +275 −0
  65. tools/testing/selftests/lsm/lsm_list_modules_test.c +137 −0
  66. tools/testing/selftests/lsm/lsm_set_self_attr_test.c +74 −0
.mailmap+4−0
@@ -478,6 +478,8 @@ Paul E. McKenney <paulmck@kernel.org> <paulmck@linux.vnet.ibm.com> · 477 unmodified lines
478478 Paul E. McKenney <paulmck@kernel.org> <paulmck@us.ibm.com>
479479 Paul Mackerras <paulus@ozlabs.org> <paulus@samba.org>
480480 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>
481483 Pavankumar Kondeti <quic_pkondeti@quicinc.com> <pkondeti@codeaurora.org>
482484 Peter A Jonsson <pj@ludd.ltu.se>
483485 Peter Oruba <peter.oruba@amd.com>
@@ -542,6 +544,8 @@ Sebastian Reichel <sre@kernel.org> <sebastian.reichel@collabora.co.uk> · 58 unmodified lines
542544 Sebastian Reichel <sre@kernel.org> <sre@debian.org>
543545 Sedat Dilek <sedat.dilek@gmail.com> <sedat.dilek@credativ.de>
544546 Senthilkumar N L <quic_snlakshm@quicinc.com> <snlakshm@codeaurora.org>
547+Serge Hallyn <sergeh@kernel.org> <serge.hallyn@canonical.com>
548+Serge Hallyn <sergeh@kernel.org> <serue@us.ibm.com>
545549 Seth Forshee <sforshee@kernel.org> <seth.forshee@canonical.com>
546550 Shannon Nelson <shannon.nelson@amd.com> <snelson@pensando.io>
547551 Shannon Nelson <shannon.nelson@amd.com> <shannon.nelson@intel.com>
Documentation/userspace-api/index.rst+1−0
@@ -33,6 +33,7 @@ place where this information is gathered. · 32 unmodified lines
3333 sysfs-platform_profile
3434 vduse
3535 futex2
36+ lsm
3637
3738 .. only:: subproject and html
3839
Documentation/userspace-api/lsm.rst+73−0
@@ -0,0 +1,73 @@
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
MAINTAINERS+14−3
@@ -12417,6 +12417,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/har · 12416 unmodified lines
1241712417 F: Documentation/admin-guide/LSM/LoadPin.rst
1241812418 F: security/loadpin/
1241912419
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+
1242012426 LOCKING PRIMITIVES
1242112427 M: Peter Zijlstra <peterz@infradead.org>
1242212428 M: Ingo Molnar <mingo@redhat.com>
@@ -19455,12 +19461,17 @@ SECURITY SUBSYSTEM · 7032 unmodified lines
1945519461 M: Paul Moore <paul@paul-moore.com>
1945619462 M: James Morris <jmorris@namei.org>
1945719463 M: "Serge E. Hallyn" <serge@hallyn.com>
19458−L: linux-security-module@vger.kernel.org (suggested Cc:)
19464+L: linux-security-module@vger.kernel.org
1945919465 S: Supported
19460−W: http://kernsec.org/
19461−T: git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm.git
19466+Q: https://patchwork.kernel.org/project/linux-security-module/list
19467+B: mailto:linux-security-module@vger.kernel.org
19468+P: https://github.com/LinuxSecurityModule/kernel/blob/main/README.md
19469+T: git https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm.git
19470+F: include/uapi/linux/lsm.h
1946219471 F: security/
19472+F: tools/testing/selftests/lsm/
1946319473 X: security/selinux/
19474+K: \bsecurity_[a-z_0-9]\+\b
1946419475
1946519476 SELINUX SECURITY MODULE
1946619477 M: Paul Moore <paul@paul-moore.com>
arch/alpha/kernel/syscalls/syscall.tbl+3−0
@@ -498,3 +498,6 @@ · 497 unmodified lines
498498 566 common futex_requeue sys_futex_requeue
499499 567 common statmount sys_statmount
500500 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
arch/arm/tools/syscall.tbl+3−0
@@ -472,3 +472,6 @@ · 471 unmodified lines
472472 456 common futex_requeue sys_futex_requeue
473473 457 common statmount sys_statmount
474474 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
arch/arm64/include/asm/unistd.h+1−1
@@ -39,7 +39,7 @@ · 38 unmodified lines
3939 #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5)
4040 #define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800)
4141
42−#define __NR_compat_syscalls 459
42+#define __NR_compat_syscalls 462
4343 #endif
4444
4545 #define __ARCH_WANT_SYS_CLONE
arch/arm64/include/asm/unistd32.h+6−0
@@ -923,6 +923,12 @@ __SYSCALL(__NR_futex_requeue, sys_futex_requeue) · 922 unmodified lines
923923 __SYSCALL(__NR_statmount, sys_statmount)
924924 #define __NR_listmount 458
925925 __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)
926932
927933 /*
928934 * Please add new compat syscalls above this comment and update
arch/m68k/kernel/syscalls/syscall.tbl+3−0
@@ -458,3 +458,6 @@ · 457 unmodified lines
458458 456 common futex_requeue sys_futex_requeue
459459 457 common statmount sys_statmount
460460 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
arch/microblaze/kernel/syscalls/syscall.tbl+3−0
@@ -464,3 +464,6 @@ · 463 unmodified lines
464464 456 common futex_requeue sys_futex_requeue
465465 457 common statmount sys_statmount
466466 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
arch/mips/kernel/syscalls/syscall_n32.tbl+3−0
@@ -397,3 +397,6 @@ · 396 unmodified lines
397397 456 n32 futex_requeue sys_futex_requeue
398398 457 n32 statmount sys_statmount
399399 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
arch/mips/kernel/syscalls/syscall_n64.tbl+3−0
@@ -373,3 +373,6 @@ · 372 unmodified lines
373373 456 n64 futex_requeue sys_futex_requeue
374374 457 n64 statmount sys_statmount
375375 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
arch/mips/kernel/syscalls/syscall_o32.tbl+3−0
@@ -446,3 +446,6 @@ · 445 unmodified lines
446446 456 o32 futex_requeue sys_futex_requeue
447447 457 o32 statmount sys_statmount
448448 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
arch/parisc/kernel/syscalls/syscall.tbl+3−0
@@ -457,3 +457,6 @@ · 456 unmodified lines
457457 456 common futex_requeue sys_futex_requeue
458458 457 common statmount sys_statmount
459459 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
arch/powerpc/kernel/syscalls/syscall.tbl+3−0
@@ -545,3 +545,6 @@ · 544 unmodified lines
545545 456 common futex_requeue sys_futex_requeue
546546 457 common statmount sys_statmount
547547 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
arch/s390/kernel/syscalls/syscall.tbl+3−0
@@ -461,3 +461,6 @@ · 460 unmodified lines
461461 456 common futex_requeue sys_futex_requeue sys_futex_requeue
462462 457 common statmount sys_statmount sys_statmount
463463 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
arch/sh/kernel/syscalls/syscall.tbl+3−0
@@ -461,3 +461,6 @@ · 460 unmodified lines
461461 456 common futex_requeue sys_futex_requeue
462462 457 common statmount sys_statmount
463463 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
arch/sparc/kernel/syscalls/syscall.tbl+3−0
@@ -504,3 +504,6 @@ · 503 unmodified lines
504504 456 common futex_requeue sys_futex_requeue
505505 457 common statmount sys_statmount
506506 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
arch/x86/entry/syscalls/syscall_32.tbl+3−0
@@ -463,3 +463,6 @@ · 462 unmodified lines
463463 456 i386 futex_requeue sys_futex_requeue
464464 457 i386 statmount sys_statmount
465465 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
arch/x86/entry/syscalls/syscall_64.tbl+3−0
@@ -380,6 +380,9 @@ · 379 unmodified lines
380380 456 common futex_requeue sys_futex_requeue
381381 457 common statmount sys_statmount
382382 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
383386
384387 #
385388 # Due to a historical design error, certain syscalls are numbered differently
arch/xtensa/kernel/syscalls/syscall.tbl+3−0
@@ -429,3 +429,6 @@ · 428 unmodified lines
429429 456 common futex_requeue sys_futex_requeue
430430 457 common statmount sys_statmount
431431 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
fs/ioctl.c+1−2
@@ -920,8 +920,7 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, · 919 unmodified lines
920920 if (!f.file)
921921 return -EBADF;
922922
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);
925924 if (error)
926925 goto out;
927926
fs/proc/base.c+15−14
@@ -97,6 +97,7 @@ · 96 unmodified lines
9797 #include <linux/resctrl.h>
9898 #include <linux/cn_proc.h>
9999 #include <linux/ksm.h>
100+#include <uapi/linux/lsm.h>
100101 #include <trace/events/oom.h>
101102 #include "internal.h"
102103 #include "fd.h"
@@ -146,10 +147,10 @@ struct pid_entry { · 43 unmodified lines
146147 NOD(NAME, (S_IFREG|(MODE)), \
147148 NULL, &proc_single_file_operations, \
148149 { .proc_show = show } )
149−#define ATTR(LSM, NAME, MODE) \
150+#define ATTR(LSMID, NAME, MODE) \
150151 NOD(NAME, (S_IFREG|(MODE)), \
151152 NULL, &proc_pid_attr_operations, \
152− { .lsm = LSM })
153+ { .lsmid = LSMID })
153154
154155 /*
155156 * Count the number of hardlinks for the pid_entry table, excluding the .
@@ -2726,7 +2727,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf, · 2570 unmodified lines
27262727 if (!task)
27272728 return -ESRCH;
27282729
2729− length = security_getprocattr(task, PROC_I(inode)->op.lsm,
2730+ length = security_getprocattr(task, PROC_I(inode)->op.lsmid,
27302731 file->f_path.dentry->d_name.name,
27312732 &p);
27322733 put_task_struct(task);
@@ -2784,7 +2785,7 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf, · 51 unmodified lines
27842785 if (rv < 0)
27852786 goto out_free;
27862787
2787− rv = security_setprocattr(PROC_I(inode)->op.lsm,
2788+ rv = security_setprocattr(PROC_I(inode)->op.lsmid,
27882789 file->f_path.dentry->d_name.name, page,
27892790 count);
27902791 mutex_unlock(&current->signal->cred_guard_mutex);
@@ -2833,27 +2834,27 @@ static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \ · 42 unmodified lines
28332834
28342835 #ifdef CONFIG_SECURITY_SMACK
28352836 static const struct pid_entry smack_attr_dir_stuff[] = {
2836− ATTR("smack", "current", 0666),
2837+ ATTR(LSM_ID_SMACK, "current", 0666),
28372838 };
28382839 LSM_DIR_OPS(smack);
28392840 #endif
28402841
28412842 #ifdef CONFIG_SECURITY_APPARMOR
28422843 static const struct pid_entry apparmor_attr_dir_stuff[] = {
2843− ATTR("apparmor", "current", 0666),
2844− ATTR("apparmor", "prev", 0444),
2845− ATTR("apparmor", "exec", 0666),
2844+ ATTR(LSM_ID_APPARMOR, "current", 0666),
2845+ ATTR(LSM_ID_APPARMOR, "prev", 0444),
2846+ ATTR(LSM_ID_APPARMOR, "exec", 0666),
28462847 };
28472848 LSM_DIR_OPS(apparmor);
28482849 #endif
28492850
28502851 static const struct pid_entry attr_dir_stuff[] = {
2851− ATTR(NULL, "current", 0666),
2852− ATTR(NULL, "prev", 0444),
2853− ATTR(NULL, "exec", 0666),
2854− ATTR(NULL, "fscreate", 0666),
2855− ATTR(NULL, "keycreate", 0666),
2856− ATTR(NULL, "sockcreate", 0666),
2852+ ATTR(LSM_ID_UNDEF, "current", 0666),
2853+ ATTR(LSM_ID_UNDEF, "prev", 0444),
2854+ ATTR(LSM_ID_UNDEF, "exec", 0666),
2855+ ATTR(LSM_ID_UNDEF, "fscreate", 0666),
2856+ ATTR(LSM_ID_UNDEF, "keycreate", 0666),
2857+ ATTR(LSM_ID_UNDEF, "sockcreate", 0666),
28572858 #ifdef CONFIG_SECURITY_SMACK
28582859 DIR("smack", 0555,
28592860 proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
fs/proc/internal.h+1−1
@@ -92,7 +92,7 @@ union proc_op { · 91 unmodified lines
9292 int (*proc_show)(struct seq_file *m,
9393 struct pid_namespace *ns, struct pid *pid,
9494 struct task_struct *task);
95− const char *lsm;
95+ int lsmid;
9696 };
9797
9898 struct proc_inode {
include/linux/lsm_hook_defs.h+6−0
@@ -171,6 +171,8 @@ LSM_HOOK(int, 0, file_alloc_security, struct file *file) · 170 unmodified lines
171171 LSM_HOOK(void, LSM_RET_VOID, file_free_security, struct file *file)
172172 LSM_HOOK(int, 0, file_ioctl, struct file *file, unsigned int cmd,
173173 unsigned long arg)
174+LSM_HOOK(int, 0, file_ioctl_compat, struct file *file, unsigned int cmd,
175+ unsigned long arg)
174176 LSM_HOOK(int, 0, mmap_addr, unsigned long addr)
175177 LSM_HOOK(int, 0, mmap_file, struct file *file, unsigned long reqprot,
176178 unsigned long prot, unsigned long flags)
@@ -262,6 +264,10 @@ LSM_HOOK(int, 0, sem_semop, struct kern_ipc_perm *perm, struct sembuf *sops, · 85 unmodified lines
262264 LSM_HOOK(int, 0, netlink_send, struct sock *sk, struct sk_buff *skb)
263265 LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry,
264266 struct inode *inode)
267+LSM_HOOK(int, -EOPNOTSUPP, getselfattr, unsigned int attr,
268+ struct lsm_ctx __user *ctx, size_t *size, u32 flags)
269+LSM_HOOK(int, -EOPNOTSUPP, setselfattr, unsigned int attr,
270+ struct lsm_ctx *ctx, size_t size, u32 flags)
265271 LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name,
266272 char **value)
267273 LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size)
include/linux/lsm_hooks.h+15−2
@@ -25,6 +25,7 @@ · 24 unmodified lines
2525 #ifndef __LINUX_LSM_HOOKS_H
2626 #define __LINUX_LSM_HOOKS_H
2727
28+#include <uapi/linux/lsm.h>
2829 #include <linux/security.h>
2930 #include <linux/init.h>
3031 #include <linux/rculist.h>
@@ -42,6 +43,18 @@ struct security_hook_heads { · 11 unmodified lines
4243 #undef LSM_HOOK
4344 } __randomize_layout;
4445
46+/**
47+ * struct lsm_id - Identify a Linux Security Module.
48+ * @lsm: name of the LSM, must be approved by the LSM maintainers
49+ * @id: LSM ID number from uapi/linux/lsm.h
50+ *
51+ * Contains the information that identifies the LSM.
52+ */
53+struct lsm_id {
54+ const char *name;
55+ u64 id;
56+};
57+
4558 /*
4659 * Security module hook list structure.
4760 * For use with generic list macros for common operations.
@@ -50,7 +63,7 @@ struct security_hook_list { · 2 unmodified lines
5063 struct hlist_node list;
5164 struct hlist_head *head;
5265 union security_list_options hook;
53− const char *lsm;
66+ const struct lsm_id *lsmid;
5467 } __randomize_layout;
5568
5669 /*
@@ -104,7 +117,7 @@ extern struct security_hook_heads security_hook_heads; · 47 unmodified lines
104117 extern char *lsm_names;
105118
106119 extern void security_add_hooks(struct security_hook_list *hooks, int count,
107− const char *lsm);
120+ const struct lsm_id *lsmid);
108121
109122 #define LSM_FLAG_LEGACY_MAJOR BIT(0)
110123 #define LSM_FLAG_EXCLUSIVE BIT(1)
include/linux/security.h+50−6
@@ -32,6 +32,7 @@ · 31 unmodified lines
3232 #include <linux/string.h>
3333 #include <linux/mm.h>
3434 #include <linux/sockptr.h>
35+#include <uapi/linux/lsm.h>
3536
3637 struct linux_binprm;
3738 struct cred;
@@ -60,6 +61,7 @@ struct fs_parameter; · 22 unmodified lines
6061 enum fs_value_type;
6162 struct watch;
6263 struct watch_notification;
64+struct lsm_ctx;
6365
6466 /* Default (no) options for the capable function */
6567 #define CAP_OPT_NONE 0x0
@@ -138,6 +140,8 @@ enum lockdown_reason { · 72 unmodified lines
138140 };
139141
140142 extern const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1];
143+extern u32 lsm_active_cnt;
144+extern const struct lsm_id *lsm_idlist[];
141145
142146 /* These functions are in security/commoncap.c */
143147 extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
@@ -261,6 +265,7 @@ int unregister_blocking_lsm_notifier(struct notifier_block *nb); · 117 unmodified lines
261265 /* prototypes */
262266 extern int security_init(void);
263267 extern int early_security_init(void);
268+extern u64 lsm_name_to_attr(const char *name);
264269
265270 /* Security operations */
266271 int security_binder_set_context_mgr(const struct cred *mgr);
@@ -389,6 +394,8 @@ int security_file_permission(struct file *file, int mask); · 122 unmodified lines
389394 int security_file_alloc(struct file *file);
390395 void security_file_free(struct file *file);
391396 int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
397+int security_file_ioctl_compat(struct file *file, unsigned int cmd,
398+ unsigned long arg);
392399 int security_mmap_file(struct file *file, unsigned long prot,
393400 unsigned long flags);
394401 int security_mmap_addr(unsigned long addr);
@@ -470,10 +477,13 @@ int security_sem_semctl(struct kern_ipc_perm *sma, int cmd); · 75 unmodified lines
470477 int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
471478 unsigned nsops, int alter);
472479 void security_d_instantiate(struct dentry *dentry, struct inode *inode);
473−int security_getprocattr(struct task_struct *p, const char *lsm, const char *name,
480+int security_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
481+ size_t __user *size, u32 flags);
482+int security_setselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
483+ size_t size, u32 flags);
484+int security_getprocattr(struct task_struct *p, int lsmid, const char *name,
474485 char **value);
475−int security_setprocattr(const char *lsm, const char *name, void *value,
476− size_t size);
486+int security_setprocattr(int lsmid, const char *name, void *value, size_t size);
477487 int security_netlink_send(struct sock *sk, struct sk_buff *skb);
478488 int security_ismaclabel(const char *name);
479489 int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
@@ -484,6 +494,8 @@ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); · 4 unmodified lines
484494 int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
485495 int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
486496 int security_locked_down(enum lockdown_reason what);
497+int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, size_t *uctx_len,
498+ void *val, size_t val_len, u64 id, u64 flags);
487499 #else /* CONFIG_SECURITY */
488500
489501 static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data)
@@ -501,6 +513,11 @@ static inline int unregister_blocking_lsm_notifier(struct notifier_block *nb) · 11 unmodified lines
501513 return 0;
502514 }
503515
516+static inline u64 lsm_name_to_attr(const char *name)
517+{
518+ return LSM_ATTR_UNDEF;
519+}
520+
504521 static inline void security_free_mnt_opts(void **mnt_opts)
505522 {
506523 }
@@ -987,6 +1004,13 @@ static inline int security_file_ioctl(struct file *file, unsigned int cmd, · 480 unmodified lines
9871004 return 0;
9881005 }
9891006
1007+static inline int security_file_ioctl_compat(struct file *file,
1008+ unsigned int cmd,
1009+ unsigned long arg)
1010+{
1011+ return 0;
1012+}
1013+
9901014 static inline int security_mmap_file(struct file *file, unsigned long prot,
9911015 unsigned long flags)
9921016 {
@@ -1337,14 +1361,28 @@ static inline void security_d_instantiate(struct dentry *dentry, · 344 unmodified lines
13371361 struct inode *inode)
13381362 { }
13391363
1340−static inline int security_getprocattr(struct task_struct *p, const char *lsm,
1364+static inline int security_getselfattr(unsigned int attr,
1365+ struct lsm_ctx __user *ctx,
1366+ size_t __user *size, u32 flags)
1367+{
1368+ return -EOPNOTSUPP;
1369+}
1370+
1371+static inline int security_setselfattr(unsigned int attr,
1372+ struct lsm_ctx __user *ctx,
1373+ size_t size, u32 flags)
1374+{
1375+ return -EOPNOTSUPP;
1376+}
1377+
1378+static inline int security_getprocattr(struct task_struct *p, int lsmid,
13411379 const char *name, char **value)
13421380 {
13431381 return -EINVAL;
13441382 }
13451383
1346−static inline int security_setprocattr(const char *lsm, char *name,
1347− void *value, size_t size)
1384+static inline int security_setprocattr(int lsmid, char *name, void *value,
1385+ size_t size)
13481386 {
13491387 return -EINVAL;
13501388 }
@@ -1395,6 +1433,12 @@ static inline int security_locked_down(enum lockdown_reason what) · 44 unmodified lines
13951433 {
13961434 return 0;
13971435 }
1436+static inline int lsm_fill_user_ctx(struct lsm_ctx __user *uctx,
1437+ size_t *uctx_len, void *val, size_t val_len,
1438+ u64 id, u64 flags)
1439+{
1440+ return -EOPNOTSUPP;
1441+}
13981442 #endif /* CONFIG_SECURITY */
13991443
14001444 #if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE)
include/linux/syscalls.h+6−0
@@ -71,6 +71,7 @@ struct clone_args; · 70 unmodified lines
7171 struct open_how;
7272 struct mount_attr;
7373 struct landlock_ruleset_attr;
74+struct lsm_ctx;
7475 enum landlock_rule_type;
7576 struct cachestat_range;
7677 struct cachestat;
@@ -957,6 +958,11 @@ asmlinkage long sys_cachestat(unsigned int fd, · 880 unmodified lines
957958 struct cachestat_range __user *cstat_range,
958959 struct cachestat __user *cstat, unsigned int flags);
959960 asmlinkage long sys_map_shadow_stack(unsigned long addr, unsigned long size, unsigned int flags);
961+asmlinkage long sys_lsm_get_self_attr(unsigned int attr, struct lsm_ctx *ctx,
962+ size_t *size, __u32 flags);
963+asmlinkage long sys_lsm_set_self_attr(unsigned int attr, struct lsm_ctx *ctx,
964+ size_t size, __u32 flags);
965+asmlinkage long sys_lsm_list_modules(u64 *ids, size_t *size, u32 flags);
960966
961967 /*
962968 * Architecture-specific system calls
include/uapi/asm-generic/unistd.h+8−1
@@ -835,8 +835,15 @@ __SYSCALL(__NR_statmount, sys_statmount) · 834 unmodified lines
835835 #define __NR_listmount 458
836836 __SYSCALL(__NR_listmount, sys_listmount)
837837
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+
838845 #undef __NR_syscalls
839−#define __NR_syscalls 459
846+#define __NR_syscalls 462
840847
841848 /*
842849 * 32 bit systems traditionally used different
include/uapi/linux/lsm.h+90−0
@@ -0,0 +1,90 @@
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 */
kernel/sys_ni.c+3−0
@@ -171,6 +171,9 @@ COND_SYSCALL(landlock_add_rule); · 170 unmodified lines
171171 COND_SYSCALL(landlock_restrict_self);
172172 COND_SYSCALL(fadvise64_64);
173173 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);
174177
175178 /* CONFIG_MMU only */
176179 COND_SYSCALL(swapon);
net/netlabel/netlabel_calipso.c+26−23
@@ -54,6 +54,28 @@ static const struct nla_policy calipso_genl_policy[NLBL_CALIPSO_A_MAX + 1] = { · 53 unmodified lines
5454 [NLBL_CALIPSO_A_MTYPE] = { .type = NLA_U32 },
5555 };
5656
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+
5779 /* NetLabel Command Handlers
5880 */
5981 /**
@@ -96,15 +118,18 @@ static int netlbl_calipso_add_pass(struct genl_info *info, · 36 unmodified lines
96118 *
97119 */
98120 static int netlbl_calipso_add(struct sk_buff *skb, struct genl_info *info)
99−
100121 {
101122 int ret_val = -EINVAL;
102123 struct netlbl_audit audit_info;
124+ const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
103125
104126 if (!info->attrs[NLBL_CALIPSO_A_DOI] ||
105127 !info->attrs[NLBL_CALIPSO_A_MTYPE])
106128 return -EINVAL;
107129
130+ if (!ops)
131+ return -EOPNOTSUPP;
132+
108133 netlbl_netlink_auditinfo(&audit_info);
109134 switch (nla_get_u32(info->attrs[NLBL_CALIPSO_A_MTYPE])) {
110135 case CALIPSO_MAP_PASS:
@@ -363,28 +388,6 @@ int __init netlbl_calipso_genl_init(void) · 252 unmodified lines
363388 return genl_register_family(&netlbl_calipso_gnl_family);
364389 }
365390
366−static const struct netlbl_calipso_ops *calipso_ops;
367−
368−/**
369− * netlbl_calipso_ops_register - Register the CALIPSO operations
370− * @ops: ops to register
371− *
372− * Description:
373− * Register the CALIPSO packet engine operations.
374− *
375− */
376−const struct netlbl_calipso_ops *
377−netlbl_calipso_ops_register(const struct netlbl_calipso_ops *ops)
378−{
379− return xchg(&calipso_ops, ops);
380−}
381−EXPORT_SYMBOL(netlbl_calipso_ops_register);
382−
383−static const struct netlbl_calipso_ops *netlbl_calipso_ops_get(void)
384−{
385− return READ_ONCE(calipso_ops);
386−}
387−
388391 /**
389392 * calipso_doi_add - Add a new DOI to the CALIPSO protocol engine
390393 * @doi_def: the DOI structure
security/Makefile+1−0
@@ -7,6 +7,7 @@ obj-$(CONFIG_KEYS) += keys/ · 6 unmodified lines
77
88 # always enable default capabilities
99 obj-y += commoncap.o
10+obj-$(CONFIG_SECURITY) += lsm_syscalls.o
1011 obj-$(CONFIG_MMU) += min_addr.o
1112
1213 # Object file lists
security/apparmor/include/procattr.h+1−1
@@ -11,7 +11,7 @@ · 10 unmodified lines
1111 #ifndef __AA_PROCATTR_H
1212 #define __AA_PROCATTR_H
1313
14−int aa_getprocattr(struct aa_label *label, char **string);
14+int aa_getprocattr(struct aa_label *label, char **string, bool newline);
1515 int aa_setprocattr_changehat(char *args, size_t size, int flags);
1616
1717 #endif /* __AA_PROCATTR_H */
security/apparmor/lsm.c+83−7
@@ -24,6 +24,7 @@ · 23 unmodified lines
2424 #include <linux/zstd.h>
2525 #include <net/sock.h>
2626 #include <uapi/linux/mount.h>
27+#include <uapi/linux/lsm.h>
2728
2829 #include "include/apparmor.h"
2930 #include "include/apparmorfs.h"
@@ -775,6 +776,46 @@ static int apparmor_sb_pivotroot(const struct path *old_path, · 745 unmodified lines
775776 return error;
776777 }
777778
779+static int apparmor_getselfattr(unsigned int attr, struct lsm_ctx __user *lx,
780+ size_t *size, u32 flags)
781+{
782+ int error = -ENOENT;
783+ struct aa_task_ctx *ctx = task_ctx(current);
784+ struct aa_label *label = NULL;
785+ char *value;
786+
787+ switch (attr) {
788+ case LSM_ATTR_CURRENT:
789+ label = aa_get_newest_label(cred_label(current_cred()));
790+ break;
791+ case LSM_ATTR_PREV:
792+ if (ctx->previous)
793+ label = aa_get_newest_label(ctx->previous);
794+ break;
795+ case LSM_ATTR_EXEC:
796+ if (ctx->onexec)
797+ label = aa_get_newest_label(ctx->onexec);
798+ break;
799+ default:
800+ error = -EOPNOTSUPP;
801+ break;
802+ }
803+
804+ if (label) {
805+ error = aa_getprocattr(label, &value, false);
806+ if (error > 0)
807+ error = lsm_fill_user_ctx(lx, size, value, error,
808+ LSM_ID_APPARMOR, 0);
809+ kfree(value);
810+ }
811+
812+ aa_put_label(label);
813+
814+ if (error < 0)
815+ return error;
816+ return 1;
817+}
818+
778819 static int apparmor_getprocattr(struct task_struct *task, const char *name,
779820 char **value)
780821 {
@@ -794,7 +835,7 @@ static int apparmor_getprocattr(struct task_struct *task, const char *name, · 13 unmodified lines
794835 error = -EINVAL;
795836
796837 if (label)
797− error = aa_getprocattr(label, value);
838+ error = aa_getprocattr(label, value, true);
798839
799840 aa_put_label(label);
800841 put_cred(cred);
@@ -802,8 +843,7 @@ static int apparmor_getprocattr(struct task_struct *task, const char *name, · 1 unmodified line
802843 return error;
803844 }
804845
805−static int apparmor_setprocattr(const char *name, void *value,
806− size_t size)
846+static int do_setattr(u64 attr, void *value, size_t size)
807847 {
808848 char *command, *largs = NULL, *args = value;
809849 size_t arg_size;
@@ -834,7 +874,7 @@ static int apparmor_setprocattr(const char *name, void *value, · 24 unmodified lines
834874 goto out;
835875
836876 arg_size = size - (args - (largs ? largs : (char *) value));
837− if (strcmp(name, "current") == 0) {
877+ if (attr == LSM_ATTR_CURRENT) {
838878 if (strcmp(command, "changehat") == 0) {
839879 error = aa_setprocattr_changehat(args, arg_size,
840880 AA_CHANGE_NOFLAGS);
@@ -849,7 +889,7 @@ static int apparmor_setprocattr(const char *name, void *value, · 8 unmodified lines
849889 error = aa_change_profile(args, AA_CHANGE_STACK);
850890 } else
851891 goto fail;
852− } else if (strcmp(name, "exec") == 0) {
892+ } else if (attr == LSM_ATTR_EXEC) {
853893 if (strcmp(command, "exec") == 0)
854894 error = aa_change_profile(args, AA_CHANGE_ONEXEC);
855895 else if (strcmp(command, "stack") == 0)
@@ -869,13 +909,42 @@ out: · 13 unmodified lines
869909
870910 fail:
871911 ad.subj_label = begin_current_label_crit_section();
872− ad.info = name;
912+ if (attr == LSM_ATTR_CURRENT)
913+ ad.info = "current";
914+ else if (attr == LSM_ATTR_EXEC)
915+ ad.info = "exec";
916+ else
917+ ad.info = "invalid";
873918 ad.error = error = -EINVAL;
874919 aa_audit_msg(AUDIT_APPARMOR_DENIED, &ad, NULL);
875920 end_current_label_crit_section(ad.subj_label);
876921 goto out;
877922 }
878923
924+static int apparmor_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
925+ size_t size, u32 flags)
926+{
927+ int rc;
928+
929+ if (attr != LSM_ATTR_CURRENT && attr != LSM_ATTR_EXEC)
930+ return -EOPNOTSUPP;
931+
932+ rc = do_setattr(attr, ctx->ctx, ctx->ctx_len);
933+ if (rc > 0)
934+ return 0;
935+ return rc;
936+}
937+
938+static int apparmor_setprocattr(const char *name, void *value,
939+ size_t size)
940+{
941+ int attr = lsm_name_to_attr(name);
942+
943+ if (attr)
944+ return do_setattr(attr, value, size);
945+ return -EINVAL;
946+}
947+
879948 /**
880949 * apparmor_bprm_committing_creds - do task cleanup on committing new creds
881950 * @bprm: binprm for the exec (NOT NULL)
@@ -1385,6 +1454,11 @@ struct lsm_blob_sizes apparmor_blob_sizes __ro_after_init = { · 503 unmodified lines
13851454 .lbs_task = sizeof(struct aa_task_ctx),
13861455 };
13871456
1457+static const struct lsm_id apparmor_lsmid = {
1458+ .name = "apparmor",
1459+ .id = LSM_ID_APPARMOR,
1460+};
1461+
13881462 static struct security_hook_list apparmor_hooks[] __ro_after_init = {
13891463 LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
13901464 LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
@@ -1418,6 +1492,8 @@ static struct security_hook_list apparmor_hooks[] __ro_after_init = { · 27 unmodified lines
14181492 LSM_HOOK_INIT(file_lock, apparmor_file_lock),
14191493 LSM_HOOK_INIT(file_truncate, apparmor_file_truncate),
14201494
1495+ LSM_HOOK_INIT(getselfattr, apparmor_getselfattr),
1496+ LSM_HOOK_INIT(setselfattr, apparmor_setselfattr),
14211497 LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
14221498 LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
14231499
@@ -2202,7 +2278,7 @@ static int __init apparmor_init(void) · 778 unmodified lines
22022278 goto buffers_out;
22032279 }
22042280 security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks),
2205− "apparmor");
2281+ &apparmor_lsmid);
22062282
22072283 /* Report that AppArmor successfully initialized */
22082284 apparmor_initialized = 1;
security/apparmor/procattr.c+6−4
@@ -20,6 +20,7 @@ · 19 unmodified lines
2020 * aa_getprocattr - Return the label information for @label
2121 * @label: the label to print label info about (NOT NULL)
2222 * @string: Returns - string containing the label info (NOT NULL)
23+ * @newline: indicates that a newline should be added
2324 *
2425 * Requires: label != NULL && string != NULL
2526 *
@@ -27,7 +28,7 @@ · 1 unmodified line
2728 *
2829 * Returns: size of string placed in @string else error code on failure
2930 */
30−int aa_getprocattr(struct aa_label *label, char **string)
31+int aa_getprocattr(struct aa_label *label, char **string, bool newline)
3132 {
3233 struct aa_ns *ns = labels_ns(label);
3334 struct aa_ns *current_ns = aa_get_current_ns();
@@ -57,11 +58,12 @@ int aa_getprocattr(struct aa_label *label, char **string) · 23 unmodified lines
5758 return len;
5859 }
5960
60− (*string)[len] = '\n';
61− (*string)[len + 1] = 0;
61+ if (newline)
62+ (*string)[len++] = '\n';
63+ (*string)[len] = 0;
6264
6365 aa_put_ns(current_ns);
64− return len + 1;
66+ return len;
6567 }
6668
6769 /**
security/bpf/hooks.c+8−1
@@ -5,6 +5,7 @@ · 4 unmodified lines
55 */
66 #include <linux/lsm_hooks.h>
77 #include <linux/bpf_lsm.h>
8+#include <uapi/linux/lsm.h>
89
910 static struct security_hook_list bpf_lsm_hooks[] __ro_after_init = {
1011 #define LSM_HOOK(RET, DEFAULT, NAME, ...) \
@@ -15,9 +16,15 @@ static struct security_hook_list bpf_lsm_hooks[] __ro_after_init = { · 4 unmodified lines
1516 LSM_HOOK_INIT(task_free, bpf_task_storage_free),
1617 };
1718
19+static const struct lsm_id bpf_lsmid = {
20+ .name = "bpf",
21+ .id = LSM_ID_BPF,
22+};
23+
1824 static int __init bpf_lsm_init(void)
1925 {
20− security_add_hooks(bpf_lsm_hooks, ARRAY_SIZE(bpf_lsm_hooks), "bpf");
26+ security_add_hooks(bpf_lsm_hooks, ARRAY_SIZE(bpf_lsm_hooks),
27+ &bpf_lsmid);
2128 pr_info("LSM support for eBPF active\n");
2229 return 0;
2330 }
security/commoncap.c+7−1
@@ -25,6 +25,7 @@ · 24 unmodified lines
2525 #include <linux/binfmts.h>
2626 #include <linux/personality.h>
2727 #include <linux/mnt_idmapping.h>
28+#include <uapi/linux/lsm.h>
2829
2930 /*
3031 * If a non-root user executes a setuid-root binary in
@@ -1440,6 +1441,11 @@ int cap_mmap_file(struct file *file, unsigned long reqprot, · 1409 unmodified lines
14401441
14411442 #ifdef CONFIG_SECURITY
14421443
1444+static const struct lsm_id capability_lsmid = {
1445+ .name = "capability",
1446+ .id = LSM_ID_CAPABILITY,
1447+};
1448+
14431449 static struct security_hook_list capability_hooks[] __ro_after_init = {
14441450 LSM_HOOK_INIT(capable, cap_capable),
14451451 LSM_HOOK_INIT(settime, cap_settime),
@@ -1464,7 +1470,7 @@ static struct security_hook_list capability_hooks[] __ro_after_init = { · 18 unmodified lines
14641470 static int __init capability_init(void)
14651471 {
14661472 security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks),
1467− "capability");
1473+ &capability_lsmid);
14681474 return 0;
14691475 }
14701476
security/landlock/cred.c+1−1
@@ -42,5 +42,5 @@ static struct security_hook_list landlock_hooks[] __ro_after_init = { · 41 unmodified lines
4242 __init void landlock_add_cred_hooks(void)
4343 {
4444 security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
45− LANDLOCK_NAME);
45+ &landlock_lsmid);
4646 }
security/landlock/fs.c+1−1
@@ -1223,5 +1223,5 @@ static struct security_hook_list landlock_hooks[] __ro_after_init = { · 1222 unmodified lines
12231223 __init void landlock_add_fs_hooks(void)
12241224 {
12251225 security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
1226− LANDLOCK_NAME);
1226+ &landlock_lsmid);
12271227 }
security/landlock/net.c+1−1
@@ -196,5 +196,5 @@ static struct security_hook_list landlock_hooks[] __ro_after_init = { · 195 unmodified lines
196196 __init void landlock_add_net_hooks(void)
197197 {
198198 security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
199− LANDLOCK_NAME);
199+ &landlock_lsmid);
200200 }
security/landlock/ptrace.c+1−1
@@ -116,5 +116,5 @@ static struct security_hook_list landlock_hooks[] __ro_after_init = { · 115 unmodified lines
116116 __init void landlock_add_ptrace_hooks(void)
117117 {
118118 security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
119− LANDLOCK_NAME);
119+ &landlock_lsmid);
120120 }
security/landlock/setup.c+6−0
@@ -8,6 +8,7 @@ · 7 unmodified lines
88
99 #include <linux/init.h>
1010 #include <linux/lsm_hooks.h>
11+#include <uapi/linux/lsm.h>
1112
1213 #include "common.h"
1314 #include "cred.h"
@@ -25,6 +26,11 @@ struct lsm_blob_sizes landlock_blob_sizes __ro_after_init = { · 11 unmodified lines
2526 .lbs_superblock = sizeof(struct landlock_superblock_security),
2627 };
2728
29+const struct lsm_id landlock_lsmid = {
30+ .name = LANDLOCK_NAME,
31+ .id = LSM_ID_LANDLOCK,
32+};
33+
2834 static int __init landlock_init(void)
2935 {
3036 landlock_add_cred_hooks();
security/landlock/setup.h+1−0
@@ -14,5 +14,6 @@ · 13 unmodified lines
1414 extern bool landlock_initialized;
1515
1616 extern struct lsm_blob_sizes landlock_blob_sizes;
17+extern const struct lsm_id landlock_lsmid;
1718
1819 #endif /* _SECURITY_LANDLOCK_SETUP_H */
security/loadpin/loadpin.c+8−1
@@ -20,6 +20,7 @@ · 19 unmodified lines
2020 #include <linux/string_helpers.h>
2121 #include <linux/dm-verity-loadpin.h>
2222 #include <uapi/linux/loadpin.h>
23+#include <uapi/linux/lsm.h>
2324
2425 #define VERITY_DIGEST_FILE_HEADER "# LOADPIN_TRUSTED_VERITY_ROOT_DIGESTS"
2526
@@ -208,6 +209,11 @@ static int loadpin_load_data(enum kernel_load_data_id id, bool contents) · 182 unmodified lines
208209 return loadpin_check(NULL, (enum kernel_read_file_id) id);
209210 }
210211
212+static const struct lsm_id loadpin_lsmid = {
213+ .name = "loadpin",
214+ .id = LSM_ID_LOADPIN,
215+};
216+
211217 static struct security_hook_list loadpin_hooks[] __ro_after_init = {
212218 LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
213219 LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
@@ -259,7 +265,8 @@ static int __init loadpin_init(void) · 45 unmodified lines
259265 if (!register_sysctl("kernel/loadpin", loadpin_sysctl_table))
260266 pr_notice("sysctl registration failed!\n");
261267 #endif
262− security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin");
268+ security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks),
269+ &loadpin_lsmid);
263270
264271 return 0;
265272 }
security/lockdown/lockdown.c+7−1
@@ -13,6 +13,7 @@ · 12 unmodified lines
1313 #include <linux/security.h>
1414 #include <linux/export.h>
1515 #include <linux/lsm_hooks.h>
16+#include <uapi/linux/lsm.h>
1617
1718 static enum lockdown_reason kernel_locked_down;
1819
@@ -75,6 +76,11 @@ static struct security_hook_list lockdown_hooks[] __ro_after_init = { · 56 unmodified lines
7576 LSM_HOOK_INIT(locked_down, lockdown_is_locked_down),
7677 };
7778
79+const struct lsm_id lockdown_lsmid = {
80+ .name = "lockdown",
81+ .id = LSM_ID_LOCKDOWN,
82+};
83+
7884 static int __init lockdown_lsm_init(void)
7985 {
8086 #if defined(CONFIG_LOCK_DOWN_KERNEL_FORCE_INTEGRITY)
@@ -83,7 +89,7 @@ static int __init lockdown_lsm_init(void) · 2 unmodified lines
8389 lock_kernel_down("Kernel configuration", LOCKDOWN_CONFIDENTIALITY_MAX);
8490 #endif
8591 security_add_hooks(lockdown_hooks, ARRAY_SIZE(lockdown_hooks),
86− "lockdown");
92+ &lockdown_lsmid);
8793 return 0;
8894 }
8995
security/lsm_syscalls.c+120−0
@@ -0,0 +1,120 @@
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+}
security/safesetid/lsm.c+8−1
@@ -19,6 +19,7 @@ · 18 unmodified lines
1919 #include <linux/ptrace.h>
2020 #include <linux/sched/task_stack.h>
2121 #include <linux/security.h>
22+#include <uapi/linux/lsm.h>
2223 #include "lsm.h"
2324
2425 /* Flag indicating whether initialization completed */
@@ -261,6 +262,11 @@ static int safesetid_task_fix_setgroups(struct cred *new, const struct cred *old · 236 unmodified lines
261262 return 0;
262263 }
263264
265+static const struct lsm_id safesetid_lsmid = {
266+ .name = "safesetid",
267+ .id = LSM_ID_SAFESETID,
268+};
269+
264270 static struct security_hook_list safesetid_security_hooks[] = {
265271 LSM_HOOK_INIT(task_fix_setuid, safesetid_task_fix_setuid),
266272 LSM_HOOK_INIT(task_fix_setgid, safesetid_task_fix_setgid),
@@ -271,7 +277,8 @@ static struct security_hook_list safesetid_security_hooks[] = { · 4 unmodified lines
271277 static int __init safesetid_security_init(void)
272278 {
273279 security_add_hooks(safesetid_security_hooks,
274− ARRAY_SIZE(safesetid_security_hooks), "safesetid");
280+ ARRAY_SIZE(safesetid_security_hooks),
281+ &safesetid_lsmid);
275282
276283 /* Report that SafeSetID successfully initialized */
277284 safesetid_initialized = 1;
security/security.c+261−12
@@ -34,6 +34,24 @@ · 33 unmodified lines
3434 /* How many LSMs were built into the kernel? */
3535 #define LSM_COUNT (__end_lsm_info - __start_lsm_info)
3636
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+
3755 /*
3856 * These are descriptions of the reasons that can be passed to the
3957 * security_locked_down() LSM hook. Placing this array here allows
@@ -245,6 +263,12 @@ static void __init initialize_lsm(struct lsm_info *lsm) · 205 unmodified lines
245263 }
246264 }
247265
266+/*
267+ * Current index to use while initializing the lsm id list.
268+ */
269+u32 lsm_active_cnt __ro_after_init;
270+const struct lsm_id *lsm_idlist[LSM_CONFIG_COUNT];
271+
248272 /* Populate ordered LSMs list from comma-separated LSM name list. */
249273 static void __init ordered_lsm_parse(const char *order, const char *origin)
250274 {
@@ -513,17 +537,29 @@ static int lsm_append(const char *new, char **result) · 262 unmodified lines
513537 * security_add_hooks - Add a modules hooks to the hook lists.
514538 * @hooks: the hooks to add
515539 * @count: the number of hooks to add
516− * @lsm: the name of the security module
540+ * @lsmid: the identification information for the security module
517541 *
518542 * Each LSM has to register its hooks with the infrastructure.
519543 */
520544 void __init security_add_hooks(struct security_hook_list *hooks, int count,
521− const char *lsm)
545+ const struct lsm_id *lsmid)
522546 {
523547 int i;
524548
549+ /*
550+ * A security module may call security_add_hooks() more
551+ * than once during initialization, and LSM initialization
552+ * is serialized. Landlock is one such case.
553+ * Look at the previous entry, if there is one, for duplication.
554+ */
555+ if (lsm_active_cnt == 0 || lsm_idlist[lsm_active_cnt - 1] != lsmid) {
556+ if (lsm_active_cnt >= LSM_CONFIG_COUNT)
557+ panic("%s Too many LSMs registered.\n", __func__);
558+ lsm_idlist[lsm_active_cnt++] = lsmid;
559+ }
560+
525561 for (i = 0; i < count; i++) {
526− hooks[i].lsm = lsm;
562+ hooks[i].lsmid = lsmid;
527563 hlist_add_tail_rcu(&hooks[i].list, hooks[i].head);
528564 }
529565
@@ -532,7 +568,7 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count, · 2 unmodified lines
532568 * and fix this up afterwards.
533569 */
534570 if (slab_is_available()) {
535− if (lsm_append(lsm, &lsm_names) < 0)
571+ if (lsm_append(lsmid->name, &lsm_names) < 0)
536572 panic("%s - Cannot get early memory.\n", __func__);
537573 }
538574 }
@@ -734,6 +770,54 @@ static int lsm_superblock_alloc(struct super_block *sb) · 195 unmodified lines
734770 return 0;
735771 }
736772
773+/**
774+ * lsm_fill_user_ctx - Fill a user space lsm_ctx structure
775+ * @uctx: a userspace LSM context to be filled
776+ * @uctx_len: available uctx size (input), used uctx size (output)
777+ * @val: the new LSM context value
778+ * @val_len: the size of the new LSM context value
779+ * @id: LSM id
780+ * @flags: LSM defined flags
781+ *
782+ * Fill all of the fields in a userspace lsm_ctx structure.
783+ *
784+ * Returns 0 on success, -E2BIG if userspace buffer is not large enough,
785+ * -EFAULT on a copyout error, -ENOMEM if memory can't be allocated.
786+ */
787+int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, size_t *uctx_len,
788+ void *val, size_t val_len,
789+ u64 id, u64 flags)
790+{
791+ struct lsm_ctx *nctx = NULL;
792+ size_t nctx_len;
793+ int rc = 0;
794+
795+ nctx_len = ALIGN(struct_size(nctx, ctx, val_len), sizeof(void *));
796+ if (nctx_len > *uctx_len) {
797+ rc = -E2BIG;
798+ goto out;
799+ }
800+
801+ nctx = kzalloc(nctx_len, GFP_KERNEL);
802+ if (nctx == NULL) {
803+ rc = -ENOMEM;
804+ goto out;
805+ }
806+ nctx->id = id;
807+ nctx->flags = flags;
808+ nctx->len = nctx_len;
809+ nctx->ctx_len = val_len;
810+ memcpy(nctx->ctx, val, val_len);
811+
812+ if (copy_to_user(uctx, nctx, nctx_len))
813+ rc = -EFAULT;
814+
815+out:
816+ kfree(nctx);
817+ *uctx_len = nctx_len;
818+ return rc;
819+}
820+
737821 /*
738822 * The default value of the LSM hook is defined in linux/lsm_hook_defs.h and
739823 * can be accessed with:
@@ -2642,6 +2726,24 @@ int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) · 1902 unmodified lines
26422726 }
26432727 EXPORT_SYMBOL_GPL(security_file_ioctl);
26442728
2729+/**
2730+ * security_file_ioctl_compat() - Check if an ioctl is allowed in compat mode
2731+ * @file: associated file
2732+ * @cmd: ioctl cmd
2733+ * @arg: ioctl arguments
2734+ *
2735+ * Compat version of security_file_ioctl() that correctly handles 32-bit
2736+ * processes running on 64-bit kernels.
2737+ *
2738+ * Return: Returns 0 if permission is granted.
2739+ */
2740+int security_file_ioctl_compat(struct file *file, unsigned int cmd,
2741+ unsigned long arg)
2742+{
2743+ return call_int_hook(file_ioctl_compat, 0, file, cmd, arg);
2744+}
2745+EXPORT_SYMBOL_GPL(security_file_ioctl_compat);
2746+
26452747 static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
26462748 {
26472749 /*
@@ -3794,10 +3896,158 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode) · 1146 unmodified lines
37943896 }
37953897 EXPORT_SYMBOL(security_d_instantiate);
37963898
3899+/*
3900+ * Please keep this in sync with it's counterpart in security/lsm_syscalls.c
3901+ */
3902+
3903+/**
3904+ * security_getselfattr - Read an LSM attribute of the current process.
3905+ * @attr: which attribute to return
3906+ * @uctx: the user-space destination for the information, or NULL
3907+ * @size: pointer to the size of space available to receive the data
3908+ * @flags: special handling options. LSM_FLAG_SINGLE indicates that only
3909+ * attributes associated with the LSM identified in the passed @ctx be
3910+ * reported.
3911+ *
3912+ * A NULL value for @uctx can be used to get both the number of attributes
3913+ * and the size of the data.
3914+ *
3915+ * Returns the number of attributes found on success, negative value
3916+ * on error. @size is reset to the total size of the data.
3917+ * If @size is insufficient to contain the data -E2BIG is returned.
3918+ */
3919+int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx,
3920+ size_t __user *size, u32 flags)
3921+{
3922+ struct security_hook_list *hp;
3923+ struct lsm_ctx lctx = { .id = LSM_ID_UNDEF, };
3924+ u8 __user *base = (u8 __user *)uctx;
3925+ size_t total = 0;
3926+ size_t entrysize;
3927+ size_t left;
3928+ bool toobig = false;
3929+ bool single = false;
3930+ int count = 0;
3931+ int rc;
3932+
3933+ if (attr == LSM_ATTR_UNDEF)
3934+ return -EINVAL;
3935+ if (size == NULL)
3936+ return -EINVAL;
3937+ if (get_user(left, size))
3938+ return -EFAULT;
3939+
3940+ if (flags) {
3941+ /*
3942+ * Only flag supported is LSM_FLAG_SINGLE
3943+ */
3944+ if (flags != LSM_FLAG_SINGLE || !uctx)
3945+ return -EINVAL;
3946+ if (copy_from_user(&lctx, uctx, sizeof(lctx)))
3947+ return -EFAULT;
3948+ /*
3949+ * If the LSM ID isn't specified it is an error.
3950+ */
3951+ if (lctx.id == LSM_ID_UNDEF)
3952+ return -EINVAL;
3953+ single = true;
3954+ }
3955+
3956+ /*
3957+ * In the usual case gather all the data from the LSMs.
3958+ * In the single case only get the data from the LSM specified.
3959+ */
3960+ hlist_for_each_entry(hp, &security_hook_heads.getselfattr, list) {
3961+ if (single && lctx.id != hp->lsmid->id)
3962+ continue;
3963+ entrysize = left;
3964+ if (base)
3965+ uctx = (struct lsm_ctx __user *)(base + total);
3966+ rc = hp->hook.getselfattr(attr, uctx, &entrysize, flags);
3967+ if (rc == -EOPNOTSUPP) {
3968+ rc = 0;
3969+ continue;
3970+ }
3971+ if (rc == -E2BIG) {
3972+ rc = 0;
3973+ left = 0;
3974+ toobig = true;
3975+ } else if (rc < 0)
3976+ return rc;
3977+ else
3978+ left -= entrysize;
3979+
3980+ total += entrysize;
3981+ count += rc;
3982+ if (single)
3983+ break;
3984+ }
3985+ if (put_user(total, size))
3986+ return -EFAULT;
3987+ if (toobig)
3988+ return -E2BIG;
3989+ if (count == 0)
3990+ return LSM_RET_DEFAULT(getselfattr);
3991+ return count;
3992+}
3993+
3994+/*
3995+ * Please keep this in sync with it's counterpart in security/lsm_syscalls.c
3996+ */
3997+
3998+/**
3999+ * security_setselfattr - Set an LSM attribute on the current process.
4000+ * @attr: which attribute to set
4001+ * @uctx: the user-space source for the information
4002+ * @size: the size of the data
4003+ * @flags: reserved for future use, must be 0
4004+ *
4005+ * Set an LSM attribute for the current process. The LSM, attribute
4006+ * and new value are included in @uctx.
4007+ *
4008+ * Returns 0 on success, -EINVAL if the input is inconsistent, -EFAULT
4009+ * if the user buffer is inaccessible, E2BIG if size is too big, or an
4010+ * LSM specific failure.
4011+ */
4012+int security_setselfattr(unsigned int attr, struct lsm_ctx __user *uctx,
4013+ size_t size, u32 flags)
4014+{
4015+ struct security_hook_list *hp;
4016+ struct lsm_ctx *lctx;
4017+ int rc = LSM_RET_DEFAULT(setselfattr);
4018+
4019+ if (flags)
4020+ return -EINVAL;
4021+ if (size < sizeof(*lctx))
4022+ return -EINVAL;
4023+ if (size > PAGE_SIZE)
4024+ return -E2BIG;
4025+
4026+ lctx = memdup_user(uctx, size);
4027+ if (IS_ERR(lctx))
4028+ return PTR_ERR(lctx);
4029+
4030+ if (size < lctx->len || size < lctx->ctx_len + sizeof(*lctx) ||
4031+ lctx->len < lctx->ctx_len + sizeof(*lctx)) {
4032+ rc = -EINVAL;
4033+ goto free_out;
4034+ }
4035+
4036+ hlist_for_each_entry(hp, &security_hook_heads.setselfattr, list)
4037+ if ((hp->lsmid->id) == lctx->id) {
4038+ rc = hp->hook.setselfattr(attr, lctx, size, flags);
4039+ break;
4040+ }
4041+
4042+free_out:
4043+ kfree(lctx);
4044+ return rc;
4045+}
4046+
37974047 /**
37984048 * security_getprocattr() - Read an attribute for a task
37994049 * @p: the task
3800− * @lsm: LSM name
4050+ * @lsmid: LSM identification
38014051 * @name: attribute name
38024052 * @value: attribute value
38034053 *
@@ -3805,13 +4055,13 @@ EXPORT_SYMBOL(security_d_instantiate); · 1 unmodified line
38054055 *
38064056 * Return: Returns the length of @value on success, a negative value otherwise.
38074057 */
3808−int security_getprocattr(struct task_struct *p, const char *lsm,
3809− const char *name, char **value)
4058+int security_getprocattr(struct task_struct *p, int lsmid, const char *name,
4059+ char **value)
38104060 {
38114061 struct security_hook_list *hp;
38124062
38134063 hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) {
3814− if (lsm != NULL && strcmp(lsm, hp->lsm))
4064+ if (lsmid != 0 && lsmid != hp->lsmid->id)
38154065 continue;
38164066 return hp->hook.getprocattr(p, name, value);
38174067 }
@@ -3820,7 +4070,7 @@ int security_getprocattr(struct task_struct *p, const char *lsm, · 2 unmodified lines
38204070
38214071 /**
38224072 * security_setprocattr() - Set an attribute for a task
3823− * @lsm: LSM name
4073+ * @lsmid: LSM identification
38244074 * @name: attribute name
38254075 * @value: attribute value
38264076 * @size: attribute value size
@@ -3830,13 +4080,12 @@ int security_getprocattr(struct task_struct *p, const char *lsm, · 3 unmodified lines
38304080 *
38314081 * Return: Returns bytes written on success, a negative value otherwise.
38324082 */
3833−int security_setprocattr(const char *lsm, const char *name, void *value,
3834− size_t size)
4083+int security_setprocattr(int lsmid, const char *name, void *value, size_t size)
38354084 {
38364085 struct security_hook_list *hp;
38374086
38384087 hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) {
3839− if (lsm != NULL && strcmp(lsm, hp->lsm))
4088+ if (lsmid != 0 && lsmid != hp->lsmid->id)
38404089 continue;
38414090 return hp->hook.setprocattr(name, value, size);
38424091 }
security/selinux/hooks.c+145−28
@@ -92,6 +92,7 @@ · 91 unmodified lines
9292 #include <linux/fsnotify.h>
9393 #include <linux/fanotify.h>
9494 #include <linux/io_uring.h>
95+#include <uapi/linux/lsm.h>
9596
9697 #include "avc.h"
9798 #include "objsec.h"
@@ -3738,6 +3739,33 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, · 3640 unmodified lines
37383739 return error;
37393740 }
37403741
3742+static int selinux_file_ioctl_compat(struct file *file, unsigned int cmd,
3743+ unsigned long arg)
3744+{
3745+ /*
3746+ * If we are in a 64-bit kernel running 32-bit userspace, we need to
3747+ * make sure we don't compare 32-bit flags to 64-bit flags.
3748+ */
3749+ switch (cmd) {
3750+ case FS_IOC32_GETFLAGS:
3751+ cmd = FS_IOC_GETFLAGS;
3752+ break;
3753+ case FS_IOC32_SETFLAGS:
3754+ cmd = FS_IOC_SETFLAGS;
3755+ break;
3756+ case FS_IOC32_GETVERSION:
3757+ cmd = FS_IOC_GETVERSION;
3758+ break;
3759+ case FS_IOC32_SETVERSION:
3760+ cmd = FS_IOC_SETVERSION;
3761+ break;
3762+ default:
3763+ break;
3764+ }
3765+
3766+ return selinux_file_ioctl(file, cmd, arg);
3767+}
3768+
37413769 static int default_noexec __ro_after_init;
37423770
37433771 static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
@@ -6313,8 +6341,8 @@ static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode) · 2569 unmodified lines
63136341 inode_doinit_with_dentry(inode, dentry);
63146342 }
63156343
6316−static int selinux_getprocattr(struct task_struct *p,
6317− const char *name, char **value)
6344+static int selinux_lsm_getattr(unsigned int attr, struct task_struct *p,
6345+ char **value)
63186346 {
63196347 const struct task_security_struct *__tsec;
63206348 u32 sid;
@@ -6331,20 +6359,27 @@ static int selinux_getprocattr(struct task_struct *p, · 10 unmodified lines
63316359 goto bad;
63326360 }
63336361
6334− if (!strcmp(name, "current"))
6362+ switch (attr) {
6363+ case LSM_ATTR_CURRENT:
63356364 sid = __tsec->sid;
6336− else if (!strcmp(name, "prev"))
6365+ break;
6366+ case LSM_ATTR_PREV:
63376367 sid = __tsec->osid;
6338− else if (!strcmp(name, "exec"))
6368+ break;
6369+ case LSM_ATTR_EXEC:
63396370 sid = __tsec->exec_sid;
6340− else if (!strcmp(name, "fscreate"))
6371+ break;
6372+ case LSM_ATTR_FSCREATE:
63416373 sid = __tsec->create_sid;
6342− else if (!strcmp(name, "keycreate"))
6374+ break;
6375+ case LSM_ATTR_KEYCREATE:
63436376 sid = __tsec->keycreate_sid;
6344− else if (!strcmp(name, "sockcreate"))
6377+ break;
6378+ case LSM_ATTR_SOCKCREATE:
63456379 sid = __tsec->sockcreate_sid;
6346− else {
6347− error = -EINVAL;
6380+ break;
6381+ default:
6382+ error = -EOPNOTSUPP;
63486383 goto bad;
63496384 }
63506385 rcu_read_unlock();
@@ -6362,7 +6397,7 @@ bad: · 11 unmodified lines
63626397 return error;
63636398 }
63646399
6365−static int selinux_setprocattr(const char *name, void *value, size_t size)
6400+static int selinux_lsm_setattr(u64 attr, void *value, size_t size)
63666401 {
63676402 struct task_security_struct *tsec;
63686403 struct cred *new;
@@ -6373,23 +6408,31 @@ static int selinux_setprocattr(const char *name, void *value, size_t size) · 4 unmodified lines
63736408 /*
63746409 * Basic control over ability to set these attributes at all.
63756410 */
6376− if (!strcmp(name, "exec"))
6411+ switch (attr) {
6412+ case LSM_ATTR_EXEC:
63776413 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
63786414 PROCESS__SETEXEC, NULL);
6379− else if (!strcmp(name, "fscreate"))
6415+ break;
6416+ case LSM_ATTR_FSCREATE:
63806417 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
63816418 PROCESS__SETFSCREATE, NULL);
6382− else if (!strcmp(name, "keycreate"))
6419+ break;
6420+ case LSM_ATTR_KEYCREATE:
63836421 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
63846422 PROCESS__SETKEYCREATE, NULL);
6385− else if (!strcmp(name, "sockcreate"))
6423+ break;
6424+ case LSM_ATTR_SOCKCREATE:
63866425 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
63876426 PROCESS__SETSOCKCREATE, NULL);
6388− else if (!strcmp(name, "current"))
6427+ break;
6428+ case LSM_ATTR_CURRENT:
63896429 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
63906430 PROCESS__SETCURRENT, NULL);
6391− else
6392− error = -EINVAL;
6431+ break;
6432+ default:
6433+ error = -EOPNOTSUPP;
6434+ break;
6435+ }
63936436 if (error)
63946437 return error;
63956438
@@ -6401,13 +6444,14 @@ static int selinux_setprocattr(const char *name, void *value, size_t size) · 5 unmodified lines
64016444 }
64026445 error = security_context_to_sid(value, size,
64036446 &sid, GFP_KERNEL);
6404− if (error == -EINVAL && !strcmp(name, "fscreate")) {
6447+ if (error == -EINVAL && attr == LSM_ATTR_FSCREATE) {
64056448 if (!has_cap_mac_admin(true)) {
64066449 struct audit_buffer *ab;
64076450 size_t audit_size;
64086451
6409− /* We strip a nul only if it is at the end, otherwise the
6410− * context contains a nul and we should audit that */
6452+ /* We strip a nul only if it is at the end,
6453+ * otherwise the context contains a nul and
6454+ * we should audit that */
64116455 if (str[size - 1] == '\0')
64126456 audit_size = size - 1;
64136457 else
@@ -6418,7 +6462,8 @@ static int selinux_setprocattr(const char *name, void *value, size_t size) · 4 unmodified lines
64186462 if (!ab)
64196463 return error;
64206464 audit_log_format(ab, "op=fscreate invalid_context=");
6421− audit_log_n_untrustedstring(ab, value, audit_size);
6465+ audit_log_n_untrustedstring(ab, value,
6466+ audit_size);
64226467 audit_log_end(ab);
64236468
64246469 return error;
@@ -6441,11 +6486,11 @@ static int selinux_setprocattr(const char *name, void *value, size_t size) · 16 unmodified lines
64416486 checks and may_create for the file creation checks. The
64426487 operation will then fail if the context is not permitted. */
64436488 tsec = selinux_cred(new);
6444− if (!strcmp(name, "exec")) {
6489+ if (attr == LSM_ATTR_EXEC) {
64456490 tsec->exec_sid = sid;
6446− } else if (!strcmp(name, "fscreate")) {
6491+ } else if (attr == LSM_ATTR_FSCREATE) {
64476492 tsec->create_sid = sid;
6448− } else if (!strcmp(name, "keycreate")) {
6493+ } else if (attr == LSM_ATTR_KEYCREATE) {
64496494 if (sid) {
64506495 error = avc_has_perm(mysid, sid,
64516496 SECCLASS_KEY, KEY__CREATE, NULL);
@@ -6453,9 +6498,9 @@ static int selinux_setprocattr(const char *name, void *value, size_t size) · 1 unmodified line
64536498 goto abort_change;
64546499 }
64556500 tsec->keycreate_sid = sid;
6456− } else if (!strcmp(name, "sockcreate")) {
6501+ } else if (attr == LSM_ATTR_SOCKCREATE) {
64576502 tsec->sockcreate_sid = sid;
6458− } else if (!strcmp(name, "current")) {
6503+ } else if (attr == LSM_ATTR_CURRENT) {
64596504 error = -EINVAL;
64606505 if (sid == 0)
64616506 goto abort_change;
@@ -6496,6 +6541,69 @@ abort_change: · 34 unmodified lines
64966541 return error;
64976542 }
64986543
6544+/**
6545+ * selinux_getselfattr - Get SELinux current task attributes
6546+ * @attr: the requested attribute
6547+ * @ctx: buffer to receive the result
6548+ * @size: buffer size (input), buffer size used (output)
6549+ * @flags: unused
6550+ *
6551+ * Fill the passed user space @ctx with the details of the requested
6552+ * attribute.
6553+ *
6554+ * Returns the number of attributes on success, an error code otherwise.
6555+ * There will only ever be one attribute.
6556+ */
6557+static int selinux_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
6558+ size_t *size, u32 flags)
6559+{
6560+ int rc;
6561+ char *val;
6562+ int val_len;
6563+
6564+ val_len = selinux_lsm_getattr(attr, current, &val);
6565+ if (val_len < 0)
6566+ return val_len;
6567+ rc = lsm_fill_user_ctx(ctx, size, val, val_len, LSM_ID_SELINUX, 0);
6568+ kfree(val);
6569+ return (!rc ? 1 : rc);
6570+}
6571+
6572+static int selinux_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
6573+ size_t size, u32 flags)
6574+{
6575+ int rc;
6576+
6577+ rc = selinux_lsm_setattr(attr, ctx->ctx, ctx->ctx_len);
6578+ if (rc > 0)
6579+ return 0;
6580+ return rc;
6581+}
6582+
6583+static int selinux_getprocattr(struct task_struct *p,
6584+ const char *name, char **value)
6585+{
6586+ unsigned int attr = lsm_name_to_attr(name);
6587+ int rc;
6588+
6589+ if (attr) {
6590+ rc = selinux_lsm_getattr(attr, p, value);
6591+ if (rc != -EOPNOTSUPP)
6592+ return rc;
6593+ }
6594+
6595+ return -EINVAL;
6596+}
6597+
6598+static int selinux_setprocattr(const char *name, void *value, size_t size)
6599+{
6600+ int attr = lsm_name_to_attr(name);
6601+
6602+ if (attr)
6603+ return selinux_lsm_setattr(attr, value, size);
6604+ return -EINVAL;
6605+}
6606+
64996607 static int selinux_ismaclabel(const char *name)
65006608 {
65016609 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
@@ -6978,6 +7086,11 @@ static int selinux_uring_cmd(struct io_uring_cmd *ioucmd) · 476 unmodified lines
69787086 }
69797087 #endif /* CONFIG_IO_URING */
69807088
7089+static const struct lsm_id selinux_lsmid = {
7090+ .name = "selinux",
7091+ .id = LSM_ID_SELINUX,
7092+};
7093+
69817094 /*
69827095 * IMPORTANT NOTE: When adding new hooks, please be careful to keep this order:
69837096 * 1. any hooks that don't belong to (2.) or (3.) below,
@@ -7064,6 +7177,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { · 80 unmodified lines
70647177 LSM_HOOK_INIT(file_permission, selinux_file_permission),
70657178 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
70667179 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
7180+ LSM_HOOK_INIT(file_ioctl_compat, selinux_file_ioctl_compat),
70677181 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
70687182 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
70697183 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
@@ -7119,6 +7233,8 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { · 49 unmodified lines
71197233
71207234 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
71217235
7236+ LSM_HOOK_INIT(getselfattr, selinux_getselfattr),
7237+ LSM_HOOK_INIT(setselfattr, selinux_setselfattr),
71227238 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
71237239 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
71247240
@@ -7298,7 +7414,8 @@ static __init int selinux_init(void) · 173 unmodified lines
72987414
72997415 hashtab_cache_init();
73007416
7301− security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
7417+ security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks),
7418+ &selinux_lsmid);
73027419
73037420 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
73047421 panic("SELinux: Unable to register AVC netcache callback\n");
security/smack/smack_lsm.c+87−6
@@ -43,6 +43,7 @@ · 42 unmodified lines
4343 #include <linux/fs_parser.h>
4444 #include <linux/watch_queue.h>
4545 #include <linux/io_uring.h>
46+#include <uapi/linux/lsm.h>
4647 #include "smack.h"
4748
4849 #define TRANS_TRUE "TRUE"
@@ -3625,6 +3626,35 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) · 3576 unmodified lines
36253626 return;
36263627 }
36273628
3629+/**
3630+ * smack_getselfattr - Smack current process attribute
3631+ * @attr: which attribute to fetch
3632+ * @ctx: buffer to receive the result
3633+ * @size: available size in, actual size out
3634+ * @flags: unused
3635+ *
3636+ * Fill the passed user space @ctx with the details of the requested
3637+ * attribute.
3638+ *
3639+ * Returns the number of attributes on success, an error code otherwise.
3640+ * There will only ever be one attribute.
3641+ */
3642+static int smack_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
3643+ size_t *size, u32 flags)
3644+{
3645+ int rc;
3646+ struct smack_known *skp;
3647+
3648+ if (attr != LSM_ATTR_CURRENT)
3649+ return -EOPNOTSUPP;
3650+
3651+ skp = smk_of_current();
3652+ rc = lsm_fill_user_ctx(ctx, size,
3653+ skp->smk_known, strlen(skp->smk_known) + 1,
3654+ LSM_ID_SMACK, 0);
3655+ return (!rc ? 1 : rc);
3656+}
3657+
36283658 /**
36293659 * smack_getprocattr - Smack process attribute access
36303660 * @p: the object task
@@ -3654,8 +3684,8 @@ static int smack_getprocattr(struct task_struct *p, const char *name, char **val · 23 unmodified lines
36543684 }
36553685
36563686 /**
3657− * smack_setprocattr - Smack process attribute setting
3658− * @name: the name of the attribute in /proc/.../attr
3687+ * do_setattr - Smack process attribute setting
3688+ * @attr: the ID of the attribute
36593689 * @value: the value to set
36603690 * @size: the size of the value
36613691 *
@@ -3664,7 +3694,7 @@ static int smack_getprocattr(struct task_struct *p, const char *name, char **val · 2 unmodified lines
36643694 *
36653695 * Returns the length of the smack label or an error code
36663696 */
3667−static int smack_setprocattr(const char *name, void *value, size_t size)
3697+static int do_setattr(u64 attr, void *value, size_t size)
36683698 {
36693699 struct task_smack *tsp = smack_cred(current_cred());
36703700 struct cred *new;
@@ -3678,8 +3708,8 @@ static int smack_setprocattr(const char *name, void *value, size_t size) · 7 unmodified lines
36783708 if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
36793709 return -EINVAL;
36803710
3681− if (strcmp(name, "current") != 0)
3682− return -EINVAL;
3711+ if (attr != LSM_ATTR_CURRENT)
3712+ return -EOPNOTSUPP;
36833713
36843714 skp = smk_import_entry(value, size);
36853715 if (IS_ERR(skp))
@@ -3718,6 +3748,49 @@ static int smack_setprocattr(const char *name, void *value, size_t size) · 32 unmodified lines
37183748 return size;
37193749 }
37203750
3751+/**
3752+ * smack_setselfattr - Set a Smack process attribute
3753+ * @attr: which attribute to set
3754+ * @ctx: buffer containing the data
3755+ * @size: size of @ctx
3756+ * @flags: unused
3757+ *
3758+ * Fill the passed user space @ctx with the details of the requested
3759+ * attribute.
3760+ *
3761+ * Returns 0 on success, an error code otherwise.
3762+ */
3763+static int smack_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
3764+ size_t size, u32 flags)
3765+{
3766+ int rc;
3767+
3768+ rc = do_setattr(attr, ctx->ctx, ctx->ctx_len);
3769+ if (rc > 0)
3770+ return 0;
3771+ return rc;
3772+}
3773+
3774+/**
3775+ * smack_setprocattr - Smack process attribute setting
3776+ * @name: the name of the attribute in /proc/.../attr
3777+ * @value: the value to set
3778+ * @size: the size of the value
3779+ *
3780+ * Sets the Smack value of the task. Only setting self
3781+ * is permitted and only with privilege
3782+ *
3783+ * Returns the length of the smack label or an error code
3784+ */
3785+static int smack_setprocattr(const char *name, void *value, size_t size)
3786+{
3787+ int attr = lsm_name_to_attr(name);
3788+
3789+ if (attr != LSM_ATTR_UNDEF)
3790+ return do_setattr(attr, value, size);
3791+ return -EINVAL;
3792+}
3793+
37213794 /**
37223795 * smack_unix_stream_connect - Smack access on UDS
37233796 * @sock: one sock
@@ -4933,6 +5006,11 @@ struct lsm_blob_sizes smack_blob_sizes __ro_after_init = { · 1209 unmodified lines
49335006 .lbs_xattr_count = SMACK_INODE_INIT_XATTRS,
49345007 };
49355008
5009+static const struct lsm_id smack_lsmid = {
5010+ .name = "smack",
5011+ .id = LSM_ID_SMACK,
5012+};
5013+
49365014 static struct security_hook_list smack_hooks[] __ro_after_init = {
49375015 LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
49385016 LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
@@ -4973,6 +5051,7 @@ static struct security_hook_list smack_hooks[] __ro_after_init = { · 34 unmodified lines
49735051
49745052 LSM_HOOK_INIT(file_alloc_security, smack_file_alloc_security),
49755053 LSM_HOOK_INIT(file_ioctl, smack_file_ioctl),
5054+ LSM_HOOK_INIT(file_ioctl_compat, smack_file_ioctl),
49765055 LSM_HOOK_INIT(file_lock, smack_file_lock),
49775056 LSM_HOOK_INIT(file_fcntl, smack_file_fcntl),
49785057 LSM_HOOK_INIT(mmap_file, smack_mmap_file),
@@ -5027,6 +5106,8 @@ static struct security_hook_list smack_hooks[] __ro_after_init = { · 48 unmodified lines
50275106
50285107 LSM_HOOK_INIT(d_instantiate, smack_d_instantiate),
50295108
5109+ LSM_HOOK_INIT(getselfattr, smack_getselfattr),
5110+ LSM_HOOK_INIT(setselfattr, smack_setselfattr),
50305111 LSM_HOOK_INIT(getprocattr, smack_getprocattr),
50315112 LSM_HOOK_INIT(setprocattr, smack_setprocattr),
50325113
@@ -5140,7 +5221,7 @@ static __init int smack_init(void) · 107 unmodified lines
51405221 /*
51415222 * Register with LSM
51425223 */
5143− security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), "smack");
5224+ security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), &smack_lsmid);
51445225 smack_enabled = 1;
51455226
51465227 pr_info("Smack: Initializing.\n");
security/tomoyo/tomoyo.c+9−1
@@ -6,6 +6,7 @@ · 5 unmodified lines
66 */
77
88 #include <linux/lsm_hooks.h>
9+#include <uapi/linux/lsm.h>
910 #include "common.h"
1011
1112 /**
@@ -542,6 +543,11 @@ static void tomoyo_task_free(struct task_struct *task) · 530 unmodified lines
542543 }
543544 }
544545
546+static const struct lsm_id tomoyo_lsmid = {
547+ .name = "tomoyo",
548+ .id = LSM_ID_TOMOYO,
549+};
550+
545551 /*
546552 * tomoyo_security_ops is a "struct security_operations" which is used for
547553 * registering TOMOYO.
@@ -568,6 +574,7 @@ static struct security_hook_list tomoyo_hooks[] __ro_after_init = { · 20 unmodified lines
568574 LSM_HOOK_INIT(path_rename, tomoyo_path_rename),
569575 LSM_HOOK_INIT(inode_getattr, tomoyo_inode_getattr),
570576 LSM_HOOK_INIT(file_ioctl, tomoyo_file_ioctl),
577+ LSM_HOOK_INIT(file_ioctl_compat, tomoyo_file_ioctl),
571578 LSM_HOOK_INIT(path_chmod, tomoyo_path_chmod),
572579 LSM_HOOK_INIT(path_chown, tomoyo_path_chown),
573580 LSM_HOOK_INIT(path_chroot, tomoyo_path_chroot),
@@ -595,7 +602,8 @@ static int __init tomoyo_init(void) · 21 unmodified lines
595602 struct tomoyo_task *s = tomoyo_task(current);
596603
597604 /* register ourselves with the security framework */
598− security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo");
605+ security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks),
606+ &tomoyo_lsmid);
599607 pr_info("TOMOYO Linux initialized\n");
600608 s->domain_info = &tomoyo_kernel_domain;
601609 atomic_inc(&tomoyo_kernel_domain.users);
security/yama/yama_lsm.c+7−1
@@ -18,6 +18,7 @@ · 17 unmodified lines
1818 #include <linux/task_work.h>
1919 #include <linux/sched.h>
2020 #include <linux/spinlock.h>
21+#include <uapi/linux/lsm.h>
2122
2223 #define YAMA_SCOPE_DISABLED 0
2324 #define YAMA_SCOPE_RELATIONAL 1
@@ -421,6 +422,11 @@ static int yama_ptrace_traceme(struct task_struct *parent) · 397 unmodified lines
421422 return rc;
422423 }
423424
425+static const struct lsm_id yama_lsmid = {
426+ .name = "yama",
427+ .id = LSM_ID_YAMA,
428+};
429+
424430 static struct security_hook_list yama_hooks[] __ro_after_init = {
425431 LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check),
426432 LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme),
@@ -471,7 +477,7 @@ static inline void yama_init_sysctl(void) { } · 44 unmodified lines
471477 static int __init yama_init(void)
472478 {
473479 pr_info("Yama: becoming mindful.\n");
474− security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), "yama");
480+ security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), &yama_lsmid);
475481 yama_init_sysctl();
476482 return 0;
477483 }
tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl+5−0
@@ -371,3 +371,8 @@ · 370 unmodified lines
371371 454 n64 futex_wake sys_futex_wake
372372 455 n64 futex_wait sys_futex_wait
373373 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
tools/perf/arch/powerpc/entry/syscalls/syscall.tbl+5−0
@@ -543,3 +543,8 @@ · 542 unmodified lines
543543 454 common futex_wake sys_futex_wake
544544 455 common futex_wait sys_futex_wait
545545 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
tools/perf/arch/s390/entry/syscalls/syscall.tbl+5−0
@@ -459,3 +459,8 @@ · 458 unmodified lines
459459 454 common futex_wake sys_futex_wake sys_futex_wake
460460 455 common futex_wait sys_futex_wait sys_futex_wait
461461 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
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl+5−0
@@ -378,6 +378,11 @@ · 377 unmodified lines
378378 454 common futex_wake sys_futex_wake
379379 455 common futex_wait sys_futex_wait
380380 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
381386
382387 #
383388 # Due to a historical design error, certain syscalls are numbered differently
tools/testing/selftests/Makefile+1−0
@@ -45,6 +45,7 @@ TARGETS += landlock · 44 unmodified lines
4545 TARGETS += lib
4646 TARGETS += livepatch
4747 TARGETS += lkdtm
48+TARGETS += lsm
4849 TARGETS += membarrier
4950 TARGETS += memfd
5051 TARGETS += memory-hotplug
tools/testing/selftests/lsm/.gitignore+1−0
@@ -0,0 +1 @@
1+/*_test
tools/testing/selftests/lsm/Makefile+17−0
@@ -0,0 +1,17 @@
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
tools/testing/selftests/lsm/common.c+89−0
@@ -0,0 +1,89 @@
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+}
tools/testing/selftests/lsm/common.h+33−0
@@ -0,0 +1,33 @@
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);
tools/testing/selftests/lsm/config+3−0
@@ -0,0 +1,3 @@
1+CONFIG_SYSFS=y
2+CONFIG_SECURITY=y
3+CONFIG_SECURITYFS=y
tools/testing/selftests/lsm/lsm_get_self_attr_test.c+275−0
@@ -0,0 +1,275 @@
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
tools/testing/selftests/lsm/lsm_list_modules_test.c+137−0
@@ -0,0 +1,137 @@
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
tools/testing/selftests/lsm/lsm_set_self_attr_test.c+74−0
@@ -0,0 +1,74 @@
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