From: Eduard Zingerman <eddyz87@gmail.com>
To: Alan Maguire <alan.maguire@oracle.com>,
bpf@vger.kernel.org, ast@kernel.org
Cc: andrii@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev,
kernel-team@fb.com, yonghong.song@linux.dev,
jose.marchesi@oracle.com
Subject: Re: [PATCH bpf-next 0/1] use preserve_static_offset in bpf uapi headers
Date: Fri, 08 Dec 2023 16:21:46 +0200 [thread overview]
Message-ID: <069960f88faa6740b9059ff428f7f209d8e8d6d2.camel@gmail.com> (raw)
In-Reply-To: <1d2a2af0-40db-80f9-da13-caf53f3d9118@oracle.com>
On Fri, 2023-12-08 at 12:27 +0000, Alan Maguire wrote:
[...]
> Sorry if this is a digression, but I'm trying to understand how
> this might intersect with vmlinux.h's
>
> #pragma clang attribute push (__attribute__((preserve_access_index)),
> apply_to = record
>
> Since that is currently applied to all structures in vmlinux.h, does
> that protect us from the above scenario when BPF code is compiled and
> #include's vmlinux.h (I suspect not from what you say below but just
> wanted to check)? I realize we get extra relocation info that we don't
> need since the offsets for these BPF context structures are recalcuated
> by the verifier, but given that clang needs to record the relocations,
> does it also constrain the generated code to avoid these "increment
> pointer, use zero offset" instruction patterns? Or can they still occur
> with preserve_access_index applied to the structure? Sorry, might be a
> naive question but it's not clear to me how (if at all) the mechanisms
> might interact.
Unfortunately preserve_access_index does not save us from this problem.
This is the case because field reads and writes are split as two LLVM
IR instructions: getelementptr to get an address, and load/store
to/from that address. The preserve_access_index transformation
rewrites the getelementptr but does not touch load/store.
For example, consider the following C code:
/* #define __ctx __attribute__((preserve_static_offset)) */
/* #define __pai */
#define __ctx
#define __pai __attribute__((preserve_access_index))
extern int magic2(int);
struct bpf_sock {
int bound_dev_if;
int family;
} __ctx __pai;
struct bpf_sockopt {
int _;
struct bpf_sock *sk;
int level;
int optlen;
} __ctx __pai;
int known_load_sink_example_1(struct bpf_sockopt *ctx)
{
unsigned g = 0;
switch (ctx->level) {
case 10:
g = magic2(ctx->sk->family);
break;
case 20:
g = magic2(ctx->optlen);
break;
}
return g % 2;
}
Here is how it is compiled:
$ clang -g -O2 --target=bpf -mcpu=v3 -c e3.c -o - | llvm-objdump --no-show-raw-insn -Sdr -
...
0000000000000000 <known_load_sink_example_1>:
; switch (ctx->level) {
0: r2 = *(u32 *)(r1 + 0x10)
0000000000000000: CO-RE <byte_off> [2] struct bpf_sockopt::level (0:2)
1: if w2 == 0x14 goto +0x5 <LBB0_3>
2: w0 = 0x0
; switch (ctx->level) {
3: if w2 != 0xa goto +0x8 <LBB0_5>
; g = magic2(ctx->sk->family);
4: r1 = *(u64 *)(r1 + 0x8)
0000000000000020: CO-RE <byte_off> [2] struct bpf_sockopt::sk (0:1)
5: r2 = 0x4
0000000000000028: CO-RE <byte_off> [7] struct bpf_sock::family (0:1)
6: goto +0x1 <LBB0_4>
0000000000000038 <LBB0_3>:
7: r2 = 0x14
0000000000000038: CO-RE <byte_off> [2] struct bpf_sockopt::optlen (0:3)
0000000000000040 <LBB0_4>:
8: r1 += r2
9: r1 = *(u32 *)(r1 + 0x0) <---------------- verifier error would
10: call -0x1 be reported for this insn
0000000000000050: R_BPF_64_32 magic2
; return g % 2;
11: w0 &= 0x1
0000000000000060 <LBB0_5>:
12: exit
> The reason I ask is if it was safe to assume that code generation would
> avoid such patterns with preserve_access_index, it might avoid needing
> to update vmlinux.h generation.
In current LLVM implementation preserve_static_offset has priority
over preserve_access_index. So changing __pai/__ctx definitions above helps.
(And this priority of one attribute over the other was the reason to
have preserve_static_offset as an attribute, not as
btf_decl_tag("preserve_static_offset"). Although that is unfortunate
for vmlinux.h, as we already have means to preserve decl tags).
[...]
> > How to add the same definitions in vmlinux.h is an open question,
> > and most likely requires bpftool modification:
> > - Hard code generation of __bpf_ctx based on type names?
> > - Mark context types with some special
> > __attribute__((btf_decl_tag("preserve_static_offset")))
> > and convert it to __attribute__((preserve_static_offset))?
>
> To me it seems like whatever mechanism supports identification of such
> structures would need to live in vmlinux BTF as ideally it should be
> possible to generate vmlinux.h purely from that BTF. That seems to argue
> for the declaration tag approach.
Tbh, I like the decl tag approach a bit more too.
Although macro definition would be somewhat ridiculous:
#if __has_attribute(preserve_static_offset) && defined(__bpf__)
#define __bpf_ctx __attribute__((preserve_static_offset)) \
__attribute__((btf_decl_tag("preserve_static_offset")))
#else
#define __bpf_ctx
#endif
Thanks,
Eduard
next prev parent reply other threads:[~2023-12-08 14:21 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-08 0:05 [PATCH bpf-next 0/1] use preserve_static_offset in bpf uapi headers Eduard Zingerman
2023-12-08 0:05 ` [PATCH bpf-next 1/1] bpf: Mark virtual BPF context structures as preserve_static_offset Eduard Zingerman
2023-12-08 3:36 ` Yonghong Song
2023-12-08 14:23 ` Eduard Zingerman
2023-12-08 2:28 ` [PATCH bpf-next 0/1] use preserve_static_offset in bpf uapi headers Yonghong Song
2023-12-08 14:34 ` Eduard Zingerman
2023-12-08 17:19 ` Yonghong Song
2023-12-08 20:54 ` Eduard Zingerman
2023-12-08 17:30 ` Yonghong Song
2023-12-08 17:46 ` Alexei Starovoitov
2023-12-08 20:35 ` Eduard Zingerman
2023-12-08 12:27 ` Alan Maguire
2023-12-08 14:21 ` Eduard Zingerman [this message]
2023-12-08 15:35 ` Alan Maguire
2023-12-08 15:39 ` Eduard Zingerman
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=069960f88faa6740b9059ff428f7f209d8e8d6d2.camel@gmail.com \
--to=eddyz87@gmail.com \
--cc=alan.maguire@oracle.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=jose.marchesi@oracle.com \
--cc=kernel-team@fb.com \
--cc=martin.lau@linux.dev \
--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