Commit 0a87bc2e authored by David S. Miller's avatar David S. Miller

Merge branch 'bpf-improve-verifier-ARG_CONST_SIZE_OR_ZERO-semantics'

Yonghong Song says:

====================
bpf: improve verifier ARG_CONST_SIZE_OR_ZERO semantics

This patch set intends to change verifier ARG_CONST_SIZE_OR_ZERO
semantics so that simpler bpf programs can be written with verifier
acceptance. Patch #1 comment provided the detailed examples and
the patch itself implements the new semantics. Patch #2
changes bpf_probe_read helper arg2 type from
ARG_CONST_SIZE to ARG_CONST_SIZE_OR_ZERO. Patch #3 fixed a few
test cases and added some for better coverage.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3a9b76fd b6ff6391
...@@ -799,12 +799,13 @@ static int check_stack_read(struct bpf_verifier_env *env, ...@@ -799,12 +799,13 @@ static int check_stack_read(struct bpf_verifier_env *env,
/* check read/write into map element returned by bpf_map_lookup_elem() */ /* check read/write into map element returned by bpf_map_lookup_elem() */
static int __check_map_access(struct bpf_verifier_env *env, u32 regno, int off, static int __check_map_access(struct bpf_verifier_env *env, u32 regno, int off,
int size) int size, bool zero_size_allowed)
{ {
struct bpf_reg_state *regs = cur_regs(env); struct bpf_reg_state *regs = cur_regs(env);
struct bpf_map *map = regs[regno].map_ptr; struct bpf_map *map = regs[regno].map_ptr;
if (off < 0 || size <= 0 || off + size > map->value_size) { if (off < 0 || size < 0 || (size == 0 && !zero_size_allowed) ||
off + size > map->value_size) {
verbose(env, "invalid access to map value, value_size=%d off=%d size=%d\n", verbose(env, "invalid access to map value, value_size=%d off=%d size=%d\n",
map->value_size, off, size); map->value_size, off, size);
return -EACCES; return -EACCES;
...@@ -814,7 +815,7 @@ static int __check_map_access(struct bpf_verifier_env *env, u32 regno, int off, ...@@ -814,7 +815,7 @@ static int __check_map_access(struct bpf_verifier_env *env, u32 regno, int off,
/* check read/write into a map element with possible variable offset */ /* check read/write into a map element with possible variable offset */
static int check_map_access(struct bpf_verifier_env *env, u32 regno, static int check_map_access(struct bpf_verifier_env *env, u32 regno,
int off, int size) int off, int size, bool zero_size_allowed)
{ {
struct bpf_verifier_state *state = env->cur_state; struct bpf_verifier_state *state = env->cur_state;
struct bpf_reg_state *reg = &state->regs[regno]; struct bpf_reg_state *reg = &state->regs[regno];
...@@ -837,7 +838,8 @@ static int check_map_access(struct bpf_verifier_env *env, u32 regno, ...@@ -837,7 +838,8 @@ static int check_map_access(struct bpf_verifier_env *env, u32 regno,
regno); regno);
return -EACCES; return -EACCES;
} }
err = __check_map_access(env, regno, reg->smin_value + off, size); err = __check_map_access(env, regno, reg->smin_value + off, size,
zero_size_allowed);
if (err) { if (err) {
verbose(env, "R%d min value is outside of the array range\n", verbose(env, "R%d min value is outside of the array range\n",
regno); regno);
...@@ -853,7 +855,8 @@ static int check_map_access(struct bpf_verifier_env *env, u32 regno, ...@@ -853,7 +855,8 @@ static int check_map_access(struct bpf_verifier_env *env, u32 regno,
regno); regno);
return -EACCES; return -EACCES;
} }
err = __check_map_access(env, regno, reg->umax_value + off, size); err = __check_map_access(env, regno, reg->umax_value + off, size,
zero_size_allowed);
if (err) if (err)
verbose(env, "R%d max value is outside of the array range\n", verbose(env, "R%d max value is outside of the array range\n",
regno); regno);
...@@ -889,12 +892,13 @@ static bool may_access_direct_pkt_data(struct bpf_verifier_env *env, ...@@ -889,12 +892,13 @@ static bool may_access_direct_pkt_data(struct bpf_verifier_env *env,
} }
static int __check_packet_access(struct bpf_verifier_env *env, u32 regno, static int __check_packet_access(struct bpf_verifier_env *env, u32 regno,
int off, int size) int off, int size, bool zero_size_allowed)
{ {
struct bpf_reg_state *regs = cur_regs(env); struct bpf_reg_state *regs = cur_regs(env);
struct bpf_reg_state *reg = &regs[regno]; struct bpf_reg_state *reg = &regs[regno];
if (off < 0 || size <= 0 || (u64)off + size > reg->range) { if (off < 0 || size < 0 || (size == 0 && !zero_size_allowed) ||
(u64)off + size > reg->range) {
verbose(env, "invalid access to packet, off=%d size=%d, R%d(id=%d,off=%d,r=%d)\n", verbose(env, "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); off, size, regno, reg->id, reg->off, reg->range);
return -EACCES; return -EACCES;
...@@ -903,7 +907,7 @@ static int __check_packet_access(struct bpf_verifier_env *env, u32 regno, ...@@ -903,7 +907,7 @@ static int __check_packet_access(struct bpf_verifier_env *env, u32 regno,
} }
static int check_packet_access(struct bpf_verifier_env *env, u32 regno, int off, static int check_packet_access(struct bpf_verifier_env *env, u32 regno, int off,
int size) int size, bool zero_size_allowed)
{ {
struct bpf_reg_state *regs = cur_regs(env); struct bpf_reg_state *regs = cur_regs(env);
struct bpf_reg_state *reg = &regs[regno]; struct bpf_reg_state *reg = &regs[regno];
...@@ -922,7 +926,7 @@ static int check_packet_access(struct bpf_verifier_env *env, u32 regno, int off, ...@@ -922,7 +926,7 @@ static int check_packet_access(struct bpf_verifier_env *env, u32 regno, int off,
regno); regno);
return -EACCES; return -EACCES;
} }
err = __check_packet_access(env, regno, off, size); err = __check_packet_access(env, regno, off, size, zero_size_allowed);
if (err) { if (err) {
verbose(env, "R%d offset is outside of the packet\n", regno); verbose(env, "R%d offset is outside of the packet\n", regno);
return err; return err;
...@@ -1097,7 +1101,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn ...@@ -1097,7 +1101,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
return -EACCES; return -EACCES;
} }
err = check_map_access(env, regno, off, size); err = check_map_access(env, regno, off, size, false);
if (!err && t == BPF_READ && value_regno >= 0) if (!err && t == BPF_READ && value_regno >= 0)
mark_reg_unknown(env, regs, value_regno); mark_reg_unknown(env, regs, value_regno);
...@@ -1184,7 +1188,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn ...@@ -1184,7 +1188,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
value_regno); value_regno);
return -EACCES; return -EACCES;
} }
err = check_packet_access(env, regno, off, size); err = check_packet_access(env, regno, off, size, false);
if (!err && t == BPF_READ && value_regno >= 0) if (!err && t == BPF_READ && value_regno >= 0)
mark_reg_unknown(env, regs, value_regno); mark_reg_unknown(env, regs, value_regno);
} else { } else {
...@@ -1281,7 +1285,7 @@ static int check_stack_boundary(struct bpf_verifier_env *env, int regno, ...@@ -1281,7 +1285,7 @@ static int check_stack_boundary(struct bpf_verifier_env *env, int regno,
} }
off = regs[regno].off + regs[regno].var_off.value; off = regs[regno].off + regs[regno].var_off.value;
if (off >= 0 || off < -MAX_BPF_STACK || off + access_size > 0 || if (off >= 0 || off < -MAX_BPF_STACK || off + access_size > 0 ||
access_size <= 0) { access_size < 0 || (access_size == 0 && !zero_size_allowed)) {
verbose(env, "invalid stack type R%d off=%d access_size=%d\n", verbose(env, "invalid stack type R%d off=%d access_size=%d\n",
regno, off, access_size); regno, off, access_size);
return -EACCES; return -EACCES;
...@@ -1319,9 +1323,11 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno, ...@@ -1319,9 +1323,11 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
switch (reg->type) { switch (reg->type) {
case PTR_TO_PACKET: case PTR_TO_PACKET:
case PTR_TO_PACKET_META: case PTR_TO_PACKET_META:
return check_packet_access(env, regno, reg->off, access_size); return check_packet_access(env, regno, reg->off, access_size,
zero_size_allowed);
case PTR_TO_MAP_VALUE: case PTR_TO_MAP_VALUE:
return check_map_access(env, regno, reg->off, access_size); return check_map_access(env, regno, reg->off, access_size,
zero_size_allowed);
default: /* scalar_value|ptr_to_stack or invalid ptr */ default: /* scalar_value|ptr_to_stack or invalid ptr */
return check_stack_boundary(env, regno, access_size, return check_stack_boundary(env, regno, access_size,
zero_size_allowed, meta); zero_size_allowed, meta);
...@@ -1415,7 +1421,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno, ...@@ -1415,7 +1421,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
} }
if (type_is_pkt_pointer(type)) if (type_is_pkt_pointer(type))
err = check_packet_access(env, regno, reg->off, err = check_packet_access(env, regno, reg->off,
meta->map_ptr->key_size); meta->map_ptr->key_size,
false);
else else
err = check_stack_boundary(env, regno, err = check_stack_boundary(env, regno,
meta->map_ptr->key_size, meta->map_ptr->key_size,
...@@ -1431,7 +1438,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno, ...@@ -1431,7 +1438,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
} }
if (type_is_pkt_pointer(type)) if (type_is_pkt_pointer(type))
err = check_packet_access(env, regno, reg->off, err = check_packet_access(env, regno, reg->off,
meta->map_ptr->value_size); meta->map_ptr->value_size,
false);
else else
err = check_stack_boundary(env, regno, err = check_stack_boundary(env, regno,
meta->map_ptr->value_size, meta->map_ptr->value_size,
......
...@@ -78,12 +78,16 @@ EXPORT_SYMBOL_GPL(trace_call_bpf); ...@@ -78,12 +78,16 @@ EXPORT_SYMBOL_GPL(trace_call_bpf);
BPF_CALL_3(bpf_probe_read, void *, dst, u32, size, const void *, unsafe_ptr) BPF_CALL_3(bpf_probe_read, void *, dst, u32, size, const void *, unsafe_ptr)
{ {
int ret; int ret = 0;
if (unlikely(size == 0))
goto out;
ret = probe_kernel_read(dst, unsafe_ptr, size); ret = probe_kernel_read(dst, unsafe_ptr, size);
if (unlikely(ret < 0)) if (unlikely(ret < 0))
memset(dst, 0, size); memset(dst, 0, size);
out:
return ret; return ret;
} }
...@@ -92,7 +96,7 @@ static const struct bpf_func_proto bpf_probe_read_proto = { ...@@ -92,7 +96,7 @@ static const struct bpf_func_proto bpf_probe_read_proto = {
.gpl_only = true, .gpl_only = true,
.ret_type = RET_INTEGER, .ret_type = RET_INTEGER,
.arg1_type = ARG_PTR_TO_UNINIT_MEM, .arg1_type = ARG_PTR_TO_UNINIT_MEM,
.arg2_type = ARG_CONST_SIZE, .arg2_type = ARG_CONST_SIZE_OR_ZERO,
.arg3_type = ARG_ANYTHING, .arg3_type = ARG_ANYTHING,
}; };
......
...@@ -3579,7 +3579,7 @@ static struct bpf_test tests[] = { ...@@ -3579,7 +3579,7 @@ static struct bpf_test tests[] = {
.prog_type = BPF_PROG_TYPE_SCHED_CLS, .prog_type = BPF_PROG_TYPE_SCHED_CLS,
}, },
{ {
"helper access to packet: test19, cls helper fail range zero", "helper access to packet: test19, cls helper range zero",
.insns = { .insns = {
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
offsetof(struct __sk_buff, data)), offsetof(struct __sk_buff, data)),
...@@ -3599,8 +3599,7 @@ static struct bpf_test tests[] = { ...@@ -3599,8 +3599,7 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_0, 0), BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.result = REJECT, .result = ACCEPT,
.errstr = "invalid access to packet",
.prog_type = BPF_PROG_TYPE_SCHED_CLS, .prog_type = BPF_PROG_TYPE_SCHED_CLS,
}, },
{ {
...@@ -4379,10 +4378,10 @@ static struct bpf_test tests[] = { ...@@ -4379,10 +4378,10 @@ static struct bpf_test tests[] = {
BPF_LD_MAP_FD(BPF_REG_1, 0), BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4), BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), BPF_MOV64_IMM(BPF_REG_1, 0),
BPF_MOV64_IMM(BPF_REG_2, 0), BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
BPF_MOV64_IMM(BPF_REG_3, 0), BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_EMIT_CALL(BPF_FUNC_probe_read), BPF_EMIT_CALL(BPF_FUNC_probe_write_user),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.fixup_map2 = { 3 }, .fixup_map2 = { 3 },
...@@ -4486,9 +4485,10 @@ static struct bpf_test tests[] = { ...@@ -4486,9 +4485,10 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, BPF_ALU64_IMM(BPF_ADD, BPF_REG_1,
offsetof(struct test_val, foo)), offsetof(struct test_val, foo)),
BPF_MOV64_IMM(BPF_REG_2, 0), BPF_MOV64_REG(BPF_REG_2, BPF_REG_1),
BPF_MOV64_IMM(BPF_REG_1, 0),
BPF_MOV64_IMM(BPF_REG_3, 0), BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_EMIT_CALL(BPF_FUNC_probe_read), BPF_EMIT_CALL(BPF_FUNC_probe_write_user),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.fixup_map2 = { 3 }, .fixup_map2 = { 3 },
...@@ -4622,13 +4622,14 @@ static struct bpf_test tests[] = { ...@@ -4622,13 +4622,14 @@ static struct bpf_test tests[] = {
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
BPF_MOV64_IMM(BPF_REG_3, 0), BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3), BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
BPF_MOV64_IMM(BPF_REG_2, 0), BPF_MOV64_REG(BPF_REG_2, BPF_REG_1),
BPF_MOV64_IMM(BPF_REG_1, 0),
BPF_MOV64_IMM(BPF_REG_3, 0), BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_EMIT_CALL(BPF_FUNC_probe_read), BPF_EMIT_CALL(BPF_FUNC_probe_write_user),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.fixup_map2 = { 3 }, .fixup_map2 = { 3 },
.errstr = "R1 min value is outside of the array range", .errstr = "R2 min value is outside of the array range",
.result = REJECT, .result = REJECT,
.prog_type = BPF_PROG_TYPE_TRACEPOINT, .prog_type = BPF_PROG_TYPE_TRACEPOINT,
}, },
...@@ -4765,13 +4766,14 @@ static struct bpf_test tests[] = { ...@@ -4765,13 +4766,14 @@ static struct bpf_test tests[] = {
BPF_JMP_IMM(BPF_JGT, BPF_REG_3, BPF_JMP_IMM(BPF_JGT, BPF_REG_3,
offsetof(struct test_val, foo), 4), offsetof(struct test_val, foo), 4),
BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3), BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
BPF_MOV64_IMM(BPF_REG_2, 0), BPF_MOV64_REG(BPF_REG_2, BPF_REG_1),
BPF_MOV64_IMM(BPF_REG_1, 0),
BPF_MOV64_IMM(BPF_REG_3, 0), BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_EMIT_CALL(BPF_FUNC_probe_read), BPF_EMIT_CALL(BPF_FUNC_probe_write_user),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.fixup_map2 = { 3 }, .fixup_map2 = { 3 },
.errstr = "R1 min value is outside of the array range", .errstr = "R2 min value is outside of the array range",
.result = REJECT, .result = REJECT,
.prog_type = BPF_PROG_TYPE_TRACEPOINT, .prog_type = BPF_PROG_TYPE_TRACEPOINT,
}, },
...@@ -5350,7 +5352,7 @@ static struct bpf_test tests[] = { ...@@ -5350,7 +5352,7 @@ static struct bpf_test tests[] = {
BPF_EMIT_CALL(BPF_FUNC_probe_read), BPF_EMIT_CALL(BPF_FUNC_probe_read),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr = "invalid stack type R1 off=-64 access_size=0", .errstr = "invalid indirect read from stack off -64+0 size 64",
.result = REJECT, .result = REJECT,
.prog_type = BPF_PROG_TYPE_TRACEPOINT, .prog_type = BPF_PROG_TYPE_TRACEPOINT,
}, },
...@@ -5505,7 +5507,7 @@ static struct bpf_test tests[] = { ...@@ -5505,7 +5507,7 @@ static struct bpf_test tests[] = {
BPF_MOV64_IMM(BPF_REG_0, 0), BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr = "invalid stack type R1 off=-64 access_size=0", .errstr = "invalid indirect read from stack off -64+0 size 64",
.result = REJECT, .result = REJECT,
.prog_type = BPF_PROG_TYPE_TRACEPOINT, .prog_type = BPF_PROG_TYPE_TRACEPOINT,
}, },
...@@ -5668,7 +5670,7 @@ static struct bpf_test tests[] = { ...@@ -5668,7 +5670,7 @@ static struct bpf_test tests[] = {
.prog_type = BPF_PROG_TYPE_SCHED_CLS, .prog_type = BPF_PROG_TYPE_SCHED_CLS,
}, },
{ {
"helper access to variable memory: size = 0 not allowed on != NULL", "helper access to variable memory: size = 0 allowed on != NULL stack pointer",
.insns = { .insns = {
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
...@@ -5681,8 +5683,99 @@ static struct bpf_test tests[] = { ...@@ -5681,8 +5683,99 @@ static struct bpf_test tests[] = {
BPF_EMIT_CALL(BPF_FUNC_csum_diff), BPF_EMIT_CALL(BPF_FUNC_csum_diff),
BPF_EXIT_INSN(), BPF_EXIT_INSN(),
}, },
.errstr = "invalid stack type R1 off=-8 access_size=0", .result = ACCEPT,
.result = REJECT, .prog_type = BPF_PROG_TYPE_SCHED_CLS,
},
{
"helper access to variable memory: size = 0 allowed on != NULL map pointer",
.insns = {
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
BPF_MOV64_IMM(BPF_REG_2, 0),
BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_MOV64_IMM(BPF_REG_4, 0),
BPF_MOV64_IMM(BPF_REG_5, 0),
BPF_EMIT_CALL(BPF_FUNC_csum_diff),
BPF_EXIT_INSN(),
},
.fixup_map1 = { 3 },
.result = ACCEPT,
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
},
{
"helper access to variable memory: size possible = 0 allowed on != NULL stack pointer",
.insns = {
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0),
BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 8, 7),
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, 0),
BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_MOV64_IMM(BPF_REG_4, 0),
BPF_MOV64_IMM(BPF_REG_5, 0),
BPF_EMIT_CALL(BPF_FUNC_csum_diff),
BPF_EXIT_INSN(),
},
.fixup_map1 = { 3 },
.result = ACCEPT,
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
},
{
"helper access to variable memory: size possible = 0 allowed on != NULL map pointer",
.insns = {
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
BPF_FUNC_map_lookup_elem),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0),
BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 8, 4),
BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_MOV64_IMM(BPF_REG_4, 0),
BPF_MOV64_IMM(BPF_REG_5, 0),
BPF_EMIT_CALL(BPF_FUNC_csum_diff),
BPF_EXIT_INSN(),
},
.fixup_map1 = { 3 },
.result = ACCEPT,
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
},
{
"helper access to variable memory: size possible = 0 allowed on != NULL packet pointer",
.insns = {
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
offsetof(struct __sk_buff, data)),
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
offsetof(struct __sk_buff, data_end)),
BPF_MOV64_REG(BPF_REG_0, BPF_REG_6),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 7),
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 0),
BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 8, 4),
BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_MOV64_IMM(BPF_REG_4, 0),
BPF_MOV64_IMM(BPF_REG_5, 0),
BPF_EMIT_CALL(BPF_FUNC_csum_diff),
BPF_EXIT_INSN(),
},
.result = ACCEPT,
.prog_type = BPF_PROG_TYPE_SCHED_CLS, .prog_type = BPF_PROG_TYPE_SCHED_CLS,
}, },
{ {
......
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