From: Kees Cook <keescook@chromium.org>
To: KP Singh <kpsingh@kernel.org>
Cc: Paul Moore <paul@paul-moore.com>,
linux-security-module@vger.kernel.org, bpf@vger.kernel.org,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
jackmanb@google.com, renauld@google.com, casey@schaufler-ca.com,
song@kernel.org, revest@chromium.org
Subject: Re: [PATCH bpf-next v10 5/5] bpf: Only enable BPF LSM hooks when an LSM program is attached
Date: Wed, 8 May 2024 00:48:20 -0700 [thread overview]
Message-ID: <202405080045.6D38296@keescook> (raw)
In-Reply-To: <0E524496-74E4-4419-8FE5-7675BD1834C0@kernel.org>
On Wed, May 08, 2024 at 09:00:42AM +0200, KP Singh wrote:
>
>
> > On 8 May 2024, at 03:45, Paul Moore <paul@paul-moore.com> wrote:
> >
> > On Tue, May 7, 2024 at 8:01 PM Kees Cook <keescook@chromium.org> wrote:
> >>
> >> On Wed, May 08, 2024 at 12:10:45AM +0200, KP Singh wrote:
> >>> [...]
> >>> +/**
> >>> + * security_toggle_hook - Toggle the state of the LSM hook.
> >>> + * @hook_addr: The address of the hook to be toggled.
> >>> + * @state: Whether to enable for disable the hook.
> >>> + *
> >>> + * Returns 0 on success, -EINVAL if the address is not found.
> >>> + */
> >>> +int security_toggle_hook(void *hook_addr, bool state)
> >>> +{
> >>> + struct lsm_static_call *scalls = ((void *)&static_calls_table);
> >>> + unsigned long num_entries =
> >>> + (sizeof(static_calls_table) / sizeof(struct lsm_static_call));
> >>> + int i;
> >>> +
> >>> + for (i = 0; i < num_entries; i++) {
> >>> + if (!scalls[i].hl)
> >>> + continue;
> >>> +
> >>> + if (scalls[i].hl->hook.lsm_func_addr != hook_addr)
> >>> + continue;
> >>> +
> >>> + if (state)
> >>> + static_branch_enable(scalls[i].active);
> >>> + else
> >>> + static_branch_disable(scalls[i].active);
> >>> + return 0;
> >>> + }
> >>> + return -EINVAL;
> >>> +}
> >>
> >> First of all: patches 1-4 are great. They have a measurable performance
> >> benefit; let's get those in.
> >>
> >> But here I come to patch 5 where I will suggest the exact opposite of
> >> what Paul said in v9 for patch 5. :P
> >
> > For those looking up v9 of the patchset, you'll be looking for patch
> > *4*, not patch 5, as there were only four patches in the v9 series.
> > Patch 4/5 in the v10 series is a new addition to the stack.
> >
> > Beyond that, I'm guessing you are referring to my comment regarding
> > bpf_lsm_toggle_hook() Kees? The one that starts with "More ugh. If
> > we are going to solve things this way ..."?
> >
> >> I don't want to have a global function that can be used to disable LSMs.
> >> We got an entire distro (RedHat) to change their SELinux configurations
> >> to get rid of CONFIG_SECURITY_SELINUX_DISABLE (and therefore
> >> CONFIG_SECURITY_WRITABLE_HOOKS), via commit f22f9aaf6c3d ("selinux:
> >> remove the runtime disable functionality"). We cannot reintroduce that,
> >> and I'm hoping Paul will agree, given this reminder of LSM history. :)
> >>
> >> Run-time hook changing should be BPF_LSM specific, if it exists at all.
>
>
> One idea here is that only LSM hooks with default_state = false can be toggled.
>
> This would also any ROPs that try to abuse this function. Maybe we can call "default_disabled" .toggleable (or dynamic)
>
> and change the corresponding LSM_INIT_TOGGLEABLE. Kees, Paul, this may be a fair middle ground?
>
> Something like:
>
> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index 4bd1d47bb9dc..5c0918ed6b80 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -117,7 +117,7 @@ struct security_hook_list {
> struct lsm_static_call *scalls;
> union security_list_options hook;
> const struct lsm_id *lsmid;
> - bool default_enabled;
> + bool toggleable;
> } __randomize_layout;
>
> /*
> @@ -168,14 +168,18 @@ static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs,
> { \
> .scalls = static_calls_table.NAME, \
> .hook = { .NAME = HOOK }, \
> - .default_enabled = true \
> + .toggleable = false \
> }
>
> -#define LSM_HOOK_INIT_DISABLED(NAME, HOOK) \
> +/*
> + * Toggleable LSM hooks are enabled at runtime with
> + * security_toggle_hook and are initialized as inactive.
> + */
> +#define LSM_HOOK_INIT_TOGGLEABLE(NAME, HOOK) \
> { \
> .scalls = static_calls_table.NAME, \
> .hook = { .NAME = HOOK }, \
> - .default_enabled = false \
> + .toggleable = true \
> }
>
> extern char *lsm_names;
> diff --git a/security/bpf/hooks.c b/security/bpf/hooks.c
> index ed864f7430a3..ba1c3a19fb12 100644
> --- a/security/bpf/hooks.c
> +++ b/security/bpf/hooks.c
> @@ -9,7 +9,7 @@
>
> static struct security_hook_list bpf_lsm_hooks[] __ro_after_init = {
> #define LSM_HOOK(RET, DEFAULT, NAME, ...) \
> - LSM_HOOK_INIT_DISABLED(NAME, bpf_lsm_##NAME),
> + LSM_HOOK_INIT_TOGGLEABLE(NAME, bpf_lsm_##NAME),
> #include <linux/lsm_hook_defs.h>
> #undef LSM_HOOK
> LSM_HOOK_INIT(inode_free_security, bpf_inode_storage_free),
> diff --git a/security/security.c b/security/security.c
> index b3a92a67f325..a89eb8fe302b 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -407,7 +407,8 @@ static void __init lsm_static_call_init(struct security_hook_list *hl)
> __static_call_update(scall->key, scall->trampoline,
> hl->hook.lsm_func_addr);
> scall->hl = hl;
> - if (hl->default_enabled)
> + /* Toggleable hooks are inactive by default */
> + if (!hl->toggleable)
> static_branch_enable(scall->active);
> return;
> }
> @@ -901,6 +902,9 @@ int security_toggle_hook(void *hook_addr, bool state)
> int i;
>
> for (i = 0; i < num_entries; i++) {
> + if (!scalls[i].hl->toggleable)
> + continue;
> +
> if (!scalls[i].hl)
> continue;
Yeah, I like this! It's a routine that is walking read-only data to make
the choice, and it's specific to a pre-defined characteristic that an
LSM would need to opt into. My concerns are addressed! Thanks! :)
--
Kees Cook
next prev parent reply other threads:[~2024-05-08 7:48 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-07 22:10 [PATCH bpf-next v10 0/5] Reduce overhead of LSMs with static calls KP Singh
2024-05-07 22:10 ` [PATCH bpf-next v10 1/5] kernel: Add helper macros for loop unrolling KP Singh
2024-05-07 22:10 ` [PATCH bpf-next v10 2/5] security: Count the LSMs enabled at compile time KP Singh
2024-05-07 22:10 ` [PATCH bpf-next v10 3/5] security: Replace indirect LSM hook calls with static calls KP Singh
2024-05-07 22:10 ` [PATCH bpf-next v10 4/5] security: Update non standard hooks to use " KP Singh
2024-05-07 22:10 ` [PATCH bpf-next v10 5/5] bpf: Only enable BPF LSM hooks when an LSM program is attached KP Singh
2024-05-08 0:01 ` Kees Cook
2024-05-08 1:45 ` Paul Moore
2024-05-08 2:35 ` Kees Cook
2024-05-09 20:08 ` Paul Moore
2024-05-08 7:00 ` KP Singh
2024-05-08 7:48 ` Kees Cook [this message]
2024-05-09 20:24 ` Paul Moore
2024-05-10 13:23 ` KP Singh
2024-05-15 16:08 ` KP Singh
2024-05-15 16:44 ` KP Singh
2024-05-15 16:57 ` Casey Schaufler
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=202405080045.6D38296@keescook \
--to=keescook@chromium.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=casey@schaufler-ca.com \
--cc=daniel@iogearbox.net \
--cc=jackmanb@google.com \
--cc=kpsingh@kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=paul@paul-moore.com \
--cc=renauld@google.com \
--cc=revest@chromium.org \
--cc=song@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.