> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 1e8688975d16..a1b54da1ded2 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c

[ ... ]

> @@ -13683,11 +13683,18 @@ static int bpf_link__detach_struct_ops(struct 
> bpf_link *link)
>       return close(link->fd);
>  }
>
> -struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map)
> +struct bpf_link *bpf_map__attach_struct_ops_opts(const struct bpf_map *map,
> +                                              const struct 
> bpf_struct_ops_opts *opts)
>  {
> +     DECLARE_LIBBPF_OPTS(bpf_link_create_opts, link_opts);
>       struct bpf_link_struct_ops *link;
> +     int err, fd, target_fd;
>       __u32 zero = 0;
> -     int err, fd;
> +
> +     if (!OPTS_VALID(opts, bpf_struct_ops_opts)) {
> +             pr_warn("map '%s': invalid opts\n", map->name);
> +             return libbpf_err_ptr(-EINVAL);
> +     }
>
>       if (!bpf_map__is_struct_ops(map)) {
>               pr_warn("map '%s': can't attach non-struct_ops map\n", 
> map->name);

[ ... ]

> @@ -13724,7 +13731,9 @@ struct bpf_link *bpf_map__attach_struct_ops(const 
> struct bpf_map *map)
>               return &link->link;
>       }
>
> -     fd = bpf_link_create(map->fd, 0, BPF_STRUCT_OPS, NULL);
> +     link_opts.flags = OPTS_GET(opts, flags, 0);
> +     target_fd = OPTS_GET(opts, target_fd, 0);
> +     fd = bpf_link_create(map->fd, target_fd, BPF_STRUCT_OPS, &link_opts);

The expected_revision field declared in struct bpf_struct_ops_opts is never
read or used. The code only reads flags and target_fd from opts, which could
cause silent data loss if users set expected_revision expecting it to be
honored.

Looking at similar opts structures (bpf_cgroup_opts, bpf_tcx_opts,
bpf_netkit_opts), they all pass expected_revision to bpf_link_create_opts.
Should expected_revision be propagated here as well?

This was raised by [email protected] in v3:
https://lore.kernel.org/bpf/3af5210f45be4a508e584263a5517781ca762d28d4f6b831b987795662715...@mail.kernel.org/

>       if (fd < 0) {
>               free(link);
>               return libbpf_err_ptr(fd);

[ ... ]

> diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> index bba4e8464396..18af178547ad 100644
> --- a/tools/lib/bpf/libbpf.h
> +++ b/tools/lib/bpf/libbpf.h
> @@ -945,6 +945,20 @@ bpf_program__attach_cgroup_opts(const struct bpf_program 
> *prog, int cgroup_fd,
>  struct bpf_map;
>
>  LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map 
> *map);
> +
> +struct bpf_struct_ops_opts {
> +     /* size of this struct, for forward/backward compatibility */
> +     size_t sz;
> +     __u32 flags;
> +     __u32 target_fd;
> +     __u64 expected_revision;
> +     size_t :0;
> +};
> +#define bpf_struct_ops_opts__last_field expected_revision
> +
> +LIBBPF_API struct bpf_link *
> +bpf_map__attach_struct_ops_opts(const struct bpf_map *map,
> +                             const struct bpf_struct_ops_opts *opts);
>  LIBBPF_API int bpf_link__update_map(struct bpf_link *link, const struct 
> bpf_map *map);
>
>  struct bpf_iter_attach_opts {

[ ... ]


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/26429228214

Reply via email to