From: Eduard Zingerman <eddyz87@gmail.com>
To: Kumar Kartikeya Dwivedi <memxor@gmail.com>, bpf@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
Andrii Nakryiko <andrii@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Martin KaFai Lau <martin.lau@kernel.org>,
David Vernet <void@manifault.com>, Tejun Heo <tj@kernel.org>,
Raj Sahu <rjsu26@vt.edu>, Dan Williams <djwillia@vt.edu>,
Rishabh Iyer <rishabh.iyer@epfl.ch>,
Sanidhya Kashyap <sanidhya.kashyap@epfl.ch>
Subject: Re: [RFC PATCH v1 05/14] bpf: Implement BPF exception frame descriptor generation
Date: Thu, 15 Feb 2024 20:24:04 +0200 [thread overview]
Message-ID: <ff88196b95f3f05e8fa2172c101cb29a55a9c3f2.camel@gmail.com> (raw)
In-Reply-To: <20240201042109.1150490-6-memxor@gmail.com>
On Thu, 2024-02-01 at 04:21 +0000, Kumar Kartikeya Dwivedi wrote:
Question: are there any real-life programs adapted to use exceptions
with cleanup feature? It would be interesting to see how robust
one-descriptor-per-pc is in practice, and also how it affects memory
consumption during verification.
The algorithm makes sense to me, a few comments/nits below.
[...]
> +static int find_and_merge_frame_desc(struct bpf_verifier_env *env, struct bpf_exception_frame_desc_tab *fdtab, u64 pc, struct bpf_frame_desc_reg_entry *fd)
> +{
> + struct bpf_exception_frame_desc **descs = NULL, *desc = NULL, *p;
> + int ret = 0;
> +
> + for (int i = 0; i < fdtab->cnt; i++) {
> + if (pc != fdtab->desc[i]->pc)
> + continue;
> + descs = &fdtab->desc[i];
> + desc = fdtab->desc[i];
> + break;
> + }
> +
> + if (!desc) {
> + verbose(env, "frame_desc: find_and_merge: cannot find frame descriptor for pc=%llu, creating new entry\n", pc);
> + return -ENOENT;
> + }
> +
> + if (fd->off < 0)
> + goto stack;
Nit: maybe write it down as
if (fd->off >= 0)
return merge_frame_desc(...);
and avoid goto?
[...]
> +static int gen_exception_frame_desc_stack_entry(struct bpf_verifier_env *env, struct bpf_func_state *frame, int stack_off)
> +{
> + int spi = stack_off / BPF_REG_SIZE, off = -stack_off - 1;
> + struct bpf_reg_state *reg, not_init_reg, null_reg;
> + int slot_type, ret;
> +
> + __mark_reg_not_init(env, ¬_init_reg);
> + __mark_reg_known_zero(&null_reg);
__mark_reg_known_zero() does not set .type field,
thus null_reg.type value is undefined.
> +
> + slot_type = frame->stack[spi].slot_type[BPF_REG_SIZE - 1];
> + reg = &frame->stack[spi].spilled_ptr;
> +
> + switch (slot_type) {
> + case STACK_SPILL:
> + /* We skip all kinds of scalar registers, except NULL values, which consume a slot. */
> + if (is_spilled_scalar_reg(&frame->stack[spi]) && !register_is_null(&frame->stack[spi].spilled_ptr))
> + break;
> + ret = gen_exception_frame_desc_reg_entry(env, reg, off, frame->frameno);
> + if (ret < 0)
> + return ret;
> + break;
> + case STACK_DYNPTR:
> + /* Keep iterating until we find the first slot. */
> + if (!reg->dynptr.first_slot)
> + break;
> + ret = gen_exception_frame_desc_dynptr_entry(env, reg, off, frame->frameno);
> + if (ret < 0)
> + return ret;
> + break;
> + case STACK_ITER:
> + /* Keep iterating until we find the first slot. */
> + if (!reg->ref_obj_id)
> + break;
> + ret = gen_exception_frame_desc_iter_entry(env, reg, off, frame->frameno);
> + if (ret < 0)
> + return ret;
> + break;
> + case STACK_MISC:
> + case STACK_INVALID:
> + /* Create an invalid entry for MISC and INVALID */
> + ret = gen_exception_frame_desc_reg_entry(env, ¬_init_reg, off, frame->frameno);
> + if (ret < 0)
> + return 0;
No tests are failing if I comment out this block.
Looking at the merge_frame_desc() logic it appears to me that fd
entries with fd->type == NOT_INIT would only be merged with other
NOT_INIT entries. What is the point of having such entries at all?
> + break;
> + case STACK_ZERO:
> + reg = &null_reg;
> + for (int i = BPF_REG_SIZE - 1; i >= 0; i--) {
> + if (frame->stack[spi].slot_type[i] != STACK_ZERO)
> + reg = ¬_init_reg;
> + }
> + ret = gen_exception_frame_desc_reg_entry(env, &null_reg, off, frame->frameno);
> + if (ret < 0)
> + return ret;
Same here, no tests are failing if STACK_ZERO block is commented.
In general, what is the point of adding STACK_ZERO entries?
There is a logic in place to merge NULL and non-NULL entries,
but how is it different from not adding NULL entries in a first place?
find_and_merge_frame_desc() does a linear scan over bpf_exception_frame_desc->stack
and does not rely on entries being sorted by .off field.
> + break;
> + default:
> + verbose(env, "verifier internal error: frame%d stack off=%d slot_type=%d missing handling for exception frame generation\n",
> + frame->frameno, off, slot_type);
> + return -EFAULT;
> + }
> + return 0;
> +}
next prev parent reply other threads:[~2024-02-15 18:24 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-01 4:20 [RFC PATCH v1 00/14] Exceptions - Resource Cleanup Kumar Kartikeya Dwivedi
2024-02-01 4:20 ` [RFC PATCH v1 01/14] bpf: Mark subprogs as throw reachable before do_check pass Kumar Kartikeya Dwivedi
2024-02-12 19:35 ` David Vernet
2024-02-12 22:28 ` Kumar Kartikeya Dwivedi
2024-02-15 1:01 ` Eduard Zingerman
2024-02-16 21:34 ` Kumar Kartikeya Dwivedi
2024-02-01 4:20 ` [RFC PATCH v1 02/14] bpf: Process global subprog's exception propagation Kumar Kartikeya Dwivedi
2024-02-15 1:10 ` Eduard Zingerman
2024-02-16 21:50 ` Kumar Kartikeya Dwivedi
2024-02-17 14:04 ` Eduard Zingerman
2024-02-01 4:20 ` [RFC PATCH v1 03/14] selftests/bpf: Add test for throwing global subprog with acquired refs Kumar Kartikeya Dwivedi
2024-02-15 1:10 ` Eduard Zingerman
2024-02-01 4:20 ` [RFC PATCH v1 04/14] bpf: Refactor check_pseudo_btf_id's BTF reference bump Kumar Kartikeya Dwivedi
2024-02-15 1:11 ` Eduard Zingerman
2024-02-16 21:50 ` Kumar Kartikeya Dwivedi
2024-02-01 4:21 ` [RFC PATCH v1 05/14] bpf: Implement BPF exception frame descriptor generation Kumar Kartikeya Dwivedi
2024-02-15 18:24 ` Eduard Zingerman [this message]
2024-02-16 11:23 ` Eduard Zingerman
2024-02-16 22:06 ` Kumar Kartikeya Dwivedi
2024-02-17 17:14 ` Eduard Zingerman
2024-02-20 21:58 ` Kumar Kartikeya Dwivedi
2024-02-16 22:24 ` Kumar Kartikeya Dwivedi
2024-02-01 4:21 ` [RFC PATCH v1 06/14] bpf: Adjust frame descriptor pc on instruction patching Kumar Kartikeya Dwivedi
2024-02-15 16:31 ` Eduard Zingerman
2024-02-16 21:52 ` Kumar Kartikeya Dwivedi
2024-02-17 14:08 ` Eduard Zingerman
2024-02-01 4:21 ` [RFC PATCH v1 07/14] bpf: Use hidden subprog trampoline for bpf_throw Kumar Kartikeya Dwivedi
2024-02-15 22:11 ` Eduard Zingerman
2024-02-16 21:59 ` Kumar Kartikeya Dwivedi
2024-02-17 14:22 ` Eduard Zingerman
2024-02-01 4:21 ` [RFC PATCH v1 08/14] bpf: Compute used callee saved registers for subprogs Kumar Kartikeya Dwivedi
2024-02-15 22:12 ` Eduard Zingerman
2024-02-16 22:02 ` Kumar Kartikeya Dwivedi
2024-02-17 14:26 ` Eduard Zingerman
2024-02-01 4:21 ` [RFC PATCH v1 09/14] bpf, x86: Fix up pc offsets for frame descriptor entries Kumar Kartikeya Dwivedi
2024-02-15 22:12 ` Eduard Zingerman
2024-02-16 13:33 ` Eduard Zingerman
2024-02-01 4:21 ` [RFC PATCH v1 10/14] bpf, x86: Implement runtime resource cleanup for exceptions Kumar Kartikeya Dwivedi
2024-02-16 12:02 ` Eduard Zingerman
2024-02-16 22:28 ` Kumar Kartikeya Dwivedi
2024-02-19 12:01 ` Eduard Zingerman
2024-02-01 4:21 ` [RFC PATCH v1 11/14] bpf: Release references in verifier state when throwing exceptions Kumar Kartikeya Dwivedi
2024-02-16 12:21 ` Eduard Zingerman
2024-02-01 4:21 ` [RFC PATCH v1 12/14] bpf: Register cleanup dtors for runtime unwinding Kumar Kartikeya Dwivedi
2024-02-01 4:21 ` [RFC PATCH v1 13/14] bpf: Make bpf_throw available to all program types Kumar Kartikeya Dwivedi
2024-02-01 4:21 ` [RFC PATCH v1 14/14] selftests/bpf: Add tests for exceptions runtime cleanup Kumar Kartikeya Dwivedi
2024-02-12 20:53 ` David Vernet
2024-02-12 22:43 ` Kumar Kartikeya Dwivedi
2024-02-13 19:33 ` David Vernet
2024-02-13 20:51 ` Kumar Kartikeya Dwivedi
2024-03-14 11:08 ` [RFC PATCH v1 00/14] Exceptions - Resource Cleanup Eduard Zingerman
2024-03-18 5:40 ` Kumar Kartikeya Dwivedi
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=ff88196b95f3f05e8fa2172c101cb29a55a9c3f2.camel@gmail.com \
--to=eddyz87@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=djwillia@vt.edu \
--cc=martin.lau@kernel.org \
--cc=memxor@gmail.com \
--cc=rishabh.iyer@epfl.ch \
--cc=rjsu26@vt.edu \
--cc=sanidhya.kashyap@epfl.ch \
--cc=tj@kernel.org \
--cc=void@manifault.com \
/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