On Thu, Sep 28, 2023 at 10:24:09PM +0200, KP Singh wrote: SNIP > diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c > index e97aeda3a86b..df9699bce372 100644 > --- a/kernel/bpf/trampoline.c > +++ b/kernel/bpf/trampoline.c > @@ -13,6 +13,7 @@ > #include <linux/bpf_verifier.h> > #include <linux/bpf_lsm.h> > #include <linux/delay.h> > +#include <linux/bpf_lsm.h> > > /* dummy _ops. The verifier will operate on target program's ops. */ > const struct bpf_verifier_ops bpf_extension_verifier_ops = { > @@ -514,7 +515,7 @@ static int __bpf_trampoline_link_prog(struct bpf_tramp_link *link, struct bpf_tr > { > enum bpf_tramp_prog_type kind; > struct bpf_tramp_link *link_exiting; > - int err = 0; > + int err = 0, num_lsm_progs = 0; > int cnt = 0, i; > > kind = bpf_attach_type_to_tramp(link->link.prog); > @@ -545,8 +546,14 @@ static int __bpf_trampoline_link_prog(struct bpf_tramp_link *link, struct bpf_tr > continue; > /* prog already linked */ > return -EBUSY; > + > + if (link_exiting->link.prog->type == BPF_PROG_TYPE_LSM) > + num_lsm_progs++; this looks wrong, it's never reached.. seems like we should add separate hlist_for_each_entry loop over trampoline's links for this check/init of num_lsm_progs ? jirka > } > > + if (!num_lsm_progs && link->link.prog->type == BPF_PROG_TYPE_LSM) > + bpf_lsm_toggle_hook(tr->func.addr, true); > + > hlist_add_head(&link->tramp_hlist, &tr->progs_hlist[kind]); > tr->progs_cnt[kind]++; > err = bpf_trampoline_update(tr, true /* lock_direct_mutex */); > @@ -569,8 +576,10 @@ int bpf_trampoline_link_prog(struct bpf_tramp_link *link, struct bpf_trampoline > > static int __bpf_trampoline_unlink_prog(struct bpf_tramp_link *link, struct bpf_trampoline *tr) > { > + struct bpf_tramp_link *link_exiting; > enum bpf_tramp_prog_type kind; > - int err; > + bool lsm_link_found = false; > + int err, num_lsm_progs = 0; > > kind = bpf_attach_type_to_tramp(link->link.prog); > if (kind == BPF_TRAMP_REPLACE) { > @@ -580,8 +589,24 @@ static int __bpf_trampoline_unlink_prog(struct bpf_tramp_link *link, struct bpf_ > tr->extension_prog = NULL; > return err; > } > + > + if (link->link.prog->type == BPF_PROG_TYPE_LSM) { > + hlist_for_each_entry(link_exiting, &tr->progs_hlist[kind], > + tramp_hlist) { > + if (link_exiting->link.prog->type == BPF_PROG_TYPE_LSM) > + num_lsm_progs++; > + > + if (link_exiting->link.prog == link->link.prog) > + lsm_link_found = true; > + } > + } > + > hlist_del_init(&link->tramp_hlist); > tr->progs_cnt[kind]--; > + > + if (lsm_link_found && num_lsm_progs == 1) > + bpf_lsm_toggle_hook(tr->func.addr, false); > + > return bpf_trampoline_update(tr, true /* lock_direct_mutex */); > } > > diff --git a/security/bpf/hooks.c b/security/bpf/hooks.c > index cfaf1d0e6a5f..1957244196d0 100644 > --- a/security/bpf/hooks.c > +++ b/security/bpf/hooks.c > @@ -8,7 +8,7 @@ > > static struct security_hook_list bpf_lsm_hooks[] __ro_after_init = { > #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ > - LSM_HOOK_INIT(NAME, bpf_lsm_##NAME), > + LSM_HOOK_INIT_DISABLED(NAME, bpf_lsm_##NAME), > #include <linux/lsm_hook_defs.h> > #undef LSM_HOOK > LSM_HOOK_INIT(inode_free_security, bpf_inode_storage_free), > @@ -32,3 +32,26 @@ DEFINE_LSM(bpf) = { > .init = bpf_lsm_init, > .blobs = &bpf_lsm_blob_sizes > }; > + > +void bpf_lsm_toggle_hook(void *addr, bool value) > +{ > + struct lsm_static_call *scalls; > + struct security_hook_list *h; > + int i, j; > + > + for (i = 0; i < ARRAY_SIZE(bpf_lsm_hooks); i++) { > + h = &bpf_lsm_hooks[i]; > + scalls = h->scalls; > + if (h->hook.lsm_callback == addr) > + continue; > + > + for (j = 0; j < MAX_LSM_COUNT; j++) { > + if (scalls[j].hl != h) > + continue; > + if (value) > + static_branch_enable(scalls[j].active); > + else > + static_branch_disable(scalls[j].active); > + } > + } > +} > diff --git a/security/security.c b/security/security.c > index c2c2cf6b711f..d1ee72e563cc 100644 > --- a/security/security.c > +++ b/security/security.c > @@ -382,7 +382,8 @@ static void __init lsm_static_call_init(struct security_hook_list *hl) > __static_call_update(scall->key, scall->trampoline, > hl->hook.lsm_callback); > scall->hl = hl; > - static_branch_enable(scall->active); > + if (hl->default_state) > + static_branch_enable(scall->active); > return; > } > scall++; > -- > 2.42.0.582.g8ccd20d70d-goog > >