Skip to content

R5 AppArmor and SELinux: the LSM framework, permissive and then enforcing #540

Open

Description

@tamnd

Part of #14.

rukernel has no LSM framework. The permission checks are the capability and mode checks of rk_vfs::cred and seccomp. There is no securityfs, no /sys/kernel/security/lsm, no /proc/PID/attr, no lsm_* system call, and no Landlock or Yama. The security.* xattrs can be stored and read. LTP tests that read /sys/kernel/security/lsm take the path for a kernel with no LSM. spec/13-security.md section 13.2 has the scope.

Scope

  • The LSM framework: a table of hooks with the names of include/linux/lsm_hook_defs.h, the security blobs on credentials, inodes, files, tasks, super blocks, sockets and IPC objects, the lsm= boot parameter, and the capability module as the first LSM. Call the hooks at the same places as Linux. Test: all boot tests and LTP syscalls. Exit: no change in the results, and the bench entry rows stay in the noise. Add the LSM framework with the capability module #596, Give the super blocks and the System V IPC objects their security blobs #601: the framework, the blobs and the capability module; -- only lsm passes on x86_64 and arm64.
  • securityfs at /sys/kernel/security with the file lsm, /proc/PID/attr with current, exec and prev and the directory of each module, and the system calls lsm_get_self_attr, lsm_set_self_attr and lsm_list_modules. Add Yama with kernel.yama.ptrace_scope. Test: add lsm to tools/kselftest/build.sh and run lsm_get_self_attr_test, lsm_set_self_attr_test and lsm_list_modules_test. Exit: the three pass, and LTP ptrace* does not change. Add securityfs, the lsm_* system calls and /proc/PID/attr #604, Add Yama with kernel.yama.ptrace_scope, and the lsm kselftests #605: securityfs, /proc/PID/attr, the lsm_* system calls and Yama; the three lsm kselftests pass and LTP ptrace* does not change.
  • AppArmor, complain mode: a port of security/apparmor. The policy load, replace and remove through securityfs, the unpack of the binary policy, the DFA match on paths, the attach of a profile at exec, change_profile and change_hat through /proc/PID/attr, and the audit messages to the kernel log. Test: apparmor_parser loads the profiles of Ubuntu 26.04, and aa-status lists them. Run the AppArmor regression tests (tests/regression/apparmor of the AppArmor project) in complain mode. Exit: the tests that check the load and the attach reach the pass set of the reference. Add the AppArmor module and its securityfs tree #657 Unpack the AppArmor binary policy and keep the profile tree #662 Attach the AppArmor profiles at exec and show the label in /proc/PID/attr #666 Check the open files with the AppArmor file rules #672 Let a task change its AppArmor label with change_hat and change_profile #677 AppArmor namespaces and stacks, and the regression tests in complain mode #693: rukernel passes the 5 load and attach tests and the 198 checks that pass on Linux 6.8 in complain mode.
  • AppArmor, enforce mode: a denial gives EACCES, and the file, capability, network, unix socket, signal, ptrace and user namespace rules work. Test: the AppArmor regression tests, and a new ubuntu boot test that boots Ubuntu 26.04 with AppArmor in enforce mode to multi-user.target. Exit: the regression tests reach the pass set of the reference, and the boot test passes.
  • SELinux, permissive mode: a port of security/selinux. selinuxfs at /sys/fs/selinux, the policy load, the security server and the AVC, the labels in security.selinux on ext4, xfs and tmpfs, the fs_use and genfscon rules, the context= mount options, and the label change at exec. Test: the targeted policy of Fedora 44 loads, getenforce gives Permissive, and ls -Z of the root file system gives the same labels as on the reference. Exit: the boot to multi-user.target logs the same AVC denials as the reference.
  • SELinux, enforcing mode: the network, netlink, IPC and BPF controls, and the netlink notices of policy loads. Test: the selinux-testsuite of the SELinuxProject, and a new fedora boot test that boots Fedora 44 with SELinux in enforcing mode to multi-user.target. Run the systemd TEST-06-SELINUX integration test. Exit: the selinux-testsuite reaches the pass set of the reference, apart from the listed exceptions, and the boot test passes.
  • Audit: the protocol NETLINK_AUDIT with AUDIT_GET, AUDIT_SET, the user messages, and the AVC and AppArmor records, as auditd and journald read them. Test: on the fedora boot test, ausearch -m AVC shows a denial that the test makes. Exit: the record has the same fields as on the reference.

