From: Christian Brauner <brauner@kernel.org>
To: Song Liu <song@kernel.org>, ast@kernel.org, daniel@iogearbox.net
Cc: bpf@vger.kernel.org, linux-security-module@vger.kernel.org,
linux-fsdevel@vger.kernel.org, fsverity@lists.linux.dev,
ebiggers@kernel.org, andrii@kernel.org, martin.lau@linux.dev,
viro@zeniv.linux.org.uk, casey@schaufler-ca.com,
amir73il@gmail.com, kpsingh@kernel.org, roberto.sassu@huawei.com
Subject: Re: [PATCH v13 bpf-next 1/6] bpf: Add kfunc bpf_get_file_xattr
Date: Mon, 27 Nov 2023 11:50:31 +0100 [thread overview]
Message-ID: <20231127-auffiel-wutentbrannt-7b8b3efb09e4@brauner> (raw)
In-Reply-To: <CAPhsuW7BFzsBv48xgbY4-2xhG1-GazBuQq_pnaUrJqY1q_H27w@mail.gmail.com>
On Fri, Nov 24, 2023 at 09:07:33AM -0800, Song Liu wrote:
> On Fri, Nov 24, 2023 at 12:44 AM Christian Brauner <brauner@kernel.org> wrote:
> >
> > On Thu, Nov 23, 2023 at 03:39:31PM -0800, Song Liu wrote:
> > > It is common practice for security solutions to store tags/labels in
> > > xattrs. To implement similar functionalities in BPF LSM, add new kfunc
> > > bpf_get_file_xattr().
> > >
> > > The first use case of bpf_get_file_xattr() is to implement file
> > > verifications with asymmetric keys. Specificially, security applications
> > > could use fsverity for file hashes and use xattr to store file signatures.
> > > (kfunc for fsverity hash will be added in a separate commit.)
> > >
> > > Currently, only xattrs with "user." prefix can be read with kfunc
> > > bpf_get_file_xattr(). As use cases evolve, we may add a dedicated prefix
> > > for bpf_get_file_xattr().
> > >
> > > To avoid recursion, bpf_get_file_xattr can be only called from LSM hooks.
> > >
> > > Signed-off-by: Song Liu <song@kernel.org>
> > > ---
> >
> > Looks ok to me. But see below for a question.
> >
> > If you ever allow the retrieval of additional extended attributes
> > through bfs_get_file_xattr() or other bpf interfaces we would like to be
> > Cced, please. The xattr stuff is (/me looks for suitable words)...
> >
> > Over the last months we've moved POSIX_ACL retrieval out of these
> > low-level functions. They now have a dedicated api. The same is going to
> > happen for fscaps as well.
> >
> > But even with these out of the way we would want the bpf helpers to
> > always maintain an allowlist of retrievable attributes.
>
> Agreed. We will be very specific which attributes are available to bpf
> helpers/kfuncs.
>
> >
> > > kernel/trace/bpf_trace.c | 63 ++++++++++++++++++++++++++++++++++++++++
> > > 1 file changed, 63 insertions(+)
> > >
> > > diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> > > index f0b8b7c29126..55758a6fbe90 100644
> > > --- a/kernel/trace/bpf_trace.c
> > > +++ b/kernel/trace/bpf_trace.c
> > > @@ -24,6 +24,7 @@
> > > #include <linux/key.h>
> > > #include <linux/verification.h>
> > > #include <linux/namei.h>
> > > +#include <linux/fileattr.h>
> > >
> > > #include <net/bpf_sk_storage.h>
> > >
> > > @@ -1431,6 +1432,68 @@ static int __init bpf_key_sig_kfuncs_init(void)
> > > late_initcall(bpf_key_sig_kfuncs_init);
> > > #endif /* CONFIG_KEYS */
> > >
> > > +/* filesystem kfuncs */
> > > +__bpf_kfunc_start_defs();
> > > +
> > > +/**
> > > + * bpf_get_file_xattr - get xattr of a file
> > > + * @file: file to get xattr from
> > > + * @name__str: name of the xattr
> > > + * @value_ptr: output buffer of the xattr value
> > > + *
> > > + * Get xattr *name__str* of *file* and store the output in *value_ptr*.
> > > + *
> > > + * For security reasons, only *name__str* with prefix "user." is allowed.
> > > + *
> > > + * Return: 0 on success, a negative value on error.
> > > + */
> > > +__bpf_kfunc int bpf_get_file_xattr(struct file *file, const char *name__str,
> > > + struct bpf_dynptr_kern *value_ptr)
> > > +{
> > > + struct dentry *dentry;
> > > + u32 value_len;
> > > + void *value;
> > > +
> > > + if (strncmp(name__str, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
> > > + return -EPERM;
> > > +
> > > + value_len = __bpf_dynptr_size(value_ptr);
> > > + value = __bpf_dynptr_data_rw(value_ptr, value_len);
> > > + if (!value)
> > > + return -EINVAL;
> > > +
> > > + dentry = file_dentry(file);
> > > + return __vfs_getxattr(dentry, dentry->d_inode, name__str, value, value_len);
> >
> > By calling __vfs_getxattr() from bpf_get_file_xattr() you're skipping at
> > least inode_permission() from xattr_permission(). I'm probably just
> > missing or forgot the context. But why is that ok?
>
> AFAICT, the XATTR_USER_PREFIX above is equivalent to the prefix
> check in xattr_permission().
>
> For inode_permission(), I think it is not required because we already
> have the "struct file" of the target file. Did I misunderstand something
> here?
I had overlooked that you don't allow writing xattrs. But there's still
some issues:
So if you look at the system call interface:
fgetxattr(fd)
-> getxattr()
-> do_getxattr()
-> vfs_getxattr()
-> xattr_permission()
-> __vfs_getxattr()
and io_uring:
do_getxattr()
-> vfs_getxattr()
-> xattr_permission()
-> __vfs_getxattr()
you can see that xattr_permission() is a _read/write-time check_, not an
open check. That's because the read/write permissions may depend on what
xattr is read/written. Since you don't know what xattr will be
read/written at open-time.
So there needs to be a good reason for bpf_get_file_xattr() to deviate
from the system call and io_uring interface. And I'd like to hear it,
please. :)
I think I might see the argument because you document the helper as "may
only be called from BPF LSM function" in which case you're trying to say
that bpf_get_file_xattr() is equivalent to a call to __vfs_getxattr()
from an LSM to get at it's own security xattr.
But if that's the case you really should have a way to verify that these
helpers are only callable from a specific BPF context. Because you
otherwise omit read/write-time permission checking when retrieving
xattrs which is a potentialy security issue and may be abused by a BPF
program to skip permission checks that are otherwise enforced.
Is there a way for BPF to enforce/verify that a function is only called
from a specific BPF program? It should be able to recognize that, no?
And then refuse to load that BPF program if a helper is called outside
it's intended context.
next prev parent reply other threads:[~2023-11-27 10:50 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-23 23:39 [PATCH v13 bpf-next 0/6] bpf: File verification with LSM and fsverity Song Liu
2023-11-23 23:39 ` [PATCH v13 bpf-next 1/6] bpf: Add kfunc bpf_get_file_xattr Song Liu
2023-11-24 2:53 ` Song Liu
2023-11-24 8:44 ` Christian Brauner
2023-11-24 17:07 ` Song Liu
2023-11-27 10:50 ` Christian Brauner [this message]
2023-11-27 18:05 ` Song Liu
2023-11-27 21:12 ` Song Liu
2023-11-28 9:13 ` Christian Brauner
2023-11-28 14:19 ` Song Liu
2023-11-28 15:10 ` Christian Brauner
2023-11-23 23:39 ` [PATCH v13 bpf-next 2/6] bpf, fsverity: Add kfunc bpf_get_fsverity_digest Song Liu
2023-11-23 23:39 ` [PATCH v13 bpf-next 3/6] Documentation/bpf: Add documentation for filesystem kfuncs Song Liu
2023-11-23 23:39 ` [PATCH v13 bpf-next 4/6] selftests/bpf: Sort config in alphabetic order Song Liu
2023-11-23 23:39 ` [PATCH v13 bpf-next 5/6] selftests/bpf: Add tests for filesystem kfuncs Song Liu
2023-11-27 2:08 ` Alexei Starovoitov
2023-11-27 17:16 ` Song Liu
2023-11-23 23:39 ` [PATCH v13 bpf-next 6/6] selftests/bpf: Add test that uses fsverity and xattr to sign a file Song Liu
2023-11-24 21:54 ` kernel test robot
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=20231127-auffiel-wutentbrannt-7b8b3efb09e4@brauner \
--to=brauner@kernel.org \
--cc=amir73il@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=casey@schaufler-ca.com \
--cc=daniel@iogearbox.net \
--cc=ebiggers@kernel.org \
--cc=fsverity@lists.linux.dev \
--cc=kpsingh@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=roberto.sassu@huawei.com \
--cc=song@kernel.org \
--cc=viro@zeniv.linux.org.uk \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox