Commit d91b28ed authored by Alexei Starovoitov's avatar Alexei Starovoitov Committed by David S. Miller

bpf: support decreasing order in direct packet access

when packet headers are accessed in 'decreasing' order (like TCP port
may be fetched before the program reads IP src) the llvm may generate
the following code:
[...]                // R7=pkt(id=0,off=22,r=70)
r2 = *(u32 *)(r7 +0) // good access
[...]
r7 += 40             // R7=pkt(id=0,off=62,r=70)
r8 = *(u32 *)(r7 +0) // good access
[...]
r1 = *(u32 *)(r7 -20) // this one will fail though it's within a safe range
                      // it's doing *(u32*)(skb->data + 42)
Fix verifier to recognize such code pattern

Alos turned out that 'off > range' condition is not a verifier bug.
It's a buggy program that may do something like:
if (ptr + 50 > data_end)
  return 0;
ptr += 60;
*(u32*)ptr;
in such case emit
"invalid access to packet, off=0 size=4, R1(id=0,off=60,r=50)" error message,
so all information is available for the program author to fix the program.

Fixes: 969bf05e ("bpf: direct packet access")
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Acked-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 238a9584
...@@ -683,15 +683,11 @@ static int check_packet_access(struct verifier_env *env, u32 regno, int off, ...@@ -683,15 +683,11 @@ static int check_packet_access(struct verifier_env *env, u32 regno, int off,
{ {
struct reg_state *regs = env->cur_state.regs; struct reg_state *regs = env->cur_state.regs;
struct reg_state *reg = &regs[regno]; struct reg_state *reg = &regs[regno];
int linear_size = (int) reg->range - (int) reg->off;
if (linear_size < 0 || linear_size >= MAX_PACKET_OFF) { off += reg->off;
verbose("verifier bug\n"); if (off < 0 || off + size > reg->range) {
return -EFAULT; verbose("invalid access to packet, off=%d size=%d, R%d(id=%d,off=%d,r=%d)\n",
} off, size, regno, reg->id, reg->off, reg->range);
if (off < 0 || off + size > linear_size) {
verbose("invalid access to packet, off=%d size=%d, allowed=%d\n",
off, size, linear_size);
return -EACCES; return -EACCES;
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment