Messages in this thread | | | Subject | Re: [PATCH v3 1/1] security: Add mechanism to safely (un)load LSMs after boot time | From | Tetsuo Handa <> | Date | Sun, 1 Apr 2018 19:37:56 +0900 |
| |
> +/* > + * With writable hooks, we setup a structure like this: > + * +------+ +-----------+ +-----------+ +-----------+ +--------------+ > + * | | | | | | | | | | > + * | HEAD +---> Immutable +---> Immutable +---> Null hook +---> Mutable Hook | > + * | | | Hook 1 | | Hook 2 | | | | | > + * +------+ +-----------+ +-----------+ +-----------+ +--------------+ > + * | | | > + * v v v > + * Callback Callback Callback > + * > + * The hooks before to null hook are marked only after kernel initialization. > + * The null hook, as well as the hooks succeeding it are not marked read only, > + * therefore allowing them be (un)loaded after initialization time. > + * > + * Since the null hook doesn't have a callback, we need to check if a hook > + * is the null hook prior to invoking it. > + */
Do we need to use null hook as hook == NULL? Why not overwrite null hook's hook field?
#define call_void_hook(FUNC, ...) \ do { \ struct security_hook_list *P; \ int srcu_idx = lock_lsm(); \ for (P = &security_hook_heads.FUNC; P->hook.FUNC; P = P->next) \ P->hook.FUNC(__VA_ARGS__); \ unlock_lsm(srcu_idx); } while (0)
"struct hlist_head security_hook_heads[SECURITY_HOOK_COUNT]" is marked as __ro_after_init. Built-in LSM module's "struct security_hook_list[]" is also marked as __ro_after_init. Dynamic LSM module's "struct security_hook_list[]" is not marked as __initdata.
Hook registration function appends to tail of security_hook_heads.FUNC. But, before __ro_after_init is applied, initial "struct security_hook_list dynamic_hook_list[SECURITY_HOOK_COUNT]" is appended to tail of security_hook_heads. That is, only "struct security_hook_list" at initial dynamic_hook_list[] and later are writable.
Dynamic hook registration function overwrites current dynamic_hook_list[] with supplied dynamic module's "struct security_hook_list[]". Then, dynamic hook registration function allocates memory for next dynamic_hook_list[] and appends to tail of security_hook_heads.FUNC (note that the tail element is writable because it is guaranteed to be initial dynamic_hook_list[] or later.
Before registering first built-in immutable LSM module.
r/w * +------+ * | | * | HEAD + * | | * +------+ * * *
Before registering second built-in immutable LSM module.
r/w r/w * +------+ +-----------+ * | | | | * | HEAD +---> Immutable + * | | | Hook 1 | * +------+ +-----------+ * | * v * Callback
Before registering initial dynamic_hook_list[].
r/w r/w r/w * +------+ +-----------+ +-----------+ * | | | | | | * | HEAD +---> Immutable +---> Immutable + * | | | Hook 1 | | Hook 2 | * +------+ +-----------+ +-----------+ * | | * v v * Callback Callback
After registering initial dynamic_hook_list[] and applying __ro_after_init.
r/o r/o r/o r/w * +------+ +-----------+ +-----------+ +----------------+ * | | | | | | | | * | HEAD +---> Immutable +---> Immutable +---> Hook for first + * | | | Hook 1 | | Hook 2 | | Mutable Module | * +------+ +-----------+ +-----------+ +----------------+ * | | * v v * Callback Callback
After registering first mutable LSM module.
r/o r/o r/o r/w r/w * +------+ +-----------+ +-----------+ +-----------+ +-----------------+ * | | | | | | | | | | * | HEAD +---> Immutable +---> Immutable +---> Mutable +---> Hook for second + * | | | Hook 1 | | Hook 2 | | Hook 1 | | Mutable Module | * +------+ +-----------+ +-----------+ +-----------+ +-----------------+ * | | | * v v v * Callback Callback Callback
After registering second mutable LSM module.
r/o r/o r/o r/w r/w r/w * +------+ +-----------+ +-----------+ +-----------+ +-----------+ +-----------------+ * | | | | | | | | | | | | * | HEAD +---> Immutable +---> Immutable +---> Mutable +---> Mutable +---> Hook for third + * | | | Hook 1 | | Hook 2 | | Hook 1 | | Hook 2 | | Mutable Module | * +------+ +-----------+ +-----------+ +-----------+ +-----------+ +-----------------+ * | | | * v v v * Callback Callback Callback
After protectable memory is accepted, all r/w above except the last one will be marked as r/o by allocating "Hook for X'th Mutable Module" using that allocator.
| |