> +/*
> + * 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.

Reply via email to