Done when

Ubuntu boots with AppArmor enforcing. Fedora boots with SELinux enforcing. This is the exit of the fifth item of #14.

Test each task on x86_64 and on arm64. Give the result of both in the PR body.

Linux reference: security/security.c, include/linux/lsm_hook_defs.h, security/inode.c, security/lsm_syscalls.c, security/apparmor/policy_unpack.c, security/selinux/hooks.c, security/selinux/ss/services.c, kernel/audit.c.

Activity

  1. added
    kind/featureNew behavior or a new part.
    area/securityLSMs, seccomp, Landlock, capabilities and mitigations.
    on Nov 2, 2026
  2. tamnd commented on Nov 5, 2026

    @tamnd
    OwnerAuthor

    #596 is merged. It adds the LSM framework: the hook table with the names of Linux, the first error of the modules as call_int_hook, the security blobs, the boot order with lsm= and security=, the capability module first, and the hooks of the file, exec, task and socket paths. After the rebase on #594, Cred::capable checks ns_capable in the first user namespace and then calls the capable hooks. Tests: cargo test -p rk-vfs --lib 107 passed, and -- only lsm passed on x86_64 and arm64 (-- only userns also passed on x86_64). Item 1 is ticked after the next PR, which gives the super blocks and the IPC objects their blobs.

  3. tamnd commented on Nov 5, 2026

    @tamnd
    OwnerAuthor

    #601 is merged. The super blocks get their blob in get_tree, and each message queue, semaphore set and shared memory segment has a security part with the alloc, free and associate hooks and the ipc_permission hook after the mode check. Tests: cargo test -p rk-vfs --lib 108 passed, and -- only lsm passed on x86_64 and arm64. Item 1 is now ticked. The next PR adds securityfs, /proc/PID/attr and the lsm_* system calls.

  4. tamnd commented on Nov 5, 2026

    @tamnd
    OwnerAuthor

    #604 is merged. It adds securityfs at /sys/kernel/security with the file lsm, the system calls lsm_get_self_attr, lsm_set_self_attr and lsm_list_modules, and /proc/PID/attr. Tests: the rk-vfs unit tests passed, and -- only lsm passed on x86_64 and arm64. With the LTP, lsm_get_self_attr02, lsm_list_modules01 and lsm_list_modules02 pass. The other three give TCONF until a module gives LSM_ATTR_CURRENT. Item 2 is not ticked yet: the next PR adds Yama and the lsm kselftests.

  5. tamnd commented on Nov 5, 2026

    @tamnd
    OwnerAuthor

    #605 is merged. It adds Yama with kernel.yama.ptrace_scope (0 to 3, and 3 stays) and PR_SET_PTRACER, and it adds the lsm tests to tools/kselftest/build.sh. Tests: lsm_get_self_attr_test 6/6, lsm_list_modules_test 5/5 and lsm_set_self_attr_test 4/4 pass. LTP ptrace01 to ptrace11: 9 pass, and ptrace04 and ptrace07 give TCONF, as in the baseline. -- only lsm passed on x86_64 and arm64. Item 2 is now ticked. The next PR adds NETLINK_AUDIT (item 7, part 1).

  6. tamnd commented on Nov 5, 2026

    @tamnd
    OwnerAuthor

    #613 is merged. It adds NETLINK_AUDIT with AUDIT_GET, AUDIT_SET and the user messages (#540, item 7, part 1). The records go to auditd, or to the kernel log if auditd is not there, and a copy goes to the group AUDIT_NLGRP_READLOG. Tests: cargo test -p rk-net --lib 83 passed, and -- only audit passed on x86_64 (with the bzImage and UEFI) and arm64, with 24 checks. Item 7 is not ticked: the AVC and AppArmor records need the modules, and the fedora test with ausearch -m AVC needs them too.

  7. tamnd commented on Nov 7, 2026

    @tamnd
    OwnerAuthor

    Item 3, part 1 of 5: #657 adds the AppArmor module and its securityfs tree. The module is on with apparmor=1 or when lsm= names it. /sys/kernel/security/apparmor has features/, profiles, revision, .load, .replace, .remove and policy/. A load gives EPROTO for now. Next: the unpack of the binary policy and the profile tree. Item 3 stays open.

  8. tamnd commented on Nov 8, 2026

    @tamnd
    OwnerAuthor

    Item 3, part 2 of 6: #662 unpacks the binary policy of apparmor_parser and keeps the tree of profiles. .load, .replace and .remove change the tree, and profiles and revision show it. The audit records of the changes go to the kernel log, as on Linux. Next: the label of a task, the attach at exec, the learning profiles and /proc/PID/attr. Item 3 stays open.

  9. tamnd commented on Nov 8, 2026

    @tamnd
    OwnerAuthor

    Item 3, part 3 of 6: #666 attaches the profiles at exec. The cred of a task holds its label. A program gets the profile that matches its path, with the conflict check of Linux. The exec rules give the next label, with the ix, px, cx and ux fallbacks. In complain mode, an exec with no rule makes a learning profile PARENT//null-NAME and an ALLOWED record in the kernel log. /proc/PID/attr/current shows the label and the mode. Next: the file hooks with the DFA match of the path. Item 3 stays open.

  10. tamnd commented on Nov 9, 2026

    @tamnd
    OwnerAuthor

    Item 3, part 4 of 6: #672 checks the open files with the file rules of the profiles: an open, a read, a write, an flock and an mmap. The name of a directory ends with /, and an open file keeps the label and the permissions that the rules checked. In complain mode, an operation that the rules do not allow goes on with an ALLOWED record in the kernel log, as on Linux. Next: change_profile and change_hat. Item 3 stays open.

  11. tamnd commented on Nov 9, 2026

    @tamnd
    OwnerAuthor

    Item 3, part 5 of 6: #677 lets a task change its label with changehat, changeprofile and exec in /proc/self/attr and with lsm_set_self_attr. A hat keeps the label before it with a token, and a wrong token kills the task. In complain mode, a missing hat or profile gives a learning profile. The records in the kernel log are as on Linux. Next: the tests of apparmor_parser and aa-status and the regression tests. Item 3 stays open.

  12. tamnd commented on Nov 11, 2026

    @tamnd
    OwnerAuthor

    Item 3, part 6 of 6: #693 adds the child policy namespaces and the stacks of AppArmor, and a fix of the exec hook for a script. With it, apparmor_parser loads the 162 profiles of Ubuntu 26.04, and aa-status lists them with the same modes as on Linux. tools/apparmor runs the AppArmor regression tests in complain mode under QEMU, on rukernel and on Linux 6.8.0-147-generic. The reference passes 5 of the 16 tests of the load and the attach (profiles, at_secure, complain, environ, longpath), with 198 checks. rukernel passes all these tests and checks, so it reaches the pass set of the reference. tools/apparmor/report.md has the results. Item 3 is done.

  13. tamnd commented on Nov 12, 2026

    @tamnd
    OwnerAuthor

    Item 4, part 1: #698 is merged. AppArmor enforces the file and exec rules of a profile in enforce mode. A denial of an open, a read, a write, a lock, a map or an exec gives EACCES and a DENIED record. Complain mode gives an ALLOWED record, kill mode kills the task, and a deny rule denies in each mode. The boot test apparmor passes on x86_64 (load 22.43) and arm64 (load 16.21).

    What remains for item 4: the path hooks, the capability, signal, ptrace, network, user namespace and mount rules (they are ready in the next PRs), the regression tests in enforce mode against the pass set of the reference, and the ubuntu boot test. The item is not ticked.

  14. tamnd commented on Nov 12, 2026

    @tamnd
    OwnerAuthor

    Item 4, part 2: #710 is merged. It adds the path rules of AppArmor. The VFS calls the path hooks of Linux, and an open with O_TRUNC truncates only after the LSM check. The path regression tests and readdir pass, as on Linux 6.8. The item stays open: the other rule classes and the ubuntu boot test come in the next PRs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/securityLSMs, seccomp, Landlock, capabilities and mitigations.kind/featureNew behavior or a new part.

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions