linux-security-module.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Christian Brauner <brauner@kernel.org>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: Andrii Nakryiko <andrii@kernel.org>,
	bpf@vger.kernel.org, netdev@vger.kernel.org,
	linux-fsdevel@vger.kernel.org,
	linux-security-module@vger.kernel.org, keescook@chromium.org,
	lennart@poettering.net, kernel-team@meta.com, sargun@sargun.me
Subject: Re: [PATCH v5 bpf-next 03/13] bpf: introduce BPF token object
Date: Wed, 27 Sep 2023 11:52:27 +0200	[thread overview]
Message-ID: <20230927-kaution-ventilator-33a41ee74d63@brauner> (raw)
In-Reply-To: <CAEf4BzaH64kkccc1P-hqQj6Mccr3Q6x059G=A95d=KfU=yBMJQ@mail.gmail.com>

> > > +#define BPF_TOKEN_INODE_NAME "bpf-token"
> > > +
> > > +/* Alloc anon_inode and FD for prepared token.
> > > + * Returns fd >= 0 on success; negative error, otherwise.
> > > + */
> > > +int bpf_token_new_fd(struct bpf_token *token)
> > > +{
> > > +     return anon_inode_getfd(BPF_TOKEN_INODE_NAME, &bpf_token_fops, token, O_CLOEXEC);
> >
> > It's unnecessary to use the anonymous inode infrastructure for bpf
> > tokens. It adds even more moving parts and makes reasoning about it even
> > harder. Just keep it all in bpffs. IIRC, something like the following
> > (broken, non-compiling draft) should work:
> >
> > /* bpf_token_file - get an unlinked file living in bpffs */
> > struct file *bpf_token_file(...)
> > {
> >         inode = bpf_get_inode(bpffs_mnt->mnt_sb, dir, mode);
> >         inode->i_op = &bpf_token_iop;
> >         inode->i_fop = &bpf_token_fops;
> >
> >         // some other stuff you might want or need
> >
> >         res = alloc_file_pseudo(inode, bpffs_mnt, "bpf-token", O_RDWR, &bpf_token_fops);
> > }
> >
> > Now set your private data that you might need, reserve an fd, install
> > the file into the fdtable and return the fd. You should have an unlinked
> > bpffs file that serves as your bpf token.
> 
> Just to make sure I understand. You are saying that instead of having
> `struct bpf_token *` and passing that into internal APIs
> (bpf_token_capable() and bpf_token_allow_xxx()), I should just pass
> around `struct super_block *` representing BPF FS instance? Or `struct
> bpf_mount_opts *` maybe? Or 'struct vfsmount *'? (Any preferences
> here?). Is that right?

No, that's not what I meant.

So, what you're doing right now to create a bpf token file descriptor is:

return anon_inode_getfd(BPF_TOKEN_INODE_NAME, &bpf_token_fops, token, O_CLOEXEC);

which is using the anonymous inode infrastructure. That is an entirely
different filesystems (glossing over details) that is best leveraged for
stuff like kvm fds and other stuff that doesn't need or have its own
filesytem implementation.

But you do have your own filesystem implementation so why abuse another
one to create bpf token fds when they can just be created directly from
the bpffs instance.

IOW, everything stays the same apart from the fact that bpf token fds
are actually file descriptors referring to a detached bpffs file instead
of an anonymous inode file. IOW, bpf tokens are actual bpffs objects
tied to a bpffs instance.

**BROKEN BROKEN BROKEN AND UGLY**

int bpf_token_create(union bpf_attr *attr)
{
        struct inode *inode;
        struct path path;
        struct bpf_mount_opts *mnt_opts;
        struct bpf_token *token;
        struct fd fd;
        int fd, ret;
        struct file *file;

        fd = fdget(attr->token_create.bpffs_path_fd);
        if (!fd.file)
                goto cleanup;

        if (fd.file->f_path->dentry != fd.file->f_path->dentry->d_sb->s_root)
                goto cleanup;

        inode = bpf_get_inode(fd.file->f_path->mnt->mnt_sb, NULL, 1234123412341234);
        if (!inode)
                goto cleanup;

        fd = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
        if (fd < 0)
                goto cleanup;

        clear_nlink(inode); /* make sure it is unlinked */

        file = alloc_file_pseudo(inode, fd.file->f_path->mnt, "bpf-token", O_RDWR, &&bpf_token_fops);
        if (IS_ERR(file))
                goto cleanup;

        token = bpf_token_alloc();
        if (!token)
                goto cleanup;

        /* remember bpffs owning userns for future ns_capable() checks */
        token->userns = get_user_ns(path.dentry->d_sb->s_user_ns);

        mnt_opts = path.dentry->d_sb->s_fs_info;
        token->allowed_cmds = mnt_opts->delegate_cmds;
        token->allowed_maps = mnt_opts->delegate_maps;
        token->allowed_progs = mnt_opts->delegate_progs;
        token->allowed_attachs = mnt_opts->delegate_attachs;

        file->private_data = token;
        fd_install(fd, file);
        return fd;

cleanup:
        // cleanup stuff here
        return -SOME_ERROR;
}

  reply	other threads:[~2023-09-27  9:52 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-19 21:47 [PATCH v5 bpf-next 00/13] BPF token and BPF FS-based delegation Andrii Nakryiko
2023-09-19 21:47 ` [PATCH v5 bpf-next 01/13] bpf: align CAP_NET_ADMIN checks with bpf_capable() approach Andrii Nakryiko
2023-09-19 21:47 ` [PATCH v5 bpf-next 02/13] bpf: add BPF token delegation mount options to BPF FS Andrii Nakryiko
2023-09-19 21:47 ` [PATCH v5 bpf-next 03/13] bpf: introduce BPF token object Andrii Nakryiko
2023-09-26 16:21   ` Christian Brauner
2023-09-26 22:10     ` Andrii Nakryiko
2023-09-27  9:52       ` Christian Brauner [this message]
2023-09-27 16:03         ` Andrii Nakryiko
2023-10-09 22:53           ` Paul Moore
2023-10-10  0:23             ` Andrii Nakryiko
2023-09-19 21:47 ` [PATCH v5 bpf-next 04/13] bpf: add BPF token support to BPF_MAP_CREATE command Andrii Nakryiko
2023-09-19 21:47 ` [PATCH v5 bpf-next 05/13] bpf: add BPF token support to BPF_BTF_LOAD command Andrii Nakryiko
2023-09-19 21:47 ` [PATCH v5 bpf-next 06/13] bpf: add BPF token support to BPF_PROG_LOAD command Andrii Nakryiko
2023-09-19 21:47 ` [PATCH v5 bpf-next 07/13] bpf: take into account BPF token when fetching helper protos Andrii Nakryiko
2023-09-19 21:47 ` [PATCH v5 bpf-next 08/13] bpf: consistenly use BPF token throughout BPF verifier logic Andrii Nakryiko
2023-09-19 21:47 ` [PATCH v5 bpf-next 09/13] libbpf: add bpf_token_create() API Andrii Nakryiko
2023-09-19 21:47 ` [PATCH v5 bpf-next 10/13] libbpf: add BPF token support to bpf_map_create() API Andrii Nakryiko
2023-09-19 21:47 ` [PATCH v5 bpf-next 11/13] libbpf: add BPF token support to bpf_btf_load() API Andrii Nakryiko
2023-09-19 21:47 ` [PATCH v5 bpf-next 12/13] libbpf: add BPF token support to bpf_prog_load() API Andrii Nakryiko
2023-09-19 21:48 ` [PATCH v5 bpf-next 13/13] selftests/bpf: add BPF token-enabled tests Andrii Nakryiko

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=20230927-kaution-ventilator-33a41ee74d63@brauner \
    --to=brauner@kernel.org \
    --cc=andrii.nakryiko@gmail.com \
    --cc=andrii@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=keescook@chromium.org \
    --cc=kernel-team@meta.com \
    --cc=lennart@poettering.net \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=sargun@sargun.me \
    /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;
as well as URLs for NNTP newsgroup(s).