All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matt Bobrowski <mattbobrowski@google.com>
To: Christian Brauner <brauner@kernel.org>
Cc: bpf@vger.kernel.org, Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Andrii Nakryiko <andrii@kernel.org>,
	Martin KaFai Lau <martin.lau@linux.dev>,
	Eduard Zingerman <eddyz87@gmail.com>, Song Liu <song@kernel.org>,
	Yonghong Song <yonghong.song@linux.dev>,
	Jiri Olsa <jolsa@kernel.org>,
	Alexander Viro <viro@zeniv.linux.org.uk>, Jan Kara <jack@suse.cz>,
	Kumar Kartikeya Dwivedi <memxor@gmail.com>
Subject: Re: [PATCH v2 bpf-next 1/2] bpf: enforce VFS constraints for xattr related BPF kfuncs
Date: Mon, 4 May 2026 10:39:36 +0000	[thread overview]
Message-ID: <afh3aEKMctxTg7pL@google.com> (raw)
In-Reply-To: <20260504-anzweifeln-sackkarre-911bc140473f@brauner>

On Mon, May 04, 2026 at 11:42:56AM +0200, Christian Brauner wrote:
> On Mon, May 04, 2026 at 08:54:27AM +0000, Matt Bobrowski wrote:
> > Enforce VFS constraints and semantics regarding name and value lengths
> > within the xattr related BPF kfuncs. Specifically, reject names that
> > are empty or longer than XATTR_NAME_MAX, and values larger than
> > XATTR_SIZE_MAX. Also validate the supplied flags to ensure that only
> > XATTR_CREATE and XATTR_REPLACE can be used alongside the default flag
> > value 0.
> > 
> > Fixes: 56467292794b ("bpf: fs/xattr: Add BPF kfuncs to set and remove xattrs")
> > Closes: https://lore.kernel.org/bpf/20260429221005.6D1C6C19425@smtp.kernel.org/
> > Signed-off-by: Matt Bobrowski <mattbobrowski@google.com>
> > ---
> > Changes in v2:
> >  - New helper bpf_xattr_validate_name() incorporated into pre-existing
> >    BPF kfunc bpf_cgroup_read_xattr() (Sashiko AI).
> > 
> > fs/bpf_fs_kfuncs.c | 85 ++++++++++++++++++++++++++++++++++++++--------
> >  1 file changed, 70 insertions(+), 15 deletions(-)
> > 
> > diff --git a/fs/bpf_fs_kfuncs.c b/fs/bpf_fs_kfuncs.c
> > index 9d27be058494..eb9aef1e135e 100644
> > --- a/fs/bpf_fs_kfuncs.c
> > +++ b/fs/bpf_fs_kfuncs.c
> > @@ -93,6 +93,21 @@ __bpf_kfunc int bpf_path_d_path(const struct path *path, char *buf, size_t buf__
> >  	return len;
> >  }
> >  
> > +static int bpf_xattr_validate_name(const char *name)
> > +{
> > +	u32 name_len;
> > +
> > +	/*
> > +	 * Impose the same restrictions on the supplied name as done so within
> > +	 * the VFS by helpers like import_xattr_name().
> > +	 */
> > +	name_len = strlen(name);
> > +	if (!name_len || name_len > XATTR_NAME_MAX)
> > +		return -ERANGE;
> > +
> > +	return 0;
> > +}
> 
> Can you please unify the check between import_xattr_name() and bpf,
> please. This just asks for someone starting to return different errnos
> from the two locations if we need any additional checks at some point...

I'm glad you suggested this because I was thinking the exact same
thing, although wasn't sure whether you'd be open to it.

