On Tue, Jun 23, 2026 at 8:12 PM Paul Moore <[email protected]> wrote:
>
> I have a few specific comments below, inline with the patch, but I wanted
> to make some general comments too.
>
> The kfunc additions really don't belong in the VFS kfunc file, please
> create a LSM kfunc file (call it security/bpf_lsm_kfuncs.c) and add the
> kfunc code to this new file.
>
Makes sense. I will also do similarly for the selftests.
> While moving the kfunc additions to a LSM kfunc file does sort of convert
> the VFS changes into LSM changes, Christian's comment about splitting
> this patch two patches, one with the LSM hook changes and one with the
> BPF additions, is still reasonable and a good suggestion. I would still
> CC the VFS folks on these patches and I would encourage reviews from the
> VFS folks as there is a VFS component here, albeit a somewhat small one.
>
v4 will contain 3 patches: one to introduce struct lsm_xattrs, next to
introduce the kfunc, and finally the selftests.
> > +
> > +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;
>
> I'm not sure why the "xattrs" and "xattrs_count" local variables are
> necessary, especially since they only appear to be used in the sanity
> check below. I would suggest just using the values in the struct
> directly.
>
Leftover from the previous implementation, will fix.
> > +/**
> > + * bpf_init_inode_xattr - set an xattr on a new inode from
> > inode_init_security
> > + * @xattr_ctx: inode_init_security xattr state from the hook context
> > + * @name__str: xattr name (e.g., "bpf.file_label")
> > + * @value_p: dynptr containing the xattr value
> > + *
> > + * Only callable from lsm/inode_init_security programs.
> > + *
> > + * Return: 0 on success, negative error on failure.
> > + */
> > +__bpf_kfunc int bpf_init_inode_xattr(struct xattr_ctx *xattr_ctx,
> > + const char *name__str,
> > + const struct bpf_dynptr *value_p)
> > +{
> > + return __bpf_init_inode_xattr(xattr_ctx, name__str, value_p);
> > +}
>
> I'm sure there is a reason why you split the code out into
> __bpf_init_inode_xattr() as opposed to just putting it directly in this
> kfunc, can you help me understand?
Not sure, perhaps prior convention, or something with the verifier
perhaps. I've removed it in -v4 and everything works.
> > diff --git a/include/linux/security.h b/include/linux/security.h
> > index 153e9043058f..1f8e84e7dd7e 100644
> > --- a/include/linux/security.h
> > +++ b/include/linux/security.h
> > @@ -68,6 +68,11 @@ struct watch;
> > struct watch_notification;
> > struct lsm_ctx;
> >
> > +struct xattr_ctx {
> > + struct xattr *xattrs;
> > + int *xattr_count;
> > +};
>
> I see the bots already pointed this out, and you acknowledged it, but
> since I'm looking at this I felt obliged to remind you once again about
> the rename to "struct lsm_xattrs" :)
>
Yeah, sorry about that. =)
> Also, looking at this closer, is there a reason why the "xattr_count"
> field is an integer pointer and not just an integer? We're passing
> the entire struct by reference to the individual LSMs so we shouldn't
> need this to get an updated count in the caller and having it as a
> regular integer should simplify things slightly (you could also
> make it an unsigned int while you are it).
>
Copy/paste from v2. Will change xattr_count's type to unsigned int.
> > --- 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;
>
> Re: Alexei's comments about this - if you look back at my previous
> comments, my concern was around BPF LSMs using too many slots in the
> xattr array and causing issues. If the BPF folks want to do that check
> in the kfunc located in the LSM framework I'm okay with that; the
> important part is that the BPF LSMs don't use more space than they
> previously requested.
>
Ack, will remove this attach-time check.
> > diff --git a/security/security.c b/security/security.c
> > index 71aea8fdf014..8f82a1352356 100644
> > --- a/security/security.c
> > +++ b/security/security.c
> > @@ -1334,6 +1334,7 @@ int security_inode_init_security(struct inode *inode,
> > struct inode *dir,
> > {
> > struct lsm_static_call *scall;
> > struct xattr *new_xattrs = NULL;
> > + struct xattr_ctx xattr_ctx;
> > int ret = -EOPNOTSUPP, xattr_count = 0;
>
> Since we have the xattr array/pointer and count in the new "lsm_xattrs"
> struct, I think we can remove the "new_xattrs" and "xattr_count" local
> variables in favor of the fields in the new struct.
>
Thanks! These will be eliminated in v4.
Best,
David