diff --git a/vm/inc/ubpf.h b/vm/inc/ubpf.h index 35f6046e0..bf57277bd 100644 --- a/vm/inc/ubpf.h +++ b/vm/inc/ubpf.h @@ -98,7 +98,7 @@ int ubpf_load(struct ubpf_vm *vm, const void *code, uint32_t code_len, char **er */ int ubpf_load_elf(struct ubpf_vm *vm, const void *elf, size_t elf_len, char **errmsg); -uint64_t ubpf_exec(const struct ubpf_vm *vm, void *mem, size_t mem_len); +int ubpf_exec(const struct ubpf_vm *vm, void *mem, size_t mem_len, uint64_t* bpf_return_value); ubpf_jit_fn ubpf_compile(struct ubpf_vm *vm, char **errmsg); diff --git a/vm/test.c b/vm/test.c index c7ae9a839..74e99191b 100644 --- a/vm/test.c +++ b/vm/test.c @@ -139,7 +139,8 @@ int main(int argc, char **argv) } ret = fn(mem, mem_len); } else { - ret = ubpf_exec(vm, mem, mem_len); + if (ubpf_exec(vm, mem, mem_len, &ret) < 0) + ret = UINT64_MAX; } printf("0x%"PRIx64"\n", ret); diff --git a/vm/ubpf_vm.c b/vm/ubpf_vm.c index 2dece173a..b860ba857 100644 --- a/vm/ubpf_vm.c +++ b/vm/ubpf_vm.c @@ -143,8 +143,8 @@ u32(uint64_t x) return x; } -uint64_t -ubpf_exec(const struct ubpf_vm *vm, void *mem, size_t mem_len) +int +ubpf_exec(const struct ubpf_vm *vm, void *mem, size_t mem_len, uint64_t* bpf_return_value) { uint16_t pc = 0; const struct ebpf_inst *insts = vm->insts; @@ -153,7 +153,7 @@ ubpf_exec(const struct ubpf_vm *vm, void *mem, size_t mem_len) if (!insts) { /* Code must be loaded before we can execute */ - return UINT64_MAX; + return -1; } reg[1] = (uintptr_t)mem; @@ -196,7 +196,7 @@ ubpf_exec(const struct ubpf_vm *vm, void *mem, size_t mem_len) case EBPF_OP_DIV_REG: if (reg[inst.src] == 0) { vm->error_printf(stderr, "uBPF error: division by zero at PC %u\n", cur_pc); - return UINT64_MAX; + return -1; } reg[inst.dst] = u32(reg[inst.dst]) / u32(reg[inst.src]); reg[inst.dst] &= UINT32_MAX; @@ -244,7 +244,7 @@ ubpf_exec(const struct ubpf_vm *vm, void *mem, size_t mem_len) case EBPF_OP_MOD_REG: if (reg[inst.src] == 0) { vm->error_printf(stderr, "uBPF error: division by zero at PC %u\n", cur_pc); - return UINT64_MAX; + return -1; } reg[inst.dst] = u32(reg[inst.dst]) % u32(reg[inst.src]); break; @@ -317,7 +317,7 @@ ubpf_exec(const struct ubpf_vm *vm, void *mem, size_t mem_len) case EBPF_OP_DIV64_REG: if (reg[inst.src] == 0) { vm->error_printf(stderr, "uBPF error: division by zero at PC %u\n", cur_pc); - return UINT64_MAX; + return -1; } reg[inst.dst] /= reg[inst.src]; break; @@ -354,7 +354,7 @@ ubpf_exec(const struct ubpf_vm *vm, void *mem, size_t mem_len) case EBPF_OP_MOD64_REG: if (reg[inst.src] == 0) { vm->error_printf(stderr, "uBPF error: division by zero at PC %u\n", cur_pc); - return UINT64_MAX; + return -1; } reg[inst.dst] %= reg[inst.src]; break; @@ -385,13 +385,13 @@ ubpf_exec(const struct ubpf_vm *vm, void *mem, size_t mem_len) #define BOUNDS_CHECK_LOAD(size) \ do { \ if (!bounds_check(vm, (char *)reg[inst.src] + inst.offset, size, "load", cur_pc, mem, mem_len, stack)) { \ - return UINT64_MAX; \ + return -1; \ } \ } while (0) #define BOUNDS_CHECK_STORE(size) \ do { \ if (!bounds_check(vm, (char *)reg[inst.dst] + inst.offset, size, "store", cur_pc, mem, mem_len, stack)) { \ - return UINT64_MAX; \ + return -1; \ } \ } while (0) @@ -564,7 +564,8 @@ ubpf_exec(const struct ubpf_vm *vm, void *mem, size_t mem_len) } break; case EBPF_OP_EXIT: - return reg[0]; + *bpf_return_value = reg[0]; + return 0; case EBPF_OP_CALL: reg[0] = vm->ext_funcs[inst.imm](reg[1], reg[2], reg[3], reg[4], reg[5]); break;