Linux 6.8 Merge Window

Linux v6.7 was released this past Sunday, with the Linux v6.8 merge window opening immediately afterwards. Recently I’ve started writing up the highlights of the SELinux and audit pull requests sent to Linus, but starting with the Linux v6.8 merge window I’m also going to start including the Linux Security Module (LSM) layer highlights. I’m including the LSM in these summaries because with the start of Linux v6.8 the LSM layer itself is taking a step forward in terms of user visibility and I want users, administrators, developers, and distros to be aware of changes that could impact their systems.

With all that out of the way, here are the highlights of the LSM, SELinux, and audit pull requests which Linus has merged into his tree.

UPDATE: The week of March 11, 2024, the week Linux v6.8 was released, we became aware of an incompatibility issue with the new LSM syscalls on 32-bit systems and changed the size_t parameter types to u32 to avoid problems. The syscall signatures below have been updated to reflect this change.

LSM

  • Add three new syscalls and a new kernel API structure, a first for the LSM layer. The new kernel API structure, struct lsm_ctx, is used to communicate LSM contexts across the kernel/userspace boundary.
    struct lsm_ctx {
      u64 id;
      u64 flags;
      u64 len;
      u64 ctx_len;
      u64 ctx[];
    };
    

    The id field is set to the associated LSM’s ID value (the kernel headers define a number of LSM_ID_XXX pre-processor macros for LSM IDs), the flags field is a LSM specific bitmap field that is only interpreted by the associated LSM, the len field is the total length of the structure including the trailing ctx field and any padding, the ctx_len field is the length of ctx, and the ctx field contains the LSM context. If the LSM context is a string, it should be NUL terminated.

    The first syscall, lsm_list_modules(2), returns the number of LSMs enabled in the running kernel.

    int lsm_list_modules(u64 *ids, u32 size, u32 flags);
    

    The id parameter points to an array of LSM IDs, the size parameter is set to the maximum size of the id array in bytes when invoked and on return it is set to the size of the populated id array in bytes, the flags parameter is currently unused and must be set to zero. The syscall returns zero on success and negative error codes on failure; if -E2BIG is returned the id parameter is not large enough, see the size parameter for the minimum required size.

    The second syscall, lsm_get_self_attr(2), returns the current running task’s LSM attributes from all of the enabled LSMs.

    int lsm_get_self_attr(unsigned int attr, struct lsm_ctx *ctx, u32 size, u32 flags);
    

    The attr parameter is set to the LSM attribute being requested (the kernel headers define a number of LSM_ATTR_XXX pre-processor macros for LSM attributes), the ctx parameter points to an array of lsm_ctx structures, the size parameter is set to the maximum size of the ctx array in bytes when invoked and on return it is set to the size of the populated ctx array in bytes, the flags parameter can be set to zero or LSM_FLAG_SINGLE. If flags is set to LSM_FLAG_SINGLE then only a single LSM, as specified in the ctx[0]::id field, is queried for the attribute in attr. The syscall returns the number of LSM contexts in ctx, with zero indicating no contexts are available, and negative error codes on failure; if -E2BIG is returned the ctx parameter is not large enough, see the size parameter for the minimum required size.

    The third syscall, lsm_set_self_attr(2), sets a LSM attribute in the current running task.

    int lsm_set_self_attr(unsigned int attr, struct lsm_ctx *ctx, u32 size, u32 flags);
    

    The attr parameter is set to the LSM attribute being set (the kernel headers define a number of LSM_ATTR_XXX pre-processor macros for LSM attributes), the ctx parameter points to an lsm_ctx structure, the size parameter is set to the size of the ctx structure in bytes, the flags parameter is currently unused and must be set to zero. The syscall returns zero on success, negative error codes on failure.

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

  • Add an explicit entry in the MAINTAINERS file for the Lockdown LSM. The Lockdown LSM does not currently have a dedicated maintainer, but I will continue to maintain it on an as-needed basis until an appropriate volunteer steps forward to serve as a dedicated maintainer.

  • While not strictly LSM related, the Linux v6.8 LSM pull request did also include a small fix to the CALIPSO code that resolves a memory leak which could occur when disabling IPv6 on the kernel command line and attempting to configure CALIPSO, an IPv6 labeling protocol.

