Search code examples
linuxkernellinux-security-module

Can non-exclusive (stackable) Linux Security Modules use security blobs?


I'm experimenting with Linux Security Modules, trying to make one.

My main source of knowledge about how they're supposed to work are mailing lists archives and the existing LSMs' sources, plus the few pages about them in the Linux documentation.

I understand that there are two kinds of LSMs.

  • Exclusive LSMs like SELinux / AppArmor, which have the LSM_FLAG_EXCLUSIVE flag set in their LSM definition.
  • Non-exclusive LSMs like Yama, capabilities or lockdown.

Browsing the source code of all these LSMs, I figured out non-exclusive ones never make use of security blobs. On the other hand, exclusive ones make heavy use of them.

For instance, see the AppArmor LSM definition, and the one for Yama.

So, can non-exclusive LSMs specify blob sizes and use this feature ?

Trying to find an answer, I explored the framework's source to see if maybe security blobs were switched between each LSM hook call, I guess that would allow each LSM to only have access to its own blobs and not those of another LSM.

However, we can see here in the LSM framework that it is not the case.

If my LSM declares blob sizes, can I use the blobs if my kernel also have SELinux, for instance, enabled ? Won't the structures from SELinux and mine overlap ?


Solution

  • Alright, I found the relevant code in the LSM framework.

    QED: Yes, all LSMs can use security blobs as long as they use the sizes structure as containing offsets once the module is ignited.

    Explanation:

    When you define your LSM, you use the DEFINE_LSM macro followed by various informations, including a pointer to a struct lsm_blobs_sizes.

    During its own ignition, the LSM framework (which is mostly implemented in security/security.c) manipulates your structure in a few operations.

    • It stores, in its own instance of the structure (declared here), the sum of all LSM's security blobs sizes. Precisely, looking at this stack trace:
    ordered_lsm_init()
    `- prepare_lsm(*lsm)
       `- lsm_set_blob_sizes(lsm->blobs)
          `- lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
    

    lsm_set_blob_size is responsible for the actual addition to the framework's structure instance.

    • However, combined with lsm_set_blob_sizes, it effectively replaces each size in the currently prepared LSM's struct lsm_blob_sizes with the offset at which this LSM's part of the blob resides.

    • The framework then calls their init function.

    • Later, when any structure with a security blob (a task_struct for instance) gets allocated, the framework will allocate one blob with enough space for the blobs of all security modules, which in turn will find their spot in this larger blob using the offsets in their own lsm_blobs_sizes.

    The summed-up sizes of security blobs is actually meant to be controlled using init_debug, here.

    So what this means is that all LSMs can define security blobs sizes. The framework is responsible for their allocation (and deallocation) and the blobs for different LSMs can happily live side by side in memory.