On Mon, Jun 22, 2026 at 7:57 PM Alexei Starovoitov
<[email protected]> wrote:
>
> On Thu Jun 18, 2026 at 1:34 PM PDT, David Windsor wrote:
> > +
> > +static int __bpf_init_inode_xattr(struct xattr_ctx *xattr_ctx,
> > + const char *name__str,
> > + const struct bpf_dynptr *value_p)
> > +{
> > + struct bpf_dynptr_kern *value_ptr = (struct bpf_dynptr_kern *)value_p;
> > + size_t name_len;
> > + void *xattr_value;
> > + struct xattr *xattr;
> > + struct xattr *xattrs;
> > + int *xattr_count;
> > + const void *value;
> > + u32 value_len;
> > +
> > + if (!xattr_ctx || !name__str)
> > + return -EINVAL;
> > +
> > + xattrs = xattr_ctx->xattrs;
> > + xattr_count = xattr_ctx->xattr_count;
> > + if (!xattrs || !xattr_count)
> > + return -EINVAL;
> > + if (bpf_xattrs_used(xattr_ctx) >= BPF_LSM_INODE_INIT_XATTRS)
> > + return -ENOSPC;
>
> This check is good to have, but it's enough. No need to duplicate it.
> More below.
>
> > +
> > static int bpf_fs_kfuncs_filter(const struct bpf_prog *prog, u32 kfunc_id)
> > {
> > if (!btf_id_set8_contains(&bpf_fs_kfunc_set_ids, kfunc_id) ||
> > - prog->type == BPF_PROG_TYPE_LSM)
> > + prog->type == BPF_PROG_TYPE_LSM) {
> > + /* bpf_init_inode_xattr only attaches to inode_init_security.
> > */
> > + if (kfunc_id == bpf_init_inode_xattr_btf_ids[0] &&
> > + prog->aux->attach_btf_id !=
> > bpf_lsm_inode_init_security_btf_ids[0])
> > + return -EACCES;
>
> This is unnecessary. Only one hook will have xattr_ctx type.
> The normal verifier type enforcement will do its work.
>
Good point, thanks.
> > diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
> > index 1a721fc4bef5..b41b02173e24 100644
> > --- a/kernel/bpf/trampoline.c
> > +++ b/kernel/bpf/trampoline.c
> > @@ -859,6 +859,9 @@ static int bpf_trampoline_add_prog(struct
> > bpf_trampoline *tr,
> > }
> > if (cnt >= BPF_MAX_TRAMP_LINKS)
> > return -E2BIG;
> > + if (node->link->prog->aux->attach_limit &&
> > + tr->progs_cnt[kind] >= node->link->prog->aux->attach_limit)
> > + return -E2BIG;
>
> No need. The check inside kfunc is enough.
>
Paul wanted this check because it occurs at bpf prog attach time,
whereas the one in the kfunc is at inode creation time.
> > if (!hlist_unhashed(&node->tramp_hlist))
> > /* prog already linked */
> > return -EBUSY;
> > diff --git a/security/bpf/hooks.c b/security/bpf/hooks.c
> > index 40efde233f3a..d7c44c5c0e30 100644
> > --- a/security/bpf/hooks.c
> > +++ b/security/bpf/hooks.c
> > @@ -30,6 +30,7 @@ static int __init bpf_lsm_init(void)
> >
> > struct lsm_blob_sizes bpf_lsm_blob_sizes __ro_after_init = {
> > .lbs_inode = sizeof(struct bpf_storage_blob),
> > + .lbs_xattr_count = BPF_LSM_INODE_INIT_XATTRS,
> > };
> >
> > DEFINE_LSM(bpf) = {
> > diff --git a/security/integrity/evm/evm_main.c
> > b/security/integrity/evm/evm_main.c
> > index b59e3f121b8a..e0a05162accc 100644
> > --- a/security/integrity/evm/evm_main.c
> > +++ b/security/integrity/evm/evm_main.c
> > @@ -1062,14 +1062,16 @@ static int evm_inode_copy_up_xattr(struct dentry
> > *src, const char *name)
> > * evm_inode_init_security - initializes security.evm HMAC value
> > */
> > int evm_inode_init_security(struct inode *inode, struct inode *dir,
> > - const struct qstr *qstr, struct xattr *xattrs,
> > - int *xattr_count)
> > + const struct qstr *qstr,
> > + struct xattr_ctx *xattr_ctx)
>
> the rest looks good.
> Pls split the patch. Introduce xattr_ctx first across the LSMs.
> Then another patch with a new kfunc.
>
> pw-bot: cr