> > +
> >  static bool match_security_bpf_prefix(const char *name__str)
> >  {
> >  	return !strncmp(name__str, XATTR_NAME_BPF_LSM, XATTR_NAME_BPF_LSM_LEN);
> > @@ -117,10 +132,10 @@ static int bpf_xattr_read_permission(const char *name, struct inode *inode)
> >   * @name__str: name of the xattr
> >   * @value_p: output buffer of the xattr value
> >   *
> > - * Get xattr *name__str* of *dentry* and store the output in *value_ptr*.
> > + * Get xattr *name__str* of *dentry* and store the output in *value_p*.
> >   *
> > - * For security reasons, only *name__str* with prefixes "user." or
> > - * "security.bpf." are allowed.
> > + * For security reasons, only *name__str* values prefixed with "user." or
> > + * "security.bpf." are permitted.
> >   *
> >   * Return: length of the xattr value on success, a negative value on error.
> >   */
> > @@ -133,6 +148,10 @@ __bpf_kfunc int bpf_get_dentry_xattr(struct dentry *dentry, const char *name__st
> >  	void *value;
> >  	int ret;
> >  
> > +	ret = bpf_xattr_validate_name(name__str);
> > +	if (ret)
> > +		return ret;
> > +
> >  	value_len = __bpf_dynptr_size(value_ptr);
> >  	value = __bpf_dynptr_data_rw(value_ptr, value_len);
> >  	if (!value)
> > @@ -150,10 +169,10 @@ __bpf_kfunc int bpf_get_dentry_xattr(struct dentry *dentry, const char *name__st
> >   * @name__str: name of the xattr
> >   * @value_p: output buffer of the xattr value
> >   *
> > - * Get xattr *name__str* of *file* and store the output in *value_ptr*.
> > + * Get xattr *name__str* of *file* and store the output in *value_p*.
> >   *
> > - * For security reasons, only *name__str* with prefixes "user." or
> > - * "security.bpf." are allowed.
> > + * For security reasons, only *name__str* values prefixed with "user." or
> > + * "security.bpf." are permitted.
> >   *
> >   * Return: length of the xattr value on success, a negative value on error.
> >   */
> > @@ -187,10 +206,18 @@ static int bpf_xattr_write_permission(const char *name, struct inode *inode)
> >   * @value_p: xattr value
> >   * @flags: flags to pass into filesystem operations
> >   *
> > - * Set xattr *name__str* of *dentry* to the value in *value_ptr*.
> > + * Set xattr *name__str* of *dentry* to the value in *value_p*.
> >   *
> > - * For security reasons, only *name__str* with prefix "security.bpf."
> > - * is allowed.
> > + * For security reasons, only *name__str* values prefixed with "security.bpf."
> > + * are permitted.
> > + *
> > + * The length constraints imposed on both the xattr name and value abide those
> > + * that are also enforced by the VFS. Additionally, the flags argument respects
> > + * what's enforced by the VFS in the same way. By default, the flag value of 0
> > + * is permitted and an xattr will be created if it does not exist, or the value
> > + * will be replaced if the xattr already exists. More course grained control
> > + * over these exact semantics is permitted by explicitly specifying either
> > + * XATTR_CREATE or XATTR_REPLACE.
> >   *
> >   * The caller already locked dentry->d_inode.
> >   *
> > @@ -206,7 +233,17 @@ int bpf_set_dentry_xattr_locked(struct dentry *dentry, const char *name__str,
> >  	u32 value_len;
> >  	int ret;
> >  
> > +	if (flags & ~(XATTR_CREATE | XATTR_REPLACE))
> > +		return -EINVAL;
> > +
> > +	ret = bpf_xattr_validate_name(name__str);
> > +	if (ret)
> > +		return ret;
> > +
> >  	value_len = __bpf_dynptr_size(value_ptr);
> > +	if (value_len > XATTR_SIZE_MAX)
> > +		return -E2BIG;
> > +
> 
> Hm, this is also open-coded in fs/xattr.c and here now. I wonder whether
> we can easily build this around the same infra as fs/xattr.c is. So use
> struct kernel_xattr_ctx and struct kname because then all codepaths:
> 
> syscall/internal, io_uring and the bpf interface are the same thing with
> shared helpers and behavior.

At this point, I can't really see why this couldn't be done. I'll try
and introduce a set of shareable helpers which are tasked with
enforcing these constraints uniformly across all of these various
subsystems.

      reply	other threads:[~2026-05-04 10:39 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-04  8:54 [PATCH v2 bpf-next 1/2] bpf: enforce VFS constraints for xattr related BPF kfuncs Matt Bobrowski
2026-05-04  8:54 ` [PATCH v2 bpf-next 2/2] selftests/bpf: add new negative tests " Matt Bobrowski
2026-05-04  9:31 ` [PATCH v2 bpf-next 1/2] bpf: enforce VFS constraints " bot+bpf-ci
2026-05-04  9:37 ` sashiko-bot
2026-05-04  9:42 ` Christian Brauner
2026-05-04 10:39   ` Matt Bobrowski [this message]

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=afh3aEKMctxTg7pL@google.com \
    --to=mattbobrowski@google.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=brauner@kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=jack@suse.cz \
    --cc=jolsa@kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=memxor@gmail.com \
    --cc=song@kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    --cc=yonghong.song@linux.dev \
    /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.