From 55fc280e951ab2b39f3dcb640edc1b1eebc6d173 Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Mon, 31 Aug 2026 14:43:51 -0500 Subject: Input: tsc2007 - read "ti,poll-period" as u32 The "ti,poll-period" property is documented as a normal uint32 cell. The driver used a u64 helper, which makes the helper type disagree with the schema even though the stored value is still small. Read "ti,poll-period" with the u32 helper matching the documented DT cell size. Assisted-by: Codex:gpt-5-5 Signed-off-by: Rob Herring (Arm) Link: https://patch.msgid.link/20260831194352.1185860-1-robh@kernel.org Signed-off-by: Dmitry Torokhov --- security/Kconfig | 305 + security/Kconfig.hardening | 349 + security/Makefile | 31 + security/apparmor/.gitignore | 4 + security/apparmor/.kunitconfig | 5 + security/apparmor/Kconfig | 122 + security/apparmor/Makefile | 114 + security/apparmor/af_unix.c | 806 ++ security/apparmor/apparmorfs.c | 2828 +++++++ security/apparmor/audit.c | 291 + security/apparmor/capability.c | 223 + security/apparmor/crypto.c | 61 + security/apparmor/domain.c | 1622 ++++ security/apparmor/file.c | 747 ++ security/apparmor/include/af_unix.h | 55 + security/apparmor/include/apparmor.h | 68 + security/apparmor/include/apparmorfs.h | 148 + security/apparmor/include/audit.h | 212 + security/apparmor/include/capability.h | 48 + security/apparmor/include/cred.h | 250 + security/apparmor/include/crypto.h | 38 + security/apparmor/include/domain.h | 33 + security/apparmor/include/file.h | 133 + security/apparmor/include/ipc.h | 23 + security/apparmor/include/label.h | 491 ++ security/apparmor/include/lib.h | 363 + security/apparmor/include/match.h | 193 + security/apparmor/include/mount.h | 60 + security/apparmor/include/net.h | 119 + security/apparmor/include/path.h | 33 + security/apparmor/include/perms.h | 219 + security/apparmor/include/policy.h | 450 ++ security/apparmor/include/policy_compat.h | 33 + security/apparmor/include/policy_ns.h | 153 + security/apparmor/include/policy_unpack.h | 215 + security/apparmor/include/procattr.h | 17 + security/apparmor/include/resource.h | 47 + security/apparmor/include/secid.h | 37 + security/apparmor/include/sig_names.h | 97 + security/apparmor/include/signal.h | 19 + security/apparmor/include/task.h | 105 + security/apparmor/ipc.c | 116 + security/apparmor/label.c | 2135 ++++++ security/apparmor/lib.c | 515 ++ security/apparmor/lsm.c | 2588 +++++++ security/apparmor/match.c | 832 ++ security/apparmor/mount.c | 764 ++ security/apparmor/net.c | 408 + security/apparmor/nulldfa.in | 107 + security/apparmor/path.c | 222 + security/apparmor/policy.c | 1521 ++++ security/apparmor/policy_compat.c | 333 + security/apparmor/policy_ns.c | 398 + security/apparmor/policy_unpack.c | 1803 +++++ security/apparmor/policy_unpack_test.c | 616 ++ security/apparmor/procattr.c | 141 + security/apparmor/resource.c | 206 + security/apparmor/secid.c | 155 + security/apparmor/stacksplitdfa.in | 114 + security/apparmor/task.c | 372 + security/bpf/Makefile | 5 + security/bpf/hooks.c | 42 + security/commoncap.c | 1527 ++++ security/commoncap_test.c | 288 + security/device_cgroup.c | 870 +++ security/inode.c | 380 + security/integrity/Kconfig | 137 + security/integrity/Makefile | 24 + security/integrity/digsig.c | 228 + security/integrity/digsig_asymmetric.c | 302 + security/integrity/efi_secureboot.c | 56 + security/integrity/evm/Kconfig | 76 + security/integrity/evm/Makefile | 8 + security/integrity/evm/evm.h | 89 + security/integrity/evm/evm_crypto.c | 459 ++ security/integrity/evm/evm_main.c | 1236 +++ security/integrity/evm/evm_posix_acl.c | 23 + security/integrity/evm/evm_secfs.c | 346 + security/integrity/iint.c | 71 + security/integrity/ima/Kconfig | 350 + security/integrity/ima/Makefile | 20 + security/integrity/ima/ima.h | 625 ++ security/integrity/ima/ima_api.c | 470 ++ security/integrity/ima/ima_appraise.c | 831 ++ security/integrity/ima/ima_asymmetric_keys.c | 66 + security/integrity/ima/ima_crypto.c | 519 ++ security/integrity/ima/ima_efi.c | 33 + security/integrity/ima/ima_fs.c | 849 +++ security/integrity/ima/ima_iint.c | 138 + security/integrity/ima/ima_init.c | 167 + security/integrity/ima/ima_kexec.c | 351 + security/integrity/ima/ima_main.c | 1341 ++++ security/integrity/ima/ima_modsig.c | 151 + security/integrity/ima/ima_mok.c | 49 + security/integrity/ima/ima_policy.c | 2382 ++++++ security/integrity/ima/ima_queue.c | 577 ++ security/integrity/ima/ima_queue_keys.c | 177 + security/integrity/ima/ima_template.c | 537 ++ security/integrity/ima/ima_template_lib.c | 764 ++ security/integrity/ima/ima_template_lib.h | 69 + security/integrity/integrity.h | 281 + security/integrity/integrity_audit.c | 69 + security/integrity/platform_certs/efi_parser.c | 108 + .../integrity/platform_certs/keyring_handler.c | 102 + .../integrity/platform_certs/keyring_handler.h | 55 + security/integrity/platform_certs/load_ipl_s390.c | 36 + security/integrity/platform_certs/load_powerpc.c | 160 + security/integrity/platform_certs/load_uefi.c | 238 + .../integrity/platform_certs/machine_keyring.c | 91 + .../integrity/platform_certs/platform_keyring.c | 58 + security/ipe/.gitignore | 2 + security/ipe/Kconfig | 117 + security/ipe/Makefile | 31 + security/ipe/audit.c | 279 + security/ipe/audit.h | 19 + security/ipe/digest.c | 119 + security/ipe/digest.h | 26 + security/ipe/eval.c | 393 + security/ipe/eval.h | 70 + security/ipe/fs.c | 246 + security/ipe/fs.h | 16 + security/ipe/hooks.c | 342 + security/ipe/hooks.h | 55 + security/ipe/ipe.c | 100 + security/ipe/ipe.h | 28 + security/ipe/policy.c | 244 + security/ipe/policy.h | 98 + security/ipe/policy_fs.c | 490 ++ security/ipe/policy_parser.c | 559 ++ security/ipe/policy_parser.h | 11 + security/ipe/policy_tests.c | 297 + security/keys/Kconfig | 131 + security/keys/Makefile | 32 + security/keys/big_key.c | 290 + security/keys/compat.c | 132 + security/keys/compat_dh.c | 36 + security/keys/dh.c | 313 + security/keys/encrypted-keys/Makefile | 11 + security/keys/encrypted-keys/ecryptfs_format.c | 76 + security/keys/encrypted-keys/ecryptfs_format.h | 27 + security/keys/encrypted-keys/encrypted.c | 1002 +++ security/keys/encrypted-keys/encrypted.h | 67 + security/keys/encrypted-keys/masterkey_trusted.c | 43 + security/keys/gc.c | 374 + security/keys/internal.h | 378 + security/keys/key.c | 1293 ++++ security/keys/keyctl.c | 2038 +++++ security/keys/keyctl_pkey.c | 335 + security/keys/keyring.c | 1798 +++++ security/keys/permission.c | 123 + security/keys/persistent.c | 167 + security/keys/proc.c | 323 + security/keys/process_keys.c | 965 +++ security/keys/request_key.c | 821 ++ security/keys/request_key_auth.c | 312 + security/keys/sysctl.c | 76 + security/keys/trusted-keys/Kconfig | 82 + security/keys/trusted-keys/Makefile | 20 + security/keys/trusted-keys/tpm2key.asn1 | 11 + security/keys/trusted-keys/trusted_caam.c | 191 + security/keys/trusted-keys/trusted_core.c | 410 + security/keys/trusted-keys/trusted_dcp.c | 356 + security/keys/trusted-keys/trusted_pkwm.c | 190 + security/keys/trusted-keys/trusted_tee.c | 287 + security/keys/trusted-keys/trusted_tpm1.c | 1003 +++ security/keys/trusted-keys/trusted_tpm2.c | 605 ++ security/keys/user_defined.c | 207 + security/landlock/.kunitconfig | 6 + security/landlock/Kconfig | 37 + security/landlock/Makefile | 18 + security/landlock/access.h | 151 + security/landlock/audit.c | 734 ++ security/landlock/audit.h | 76 + security/landlock/common.h | 22 + security/landlock/cred.c | 69 + security/landlock/cred.h | 158 + security/landlock/domain.c | 309 + security/landlock/domain.h | 179 + security/landlock/errata.h | 99 + security/landlock/errata/abi-1.h | 24 + security/landlock/errata/abi-4.h | 22 + security/landlock/errata/abi-6.h | 29 + security/landlock/fs.c | 2037 +++++ security/landlock/fs.h | 156 + security/landlock/id.c | 295 + security/landlock/id.h | 25 + security/landlock/limits.h | 42 + security/landlock/net.c | 379 + security/landlock/net.h | 34 + security/landlock/object.c | 67 + security/landlock/object.h | 91 + security/landlock/ruleset.c | 744 ++ security/landlock/ruleset.h | 330 + security/landlock/setup.c | 81 + security/landlock/setup.h | 22 + security/landlock/syscalls.c | 631 ++ security/landlock/task.c | 463 ++ security/landlock/task.h | 14 + security/landlock/tsync.c | 619 ++ security/landlock/tsync.h | 16 + security/loadpin/Kconfig | 44 + security/loadpin/Makefile | 2 + security/loadpin/loadpin.c | 442 ++ security/lockdown/Kconfig | 47 + security/lockdown/Makefile | 1 + security/lockdown/lockdown.c | 172 + security/lsm.h | 50 + security/lsm_audit.c | 457 ++ security/lsm_init.c | 568 ++ security/lsm_notifier.c | 31 + security/lsm_syscalls.c | 129 + security/min_addr.c | 62 + security/safesetid/Kconfig | 15 + security/safesetid/Makefile | 7 + security/safesetid/lsm.c | 293 + security/safesetid/lsm.h | 75 + security/safesetid/securityfs.c | 347 + security/security.c | 5718 ++++++++++++++ security/selinux/.gitignore | 4 + security/selinux/Kconfig | 100 + security/selinux/Makefile | 44 + security/selinux/avc.c | 1208 +++ security/selinux/genheaders.c | 154 + security/selinux/hooks.c | 7993 ++++++++++++++++++++ security/selinux/ibpkey.c | 235 + security/selinux/ima.c | 120 + security/selinux/include/audit.h | 71 + security/selinux/include/avc.h | 172 + security/selinux/include/avc_ss.h | 23 + security/selinux/include/classmap.h | 193 + security/selinux/include/conditional.h | 23 + security/selinux/include/hash.h | 47 + security/selinux/include/ibpkey.h | 35 + security/selinux/include/ima.h | 28 + security/selinux/include/initcalls.h | 19 + security/selinux/include/initial_sid_to_string.h | 38 + security/selinux/include/netif.h | 24 + security/selinux/include/netlabel.h | 137 + security/selinux/include/netnode.h | 26 + security/selinux/include/netport.h | 25 + security/selinux/include/objsec.h | 290 + security/selinux/include/policycap.h | 29 + security/selinux/include/policycap_names.h | 29 + security/selinux/include/security.h | 414 + security/selinux/include/xfrm.h | 94 + security/selinux/initcalls.c | 52 + security/selinux/netif.c | 283 + security/selinux/netlabel.c | 619 ++ security/selinux/netlink.c | 120 + security/selinux/netnode.c | 307 + security/selinux/netport.c | 235 + security/selinux/nlmsgtab.c | 234 + security/selinux/selinuxfs.c | 2016 +++++ security/selinux/ss/avtab.c | 618 ++ security/selinux/ss/avtab.h | 141 + security/selinux/ss/conditional.c | 765 ++ security/selinux/ss/conditional.h | 84 + security/selinux/ss/constraint.h | 65 + security/selinux/ss/context.c | 32 + security/selinux/ss/context.h | 204 + security/selinux/ss/ebitmap.c | 603 ++ security/selinux/ss/ebitmap.h | 156 + security/selinux/ss/hashtab.c | 199 + security/selinux/ss/hashtab.h | 154 + security/selinux/ss/mls.c | 663 ++ security/selinux/ss/mls.h | 96 + security/selinux/ss/mls_types.h | 52 + security/selinux/ss/policydb.c | 4017 ++++++++++ security/selinux/ss/policydb.h | 428 ++ security/selinux/ss/services.c | 3946 ++++++++++ security/selinux/ss/services.h | 47 + security/selinux/ss/sidtab.c | 638 ++ security/selinux/ss/sidtab.h | 160 + security/selinux/ss/symtab.c | 56 + security/selinux/ss/symtab.h | 26 + security/selinux/status.c | 122 + security/selinux/xfrm.c | 466 ++ security/smack/Kconfig | 55 + security/smack/Makefile | 9 + security/smack/smack.h | 541 ++ security/smack/smack_access.c | 756 ++ security/smack/smack_lsm.c | 5380 +++++++++++++ security/smack/smack_netfilter.c | 78 + security/smack/smackfs.c | 3044 ++++++++ security/tomoyo/.gitignore | 3 + security/tomoyo/Kconfig | 85 + security/tomoyo/Makefile | 21 + security/tomoyo/audit.c | 477 ++ security/tomoyo/common.c | 3025 ++++++++ security/tomoyo/common.h | 1292 ++++ security/tomoyo/condition.c | 1122 +++ security/tomoyo/domain.c | 950 +++ security/tomoyo/environ.c | 124 + security/tomoyo/file.c | 1050 +++ security/tomoyo/gc.c | 682 ++ security/tomoyo/group.c | 209 + security/tomoyo/load_policy.c | 110 + security/tomoyo/memory.c | 207 + security/tomoyo/mount.c | 242 + security/tomoyo/network.c | 780 ++ .../tomoyo/policy/exception_policy.conf.default | 2 + security/tomoyo/realpath.c | 310 + security/tomoyo/securityfs_if.c | 271 + security/tomoyo/tomoyo.c | 621 ++ security/tomoyo/util.c | 1106 +++ security/yama/Kconfig | 14 + security/yama/Makefile | 4 + security/yama/yama_lsm.c | 481 ++ 308 files changed, 129080 insertions(+) create mode 100644 security/Kconfig create mode 100644 security/Kconfig.hardening create mode 100644 security/Makefile create mode 100644 security/apparmor/.gitignore create mode 100644 security/apparmor/.kunitconfig create mode 100644 security/apparmor/Kconfig create mode 100644 security/apparmor/Makefile create mode 100644 security/apparmor/af_unix.c create mode 100644 security/apparmor/apparmorfs.c create mode 100644 security/apparmor/audit.c create mode 100644 security/apparmor/capability.c create mode 100644 security/apparmor/crypto.c create mode 100644 security/apparmor/domain.c create mode 100644 security/apparmor/file.c create mode 100644 security/apparmor/include/af_unix.h create mode 100644 security/apparmor/include/apparmor.h create mode 100644 security/apparmor/include/apparmorfs.h create mode 100644 security/apparmor/include/audit.h create mode 100644 security/apparmor/include/capability.h create mode 100644 security/apparmor/include/cred.h create mode 100644 security/apparmor/include/crypto.h create mode 100644 security/apparmor/include/domain.h create mode 100644 security/apparmor/include/file.h create mode 100644 security/apparmor/include/ipc.h create mode 100644 security/apparmor/include/label.h create mode 100644 security/apparmor/include/lib.h create mode 100644 security/apparmor/include/match.h create mode 100644 security/apparmor/include/mount.h create mode 100644 security/apparmor/include/net.h create mode 100644 security/apparmor/include/path.h create mode 100644 security/apparmor/include/perms.h create mode 100644 security/apparmor/include/policy.h create mode 100644 security/apparmor/include/policy_compat.h create mode 100644 security/apparmor/include/policy_ns.h create mode 100644 security/apparmor/include/policy_unpack.h create mode 100644 security/apparmor/include/procattr.h create mode 100644 security/apparmor/include/resource.h create mode 100644 security/apparmor/include/secid.h create mode 100644 security/apparmor/include/sig_names.h create mode 100644 security/apparmor/include/signal.h create mode 100644 security/apparmor/include/task.h create mode 100644 security/apparmor/ipc.c create mode 100644 security/apparmor/label.c create mode 100644 security/apparmor/lib.c create mode 100644 security/apparmor/lsm.c create mode 100644 security/apparmor/match.c create mode 100644 security/apparmor/mount.c create mode 100644 security/apparmor/net.c create mode 100644 security/apparmor/nulldfa.in create mode 100644 security/apparmor/path.c create mode 100644 security/apparmor/policy.c create mode 100644 security/apparmor/policy_compat.c create mode 100644 security/apparmor/policy_ns.c create mode 100644 security/apparmor/policy_unpack.c create mode 100644 security/apparmor/policy_unpack_test.c create mode 100644 security/apparmor/procattr.c create mode 100644 security/apparmor/resource.c create mode 100644 security/apparmor/secid.c create mode 100644 security/apparmor/stacksplitdfa.in create mode 100644 security/apparmor/task.c create mode 100644 security/bpf/Makefile create mode 100644 security/bpf/hooks.c create mode 100644 security/commoncap.c create mode 100644 security/commoncap_test.c create mode 100644 security/device_cgroup.c create mode 100644 security/inode.c create mode 100644 security/integrity/Kconfig create mode 100644 security/integrity/Makefile create mode 100644 security/integrity/digsig.c create mode 100644 security/integrity/digsig_asymmetric.c create mode 100644 security/integrity/efi_secureboot.c create mode 100644 security/integrity/evm/Kconfig create mode 100644 security/integrity/evm/Makefile create mode 100644 security/integrity/evm/evm.h create mode 100644 security/integrity/evm/evm_crypto.c create mode 100644 security/integrity/evm/evm_main.c create mode 100644 security/integrity/evm/evm_posix_acl.c create mode 100644 security/integrity/evm/evm_secfs.c create mode 100644 security/integrity/iint.c create mode 100644 security/integrity/ima/Kconfig create mode 100644 security/integrity/ima/Makefile create mode 100644 security/integrity/ima/ima.h create mode 100644 security/integrity/ima/ima_api.c create mode 100644 security/integrity/ima/ima_appraise.c create mode 100644 security/integrity/ima/ima_asymmetric_keys.c create mode 100644 security/integrity/ima/ima_crypto.c create mode 100644 security/integrity/ima/ima_efi.c create mode 100644 security/integrity/ima/ima_fs.c create mode 100644 security/integrity/ima/ima_iint.c create mode 100644 security/integrity/ima/ima_init.c create mode 100644 security/integrity/ima/ima_kexec.c create mode 100644 security/integrity/ima/ima_main.c create mode 100644 security/integrity/ima/ima_modsig.c create mode 100644 security/integrity/ima/ima_mok.c create mode 100644 security/integrity/ima/ima_policy.c create mode 100644 security/integrity/ima/ima_queue.c create mode 100644 security/integrity/ima/ima_queue_keys.c create mode 100644 security/integrity/ima/ima_template.c create mode 100644 security/integrity/ima/ima_template_lib.c create mode 100644 security/integrity/ima/ima_template_lib.h create mode 100644 security/integrity/integrity.h create mode 100644 security/integrity/integrity_audit.c create mode 100644 security/integrity/platform_certs/efi_parser.c create mode 100644 security/integrity/platform_certs/keyring_handler.c create mode 100644 security/integrity/platform_certs/keyring_handler.h create mode 100644 security/integrity/platform_certs/load_ipl_s390.c create mode 100644 security/integrity/platform_certs/load_powerpc.c create mode 100644 security/integrity/platform_certs/load_uefi.c create mode 100644 security/integrity/platform_certs/machine_keyring.c create mode 100644 security/integrity/platform_certs/platform_keyring.c create mode 100644 security/ipe/.gitignore create mode 100644 security/ipe/Kconfig create mode 100644 security/ipe/Makefile create mode 100644 security/ipe/audit.c create mode 100644 security/ipe/audit.h create mode 100644 security/ipe/digest.c create mode 100644 security/ipe/digest.h create mode 100644 security/ipe/eval.c create mode 100644 security/ipe/eval.h create mode 100644 security/ipe/fs.c create mode 100644 security/ipe/fs.h create mode 100644 security/ipe/hooks.c create mode 100644 security/ipe/hooks.h create mode 100644 security/ipe/ipe.c create mode 100644 security/ipe/ipe.h create mode 100644 security/ipe/policy.c create mode 100644 security/ipe/policy.h create mode 100644 security/ipe/policy_fs.c create mode 100644 security/ipe/policy_parser.c create mode 100644 security/ipe/policy_parser.h create mode 100644 security/ipe/policy_tests.c create mode 100644 security/keys/Kconfig create mode 100644 security/keys/Makefile create mode 100644 security/keys/big_key.c create mode 100644 security/keys/compat.c create mode 100644 security/keys/compat_dh.c create mode 100644 security/keys/dh.c create mode 100644 security/keys/encrypted-keys/Makefile create mode 100644 security/keys/encrypted-keys/ecryptfs_format.c create mode 100644 security/keys/encrypted-keys/ecryptfs_format.h create mode 100644 security/keys/encrypted-keys/encrypted.c create mode 100644 security/keys/encrypted-keys/encrypted.h create mode 100644 security/keys/encrypted-keys/masterkey_trusted.c create mode 100644 security/keys/gc.c create mode 100644 security/keys/internal.h create mode 100644 security/keys/key.c create mode 100644 security/keys/keyctl.c create mode 100644 security/keys/keyctl_pkey.c create mode 100644 security/keys/keyring.c create mode 100644 security/keys/permission.c create mode 100644 security/keys/persistent.c create mode 100644 security/keys/proc.c create mode 100644 security/keys/process_keys.c create mode 100644 security/keys/request_key.c create mode 100644 security/keys/request_key_auth.c create mode 100644 security/keys/sysctl.c create mode 100644 security/keys/trusted-keys/Kconfig create mode 100644 security/keys/trusted-keys/Makefile create mode 100644 security/keys/trusted-keys/tpm2key.asn1 create mode 100644 security/keys/trusted-keys/trusted_caam.c create mode 100644 security/keys/trusted-keys/trusted_core.c create mode 100644 security/keys/trusted-keys/trusted_dcp.c create mode 100644 security/keys/trusted-keys/trusted_pkwm.c create mode 100644 security/keys/trusted-keys/trusted_tee.c create mode 100644 security/keys/trusted-keys/trusted_tpm1.c create mode 100644 security/keys/trusted-keys/trusted_tpm2.c create mode 100644 security/keys/user_defined.c create mode 100644 security/landlock/.kunitconfig create mode 100644 security/landlock/Kconfig create mode 100644 security/landlock/Makefile create mode 100644 security/landlock/access.h create mode 100644 security/landlock/audit.c create mode 100644 security/landlock/audit.h create mode 100644 security/landlock/common.h create mode 100644 security/landlock/cred.c create mode 100644 security/landlock/cred.h create mode 100644 security/landlock/domain.c create mode 100644 security/landlock/domain.h create mode 100644 security/landlock/errata.h create mode 100644 security/landlock/errata/abi-1.h create mode 100644 security/landlock/errata/abi-4.h create mode 100644 security/landlock/errata/abi-6.h create mode 100644 security/landlock/fs.c create mode 100644 security/landlock/fs.h create mode 100644 security/landlock/id.c create mode 100644 security/landlock/id.h create mode 100644 security/landlock/limits.h create mode 100644 security/landlock/net.c create mode 100644 security/landlock/net.h create mode 100644 security/landlock/object.c create mode 100644 security/landlock/object.h create mode 100644 security/landlock/ruleset.c create mode 100644 security/landlock/ruleset.h create mode 100644 security/landlock/setup.c create mode 100644 security/landlock/setup.h create mode 100644 security/landlock/syscalls.c create mode 100644 security/landlock/task.c create mode 100644 security/landlock/task.h create mode 100644 security/landlock/tsync.c create mode 100644 security/landlock/tsync.h create mode 100644 security/loadpin/Kconfig create mode 100644 security/loadpin/Makefile create mode 100644 security/loadpin/loadpin.c create mode 100644 security/lockdown/Kconfig create mode 100644 security/lockdown/Makefile create mode 100644 security/lockdown/lockdown.c create mode 100644 security/lsm.h create mode 100644 security/lsm_audit.c create mode 100644 security/lsm_init.c create mode 100644 security/lsm_notifier.c create mode 100644 security/lsm_syscalls.c create mode 100644 security/min_addr.c create mode 100644 security/safesetid/Kconfig create mode 100644 security/safesetid/Makefile create mode 100644 security/safesetid/lsm.c create mode 100644 security/safesetid/lsm.h create mode 100644 security/safesetid/securityfs.c create mode 100644 security/security.c create mode 100644 security/selinux/.gitignore create mode 100644 security/selinux/Kconfig create mode 100644 security/selinux/Makefile create mode 100644 security/selinux/avc.c create mode 100644 security/selinux/genheaders.c create mode 100644 security/selinux/hooks.c create mode 100644 security/selinux/ibpkey.c create mode 100644 security/selinux/ima.c create mode 100644 security/selinux/include/audit.h create mode 100644 security/selinux/include/avc.h create mode 100644 security/selinux/include/avc_ss.h create mode 100644 security/selinux/include/classmap.h create mode 100644 security/selinux/include/conditional.h create mode 100644 security/selinux/include/hash.h create mode 100644 security/selinux/include/ibpkey.h create mode 100644 security/selinux/include/ima.h create mode 100644 security/selinux/include/initcalls.h create mode 100644 security/selinux/include/initial_sid_to_string.h create mode 100644 security/selinux/include/netif.h create mode 100644 security/selinux/include/netlabel.h create mode 100644 security/selinux/include/netnode.h create mode 100644 security/selinux/include/netport.h create mode 100644 security/selinux/include/objsec.h create mode 100644 security/selinux/include/policycap.h create mode 100644 security/selinux/include/policycap_names.h create mode 100644 security/selinux/include/security.h create mode 100644 security/selinux/include/xfrm.h create mode 100644 security/selinux/initcalls.c create mode 100644 security/selinux/netif.c create mode 100644 security/selinux/netlabel.c create mode 100644 security/selinux/netlink.c create mode 100644 security/selinux/netnode.c create mode 100644 security/selinux/netport.c create mode 100644 security/selinux/nlmsgtab.c create mode 100644 security/selinux/selinuxfs.c create mode 100644 security/selinux/ss/avtab.c create mode 100644 security/selinux/ss/avtab.h create mode 100644 security/selinux/ss/conditional.c create mode 100644 security/selinux/ss/conditional.h create mode 100644 security/selinux/ss/constraint.h create mode 100644 security/selinux/ss/context.c create mode 100644 security/selinux/ss/context.h create mode 100644 security/selinux/ss/ebitmap.c create mode 100644 security/selinux/ss/ebitmap.h create mode 100644 security/selinux/ss/hashtab.c create mode 100644 security/selinux/ss/hashtab.h create mode 100644 security/selinux/ss/mls.c create mode 100644 security/selinux/ss/mls.h create mode 100644 security/selinux/ss/mls_types.h create mode 100644 security/selinux/ss/policydb.c create mode 100644 security/selinux/ss/policydb.h create mode 100644 security/selinux/ss/services.c create mode 100644 security/selinux/ss/services.h create mode 100644 security/selinux/ss/sidtab.c create mode 100644 security/selinux/ss/sidtab.h create mode 100644 security/selinux/ss/symtab.c create mode 100644 security/selinux/ss/symtab.h create mode 100644 security/selinux/status.c create mode 100644 security/selinux/xfrm.c create mode 100644 security/smack/Kconfig create mode 100644 security/smack/Makefile create mode 100644 security/smack/smack.h create mode 100644 security/smack/smack_access.c create mode 100644 security/smack/smack_lsm.c create mode 100644 security/smack/smack_netfilter.c create mode 100644 security/smack/smackfs.c create mode 100644 security/tomoyo/.gitignore create mode 100644 security/tomoyo/Kconfig create mode 100644 security/tomoyo/Makefile create mode 100644 security/tomoyo/audit.c create mode 100644 security/tomoyo/common.c create mode 100644 security/tomoyo/common.h create mode 100644 security/tomoyo/condition.c create mode 100644 security/tomoyo/domain.c create mode 100644 security/tomoyo/environ.c create mode 100644 security/tomoyo/file.c create mode 100644 security/tomoyo/gc.c create mode 100644 security/tomoyo/group.c create mode 100644 security/tomoyo/load_policy.c create mode 100644 security/tomoyo/memory.c create mode 100644 security/tomoyo/mount.c create mode 100644 security/tomoyo/network.c create mode 100644 security/tomoyo/policy/exception_policy.conf.default create mode 100644 security/tomoyo/realpath.c create mode 100644 security/tomoyo/securityfs_if.c create mode 100644 security/tomoyo/tomoyo.c create mode 100644 security/tomoyo/util.c create mode 100644 security/yama/Kconfig create mode 100644 security/yama/Makefile create mode 100644 security/yama/yama_lsm.c (limited to 'security') diff --git a/security/Kconfig b/security/Kconfig new file mode 100644 index 000000000..f7bf6cdc6 --- /dev/null +++ b/security/Kconfig @@ -0,0 +1,305 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Security configuration +# + +menu "Security options" + +source "security/keys/Kconfig" + +config SECURITY_DMESG_RESTRICT + bool "Restrict unprivileged access to the kernel syslog" + default n + help + This enforces restrictions on unprivileged users reading the kernel + syslog via dmesg(8). + + If this option is not selected, no restrictions will be enforced + unless the dmesg_restrict sysctl is explicitly set to (1). + + If you are unsure how to answer this question, answer N. + +choice + prompt "Allow /proc/pid/mem access override" + default PROC_MEM_FORCE_PTRACE + help + Traditionally /proc/pid/mem allows users to override memory + permissions for users like ptrace, assuming they have ptrace + capability. + + This allows people to limit that - either never override, or + require actual active ptrace attachment (default). + +config PROC_MEM_ALWAYS_FORCE + bool "Traditional /proc/pid/mem behavior" + help + This allows /proc/pid/mem accesses to override memory mapping + permissions if you have ptrace access rights. + +config PROC_MEM_FORCE_PTRACE + bool "Require active ptrace() use for access override" + help + This allows /proc/pid/mem accesses to override memory mapping + permissions for active ptracers like gdb. + +config PROC_MEM_NO_FORCE + bool "Never" + help + Never override memory mapping permissions + +endchoice + +config MSEAL_SYSTEM_MAPPINGS + bool "mseal system mappings" + depends on 64BIT + depends on ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS + depends on !CHECKPOINT_RESTORE + help + Apply mseal on system mappings. + The system mappings includes vdso, vvar, vvar_vclock, + vectors (arm compat-mode), sigpage (arm compat-mode), uprobes. + + A 64-bit kernel is required for the memory sealing feature. + No specific hardware features from the CPU are needed. + + WARNING: This feature breaks programs which rely on relocating + or unmapping system mappings. Known broken software at the time + of writing includes CHECKPOINT_RESTORE, UML, gVisor, rr. Therefore + this config can't be enabled universally. + + For complete descriptions of memory sealing, please see + Documentation/userspace-api/mseal.rst + +config SECURITY + bool "Enable different security models" + depends on SYSFS + depends on MULTIUSER + help + This allows you to choose different security modules to be + configured into your kernel. + + If this option is not selected, the default Linux security + model will be used. + + If you are unsure how to answer this question, answer N. + +config HAS_SECURITY_AUDIT + def_bool y + depends on AUDIT + depends on SECURITY + +config SECURITYFS + bool "Enable the securityfs filesystem" + help + This will build the securityfs filesystem. It is currently used by + various security modules (AppArmor, IMA, SafeSetID, TOMOYO, TPM). + + If you are unsure how to answer this question, answer N. + +config SECURITY_NETWORK + bool "Socket and Networking Security Hooks" + depends on SECURITY + help + This enables the socket and networking security hooks. + If enabled, a security module can use these hooks to + implement socket and networking access controls. + If you are unsure how to answer this question, answer N. + +config SECURITY_INFINIBAND + bool "Infiniband Security Hooks" + depends on SECURITY && INFINIBAND + help + This enables the Infiniband security hooks. + If enabled, a security module can use these hooks to + implement Infiniband access controls. + If you are unsure how to answer this question, answer N. + +config SECURITY_NETWORK_XFRM + bool "XFRM (IPSec) Networking Security Hooks" + depends on XFRM && SECURITY_NETWORK + help + This enables the XFRM (IPSec) networking security hooks. + If enabled, a security module can use these hooks to + implement per-packet access controls based on labels + derived from IPSec policy. Non-IPSec communications are + designated as unlabelled, and only sockets authorized + to communicate unlabelled data can send without using + IPSec. + If you are unsure how to answer this question, answer N. + +config SECURITY_PATH + bool "Security hooks for pathname based access control" + depends on SECURITY + help + This enables the security hooks for pathname based access control. + If enabled, a security module can use these hooks to + implement pathname based access controls. + If you are unsure how to answer this question, answer N. + +config INTEL_TXT + bool "Enable Intel(R) Trusted Execution Technology (Intel(R) TXT)" + depends on HAVE_INTEL_TXT + help + This option enables support for booting the kernel with the + Trusted Boot (tboot) module. This will utilize + Intel(R) Trusted Execution Technology to perform a measured launch + of the kernel. If the system does not support Intel(R) TXT, this + will have no effect. + + Intel TXT will provide higher assurance of system configuration and + initial state as well as data reset protection. This is used to + create a robust initial kernel measurement and verification, which + helps to ensure that kernel security mechanisms are functioning + correctly. This level of protection requires a root of trust outside + of the kernel itself. + + Intel TXT also helps solve real end user concerns about having + confidence that their hardware is running the VMM or kernel that + it was configured with, especially since they may be responsible for + providing such assurances to VMs and services running on it. + + See for more information + about Intel(R) TXT. + See for more information about tboot. + See Documentation/arch/x86/intel_txt.rst for a description of how to enable + Intel TXT support in a kernel boot. + + If you are unsure as to whether this is required, answer N. + +config LSM_MMAP_MIN_ADDR + int "Low address space for LSM to protect from user allocation" + depends on SECURITY && SECURITY_SELINUX + default 32768 if ARM || (ARM64 && COMPAT) + default 65536 + help + This is the portion of low virtual memory which should be protected + from userspace allocation. Keeping a user from writing to low pages + can help reduce the impact of kernel NULL pointer bugs. + + For most ia64, ppc64 and x86 users with lots of address space + a value of 65536 is reasonable and should cause no problems. + On arm and other archs it should not be higher than 32768. + Programs which use vm86 functionality or have some need to map + this low address space will need the permission specific to the + systems running LSM. + +config STATIC_USERMODEHELPER + bool "Force all usermode helper calls through a single binary" + help + By default, the kernel can call many different userspace + binary programs through the "usermode helper" kernel + interface. Some of these binaries are statically defined + either in the kernel code itself, or as a kernel configuration + option. However, some of these are dynamically created at + runtime, or can be modified after the kernel has started up. + To provide an additional layer of security, route all of these + calls through a single executable that can not have its name + changed. + + Note, it is up to this single binary to then call the relevant + "real" usermode helper binary, based on the first argument + passed to it. If desired, this program can filter and pick + and choose what real programs are called. + + If you wish for all usermode helper programs are to be + disabled, choose this option and then set + STATIC_USERMODEHELPER_PATH to an empty string. + +config STATIC_USERMODEHELPER_PATH + string "Path to the static usermode helper binary" + depends on STATIC_USERMODEHELPER + default "/sbin/usermode-helper" + help + The binary called by the kernel when any usermode helper + program is wish to be run. The "real" application's name will + be in the first argument passed to this program on the command + line. + + If you wish for all usermode helper programs to be disabled, + specify an empty string here (i.e. ""). + +source "security/selinux/Kconfig" +source "security/smack/Kconfig" +source "security/tomoyo/Kconfig" +source "security/apparmor/Kconfig" +source "security/loadpin/Kconfig" +source "security/yama/Kconfig" +source "security/safesetid/Kconfig" +source "security/lockdown/Kconfig" +source "security/landlock/Kconfig" +source "security/ipe/Kconfig" + +source "security/integrity/Kconfig" + +choice + prompt "First legacy 'major LSM' to be initialized" + default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX + default DEFAULT_SECURITY_SMACK if SECURITY_SMACK + default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO + default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR + default DEFAULT_SECURITY_DAC + + help + This choice is there only for converting CONFIG_DEFAULT_SECURITY + in old kernel configs to CONFIG_LSM in new kernel configs. Don't + change this choice unless you are creating a fresh kernel config, + for this choice will be ignored after CONFIG_LSM has been set. + + Selects the legacy "major security module" that will be + initialized first. Overridden by non-default CONFIG_LSM. + + config DEFAULT_SECURITY_SELINUX + bool "SELinux" if SECURITY_SELINUX=y + + config DEFAULT_SECURITY_SMACK + bool "Simplified Mandatory Access Control" if SECURITY_SMACK=y + + config DEFAULT_SECURITY_TOMOYO + bool "TOMOYO" if SECURITY_TOMOYO=y + + config DEFAULT_SECURITY_APPARMOR + bool "AppArmor" if SECURITY_APPARMOR=y + + config DEFAULT_SECURITY_DAC + bool "Unix Discretionary Access Controls" + +endchoice + +config LSM + string "Ordered list of enabled LSMs" + depends on SECURITY + default "landlock,lockdown,yama,loadpin,safesetid,smack,selinux,tomoyo,apparmor,ipe,bpf" if DEFAULT_SECURITY_SMACK + default "landlock,lockdown,yama,loadpin,safesetid,apparmor,selinux,smack,tomoyo,ipe,bpf" if DEFAULT_SECURITY_APPARMOR + default "landlock,lockdown,yama,loadpin,safesetid,tomoyo,ipe,bpf" if DEFAULT_SECURITY_TOMOYO + default "landlock,lockdown,yama,loadpin,safesetid,ipe,bpf" if DEFAULT_SECURITY_DAC + default "landlock,lockdown,yama,loadpin,safesetid,selinux,smack,tomoyo,apparmor,ipe,bpf" + help + A comma-separated list of LSMs, in initialization order. + Any LSMs left off this list, except for those with order + LSM_ORDER_FIRST and LSM_ORDER_LAST, which are always enabled + if selected in the kernel configuration, will be ignored. + This can be controlled at boot with the "lsm=" parameter. + + If unsure, leave this as the default. + +config SECURITY_COMMONCAP_KUNIT_TEST + bool "Build KUnit tests for commoncap" if !KUNIT_ALL_TESTS + depends on KUNIT=y && USER_NS + default KUNIT_ALL_TESTS + help + This builds the commoncap KUnit tests. + + KUnit tests run during boot and output the results to the debug log + in TAP format (https://testanything.org/). Only useful for kernel devs + running KUnit test harness and are not for inclusion into a + production build. + + For more information on KUnit and unit tests in general please refer + to the KUnit documentation in Documentation/dev-tools/kunit/. + + If unsure, say N. + +source "security/Kconfig.hardening" + +endmenu + diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening new file mode 100644 index 000000000..6923036e1 --- /dev/null +++ b/security/Kconfig.hardening @@ -0,0 +1,349 @@ +# SPDX-License-Identifier: GPL-2.0-only +menu "Kernel hardening options" + +menu "Memory initialization" + +config CC_HAS_AUTO_VAR_INIT_PATTERN + def_bool $(cc-option,-ftrivial-auto-var-init=pattern) + +config CC_HAS_AUTO_VAR_INIT_ZERO_BARE + def_bool $(cc-option,-ftrivial-auto-var-init=zero) + +config CC_HAS_AUTO_VAR_INIT_ZERO_ENABLER + # Clang 16 and later warn about using the -enable flag, but it + # is required before then. + def_bool $(cc-option,-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang) + depends on !CC_HAS_AUTO_VAR_INIT_ZERO_BARE + +config CC_HAS_AUTO_VAR_INIT_ZERO + def_bool CC_HAS_AUTO_VAR_INIT_ZERO_BARE || CC_HAS_AUTO_VAR_INIT_ZERO_ENABLER + +choice + prompt "Initialize kernel stack variables at function entry" + default INIT_STACK_ALL_PATTERN if COMPILE_TEST && CC_HAS_AUTO_VAR_INIT_PATTERN + default INIT_STACK_ALL_ZERO if CC_HAS_AUTO_VAR_INIT_ZERO + default INIT_STACK_NONE + help + This option enables initialization of stack variables at + function entry time. This has the possibility to have the + greatest coverage (since all functions can have their + variables initialized), but the performance impact depends + on the function calling complexity of a given workload's + syscalls. + + This chooses the level of coverage over classes of potentially + uninitialized variables. The selected class of variable will be + initialized before use in a function. + + config INIT_STACK_NONE + bool "no automatic stack variable initialization (weakest)" + help + Disable automatic stack variable initialization. + This leaves the kernel vulnerable to the standard + classes of uninitialized stack variable exploits + and information exposures. + + config INIT_STACK_ALL_PATTERN + bool "pattern-init everything (strongest)" + depends on CC_HAS_AUTO_VAR_INIT_PATTERN + depends on !KMSAN + help + Initializes everything on the stack (including padding) + with a specific debug value. This is intended to eliminate + all classes of uninitialized stack variable exploits and + information exposures, even variables that were warned about + having been left uninitialized. + + Pattern initialization is known to provoke many existing bugs + related to uninitialized locals, e.g. pointers receive + non-NULL values, buffer sizes and indices are very big. The + pattern is situation-specific; Clang on 64-bit uses 0xAA + repeating for all types and padding except float and double + which use 0xFF repeating (-NaN). Clang on 32-bit uses 0xFF + repeating for all types and padding. + GCC uses 0xFE repeating for all types, and zero for padding. + + config INIT_STACK_ALL_ZERO + bool "zero-init everything (strongest and safest)" + depends on CC_HAS_AUTO_VAR_INIT_ZERO + depends on !KMSAN + help + Initializes everything on the stack (including padding) + with a zero value. This is intended to eliminate all + classes of uninitialized stack variable exploits and + information exposures, even variables that were warned + about having been left uninitialized. + + Zero initialization provides safe defaults for strings + (immediately NUL-terminated), pointers (NULL), indices + (index 0), and sizes (0 length), so it is therefore more + suitable as a production security mitigation than pattern + initialization. + +endchoice + +config CC_HAS_SANCOV_STACK_DEPTH_CALLBACK + def_bool $(cc-option,-fsanitize-coverage-stack-depth-callback-min=1) + +config KSTACK_ERASE + bool "Poison kernel stack before returning from syscalls" + depends on HAVE_ARCH_KSTACK_ERASE + depends on GCC_PLUGINS || CC_HAS_SANCOV_STACK_DEPTH_CALLBACK + help + This option makes the kernel erase the kernel stack before + returning from system calls. This has the effect of leaving + the stack initialized to the poison value, which both reduces + the lifetime of any sensitive stack contents and reduces + potential for uninitialized stack variable exploits or information + exposures (it does not cover functions reaching the same stack + depth as prior functions during the same syscall). This blocks + most uninitialized stack variable attacks, with the performance + impact being driven by the depth of the stack usage, rather than + the function calling complexity. + + The performance impact on a single CPU system kernel compilation + sees a 1% slowdown, other systems and workloads may vary and you + are advised to test this feature on your expected workload before + deploying it. + +config GCC_PLUGIN_STACKLEAK + def_bool KSTACK_ERASE + depends on GCC_PLUGINS + help + This plugin was ported from grsecurity/PaX. More information at: + * https://grsecurity.net/ + * https://pax.grsecurity.net/ + +config GCC_PLUGIN_STACKLEAK_VERBOSE + bool "Report stack depth analysis instrumentation" if EXPERT + depends on GCC_PLUGIN_STACKLEAK + depends on !COMPILE_TEST # too noisy + help + This option will cause a warning to be printed each time the + stackleak plugin finds a function it thinks needs to be + instrumented. This is useful for comparing coverage between + builds. + +config KSTACK_ERASE_TRACK_MIN_SIZE + int "Minimum stack frame size of functions tracked by KSTACK_ERASE" + default 100 + range 0 4096 + depends on KSTACK_ERASE + help + The KSTACK_ERASE option instruments the kernel code for tracking + the lowest border of the kernel stack (and for some other purposes). + It inserts the __sanitizer_cov_stack_depth() call for the functions + with a stack frame size greater than or equal to this parameter. + If unsure, leave the default value 100. + +config KSTACK_ERASE_METRICS + bool "Show KSTACK_ERASE metrics in the /proc file system" + depends on KSTACK_ERASE + depends on PROC_FS + help + If this is set, KSTACK_ERASE metrics for every task are available + in the /proc file system. In particular, /proc//stack_depth + shows the maximum kernel stack consumption for the current and + previous syscalls. Although this information is not precise, it + can be useful for estimating the KSTACK_ERASE performance impact + for your workloads. + +config KSTACK_ERASE_RUNTIME_DISABLE + bool "Allow runtime disabling of kernel stack erasing" + depends on KSTACK_ERASE + help + This option provides 'stack_erasing' sysctl, which can be used in + runtime to control kernel stack erasing for kernels built with + CONFIG_KSTACK_ERASE. + +config INIT_ON_ALLOC_DEFAULT_ON + bool "Enable heap memory zeroing on allocation by default" + depends on !KMSAN + help + This has the effect of setting "init_on_alloc=1" on the kernel + command line. This can be disabled with "init_on_alloc=0". + When "init_on_alloc" is enabled, all page allocator and slab + allocator memory will be zeroed when allocated, eliminating + many kinds of "uninitialized heap memory" flaws, especially + heap content exposures. The performance impact varies by + workload, but most cases see <1% impact. Some synthetic + workloads have measured as high as 7%. + +config INIT_ON_FREE_DEFAULT_ON + bool "Enable heap memory zeroing on free by default" + depends on !KMSAN + help + This has the effect of setting "init_on_free=1" on the kernel + command line. This can be disabled with "init_on_free=0". + Similar to "init_on_alloc", when "init_on_free" is enabled, + all page allocator and slab allocator memory will be zeroed + when freed, eliminating many kinds of "uninitialized heap memory" + flaws, especially heap content exposures. The primary difference + with "init_on_free" is that data lifetime in memory is reduced, + as anything freed is wiped immediately, making live forensics or + cold boot memory attacks unable to recover freed memory contents. + The performance impact varies by workload, but is more expensive + than "init_on_alloc" due to the negative cache effects of + touching "cold" memory areas. Most cases see 3-5% impact. Some + synthetic workloads have measured as high as 8%. + +config CC_HAS_ZERO_CALL_USED_REGS + # supported by gcc-11 or newer and all supported versions of clang + def_bool $(cc-option,-fzero-call-used-regs=used-gpr) + +config ZERO_CALL_USED_REGS + bool "Enable register zeroing on function exit" + depends on CC_HAS_ZERO_CALL_USED_REGS + help + At the end of functions, always zero any caller-used register + contents. This helps ensure that temporary values are not + leaked beyond the function boundary. This means that register + contents are less likely to be available for side channels + and information exposures. Additionally, this helps reduce the + number of useful ROP gadgets by about 20% (and removes compiler + generated "write-what-where" gadgets) in the resulting kernel + image. This has a less than 1% performance impact on most + workloads. Image size growth depends on architecture, and should + be evaluated for suitability. For example, x86_64 grows by less + than 1%, and arm64 grows by about 5%. + +endmenu + +menu "Bounds checking" + +config FORTIFY_SOURCE + bool "Harden common str/mem functions against buffer overflows" + depends on ARCH_HAS_FORTIFY_SOURCE + help + Detect overflows of buffers in common string and memory functions + where the compiler can determine and validate the buffer sizes. + +config HARDENED_USERCOPY + bool "Harden memory copies between kernel and userspace" + imply STRICT_DEVMEM + help + This option checks for obviously wrong memory regions when + copying memory to/from the kernel (via copy_to_user() and + copy_from_user() functions) by rejecting memory ranges that + are larger than the specified heap object, span multiple + separately allocated pages, are not on the process stack, + or are part of the kernel text. This prevents entire classes + of heap overflow exploits and similar kernel memory exposures. + +config HARDENED_USERCOPY_DEFAULT_ON + bool "Harden memory copies by default" + depends on HARDENED_USERCOPY + default HARDENED_USERCOPY + help + This has the effect of setting "hardened_usercopy=on" on the kernel + command line. This can be disabled with "hardened_usercopy=off". + +endmenu + +menu "Hardening of kernel data structures" + +config LIST_HARDENED + bool "Check integrity of linked list manipulation" + help + Minimal integrity checking in the linked-list manipulation routines + to catch memory corruptions that are not guaranteed to result in an + immediate access fault. + + If unsure, say N. + +config RUST_BITMAP_HARDENED + bool "Check integrity of bitmap Rust API" + depends on RUST + help + Enables additional assertions in the Rust Bitmap API to catch + arguments that are not guaranteed to result in an immediate access + fault. + + If unsure, say N. + +config BUG_ON_DATA_CORRUPTION + bool "Trigger a BUG when data corruption is detected" + select LIST_HARDENED + help + Select this option if the kernel should BUG when it encounters + data corruption in kernel memory structures when they get checked + for validity. + + If unsure, say N. + +endmenu + +config CC_HAS_RANDSTRUCT + def_bool $(cc-option,-frandomize-layout-seed-file=/dev/null) + +choice + prompt "Randomize layout of sensitive kernel structures" + default RANDSTRUCT_FULL if COMPILE_TEST && (GCC_PLUGINS || CC_HAS_RANDSTRUCT) + default RANDSTRUCT_NONE + help + If you enable this, the layouts of structures that are entirely + function pointers (and have not been manually annotated with + __no_randomize_layout), or structures that have been explicitly + marked with __randomize_layout, will be randomized at compile-time. + This can introduce the requirement of an additional information + exposure vulnerability for exploits targeting these structure + types. + + Enabling this feature will introduce some performance impact, + slightly increase memory usage, and prevent the use of forensic + tools like Volatility against the system (unless the kernel + source tree isn't cleaned after kernel installation). + + The seed used for compilation is in scripts/basic/randomize.seed. + It remains after a "make clean" to allow for external modules to + be compiled with the existing seed and will be removed by a + "make mrproper" or "make distclean". This file should not be made + public, or the structure layout can be determined. + + config RANDSTRUCT_NONE + bool "Disable structure layout randomization" + help + Build normally: no structure layout randomization. + + config RANDSTRUCT_FULL + bool "Fully randomize structure layout" + depends on CC_HAS_RANDSTRUCT || GCC_PLUGINS + select MODVERSIONS if MODULES && !COMPILE_TEST + help + Fully randomize the member layout of sensitive + structures as much as possible, which may have both a + memory size and performance impact. + + One difference between the Clang and GCC plugin + implementations is the handling of bitfields. The GCC + plugin treats them as fully separate variables, + introducing sometimes significant padding. Clang tries + to keep adjacent bitfields together, but with their bit + ordering randomized. + + config RANDSTRUCT_PERFORMANCE + bool "Limit randomization of structure layout to cache-lines" + depends on GCC_PLUGINS + select MODVERSIONS if MODULES && !COMPILE_TEST + help + Randomization of sensitive kernel structures will make a + best effort at restricting randomization to cacheline-sized + groups of members. It will further not randomize bitfields + in structures. This reduces the performance hit of RANDSTRUCT + at the cost of weakened randomization. +endchoice + +config RANDSTRUCT + def_bool !RANDSTRUCT_NONE + +config GCC_PLUGIN_RANDSTRUCT + def_bool GCC_PLUGINS && RANDSTRUCT + help + Use GCC plugin to randomize structure layout. + + This plugin was ported from grsecurity/PaX. More + information at: + * https://grsecurity.net/ + * https://pax.grsecurity.net/ + +endmenu diff --git a/security/Makefile b/security/Makefile new file mode 100644 index 000000000..4601230ba --- /dev/null +++ b/security/Makefile @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the kernel security code +# + +obj-$(CONFIG_KEYS) += keys/ + +# always enable default capabilities +obj-y += commoncap.o +obj-$(CONFIG_SECURITY) += lsm_syscalls.o +obj-$(CONFIG_MMU) += min_addr.o + +# Object file lists +obj-$(CONFIG_SECURITY) += security.o lsm_notifier.o lsm_init.o +obj-$(CONFIG_SECURITYFS) += inode.o +obj-$(CONFIG_SECURITY_SELINUX) += selinux/ +obj-$(CONFIG_SECURITY_SMACK) += smack/ +obj-$(CONFIG_HAS_SECURITY_AUDIT) += lsm_audit.o +obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/ +obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/ +obj-$(CONFIG_SECURITY_YAMA) += yama/ +obj-$(CONFIG_SECURITY_LOADPIN) += loadpin/ +obj-$(CONFIG_SECURITY_SAFESETID) += safesetid/ +obj-$(CONFIG_SECURITY_LOCKDOWN_LSM) += lockdown/ +obj-$(CONFIG_CGROUPS) += device_cgroup.o +obj-$(CONFIG_BPF_LSM) += bpf/ +obj-$(CONFIG_SECURITY_LANDLOCK) += landlock/ +obj-$(CONFIG_SECURITY_IPE) += ipe/ + +# Object integrity file lists +obj-$(CONFIG_INTEGRITY) += integrity/ diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore new file mode 100644 index 000000000..6d1eb1c15 --- /dev/null +++ b/security/apparmor/.gitignore @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only +net_names.h +capability_names.h +rlim_names.h diff --git a/security/apparmor/.kunitconfig b/security/apparmor/.kunitconfig new file mode 100644 index 000000000..aa842a026 --- /dev/null +++ b/security/apparmor/.kunitconfig @@ -0,0 +1,5 @@ +CONFIG_KUNIT=y +CONFIG_NET=y +CONFIG_SECURITY=y +CONFIG_SECURITY_APPARMOR=y +CONFIG_SECURITY_APPARMOR_KUNIT_TEST=y diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig new file mode 100644 index 000000000..1e3bd4464 --- /dev/null +++ b/security/apparmor/Kconfig @@ -0,0 +1,122 @@ +# SPDX-License-Identifier: GPL-2.0-only +config SECURITY_APPARMOR + bool "AppArmor support" + depends on SECURITY && NET + select AUDIT + select SECURITY_PATH + select SECURITYFS + select SECURITY_NETWORK + default n + help + This enables the AppArmor security module. + Required userspace tools (if they are not included in your + distribution) and further information may be found at + http://apparmor.wiki.kernel.org + + If you are unsure how to answer this question, answer N. + +config SECURITY_APPARMOR_DEBUG + bool "Build AppArmor with debug code" + depends on SECURITY_APPARMOR + default n + help + Build apparmor with debugging logic in apparmor. Not all + debugging logic will necessarily be enabled. A submenu will + provide fine grained control of the debug options that are + available. + +config SECURITY_APPARMOR_DEBUG_ASSERTS + bool "Build AppArmor with debugging asserts" + depends on SECURITY_APPARMOR_DEBUG + default y + help + Enable code assertions made with AA_BUG. These are primarily + function entry preconditions but also exist at other key + points. If the assert is triggered it will trigger a WARN + message. + +config SECURITY_APPARMOR_DEBUG_MESSAGES + bool "Debug messages enabled by default" + depends on SECURITY_APPARMOR_DEBUG + default n + help + Set the default value of the apparmor.debug kernel parameter. + When enabled, various debug messages will be logged to + the kernel message buffer. + +config SECURITY_APPARMOR_INTROSPECT_POLICY + bool "Allow loaded policy to be introspected" + depends on SECURITY_APPARMOR + default y + help + This option selects whether introspection of loaded policy + is available to userspace via the apparmor filesystem. This + adds to kernel memory usage. It is required for introspection + of loaded policy, and check point and restore support. It + can be disabled for embedded systems where reducing memory and + cpu is paramount. + +config SECURITY_APPARMOR_HASH + bool "Enable introspection of sha256 hashes for loaded profiles" + depends on SECURITY_APPARMOR_INTROSPECT_POLICY + select CRYPTO_LIB_SHA256 + default y + help + This option selects whether introspection of loaded policy + hashes is available to userspace via the apparmor + filesystem. This option provides a light weight means of + checking loaded policy. This option adds to policy load + time and can be disabled for small embedded systems. + +config SECURITY_APPARMOR_HASH_DEFAULT + bool "Enable policy hash introspection by default" + depends on SECURITY_APPARMOR_HASH + default y + help + This option selects whether sha256 hashing of loaded policy + is enabled by default. The generation of sha256 hashes for + loaded policy provide system administrators a quick way to + verify that policy in the kernel matches what is expected, + however it can slow down policy load on some devices. In + these cases policy hashing can be disabled by default and + enabled only if needed. + +config SECURITY_APPARMOR_EXPORT_BINARY + bool "Allow exporting the raw binary policy" + depends on SECURITY_APPARMOR_INTROSPECT_POLICY + select ZSTD_COMPRESS + select ZSTD_DECOMPRESS + default y + help + This option allows reading back binary policy as it was loaded. + It increases the amount of kernel memory needed by policy and + also increases policy load time. This option is required for + checkpoint and restore support, and debugging of loaded policy. + +config SECURITY_APPARMOR_PARANOID_LOAD + bool "Perform full verification of loaded policy" + depends on SECURITY_APPARMOR + default y + help + This options allows controlling whether apparmor does a full + verification of loaded policy. This should not be disabled + except for embedded systems where the image is read only, + includes policy, and has some form of integrity check. + Disabling the check will speed up policy loads. + +config SECURITY_APPARMOR_KUNIT_TEST + tristate "Build KUnit tests for policy_unpack.c" if !KUNIT_ALL_TESTS + depends on KUNIT && SECURITY_APPARMOR + default KUNIT_ALL_TESTS + help + This builds the AppArmor KUnit tests. + + KUnit tests run during boot and output the results to the debug log + in TAP format (https://testanything.org/). Only useful for kernel devs + running KUnit test harness and are not for inclusion into a + production build. + + For more information on KUnit and unit tests in general please refer + to the KUnit documentation in Documentation/dev-tools/kunit/. + + If unsure, say N. diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile new file mode 100644 index 000000000..12fb41971 --- /dev/null +++ b/security/apparmor/Makefile @@ -0,0 +1,114 @@ +# SPDX-License-Identifier: GPL-2.0 +# Makefile for AppArmor Linux Security Module +# +obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o + +apparmor-y := apparmorfs.o audit.o capability.o task.o ipc.o lib.o match.o \ + path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ + resource.o secid.o file.o policy_ns.o label.o mount.o net.o \ + policy_compat.o af_unix.o +apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o + +obj-$(CONFIG_SECURITY_APPARMOR_KUNIT_TEST) += apparmor_policy_unpack_test.o +apparmor_policy_unpack_test-objs += policy_unpack_test.o + +clean-files := capability_names.h rlim_names.h net_names.h + +# Build a lower case string table of address family names +# Transform lines from +# #define AF_LOCAL 1 /* POSIX name for AF_UNIX */ +# #define AF_INET 2 /* Internet IP Protocol */ +# to +# [1] = "local", +# [2] = "inet", +# +# and build the securityfs entries for the mapping. +# Transforms lines from +# #define AF_INET 2 /* Internet IP Protocol */ +# to +# #define AA_SFS_AF_MASK "local inet" +quiet_cmd_make-af = GEN $@ +cmd_make-af = echo "static const char *const address_family_names[] = {" > $@ ;\ + sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \ + 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\ + echo "};" >> $@ ;\ + printf '%s' '\#define AA_SFS_AF_MASK "' >> $@ ;\ + sed -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \ + 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\ + $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ + +# Build a lower case string table of sock type names +# Transform lines from +# SOCK_STREAM = 1, +# to +# [1] = "stream", +quiet_cmd_make-sock = GEN $@ +cmd_make-sock = echo "static const char *const sock_type_names[] = {" >> $@ ;\ + sed $^ >>$@ -r -n \ + -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\ + echo "};" >> $@ + +# Build a lower case string table of capability names +# Transforms lines from +# #define CAP_DAC_OVERRIDE 1 +# to +# [1] = "dac_override", +quiet_cmd_make-caps = GEN $@ +cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\ + sed $< >>$@ -r -n -e '/CAP_FS_MASK/d' \ + -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\ + echo "};" >> $@ ;\ + printf '%s' '\#define AA_SFS_CAPS_MASK "' >> $@ ;\ + sed $< -r -n -e '/CAP_FS_MASK/d' \ + -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/\L\1/p' | \ + tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ + + +# Build a lower case string table of rlimit names. +# Transforms lines from +# #define RLIMIT_STACK 3 /* max stack size */ +# to +# [RLIMIT_STACK] = "stack", +# +# and build a second integer table (with the second sed cmd), that maps +# RLIMIT defines to the order defined in asm-generic/resource.h This is +# required by policy load to map policy ordering of RLIMITs to internal +# ordering for architectures that redefine an RLIMIT. +# Transforms lines from +# #define RLIMIT_STACK 3 /* max stack size */ +# to +# RLIMIT_STACK, +# +# and build the securityfs entries for the mapping. +# Transforms lines from +# #define RLIMIT_FSIZE 1 /* Maximum filesize */ +# #define RLIMIT_STACK 3 /* max stack size */ +# to +# #define AA_SFS_RLIMIT_MASK "fsize stack" +quiet_cmd_make-rlim = GEN $@ +cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \ + > $@ ;\ + sed $< >> $@ -r -n \ + -e 's/^\# ?define[ \t]+(RLIMIT_([A-Z0-9_]+)).*/[\1] = "\L\2",/p';\ + echo "};" >> $@ ;\ + echo "static const int rlim_map[RLIM_NLIMITS] = {" >> $@ ;\ + sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\ + echo "};" >> $@ ; \ + printf '%s' '\#define AA_SFS_RLIMIT_MASK "' >> $@ ;\ + sed -r -n 's/^\# ?define[ \t]+RLIMIT_([A-Z0-9_]+).*/\L\1/p' $< | \ + tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ + +$(obj)/capability.o : $(obj)/capability_names.h +$(obj)/net.o : $(obj)/net_names.h +$(obj)/resource.o : $(obj)/rlim_names.h +$(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \ + $(src)/Makefile + $(call cmd,make-caps) +$(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \ + $(src)/Makefile + $(call cmd,make-rlim) +$(obj)/net_names.h : $(srctree)/include/linux/socket.h \ + $(srctree)/include/linux/net.h \ + $(src)/Makefile + $(call cmd,make-af) + $(call cmd,make-sock) diff --git a/security/apparmor/af_unix.c b/security/apparmor/af_unix.c new file mode 100644 index 000000000..b9b22edae --- /dev/null +++ b/security/apparmor/af_unix.c @@ -0,0 +1,806 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AppArmor security module + * + * This file contains AppArmor af_unix fine grained mediation + * + * Copyright 2023 Canonical Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + */ + +#include +#include + +#include "include/audit.h" +#include "include/af_unix.h" +#include "include/apparmor.h" +#include "include/file.h" +#include "include/label.h" +#include "include/path.h" +#include "include/policy.h" +#include "include/cred.h" + + +static inline struct sock *aa_unix_sk(struct unix_sock *u) +{ + return &u->sk; +} + +static int unix_fs_perm(const char *op, u32 mask, const struct cred *subj_cred, + struct aa_label *label, const struct path *path) +{ + AA_BUG(!label); + AA_BUG(!path); + + if (unconfined(label) || !label_mediates(label, AA_CLASS_FILE)) + return 0; + + mask &= NET_FS_PERMS; + /* if !u->path.dentry socket is being shutdown - implicit delegation + * until obj delegation is supported + */ + if (path->dentry) { + /* the sunpath may not be valid for this ns so use the path */ + struct inode *inode = path->dentry->d_inode; + vfsuid_t vfsuid = i_uid_into_vfsuid(mnt_idmap(path->mnt), inode); + struct path_cond cond = { + .uid = vfsuid_into_kuid(vfsuid), + .mode = inode->i_mode, + }; + + return aa_path_perm(op, subj_cred, label, path, + PATH_SOCK_COND, mask, &cond); + } /* else implicitly delegated */ + + return 0; +} + +/* match_addr special constants */ +#define ABSTRACT_ADDR "\x00" /* abstract socket addr */ +#define ANONYMOUS_ADDR "\x01" /* anonymous endpoint, no addr */ +#define DISCONNECTED_ADDR "\x02" /* addr is another namespace */ +#define SHUTDOWN_ADDR "\x03" /* path addr is shutdown and cleared */ +#define FS_ADDR "/" /* path addr in fs */ + +static aa_state_t match_addr(struct aa_dfa *dfa, aa_state_t state, + struct sockaddr_un *addr, int addrlen) +{ + if (addr) + /* include leading \0 */ + state = aa_dfa_match_len(dfa, state, addr->sun_path, + unix_addr_len(addrlen)); + else + state = aa_dfa_match_len(dfa, state, ANONYMOUS_ADDR, 1); + /* todo: could change to out of band for cleaner separation */ + state = aa_dfa_null_transition(dfa, state); + + return state; +} + +static aa_state_t match_to_local(struct aa_policydb *policy, + aa_state_t state, u32 request, + int type, int protocol, + struct sockaddr_un *addr, int addrlen, + struct aa_perms **p, + const char **info) +{ + state = aa_match_to_prot(policy, state, request, PF_UNIX, type, + protocol, NULL, info); + if (state) { + state = match_addr(policy->dfa, state, addr, addrlen); + if (state) { + /* todo: local label matching */ + state = aa_dfa_null_transition(policy->dfa, state); + if (!state) + *info = "failed local label match"; + } else { + *info = "failed local address match"; + } + } + + return state; +} + +struct sockaddr_un *aa_sunaddr(const struct unix_sock *u, int *addrlen) +{ + struct unix_address *addr; + + /* memory barrier is sufficient see note in net/unix/af_unix.c */ + addr = smp_load_acquire(&u->addr); + if (addr) { + *addrlen = addr->len; + return addr->name; + } + *addrlen = 0; + return NULL; +} + +static aa_state_t match_to_sk(struct aa_policydb *policy, + aa_state_t state, u32 request, + struct unix_sock *u, struct aa_perms **p, + const char **info) +{ + int addrlen; + struct sockaddr_un *addr = aa_sunaddr(u, &addrlen); + + return match_to_local(policy, state, request, u->sk.sk_type, + u->sk.sk_protocol, addr, addrlen, p, info); +} + +#define CMD_ADDR 1 +#define CMD_LISTEN 2 +#define CMD_OPT 4 + +static aa_state_t match_to_cmd(struct aa_policydb *policy, aa_state_t state, + u32 request, struct unix_sock *u, + char cmd, struct aa_perms **p, + const char **info) +{ + AA_BUG(!p); + + state = match_to_sk(policy, state, request, u, p, info); + if (state && !*p) { + state = aa_dfa_match_len(policy->dfa, state, &cmd, 1); + if (!state) + *info = "failed cmd selection match"; + } + + return state; +} + +static aa_state_t match_to_peer(struct aa_policydb *policy, aa_state_t state, + u32 request, struct unix_sock *u, + struct sockaddr_un *peer_addr, int peer_addrlen, + struct aa_perms **p, const char **info) +{ + AA_BUG(!p); + + state = match_to_cmd(policy, state, request, u, CMD_ADDR, p, info); + if (state && !*p) { + state = match_addr(policy->dfa, state, peer_addr, peer_addrlen); + if (!state) + *info = "failed peer address match"; + } + + return state; +} + +static aa_state_t match_label(struct aa_profile *profile, + struct aa_ruleset *rule, aa_state_t state, + u32 request, struct aa_profile *peer, + struct aa_perms *p, + struct apparmor_audit_data *ad) +{ + AA_BUG(!profile); + AA_BUG(!peer); + + ad->peer = &peer->label; + + if (state && !p) { + state = aa_dfa_match(rule->policy->dfa, state, + peer->base.hname); + if (!state) + ad->info = "failed peer label match"; + + } + + return aa_do_perms(profile, rule->policy, state, request, p, ad); +} + + +/* unix sock creation comes before we know if the socket will be an fs + * socket + * v6 - semantics are handled by mapping in profile load + * v7 - semantics require sock create for tasks creating an fs socket. + * v8 - same as v7 + */ +static int profile_create_perm(struct aa_profile *profile, int family, + int type, int protocol, + struct apparmor_audit_data *ad) +{ + struct aa_ruleset *rules = profile->label.rules[0]; + aa_state_t state; + + AA_BUG(!profile); + AA_BUG(profile_unconfined(profile)); + + state = RULE_MEDIATES_v9NET(rules); + if (state) { + state = aa_match_to_prot(rules->policy, state, AA_MAY_CREATE, + PF_UNIX, type, protocol, NULL, + &ad->info); + + return aa_do_perms(profile, rules->policy, state, AA_MAY_CREATE, + NULL, ad); + } + + return aa_profile_af_perm(profile, ad, AA_MAY_CREATE, family, type, + protocol); +} + +static int profile_sk_perm(struct aa_profile *profile, + struct apparmor_audit_data *ad, + u32 request, struct sock *sk, const struct path *path) +{ + struct aa_ruleset *rules = profile->label.rules[0]; + struct aa_perms *p = NULL; + aa_state_t state; + + AA_BUG(!profile); + AA_BUG(!sk); + AA_BUG(profile_unconfined(profile)); + + state = RULE_MEDIATES_v9NET(rules); + if (state) { + if (is_unix_fs(sk)) + return unix_fs_perm(ad->op, request, ad->subj_cred, + &profile->label, + &unix_sk(sk)->path); + + state = match_to_sk(rules->policy, state, request, unix_sk(sk), + &p, &ad->info); + + return aa_do_perms(profile, rules->policy, state, request, p, + ad); + } + + return aa_profile_af_sk_perm(profile, ad, request, sk); +} + +static int profile_bind_perm(struct aa_profile *profile, struct sock *sk, + struct apparmor_audit_data *ad) +{ + struct aa_ruleset *rules = profile->label.rules[0]; + struct aa_perms *p = NULL; + aa_state_t state; + + AA_BUG(!profile); + AA_BUG(!sk); + AA_BUG(!ad); + AA_BUG(profile_unconfined(profile)); + + state = RULE_MEDIATES_v9NET(rules); + if (state) { + if (is_unix_addr_fs(ad->net.addr, ad->net.addrlen)) + /* under v7-9 fs hook handles bind */ + return 0; + /* bind for abstract socket */ + state = match_to_local(rules->policy, state, AA_MAY_BIND, + sk->sk_type, sk->sk_protocol, + unix_addr(ad->net.addr), + ad->net.addrlen, + &p, &ad->info); + + return aa_do_perms(profile, rules->policy, state, AA_MAY_BIND, + p, ad); + } + + return aa_profile_af_sk_perm(profile, ad, AA_MAY_BIND, sk); +} + +static int profile_listen_perm(struct aa_profile *profile, struct sock *sk, + int backlog, struct apparmor_audit_data *ad) +{ + struct aa_ruleset *rules = profile->label.rules[0]; + struct aa_perms *p = NULL; + aa_state_t state; + + AA_BUG(!profile); + AA_BUG(!sk); + AA_BUG(!ad); + AA_BUG(profile_unconfined(profile)); + + state = RULE_MEDIATES_v9NET(rules); + if (state) { + __be16 b = cpu_to_be16(backlog); + + if (is_unix_fs(sk)) + return unix_fs_perm(ad->op, AA_MAY_LISTEN, + ad->subj_cred, &profile->label, + &unix_sk(sk)->path); + + state = match_to_cmd(rules->policy, state, AA_MAY_LISTEN, + unix_sk(sk), CMD_LISTEN, &p, &ad->info); + if (state && !p) { + state = aa_dfa_match_len(rules->policy->dfa, state, + (char *) &b, 2); + if (!state) + ad->info = "failed listen backlog match"; + } + return aa_do_perms(profile, rules->policy, state, AA_MAY_LISTEN, + p, ad); + } + + return aa_profile_af_sk_perm(profile, ad, AA_MAY_LISTEN, sk); +} + +static int profile_accept_perm(struct aa_profile *profile, + struct sock *sk, + struct apparmor_audit_data *ad) +{ + struct aa_ruleset *rules = profile->label.rules[0]; + struct aa_perms *p = NULL; + aa_state_t state; + + AA_BUG(!profile); + AA_BUG(!sk); + AA_BUG(!ad); + AA_BUG(profile_unconfined(profile)); + + state = RULE_MEDIATES_v9NET(rules); + if (state) { + if (is_unix_fs(sk)) + return unix_fs_perm(ad->op, AA_MAY_ACCEPT, + ad->subj_cred, &profile->label, + &unix_sk(sk)->path); + + state = match_to_sk(rules->policy, state, AA_MAY_ACCEPT, + unix_sk(sk), &p, &ad->info); + + return aa_do_perms(profile, rules->policy, state, AA_MAY_ACCEPT, + p, ad); + } + + return aa_profile_af_sk_perm(profile, ad, AA_MAY_ACCEPT, sk); +} + +static int profile_opt_perm(struct aa_profile *profile, u32 request, + struct sock *sk, int optname, + struct apparmor_audit_data *ad) +{ + struct aa_ruleset *rules = profile->label.rules[0]; + struct aa_perms *p = NULL; + aa_state_t state; + + AA_BUG(!profile); + AA_BUG(!sk); + AA_BUG(!ad); + AA_BUG(profile_unconfined(profile)); + + state = RULE_MEDIATES_v9NET(rules); + if (state) { + __be16 b = cpu_to_be16(optname); + if (is_unix_fs(sk)) + return unix_fs_perm(ad->op, request, + ad->subj_cred, &profile->label, + &unix_sk(sk)->path); + + state = match_to_cmd(rules->policy, state, request, unix_sk(sk), + CMD_OPT, &p, &ad->info); + if (state && !p) { + state = aa_dfa_match_len(rules->policy->dfa, state, + (char *) &b, 2); + if (!state) + ad->info = "failed sockopt match"; + } + return aa_do_perms(profile, rules->policy, state, request, p, + ad); + } + + return aa_profile_af_sk_perm(profile, ad, request, sk); +} + +/* null peer_label is allowed, in which case the peer_sk label is used */ +static int profile_peer_perm(struct aa_profile *profile, u32 request, + struct sock *sk, const struct path *path, + struct sockaddr_un *peer_addr, + int peer_addrlen, const struct path *peer_path, + struct aa_label *peer_label, + struct apparmor_audit_data *ad) +{ + struct aa_ruleset *rules = profile->label.rules[0]; + struct aa_perms *p = NULL; + aa_state_t state; + + AA_BUG(!profile); + AA_BUG(profile_unconfined(profile)); + AA_BUG(!sk); + AA_BUG(!peer_label); + AA_BUG(!ad); + + state = RULE_MEDIATES_v9NET(rules); + if (state) { + struct aa_profile *peerp; + + if (peer_path) + return unix_fs_perm(ad->op, request, ad->subj_cred, + &profile->label, peer_path); + else if (path) + return unix_fs_perm(ad->op, request, ad->subj_cred, + &profile->label, path); + state = match_to_peer(rules->policy, state, request, + unix_sk(sk), + peer_addr, peer_addrlen, &p, &ad->info); + + return fn_for_each_in_scope(peer_label, peerp, + match_label(profile, rules, state, request, + peerp, p, ad)); + } + + return aa_profile_af_sk_perm(profile, ad, request, sk); +} + +/* -------------------------------- */ + +int aa_unix_create_perm(struct aa_label *label, int family, int type, + int protocol) +{ + if (!unconfined(label)) { + struct aa_profile *profile; + DEFINE_AUDIT_NET(ad, OP_CREATE, current_cred(), NULL, family, + type, protocol); + + return fn_for_each_confined(label, profile, + profile_create_perm(profile, family, type, + protocol, &ad)); + } + + return 0; +} + +static int aa_unix_label_sk_perm(const struct cred *subj_cred, + struct aa_label *label, + const char *op, u32 request, struct sock *sk, + const struct path *path) +{ + if (!unconfined(label)) { + struct aa_profile *profile; + DEFINE_AUDIT_SK(ad, op, subj_cred, sk); + + return fn_for_each_confined(label, profile, + profile_sk_perm(profile, &ad, request, sk, + path)); + } + return 0; +} + +/* revalidation, get/set attr, shutdown */ +int aa_unix_sock_perm(const char *op, u32 request, struct socket *sock) +{ + struct aa_label *label; + int error; + + label = begin_current_label_crit_section(); + error = aa_unix_label_sk_perm(current_cred(), label, op, + request, sock->sk, + is_unix_fs(sock->sk) ? &unix_sk(sock->sk)->path : NULL); + end_current_label_crit_section(label); + + return error; +} + +static int valid_addr(struct sockaddr *addr, int addr_len) +{ + struct sockaddr_un *sunaddr = unix_addr(addr); + + /* addr_len == offsetof(struct sockaddr_un, sun_path) is autobind */ + if (addr_len < offsetof(struct sockaddr_un, sun_path) || + addr_len > sizeof(*sunaddr)) + return -EINVAL; + return 0; +} + +int aa_unix_bind_perm(struct socket *sock, struct sockaddr *addr, + int addrlen) +{ + struct aa_profile *profile; + struct aa_label *label; + int error = 0; + + error = valid_addr(addr, addrlen); + if (error) + return error; + + label = begin_current_label_crit_section(); + /* fs bind is handled by mknod */ + if (!unconfined(label)) { + DEFINE_AUDIT_SK(ad, OP_BIND, current_cred(), sock->sk); + + ad.net.addr = unix_addr(addr); + ad.net.addrlen = addrlen; + + error = fn_for_each_confined(label, profile, + profile_bind_perm(profile, sock->sk, &ad)); + } + end_current_label_crit_section(label); + + return error; +} + +/* + * unix connections are covered by the + * - unix_stream_connect (stream) and unix_may_send hooks (dgram) + * - fs connect is handled by open + * This is just here to document this is not needed for af_unix + * +int aa_unix_connect_perm(struct socket *sock, struct sockaddr *address, + int addrlen) +{ + return 0; +} +*/ + +int aa_unix_listen_perm(struct socket *sock, int backlog) +{ + struct aa_profile *profile; + struct aa_label *label; + int error = 0; + + label = begin_current_label_crit_section(); + if (!unconfined(label)) { + DEFINE_AUDIT_SK(ad, OP_LISTEN, current_cred(), sock->sk); + + error = fn_for_each_confined(label, profile, + profile_listen_perm(profile, sock->sk, + backlog, &ad)); + } + end_current_label_crit_section(label); + + return error; +} + + +/* ability of sock to connect, not peer address binding */ +int aa_unix_accept_perm(struct socket *sock, struct socket *newsock) +{ + struct aa_profile *profile; + struct aa_label *label; + int error = 0; + + label = begin_current_label_crit_section(); + if (!unconfined(label)) { + DEFINE_AUDIT_SK(ad, OP_ACCEPT, current_cred(), sock->sk); + + error = fn_for_each_confined(label, profile, + profile_accept_perm(profile, sock->sk, &ad)); + } + end_current_label_crit_section(label); + + return error; +} + + +/* + * dgram handled by unix_may_sendmsg, right to send on stream done at connect + * could do per msg unix_stream here, but connect + socket transfer is + * sufficient. This is just here to document this is not needed for af_unix + * + * sendmsg, recvmsg +int aa_unix_msg_perm(const char *op, u32 request, struct socket *sock, + struct msghdr *msg, int size) +{ + return 0; +} +*/ + +int aa_unix_opt_perm(const char *op, u32 request, struct socket *sock, + int level, int optname) +{ + struct aa_profile *profile; + struct aa_label *label; + int error = 0; + + label = begin_current_label_crit_section(); + if (!unconfined(label)) { + DEFINE_AUDIT_SK(ad, op, current_cred(), sock->sk); + + error = fn_for_each_confined(label, profile, + profile_opt_perm(profile, request, sock->sk, + optname, &ad)); + } + end_current_label_crit_section(label); + + return error; +} + +static int unix_peer_perm(const struct cred *subj_cred, + struct aa_label *label, const char *op, u32 request, + struct sock *sk, const struct path *path, + struct sockaddr_un *peer_addr, int peer_addrlen, + const struct path *peer_path, struct aa_label *peer_label) +{ + struct aa_profile *profile; + DEFINE_AUDIT_SK(ad, op, subj_cred, sk); + + ad.net.peer.addr = peer_addr; + ad.net.peer.addrlen = peer_addrlen; + + return fn_for_each_confined(label, profile, + profile_peer_perm(profile, request, sk, path, + peer_addr, peer_addrlen, peer_path, + peer_label, &ad)); +} + +/* + * + * Requires: lock held on both @sk and @peer_sk + * called by unix_stream_connect, unix_may_send + */ +int aa_unix_peer_perm(const struct cred *subj_cred, + struct aa_label *label, const char *op, u32 request, + struct sock *sk, struct sock *peer_sk, + struct aa_label *peer_label) +{ + struct unix_sock *peeru = unix_sk(peer_sk); + struct unix_sock *u = unix_sk(sk); + int plen; + struct sockaddr_un *paddr = aa_sunaddr(unix_sk(peer_sk), &plen); + + AA_BUG(!label); + AA_BUG(!sk); + AA_BUG(!peer_sk); + AA_BUG(!peer_label); + + return unix_peer_perm(subj_cred, label, op, request, sk, + is_unix_fs(sk) ? &u->path : NULL, + paddr, plen, + is_unix_fs(peer_sk) ? &peeru->path : NULL, + peer_label); +} + +/* sk_plabel for comparison only */ +static void update_sk_ctx(struct sock *sk, struct aa_label *label, + struct aa_label *plabel) +{ + struct aa_label *l, *old; + struct aa_sk_ctx *ctx = aa_sock(sk); + bool update_sk; + + rcu_read_lock(); + update_sk = (plabel && + (plabel != rcu_access_pointer(ctx->peer_lastupdate) || + !aa_label_is_subset(plabel, rcu_dereference(ctx->peer)))) || + !__aa_subj_label_is_cached(label, rcu_dereference(ctx->label)); + rcu_read_unlock(); + if (!update_sk) + return; + + spin_lock(&unix_sk(sk)->lock); + old = rcu_dereference_protected(ctx->label, + lockdep_is_held(&unix_sk(sk)->lock)); + l = aa_label_merge(old, label, GFP_ATOMIC); + if (l) { + if (l != old) { + rcu_assign_pointer(ctx->label, l); + aa_put_label(old); + } else + aa_put_label(l); + } + if (plabel && rcu_access_pointer(ctx->peer_lastupdate) != plabel) { + old = rcu_dereference_protected(ctx->peer, lockdep_is_held(&unix_sk(sk)->lock)); + + if (old == plabel) { + rcu_assign_pointer(ctx->peer_lastupdate, + aa_get_label(plabel)); + } else if (aa_label_is_subset(plabel, old)) { + rcu_assign_pointer(ctx->peer_lastupdate, + aa_get_label(plabel)); + rcu_assign_pointer(ctx->peer, aa_get_label(plabel)); + aa_put_label(old); + } /* else race or a subset - don't update */ + } + spin_unlock(&unix_sk(sk)->lock); +} + +static void update_peer_ctx(struct sock *sk, struct aa_sk_ctx *ctx, + struct aa_label *label) +{ + struct aa_label *l, *old; + + spin_lock(&unix_sk(sk)->lock); + old = rcu_dereference_protected(ctx->peer, + lockdep_is_held(&unix_sk(sk)->lock)); + l = aa_label_merge(old, label, GFP_ATOMIC); + if (l) { + if (l != old) { + rcu_assign_pointer(ctx->peer, l); + aa_put_label(old); + } else + aa_put_label(l); + } + spin_unlock(&unix_sk(sk)->lock); +} + +/* This fn is only checked if something has changed in the security + * boundaries. Otherwise cached info off file is sufficient + */ +int aa_unix_file_perm(const struct cred *subj_cred, struct aa_label *label, + const char *op, u32 request, struct file *file) +{ + struct socket *sock = (struct socket *) file->private_data; + struct sockaddr_un *addr, *peer_addr; + int addrlen, peer_addrlen; + struct aa_label *plabel = NULL; + struct sock *peer_sk = NULL; + u32 sk_req = request & ~NET_PEER_MASK; + struct path path; + bool is_sk_fs; + int error = 0; + + AA_BUG(!label); + AA_BUG(!sock); + AA_BUG(!sock->sk); + AA_BUG(sock->sk->sk_family != PF_UNIX); + + /* investigate only using lock via unix_peer_get() + * addr only needs the memory barrier, but need to investigate + * path + */ + unix_state_lock(sock->sk); + peer_sk = unix_peer(sock->sk); + if (peer_sk) + sock_hold(peer_sk); + + is_sk_fs = is_unix_fs(sock->sk); + addr = aa_sunaddr(unix_sk(sock->sk), &addrlen); + path = unix_sk(sock->sk)->path; + unix_state_unlock(sock->sk); + + if (is_sk_fs && peer_sk) + sk_req = request; + if (sk_req) { + error = aa_unix_label_sk_perm(subj_cred, label, op, + sk_req, sock->sk, + is_sk_fs ? &path : NULL); + } + if (!peer_sk) + goto out; + + if (!is_sk_fs) { + bool is_peer_fs = is_unix_fs(peer_sk); + + peer_addr = aa_sunaddr(unix_sk(peer_sk), &peer_addrlen); + if (is_peer_fs) { + struct path peer_path; + + unix_state_lock(peer_sk); + peer_path = unix_sk(peer_sk)->path; + if (peer_path.dentry) + path_get(&peer_path); + unix_state_unlock(peer_sk); + + last_error(error, + unix_fs_perm(op, request, subj_cred, label, + &peer_path)); + if (peer_path.dentry) + path_put(&peer_path); + } else { + struct aa_sk_ctx *pctx = aa_sock(peer_sk); + + rcu_read_lock(); + plabel = aa_get_newest_label(pctx->label); + rcu_read_unlock(); + /* no fs check of aa_unix_peer_perm because conditions + * above ensure they will never be done + */ + last_error(error, + xcheck(unix_peer_perm(subj_cred, label, op, + MAY_READ | MAY_WRITE, sock->sk, + is_sk_fs ? &path : NULL, + peer_addr, peer_addrlen, + NULL, plabel), + unix_peer_perm(file->f_cred, plabel, op, + MAY_READ | MAY_WRITE, peer_sk, + NULL, addr, addrlen, + is_sk_fs ? &path : NULL, + label))); + if (!error && !__aa_subj_label_is_cached(plabel, label)) + update_peer_ctx(peer_sk, pctx, label); + } + } + sock_put(peer_sk); + +out: + + /* update peer cache to latest successful perm check */ + if (error == 0) + update_sk_ctx(sock->sk, label, plabel); + aa_put_label(plabel); + + return error; +} + diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c new file mode 100644 index 000000000..56155d7d5 --- /dev/null +++ b/security/apparmor/apparmorfs.c @@ -0,0 +1,2828 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AppArmor security module + * + * This file contains AppArmor /sys/kernel/security/apparmor interface functions + * + * Copyright (C) 1998-2008 Novell/SUSE + * Copyright 2009-2010 Canonical Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "include/apparmor.h" +#include "include/apparmorfs.h" +#include "include/audit.h" +#include "include/cred.h" +#include "include/crypto.h" +#include "include/ipc.h" +#include "include/label.h" +#include "include/lib.h" +#include "include/policy.h" +#include "include/policy_ns.h" +#include "include/resource.h" +#include "include/policy_unpack.h" +#include "include/task.h" + +/* + * The apparmor filesystem interface used for policy load and introspection + * The interface is split into two main components based on their function + * a securityfs component: + * used for static files that are always available, and which allows + * userspace to specify the location of the security filesystem. + * + * fns and data are prefixed with + * aa_sfs_ + * + * an apparmorfs component: + * used loaded policy content and introspection. It is not part of a + * regular mounted filesystem and is available only through the magic + * policy symlink in the root of the securityfs apparmor/ directory. + * Tasks queries will be magically redirected to the correct portion + * of the policy tree based on their confinement. + * + * fns and data are prefixed with + * aafs_ + * + * The aa_fs_ prefix is used to indicate the fn is used by both the + * securityfs and apparmorfs filesystems. + */ + +#define IREF_POISON 101 + +/* + * support fns + */ + +struct rawdata_f_data { + struct aa_loaddata *loaddata; + DECLARE_FLEX_ARRAY(char, data); +}; + +#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY + +static void rawdata_f_data_free(struct rawdata_f_data *private) +{ + if (!private) + return; + + aa_put_i_loaddata(private->loaddata); + kvfree(private); +} + +static struct rawdata_f_data *rawdata_f_data_alloc(size_t size) +{ + struct rawdata_f_data *ret; + + if (size > SIZE_MAX - sizeof(*ret)) + return ERR_PTR(-EINVAL); + + ret = kvzalloc(sizeof(*ret) + size, GFP_KERNEL); + if (!ret) + return ERR_PTR(-ENOMEM); + + return ret; +} +#endif + +/** + * mangle_name - mangle a profile name to std profile layout form + * @name: profile name to mangle (NOT NULL) + * @target: buffer to store mangled name, same length as @name (MAYBE NULL) + * + * Returns: length of mangled name + */ +static int mangle_name(const char *name, char *target) +{ + char *t = target; + + while (*name == '/' || *name == '.') + name++; + + if (target) { + for (; *name; name++) { + if (*name == '/') + *(t)++ = '.'; + else if (isspace(*name)) + *(t)++ = '_'; + else if (isalnum(*name) || strchr("._-", *name)) + *(t)++ = *name; + } + + *t = 0; + } else { + int len = 0; + for (; *name; name++) { + if (isalnum(*name) || isspace(*name) || + strchr("/._-", *name)) + len++; + } + + return len; + } + + return t - target; +} + + +/* + * aafs - core fns and data for the policy tree + */ + +#define AAFS_NAME "apparmorfs" +static struct vfsmount *aafs_mnt; +static int aafs_count; + + +static int aafs_show_path(struct seq_file *seq, struct dentry *dentry) +{ + seq_printf(seq, "%s:[%llu]", AAFS_NAME, d_inode(dentry)->i_ino); + return 0; +} + +static struct aa_ns *get_ns_common_ref(struct aa_common_ref *ref) +{ + if (ref) { + struct aa_label *reflabel = container_of(ref, struct aa_label, + count); + return aa_get_ns(labels_ns(reflabel)); + } + + return NULL; +} + +static struct aa_proxy *get_proxy_common_ref(struct aa_common_ref *ref) +{ + if (ref) + return aa_get_proxy(container_of(ref, struct aa_proxy, count)); + + return NULL; +} + +#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY +static struct aa_loaddata *get_loaddata_common_ref(struct aa_common_ref *ref) +{ + if (ref) + return aa_get_i_loaddata(container_of(ref, struct aa_loaddata, + count)); + return NULL; +} +#endif + +static void aa_put_common_ref(struct aa_common_ref *ref) +{ + if (!ref) + return; + + switch (ref->reftype) { + case REF_RAWDATA: + aa_put_i_loaddata(container_of(ref, struct aa_loaddata, + count)); + break; + case REF_PROXY: + aa_put_proxy(container_of(ref, struct aa_proxy, + count)); + break; + case REF_NS: + /* ns count is held on its unconfined label */ + aa_put_ns(labels_ns(container_of(ref, struct aa_label, count))); + break; + default: + AA_BUG(true, "unknown refcount type"); + break; + } +} + +static void aa_get_common_ref(struct aa_common_ref *ref) +{ + kref_get(&ref->count); +} + +static void aafs_evict(struct inode *inode) +{ + struct aa_common_ref *ref = inode->i_private; + + clear_inode(inode); + aa_put_common_ref(ref); + inode->i_private = (void *) IREF_POISON; +} + +static void aafs_free_inode(struct inode *inode) +{ + if (S_ISLNK(inode->i_mode)) + kfree(inode->i_link); + free_inode_nonrcu(inode); +} + +static const struct super_operations aafs_super_ops = { + .statfs = simple_statfs, + .evict_inode = aafs_evict, + .free_inode = aafs_free_inode, + .show_path = aafs_show_path, +}; + +static int apparmorfs_fill_super(struct super_block *sb, struct fs_context *fc) +{ + static struct tree_descr files[] = { {""} }; + int error; + + error = simple_fill_super(sb, AAFS_MAGIC, files); + if (error) + return error; + sb->s_op = &aafs_super_ops; + + return 0; +} + +static int apparmorfs_get_tree(struct fs_context *fc) +{ + return get_tree_single(fc, apparmorfs_fill_super); +} + +static const struct fs_context_operations apparmorfs_context_ops = { + .get_tree = apparmorfs_get_tree, +}; + +static int apparmorfs_init_fs_context(struct fs_context *fc) +{ + fc->ops = &apparmorfs_context_ops; + return 0; +} + +static struct file_system_type aafs_ops = { + .owner = THIS_MODULE, + .name = AAFS_NAME, + .init_fs_context = apparmorfs_init_fs_context, + .kill_sb = kill_anon_super, +}; + +/** + * __aafs_setup_d_inode - basic inode setup for apparmorfs + * @dir: parent directory for the dentry + * @dentry: dentry we are setting the inode up for + * @mode: permissions the file should have + * @data: data to store on inode.i_private, available in open() + * @link: if symlink, symlink target string + * @fops: struct file_operations that should be used + * @iops: struct of inode_operations that should be used + */ +static int __aafs_setup_d_inode(struct inode *dir, struct dentry *dentry, + umode_t mode, void *data, char *link, + const struct file_operations *fops, + const struct inode_operations *iops) +{ + struct inode *inode = new_inode(dir->i_sb); + + AA_BUG(!dir); + AA_BUG(!dentry); + + if (!inode) + return -ENOMEM; + + inode->i_ino = get_next_ino(); + inode->i_mode = mode; + simple_inode_init_ts(inode); + inode->i_private = data; + if (S_ISDIR(mode)) { + inode->i_op = iops ? iops : &simple_dir_inode_operations; + inode->i_fop = &simple_dir_operations; + inc_nlink(inode); + inc_nlink(dir); + } else if (S_ISLNK(mode)) { + inode->i_op = iops ? iops : &simple_symlink_inode_operations; + inode->i_link = link; + } else { + inode->i_fop = fops; + } + d_instantiate(dentry, inode); + dget(dentry); + + return 0; +} + +/** + * aafs_create - create a dentry in the apparmorfs filesystem + * + * @name: name of dentry to create + * @mode: permissions the file should have + * @parent: parent directory for this dentry + * @data: data to store on inode.i_private, available in open() + * @link: if symlink, symlink target string + * @fops: struct file_operations that should be used for + * @iops: struct of inode_operations that should be used + * + * This is the basic "create a xxx" function for apparmorfs. + * + * Returns a pointer to a dentry if it succeeds, that must be free with + * aafs_remove(). Will return ERR_PTR on failure. + */ +static struct dentry *aafs_create(const char *name, umode_t mode, + struct dentry *parent, + struct aa_common_ref *data, void *link, + const struct file_operations *fops, + const struct inode_operations *iops) +{ + struct dentry *dentry; + struct inode *dir; + int error; + + AA_BUG(!name); + AA_BUG(!parent); + + if (!(mode & S_IFMT)) + mode = (mode & S_IALLUGO) | S_IFREG; + + error = simple_pin_fs(&aafs_ops, &aafs_mnt, &aafs_count); + if (error) + return ERR_PTR(error); + + dir = d_inode(parent); + + dentry = simple_start_creating(parent, name); + if (IS_ERR(dentry)) { + error = PTR_ERR(dentry); + goto fail; + } + + error = __aafs_setup_d_inode(dir, dentry, mode, data, link, fops, iops); + simple_done_creating(dentry); + if (error) + goto fail; + + if (data) + aa_get_common_ref(data); + + return dentry; + +fail: + simple_release_fs(&aafs_mnt, &aafs_count); + return ERR_PTR(error); +} + +/** + * aafs_create_file - create a file in the apparmorfs filesystem + * + * @name: name of dentry to create + * @mode: permissions the file should have + * @parent: parent directory for this dentry + * @data: data to store on inode.i_private, available in open() + * @fops: struct file_operations that should be used for + * + * see aafs_create + */ +static struct dentry *aafs_create_file(const char *name, umode_t mode, + struct dentry *parent, + struct aa_common_ref *data, + const struct file_operations *fops) +{ + return aafs_create(name, mode, parent, data, NULL, fops, NULL); +} + +/** + * aafs_create_dir - create a directory in the apparmorfs filesystem + * + * @name: name of dentry to create + * @parent: parent directory for this dentry + * + * see aafs_create + */ +static struct dentry *aafs_create_dir(const char *name, struct dentry *parent) +{ + return aafs_create(name, S_IFDIR | 0755, parent, NULL, NULL, NULL, + NULL); +} + +/** + * aafs_remove - removes a file or directory from the apparmorfs filesystem + * + * @dentry: dentry of the file/directory/symlink to removed. + */ +static void aafs_remove(struct dentry *dentry) +{ + struct inode *dir; + + if (!dentry || IS_ERR(dentry)) + return; + + /* ->d_parent is stable as rename is not supported */ + dir = d_inode(dentry->d_parent); + dentry = start_removing_dentry(dentry->d_parent, dentry); + if (!IS_ERR(dentry) && simple_positive(dentry)) { + if (d_is_dir(dentry)) { + if (!WARN_ON(!simple_empty(dentry))) { + __simple_rmdir(dir, dentry); + dput(dentry); + } + } else { + __simple_unlink(dir, dentry); + dput(dentry); + } + d_delete(dentry); + } + end_removing(dentry); + simple_release_fs(&aafs_mnt, &aafs_count); +} + + +/* + * aa_fs - policy load/replace/remove + */ + +/** + * aa_simple_write_to_buffer - common routine for getting policy from user + * @userbuf: user buffer to copy data from (NOT NULL) + * @alloc_size: size of user buffer (REQUIRES: @alloc_size >= @copy_size) + * @copy_size: size of data to copy from user buffer + * @pos: position write is at in the file (NOT NULL) + * + * Returns: kernel buffer containing copy of user buffer data or an + * ERR_PTR on failure. + */ +static struct aa_loaddata *aa_simple_write_to_buffer(const char __user *userbuf, + size_t alloc_size, + size_t copy_size, + loff_t *pos) +{ + struct aa_loaddata *data; + + AA_BUG(copy_size > alloc_size); + + if (*pos != 0) + /* only writes from pos 0, that is complete writes */ + return ERR_PTR(-ESPIPE); + + /* freed by caller to simple_write_to_buffer */ + data = aa_loaddata_alloc(alloc_size); + if (IS_ERR(data)) + return data; + + data->size = copy_size; + if (copy_from_user(data->data, userbuf, copy_size)) { + /* trigger free - don't need to put pcount */ + aa_put_i_loaddata(data); + return ERR_PTR(-EFAULT); + } + + return data; +} + +static ssize_t policy_update(u32 mask, const char __user *buf, size_t size, + loff_t *pos, struct aa_ns *ns, + const struct cred *ocred) +{ + struct aa_loaddata *data; + struct aa_label *label; + ssize_t error; + + label = begin_current_label_crit_section(); + + /* high level check about policy management - fine grained in + * below after unpack + */ + error = aa_may_manage_policy(current_cred(), label, ns, ocred, mask); + if (error) + goto end_section; + + data = aa_simple_write_to_buffer(buf, size, size, pos); + error = PTR_ERR(data); + if (!IS_ERR(data)) { + error = aa_replace_profiles(ns, label, mask, data); + /* put pcount, which will put count and free if no + * profiles referencing it. + */ + aa_put_profile_loaddata(data); + } +end_section: + end_current_label_crit_section(label); + + return error; +} + +/* .load file hook fn to load policy */ +static ssize_t profile_load(struct file *f, const char __user *buf, size_t size, + loff_t *pos) +{ + struct aa_ns *ns = get_ns_common_ref(f->f_inode->i_private); + int error = policy_update(AA_MAY_LOAD_POLICY, buf, size, pos, ns, + f->f_cred); + + aa_put_ns(ns); + + return error; +} + +static const struct file_operations aa_fs_profile_load = { + .write = profile_load, + .llseek = default_llseek, +}; + +/* .replace file hook fn to load and/or replace policy */ +static ssize_t profile_replace(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct aa_ns *ns = get_ns_common_ref(f->f_inode->i_private); + int error = policy_update(AA_MAY_LOAD_POLICY | AA_MAY_REPLACE_POLICY, + buf, size, pos, ns, f->f_cred); + aa_put_ns(ns); + + return error; +} + +static const struct file_operations aa_fs_profile_replace = { + .write = profile_replace, + .llseek = default_llseek, +}; + +/* .remove file hook fn to remove loaded policy */ +static ssize_t profile_remove(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct aa_loaddata *data; + struct aa_label *label; + ssize_t error; + struct aa_ns *ns = get_ns_common_ref(f->f_inode->i_private); + + label = begin_current_label_crit_section(); + /* high level check about policy management - fine grained in + * below after unpack + */ + error = aa_may_manage_policy(current_cred(), label, ns, + f->f_cred, AA_MAY_REMOVE_POLICY); + if (error) + goto out; + + /* + * aa_remove_profile needs a null terminated string so 1 extra + * byte is allocated and the copied data is null terminated. + */ + data = aa_simple_write_to_buffer(buf, size + 1, size, pos); + + error = PTR_ERR(data); + if (!IS_ERR(data)) { + data->data[size] = 0; + error = aa_remove_profiles(ns, label, data->data, size); + aa_put_profile_loaddata(data); + } + out: + end_current_label_crit_section(label); + aa_put_ns(ns); + return error; +} + +static const struct file_operations aa_fs_profile_remove = { + .write = profile_remove, + .llseek = default_llseek, +}; + +struct aa_revision { + struct aa_ns *ns; + long last_read; +}; + +/* revision file hook fn for policy loads */ +static int ns_revision_release(struct inode *inode, struct file *file) +{ + struct aa_revision *rev = file->private_data; + + if (rev) { + aa_put_ns(rev->ns); + kfree(rev); + } + + return 0; +} + +static ssize_t ns_revision_read(struct file *file, char __user *buf, + size_t size, loff_t *ppos) +{ + struct aa_revision *rev = file->private_data; + char buffer[32]; + long last_read; + int avail; + + mutex_lock_nested(&rev->ns->lock, rev->ns->level); + last_read = rev->last_read; + if (last_read == rev->ns->revision) { + mutex_unlock(&rev->ns->lock); + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + if (wait_event_interruptible(rev->ns->wait, + last_read != + READ_ONCE(rev->ns->revision))) + return -ERESTARTSYS; + mutex_lock_nested(&rev->ns->lock, rev->ns->level); + } + + avail = sprintf(buffer, "%ld\n", rev->ns->revision); + if (*ppos + size > avail) { + rev->last_read = rev->ns->revision; + *ppos = 0; + } + mutex_unlock(&rev->ns->lock); + + return simple_read_from_buffer(buf, size, ppos, buffer, avail); +} + +static int ns_revision_open(struct inode *inode, struct file *file) +{ + struct aa_revision *rev = kzalloc_obj(*rev); + + if (!rev) + return -ENOMEM; + + rev->ns = get_ns_common_ref(inode->i_private); + if (!rev->ns) + rev->ns = aa_get_current_ns(); + file->private_data = rev; + + return 0; +} + +static __poll_t ns_revision_poll(struct file *file, poll_table *pt) +{ + struct aa_revision *rev = file->private_data; + __poll_t mask = 0; + + if (rev) { + mutex_lock_nested(&rev->ns->lock, rev->ns->level); + poll_wait(file, &rev->ns->wait, pt); + if (rev->last_read < rev->ns->revision) + mask |= EPOLLIN | EPOLLRDNORM; + mutex_unlock(&rev->ns->lock); + } + + return mask; +} + +void __aa_bump_ns_revision(struct aa_ns *ns) +{ + WRITE_ONCE(ns->revision, READ_ONCE(ns->revision) + 1); + wake_up_interruptible(&ns->wait); +} + +static const struct file_operations aa_fs_ns_revision_fops = { + .owner = THIS_MODULE, + .open = ns_revision_open, + .poll = ns_revision_poll, + .read = ns_revision_read, + .llseek = generic_file_llseek, + .release = ns_revision_release, +}; + +static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms, + const char *match_str, size_t match_len) +{ + struct aa_ruleset *rules = profile->label.rules[0]; + struct aa_perms tmp = { }; + aa_state_t state = DFA_NOMATCH; + + if (profile_unconfined(profile)) + return; + if (rules->file->dfa && *match_str == AA_CLASS_FILE) { + state = aa_dfa_match_len(rules->file->dfa, + rules->file->start[AA_CLASS_FILE], + match_str + 1, match_len - 1); + if (state) { + struct path_cond cond = { }; + + tmp = *(aa_lookup_condperms(current_fsuid(), + rules->file, state, &cond)); + } + } else if (rules->policy->dfa) { + if (!RULE_MEDIATES(rules, *match_str)) + return; /* no change to current perms */ + /* old user space does not correctly detect dbus mediation + * support so we may get dbus policy and requests when + * the abi doesn't support it. This can cause mediation + * regressions, so explicitly test for this situation. + */ + if (*match_str == AA_CLASS_DBUS && + !RULE_MEDIATES_v9NET(rules)) + return; /* no change to current perms */ + state = aa_dfa_match_len(rules->policy->dfa, + rules->policy->start[0], + match_str, match_len); + if (state) + tmp = *aa_lookup_perms(rules->policy, state); + } + aa_apply_modes_to_perms(profile, &tmp); + aa_perms_accum_raw(perms, &tmp); +} + + +/** + * query_data - queries a policy and writes its data to buf + * @buf: the resulting data is stored here (NOT NULL) + * @buf_len: size of buf + * @query: query string used to retrieve data + * @query_len: size of query including second NUL byte + * + * The buffers pointed to by buf and query may overlap. The query buffer is + * parsed before buf is written to. + * + * The query should look like "