From: Anton Protopopov <aspsk@isovalent.com>
To: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Cc: bpf <bpf@vger.kernel.org>
Subject: Re: [PATCH v3 bpf-next 3/7] bpf: add fd_array_cnt attribute for prog_load
Date: Tue, 3 Dec 2024 10:31:52 +0000 [thread overview]
Message-ID: <Z07eGFH+c6mX8bvg@eis> (raw)
In-Reply-To: <CAADnVQLezUADcW5gJopCyfdYaNSiA+9Zk2n5Mf2EovzCv0AnvQ@mail.gmail.com>
On 24/12/02 06:26PM, Alexei Starovoitov wrote:
> On Fri, Nov 29, 2024 at 5:26 AM Anton Protopopov <aspsk@isovalent.com> wrote:
> >
> > The fd_array attribute of the BPF_PROG_LOAD syscall may contain a set
> > of file descriptors: maps or btfs. This field was introduced as a
> > sparse array. Introduce a new attribute, fd_array_cnt, which, if
> > present, indicates that the fd_array is a continuous array of the
> > corresponding length.
> >
> > If fd_array_cnt is non-zero, then every map in the fd_array will be
> > bound to the program, as if it was used by the program. This
> > functionality is similar to the BPF_PROG_BIND_MAP syscall, but such
> > maps can be used by the verifier during the program load.
> >
> > Signed-off-by: Anton Protopopov <aspsk@isovalent.com>
> > ---
> > include/uapi/linux/bpf.h | 10 ++++
> > kernel/bpf/syscall.c | 2 +-
> > kernel/bpf/verifier.c | 94 ++++++++++++++++++++++++++++------
> > tools/include/uapi/linux/bpf.h | 10 ++++
> > 4 files changed, 100 insertions(+), 16 deletions(-)
> >
> > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > index 4162afc6b5d0..2acf9b336371 100644
> > --- a/include/uapi/linux/bpf.h
> > +++ b/include/uapi/linux/bpf.h
> > @@ -1573,6 +1573,16 @@ union bpf_attr {
> > * If provided, prog_flags should have BPF_F_TOKEN_FD flag set.
> > */
> > __s32 prog_token_fd;
> > + /* The fd_array_cnt can be used to pass the length of the
> > + * fd_array array. In this case all the [map] file descriptors
> > + * passed in this array will be bound to the program, even if
> > + * the maps are not referenced directly. The functionality is
> > + * similar to the BPF_PROG_BIND_MAP syscall, but maps can be
> > + * used by the verifier during the program load. If provided,
> > + * then the fd_array[0,...,fd_array_cnt-1] is expected to be
> > + * continuous.
> > + */
> > + __u32 fd_array_cnt;
> > };
> >
> > struct { /* anonymous struct used by BPF_OBJ_* commands */
> > diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> > index 58190ca724a2..7e3fbc23c742 100644
> > --- a/kernel/bpf/syscall.c
> > +++ b/kernel/bpf/syscall.c
> > @@ -2729,7 +2729,7 @@ static bool is_perfmon_prog_type(enum bpf_prog_type prog_type)
> > }
> >
> > /* last field in 'union bpf_attr' used by this command */
> > -#define BPF_PROG_LOAD_LAST_FIELD prog_token_fd
> > +#define BPF_PROG_LOAD_LAST_FIELD fd_array_cnt
> >
> > static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
> > {
> > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > index 8e034a22aa2a..d172f6974fd7 100644
> > --- a/kernel/bpf/verifier.c
> > +++ b/kernel/bpf/verifier.c
> > @@ -19181,22 +19181,10 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
> > return 0;
> > }
> >
> > -/* Add map behind fd to used maps list, if it's not already there, and return
> > - * its index.
> > - * Returns <0 on error, or >= 0 index, on success.
> > - */
> > -static int add_used_map_from_fd(struct bpf_verifier_env *env, int fd)
> > +static int __add_used_map(struct bpf_verifier_env *env, struct bpf_map *map)
> > {
> > - CLASS(fd, f)(fd);
> > - struct bpf_map *map;
> > int i, err;
> >
> > - map = __bpf_map_get(f);
> > - if (IS_ERR(map)) {
> > - verbose(env, "fd %d is not pointing to valid bpf_map\n", fd);
> > - return PTR_ERR(map);
> > - }
> > -
> > /* check whether we recorded this map already */
> > for (i = 0; i < env->used_map_cnt; i++)
> > if (env->used_maps[i] == map)
> > @@ -19227,6 +19215,24 @@ static int add_used_map_from_fd(struct bpf_verifier_env *env, int fd)
> > return env->used_map_cnt - 1;
> > }
> >
> > +/* Add map behind fd to used maps list, if it's not already there, and return
> > + * its index.
> > + * Returns <0 on error, or >= 0 index, on success.
> > + */
> > +static int add_used_map(struct bpf_verifier_env *env, int fd)
> > +{
> > + struct bpf_map *map;
> > + CLASS(fd, f)(fd);
> > +
> > + map = __bpf_map_get(f);
> > + if (IS_ERR(map)) {
> > + verbose(env, "fd %d is not pointing to valid bpf_map\n", fd);
> > + return PTR_ERR(map);
> > + }
> > +
> > + return __add_used_map(env, map);
> > +}
> > +
> > /* find and rewrite pseudo imm in ld_imm64 instructions:
> > *
> > * 1. if it accesses map FD, replace it with actual map pointer.
> > @@ -19318,7 +19324,7 @@ static int resolve_pseudo_ldimm64(struct bpf_verifier_env *env)
> > break;
> > }
> >
> > - map_idx = add_used_map_from_fd(env, fd);
> > + map_idx = add_used_map(env, fd);
> > if (map_idx < 0)
> > return map_idx;
> > map = env->used_maps[map_idx];
> > @@ -22526,6 +22532,61 @@ struct btf *bpf_get_btf_vmlinux(void)
> > return btf_vmlinux;
> > }
> >
> > +/*
> > + * The add_fd_from_fd_array() is executed only if fd_array_cnt is given. In
> > + * this case expect that every file descriptor in the array is either a map or
> > + * a BTF, or a hole (0). Everything else is considered to be trash.
> > + */
>
> The comment is now incorrect. 0 is not a valid hole.
> No holes are allowed. And no trash.
Thanks, fixed.
> > +static int add_fd_from_fd_array(struct bpf_verifier_env *env, int fd)
> > +{
> > + struct bpf_map *map;
> > + CLASS(fd, f)(fd);
> > + int ret;
> > +
> > + map = __bpf_map_get(f);
> > + if (!IS_ERR(map)) {
> > + ret = __add_used_map(env, map);
> > + if (ret < 0)
> > + return ret;
> > + return 0;
> > + }
> > +
> > + if (!IS_ERR(__btf_get_by_fd(f)))
> > + return 0;
>
> It is quite asymmetrical that maps get refcnted and saved
> while BTFs just checked for existence and not refcnted.
> A comment is necessary.
Added.
>
> > +
> > + verbose(env, "fd %d is not pointing to valid bpf_map or btf\n", fd);
> > + return PTR_ERR(map);
> > +}
> > +
> > +static int init_fd_array(struct bpf_verifier_env *env, union bpf_attr *attr, bpfptr_t uattr)
>
> The name still bothers me.
> The fd_array in the env and in uattr is not initialized.
>
> Maybe process_fd_array() ?
Sure, 'process_fd_array' looks fine for me.
> pw-bot: cr
next prev parent reply other threads:[~2024-12-03 10:29 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-29 13:28 [PATCH v3 bpf-next 0/7] Add fd_array_cnt attribute for BPF_PROG_LOAD Anton Protopopov
2024-11-29 13:28 ` [PATCH v3 bpf-next 1/7] bpf: add a __btf_get_by_fd helper Anton Protopopov
2024-11-29 13:28 ` [PATCH v3 bpf-next 2/7] bpf: move map/prog compatibility checks Anton Protopopov
2024-11-29 13:28 ` [PATCH v3 bpf-next 3/7] bpf: add fd_array_cnt attribute for prog_load Anton Protopopov
2024-12-03 2:26 ` Alexei Starovoitov
2024-12-03 10:31 ` Anton Protopopov [this message]
2024-11-29 13:28 ` [PATCH v3 bpf-next 4/7] libbpf: prog load: allow to use fd_array_cnt Anton Protopopov
2024-12-03 2:34 ` Alexei Starovoitov
2024-12-03 10:23 ` Anton Protopopov
2024-11-29 13:28 ` [PATCH v3 bpf-next 5/7] selftests/bpf: Add tests for fd_array_cnt Anton Protopopov
2024-12-03 2:37 ` Alexei Starovoitov
2024-12-03 10:25 ` Anton Protopopov
2024-11-29 13:28 ` [PATCH v3 bpf-next 6/7] bpf: fix potential error return Anton Protopopov
2024-11-29 13:28 ` [PATCH v3 bpf-next 7/7] selftest/bpf: replace magic constants by macros Anton Protopopov
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=Z07eGFH+c6mX8bvg@eis \
--to=aspsk@isovalent.com \
--cc=alexei.starovoitov@gmail.com \
--cc=bpf@vger.kernel.org \
/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.