From f543c2a3f7cec674f33079d75d71310d1c3ddaff Mon Sep 17 00:00:00 2001 From: Alan Jowett Date: Tue, 22 Jun 2021 15:29:18 -0600 Subject: [PATCH] ubpf_exec should separate errors returned from the return value Signed-off-by: Alan Jowett --- vm/inc/ubpf.h | 2 +- vm/test.c | 3 ++- vm/ubpf_vm.c | 21 +++++++++++---------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/vm/inc/ubpf.h b/vm/inc/ubpf.h index 1d9472bf1..cd189057f 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 2709635e0..830b691d4 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; @@ -195,7 +195,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; @@ -243,7 +243,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; @@ -316,7 +316,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; @@ -353,7 +353,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; @@ -384,13 +384,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) @@ -563,7 +563,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;