From: bot+bpf-ci@kernel.org
To: sidnayyar@google.com,ast@kernel.org,daniel@iogearbox.net,john.fastabend@gmail.com,andrii@kernel.org,eddyz87@gmail.com,memxor@gmail.com,martin.lau@linux.dev,song@kernel.org,yonghong.song@linux.dev,jolsa@kernel.org,emil@etsalapatis.com,ihor.solodrai@linux.dev,qmo@kernel.org,shuah@kernel.org
Cc: bpf@vger.kernel.org,linux-kernel@vger.kernel.org,linux-kselftest@vger.kernel.org,gprocida@google.com,nkapron@google.com,tweek@google.com,mripard@kernel.org,sidnayyar@google.com,ast@kernel.org,andrii@kernel.org,daniel@iogearbox.net,martin.lau@kernel.org,eddyz87@gmail.com,yonghong.song@linux.dev,mason@kernel.org,ihor.solodrai@linux.dev
Subject: Re: [PATCH RFC bpf-next 4/7] libbpf: Support BPF_PROG_TYPE_STRUCT_OPS in bpf_gen__prog_load()
Date: Fri, 6 Nov 2026 20:56:37 +0000 (UTC) [thread overview]
Message-ID: <d443a99c61ebd277a8b46dfeaa5061cb20a64abaffb750e390188e892aa79db8@mail.kernel.org> (raw)
In-Reply-To: <20261106-lskel-struct-ops-v1-4-a4486ffc79cb@google.com>
[-- Attachment #1: Type: text/plain, Size: 4075 bytes --]
> libbpf: Support BPF_PROG_TYPE_STRUCT_OPS in bpf_gen__prog_load()
TL;DR: In light skeletons, a kernel-module BTF fd for struct_ops may leak
(stay open in the loader's fd table) if any struct_ops program load fails,
since no error-path close is emitted.
> diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c
> --- a/tools/lib/bpf/gen_loader.c
> +++ b/tools/lib/bpf/gen_loader.c
[ ... ]
> @@ -1151,6 +1151,20 @@ void bpf_gen__prog_load(struct bpf_gen *gen,
> emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_7,
> offsetof(union bpf_attr, attach_btf_obj_fd)));
> }
> + if (prog_type == BPF_PROG_TYPE_STRUCT_OPS) {
> + move_blob2blob(gen, attr_field(prog_load_attr, expected_attach_type), 4,
> + load_attr->expected_attach_type);
> + emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
> + 0, 0, 0, load_attr->attach_btf_id));
> + emit(gen, BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_1, 0));
> + emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
> + 0, 0, 0, prog_load_attr));
> + emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_7,
> + offsetof(union bpf_attr, attach_btf_id)));
> + emit(gen, BPF_ALU64_IMM(BPF_RSH, BPF_REG_7, 32));
> + emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_7,
> + offsetof(union bpf_attr, attach_btf_obj_fd)));
> + }
> emit_relos(gen, insns_off);
> /* emit PROG_LOAD command */
> emit_sys_bpf(gen, BPF_PROG_LOAD, prog_load_attr, attr_size);
For a struct_ops type defined in a kernel module, can the module BTF fd
leak into the process running the light skeleton when a struct_ops
program fails to load?
The block above copies the upper 32 bits of the u64 at
load_attr->attach_btf_id into prog_load_attr.attach_btf_obj_fd. That
value was produced at runtime by bpf_btf_find_by_name_kind() in
bpf_gen__init_kern_struct_ops(). For a module type it creates a new fd
with __btf_new_fd() and returns:
ret | ((u64)btf_obj_fd << 32)
so this is an open fd owned by the loader.
The existing code closes module BTF fds whether the load succeeds or not:
/* successful or not, close btf module FDs used in extern ksyms and attach_btf_obj_fd */
cleanup_relos(gen, insns_off);
if (gen->attach_kind) {
emit_sys_close_blob(gen,
attr_field(prog_load_attr, attach_btf_obj_fd));
gen->attach_kind = 0;
}
emit_check_err(gen);
bpf_gen__map_create() does the same for value_type_btf_obj_fd, but the
struct_ops path here does not. The fd cannot be closed here because all
programs of the map share it. The only close is in
bpf_gen__struct_ops_update_elem(), added later in the series, which is
emitted from bpf_object_prepare_struct_ops() after all programs are
loaded and so only runs on success.
If BPF_PROG_LOAD fails for any struct_ops program (for example a verifier
rejection), emit_check_err() jumps to gen->cleanup_label. The cleanup
code emitted by bpf_gen__init() only closes the prog_fd[] stack slots and
the map fds in the blob fd_array:
for (i = 0; i < nr_progs_sz; i += 4) { ... BPF_FUNC_sys_close ... }
for (i = 0; i < nr_maps; i++)
emit_sys_close_blob(gen, blob_fd_array_off(gen, i));
Nothing there knows about st_ops->type_id_off, so the module BTF fd of
every struct_ops map initialised so far stays open in the caller's fd
table. The same applies to any later failure before
bpf_gen__struct_ops_update_elem() runs, such as another program's load or
an emit_check_err() in emit_relos(). vmlinux struct_ops types are not
affected, since the upper 32 bits are 0 and __emit_sys_close() skips
fd <= 0.
No later commit in the series adds an error-path close. Should these fds
be added to the cleanup_label path, or closed in an error branch around
the prog-load emit_check_err()?
---
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/42289585064
next prev parent reply other threads:[~2026-11-06 20:56 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-06 20:19 [PATCH RFC bpf-next 0/7] bpf: Support struct_ops in light skeletons Siddharth Nayyar
2026-11-06 20:19 ` [PATCH RFC bpf-next 1/7] bpf: Add bpf_btf_get_struct_member_info() helper Siddharth Nayyar
2026-11-06 20:56 ` bot+bpf-ci
2026-11-06 20:19 ` [PATCH RFC bpf-next 2/7] libbpf: Implement bpf_gen__init_kern_struct_ops() for light skeletons Siddharth Nayyar
2026-11-06 20:56 ` bot+bpf-ci
2026-11-06 20:19 ` [PATCH RFC bpf-next 3/7] libbpf: Support BPF_MAP_TYPE_STRUCT_OPS in bpf_gen__map_create() Siddharth Nayyar
2026-11-06 20:56 ` bot+bpf-ci
2026-11-06 20:19 ` [PATCH RFC bpf-next 4/7] libbpf: Support BPF_PROG_TYPE_STRUCT_OPS in bpf_gen__prog_load() Siddharth Nayyar
2026-11-06 20:56 ` bot+bpf-ci [this message]
2026-11-06 20:19 ` [PATCH RFC bpf-next 5/7] libbpf: Implement bpf_gen__struct_ops_update_elem() for light skeletons Siddharth Nayyar
2026-11-06 20:56 ` bot+bpf-ci
2026-11-06 20:19 ` [PATCH RFC bpf-next 6/7] bpftool: Generate attach and detach for struct_ops in " Siddharth Nayyar
2026-11-06 20:19 ` [PATCH RFC bpf-next 7/7] selftests/bpf: Add light skeleton struct_ops tests Siddharth Nayyar
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=d443a99c61ebd277a8b46dfeaa5061cb20a64abaffb750e390188e892aa79db8@mail.kernel.org \
--to=bot+bpf-ci@kernel.org \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=gprocida@google.com \
--cc=ihor.solodrai@linux.dev \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=martin.lau@kernel.org \
--cc=martin.lau@linux.dev \
--cc=mason@kernel.org \
--cc=memxor@gmail.com \
--cc=mripard@kernel.org \
--cc=nkapron@google.com \
--cc=qmo@kernel.org \
--cc=shuah@kernel.org \
--cc=sidnayyar@google.com \
--cc=song@kernel.org \
--cc=tweek@google.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®