[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220421155620.81048-1-larysa.zaremba@intel.com>
Date: Thu, 21 Apr 2022 17:56:20 +0200
From: Larysa Zaremba <larysa.zaremba@...el.com>
To: bpf <bpf@...r.kernel.org>
Cc: Larysa Zaremba <larysa.zaremba@...el.com>,
netdev <netdev@...r.kernel.org>,
Andrii Nakryiko <andrii@...nel.org>,
Alexei Starovoitov <ast@...nel.org>,
Daniel Borkmann <daniel@...earbox.net>,
Jesper Dangaard Brouer <brouer@...hat.com>,
Toke Hoiland-Jorgensen <toke@...hat.com>,
Magnus Karlsson <magnus.karlsson@...el.com>,
Maciej Fijalkowski <maciej.fijalkowski@...el.com>,
Alexander Lobakin <alexandr.lobakin@...el.com>
Subject: Accessing XDP packet memory from the end
Dear all,
Our team has encountered a need of accessing data_meta in a following way:
int xdp_meta_prog(struct xdp_md *ctx)
{
void *data_meta_ptr = (void *)(long)ctx->data_meta;
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
u64 data_size = sizeof(u32);
u32 magic_meta;
u8 offset;
offset = (u8)((s64)data - (s64)data_meta_ptr);
if (offset < data_size) {
bpf_printk("invalid offset: %ld\n", offset);
return XDP_DROP;
}
data_meta_ptr += offset;
data_meta_ptr -= data_size;
if (data_meta_ptr + data_size > data) {
return XDP_DROP;
}
magic_meta = *((u32 *)data);
bpf_printk("Magic: %d\n", magic_meta);
return XDP_PASS;
}
Unfortunately, verifier claims this code attempts to access packet with
an offset of -2 (a constant part) and negative offset is generally forbidden.
For now we have 2 solutions, one is using bpf_xdp_adjust_meta(),
which is pretty good, but not ideal for the hot path.
The second one is the patch at the end.
Do you see any other way of accessing memory from the end of data_meta/data?
What do you think about both suggested solutions?
Best regards,
Larysa Zaremba
---
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -3576,8 +3576,11 @@ static int check_packet_access(struct bpf_verifier_env *env, u32 regno, int off,
}
err = reg->range < 0 ? -EINVAL :
- __check_mem_access(env, regno, off, size, reg->range,
- zero_size_allowed);
+ __check_mem_access(env, regno, off + reg->smin_value, size,
+ reg->range + reg->smin_value, zero_size_allowed);
+ err = err ? :
+ __check_mem_access(env, regno, off + reg->umax_value, size,
+ reg->range + reg->umax_value, zero_size_allowed);
if (err) {
verbose(env, "R%d offset is outside of the packet\n", regno);
return err;
Powered by blists - more mailing lists