SELinux

  • Drop Eric Paris as a SELinux maintainer. Eric is an important part of SELinux history and I’m thankful not only for his stint as maintainer, but his numerous contributions over the years. Unfortunately, Eric has moved on to other things and hasn’t contributed to the SELinux community in several years (his last SELinux kernel commit was in 2013) making it time to officially drop Eric as a maintainer.

  • Added Ondrej Mosnacek as an official SELinux kernel subsystem reviewer. Ondrej has a long history of providing quality SELinux kernel patches and I’m looking forward to his help as an official reviewer.

  • Add a new SELinux initial SID, “init”, to represent userspace processes started before the SELinux policy is loaded in early boot. Prior to this all processes were marked with the “kernel” initial SID before the SELinux policy was loaded, making it difficult to distinguish early boot userspace processes from the kernel in the SELinux policy. For most users this will be a non-issue as the policy is loaded early enough during boot, but for users who load their SELinux policy relatively late, this should make it easier to construct meaningful security policies.

  • Internal improvements to the SELinux management filesystem, selinuxfs, that is mounted at “/sys/fs/selinux” on SELinux enabled systems. In addition to locking changes, there is a minor change in how the selinuxfs “boolean” and “class” directories are managed during a policy reload. With this change a new directory, “.swapover”, is created to temporarily contain the new “boolean” and “class” directories while they are being built. Once the new policy directories are fully populated they are swapped with the existing policy directories and the old directories are cleaned up. The “.swapover” directory, is not accessible by even privileged users on the system.

  • Fix an issue where the input sanity checking on socket bind(2) operations was slightly different depending on the presence of SELinux. This is caused by the placement of the LSM hooks in the generic socket layer as opposed to the protocol specific handler where the protocol specific sanity checks are performed.

  • Consolidate multiple open coded SELinux access vector comparisons into a single new helper function and use that instead. While this should not change the behavior of the code, it is an improvement to both the code quality and maintainability.

  • Apply the Linux kernel coding style to the SELinux kernel header files in the “security/selinux/include” directory. In the future I expect to introduce code verification tools to help developers improve initial code quality, and an important part of that is ensuring that the existing sources meets a minimum quality standard. This is a work in progress, with many files still in need of style fixes.

  • Minor improvements to the hashing function used in the filename transition code.

  • Minor fixes to synchronize function prototypes with the function definition.

  • Remove old and outdated source code comments.

Audit

  • Rework the audit command acknowledgement code in the kernel to allow for more immediate acknowledgments of audit daemon registrations. This should help improve responsiveness and reliability on heavily loaded systems with large audit backlogs.

Linux 6.7 Released

Linux v6.7 was released on Sunday, January 7th. I already wrote up a post highlighting the SELinux and audit changes that were submitted during the merge window, however there were additional changes that went in during the release candidate process which are described below.

SELinux

  • Minor changes to the SELinux credential code as part of the larger effort to remove CONFIG_DEBUG_CREDENTIALS. This should have little to no effect on SELinux.

Audit

  • Remove a WARN_ON_ONCE() based warning in the audit exe filter code as it was causing a lot of scary looking, but harmless, warnings on the console when exe filtering was used in conjunction with some eBPF programs.

In addition to my highlights, LWN.net provides a nice overall summary of the kernel changes made during the first and second weeks of the merge window.

Linux 6.7 Merge Window

Linux v6.6 was released this past Monday, with the Linux v6.7 merge window opening immediately afterwards. Below are the highlights of the SELinux and audit pull requests which Linus has merged into his tree.

SELinux

  • The CONFIG_SECURITY_SELINUX_DEBUG Kconfig option introduced in Linux v6.6 was enhanced to enable the SELinux debugging messages on the console by default. Those users who wish to have greater control over the SELinux debugging messages should enable Dynamic Debug.

  • A number of SELinux internal hash table related improvements were made in this kernel release. The role transition table moved to using the Jenkins hash hash function, the access vector tables allocation function was simplified, and the hash bucket sizes are now printed along with the other hash table statistics when SELinux debugging is enabled.

  • Annotate an internal data structure with a flexible array member to specify which field is used to indicate the length of the variable length field. This enables the kernel’s UBSAN and CONFIG_FORTIFY_SOURCE runtime analysis tools to perform memory bounds checking on the variable length fields.

  • SELinux policy load times were improved slightly thanks to the use of an optimized Hamming weight function when reading access vector fields in the policy.

Audit

  • Similar to SELinux, an internal data structure with a flexible array member was annotated to enable runtime bounds checking.