|
@@ -653,6 +653,16 @@ static int check_map_access(struct verifier_env *env, u32 regno, int off,
|
|
|
|
|
|
#define MAX_PACKET_OFF 0xffff
|
|
|
|
|
|
+static bool may_write_pkt_data(enum bpf_prog_type type)
|
|
|
+{
|
|
|
+ switch (type) {
|
|
|
+ case BPF_PROG_TYPE_XDP:
|
|
|
+ return true;
|
|
|
+ default:
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static int check_packet_access(struct verifier_env *env, u32 regno, int off,
|
|
|
int size)
|
|
|
{
|
|
@@ -806,10 +816,15 @@ static int check_mem_access(struct verifier_env *env, u32 regno, int off,
|
|
|
err = check_stack_read(state, off, size, value_regno);
|
|
|
}
|
|
|
} else if (state->regs[regno].type == PTR_TO_PACKET) {
|
|
|
- if (t == BPF_WRITE) {
|
|
|
+ if (t == BPF_WRITE && !may_write_pkt_data(env->prog->type)) {
|
|
|
verbose("cannot write into packet\n");
|
|
|
return -EACCES;
|
|
|
}
|
|
|
+ if (t == BPF_WRITE && value_regno >= 0 &&
|
|
|
+ is_pointer_value(env, value_regno)) {
|
|
|
+ verbose("R%d leaks addr into packet\n", value_regno);
|
|
|
+ return -EACCES;
|
|
|
+ }
|
|
|
err = check_packet_access(env, regno, off, size);
|
|
|
if (!err && t == BPF_READ && value_regno >= 0)
|
|
|
mark_reg_unknown_value(state->regs, value_regno);
|