From: Stephen Hemminger <stephen@networkplumber.org>
To: Konstantin Ananyev <konstantin.ananyev@huawei.com>
Cc: Konstantin Ananyev <konstantin.v.ananyev@yandex.ru>,
"dev@dpdk.org" <dev@dpdk.org>
Subject: Re: BPF standardization
Date: Fri, 19 Jul 2024 10:13:23 -0700 [thread overview]
Message-ID: <20240719101323.5e880752@hermes.local> (raw)
In-Reply-To: <956072b13b7b45fe8ce676989580f3e0@huawei.com>
On Fri, 19 Jul 2024 09:12:58 +0000
Konstantin Ananyev <konstantin.ananyev@huawei.com> wrote:
> bpf_convert_filter() uses standard approach with XOR-ing itself:
> xor r0, r0, r0
> to reset some register values.
> Unfortunately linux verifier seems way too strict here and
> doesn't allow access to register with undefined value.
> It generates error log like that for this op:
> Failed to verify program: Permission denied (13)
> LOG: func#0 @0
> 0: R1=ctx(id=0,off=0,imm=0) R10=fp0
> 0: (af) r0 ^= r0
> R0 !read_ok
> processed 1 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
>
> To overcome that, simply replace XOR with itself to explicit
> mov32 r0, #0x0
>
> Signed-off-by: Konstantin Ananyev <konstantin.ananyev@huawei.com>
> ---
> lib/bpf/bpf_convert.c | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/lib/bpf/bpf_convert.c b/lib/bpf/bpf_convert.c
> index d7ff2b4325..eceaa19c76 100644
> --- a/lib/bpf/bpf_convert.c
> +++ b/lib/bpf/bpf_convert.c
> @@ -267,8 +267,11 @@ static int bpf_convert_filter(const struct bpf_insn *prog, size_t len,
> /* Classic BPF expects A and X to be reset first. These need
> * to be guaranteed to be the first two instructions.
> */
> - *new_insn++ = EBPF_ALU64_REG(BPF_XOR, BPF_REG_A, BPF_REG_A);
> - *new_insn++ = EBPF_ALU64_REG(BPF_XOR, BPF_REG_X, BPF_REG_X);
> + //*new_insn++ = EBPF_ALU64_REG(BPF_XOR, BPF_REG_A, BPF_REG_A);
> + //*new_insn++ = EBPF_ALU64_REG(BPF_XOR, BPF_REG_X, BPF_REG_X);
> +
> + *new_insn++ = BPF_MOV32_IMM(BPF_REG_A, 0);
> + *new_insn++ = BPF_MOV32_IMM(BPF_REG_X, 0);
>
> /* All programs must keep CTX in callee saved BPF_REG_CTX.
> * In eBPF case it's done by the compiler, here we need to
This was taken from how kernel converts cBPF and the prologue it generates.
Surprising that verifier gags?
see net/core/filter.c
/* Classic BPF related prologue emission. */
if (new_prog) {
/* Classic BPF expects A and X to be reset first. These need
* to be guaranteed to be the first two instructions.
*/
*new_insn++ = BPF_ALU32_REG(BPF_XOR, BPF_REG_A, BPF_REG_A);
*new_insn++ = BPF_ALU32_REG(BPF_XOR, BPF_REG_X, BPF_REG_X);
/* All programs must keep CTX in callee saved BPF_REG_CTX.
* In eBPF case it's done by the compiler, here we need to
* do this ourself. Initial CTX is present in BPF_REG_ARG1.
*/
*new_insn++ = BPF_MOV64_REG(BPF_REG_CTX, BPF_REG_ARG1);
if (*seen_ld_abs) {
/* For packet access in classic BPF, cache skb->data
* in callee-saved BPF R8 and skb->len - skb->data_len
* (headlen) in BPF R9. Since classic BPF is read-only
* on CTX, we only need to cache it once.
*/
*new_insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, data),
BPF_REG_D, BPF_REG_CTX,
offsetof(struct sk_buff, data));
*new_insn++ = BPF_LDX_MEM(BPF_W, BPF_REG_H, BPF_REG_CTX,
offsetof(struct sk_buff, len));
*new_insn++ = BPF_LDX_MEM(BPF_W, BPF_REG_TMP, BPF_REG_CTX,
offsetof(struct sk_buff, data_len));
*new_insn++ = BPF_ALU32_REG(BPF_SUB, BPF_REG_H, BPF_REG_TMP);
}
next prev parent reply other threads:[~2024-07-19 17:13 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-30 23:23 Stephen Hemminger
2024-07-19 9:12 ` Konstantin Ananyev
2024-07-19 17:13 ` Stephen Hemminger [this message]
2024-07-19 18:29 ` Konstantin Ananyev
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=20240719101323.5e880752@hermes.local \
--to=stephen@networkplumber.org \
--cc=dev@dpdk.org \
--cc=konstantin.ananyev@huawei.com \
--cc=konstantin.v.ananyev@yandex.ru \
/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;
as well as URLs for NNTP newsgroup(s).