[PATCH v3 1/1] security: Add mechanism to safely (un)load LSMs after boot time

Tetsuo Handa penguin-kernel at I-love.SAKURA.ne.jp
Sun Apr 1 10:37:56 UTC 2018


> +/*
> + * 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.
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the Linux-security-module-archive mailing list