Re: [PATCH bpf-next 4/8] bpf, lsm: Let BPF LSM provide xattrs at inode creation

From: Paul Moore

Date: Wed Sep 23 2026 - 14:13:08 EST


On Tue, Sep 15, 2026 at 11:07 AM Daniel Borkmann <daniel@xxxxxxxxxxxxx> wrote:
>
> From: David Windsor <dwindsor@xxxxxxxxx>
>
> Many in-kernel LSMs (SELinux, Smack, IMA) store security labels in extended
> attributes. For these LSMs, atomic labeling during inode creation is
> critical: if the inode becomes accessible before its xattr is set, it is
> briefly unlabeled, which can disrupt LSMs making policy decisions based
> on file labels. Existing LSMs solve this by setting xattrs in the
> inode_init_security hook, which runs before the inode becomes accessible.
> BPF LSM programs currently lack this capability because the hook uses an
> output parameter (xattr_count) that BPF programs cannot write to, and
> existing kfuncs like bpf_set_dentry_xattr() require a dentry that isn't
> available until after the inode is accessible.
>
> Add a bpf_inode_init_xattr() kfunc that takes the hook's own xattrs and
> xattr_count arguments, passed through from the program's context, and
> claims a slot via lsm_get_xattr_slot() on the program's behalf. The
> xattr_count output argument is exposed to inode_init_security programs
> as trusted read-only memory, so programs can pass it to the kfunc but
> cannot modify the count themselves.
>
> Reserve BPF_LSM_INODE_INIT_XATTRS slots in bpf_lsm_blob_sizes the way
> every other xattr-providing LSM does, for the life of the kernel. The
> framework keys the collection off the reserved slot count, so a kernel
> built with CONFIG_BPF_LSM=y now allocates the xattr array on every inode
> creation, whether or not a program sits on the hook.
>
> Give the hook a strong prototype in bpf_lsm_proto.c so that its qstr and
> xattrs arguments are marked __nullable. Both can be NULL for some callers.
> Without the annotation the verifier otherwise hands the program a trusted
> non-NULL pointer which it dereferences. Also, keep the hook out of the
> sleepable set. inode_init_security runs inside the transaction creating
> the inode, with a journal handle held on ext4 and btrfs and the parent's
> i_rwsem down, which is why everything on the path allocates GFP_NOFS.
>
> Signed-off-by: David Windsor <dwindsor@xxxxxxxxx>
> Co-developed-by: Daniel Borkmann <daniel@xxxxxxxxxxxxx>
> Signed-off-by: Daniel Borkmann <daniel@xxxxxxxxxxxxx>
> ---
> fs/bpf_fs_kfuncs.c | 99 ++++++++++++++++++++++++++++++++++++++
> include/linux/bpf_lsm.h | 11 ++++-
> kernel/bpf/bpf_lsm.c | 22 ++++++++-
> kernel/bpf/bpf_lsm_proto.c | 15 ++++++
> security/bpf/hooks.c | 1 +
> 5 files changed, 145 insertions(+), 3 deletions(-)

@Daniel, you were CC'd on David's previous patches, so I'm guessing
you saw my objection[1], but just in case you hadn't please look at my
comments where I requested that David's proposed LSM kfunc be located
in security/bpf_lsm_kfuncs.c as opposed to fs/bpf_fs_kfuncs.c. It
would be really nice if we could sort this out now and avoid having
this drag out or escalate.

@David, simply for my own understanding, did you ask Daniel to do
this, or was Daniel operating on his own with this patchset?

[1] https://lore.kernel.org/linux-security-module/CAHC9VhTS7rSnBqg00ZxNkcZyh_=EeJmn_4z3CTCCxreEEDtTtg@xxxxxxxxxxxxxx/

--
paul-moore.com