From 06ce17e825e354482d8d1be85f2fd5904a7053c7 Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Thu, 11 Jan 2024 10:37:28 -0800 Subject: [PATCH] Update to latest bpf_conformance suite Signed-off-by: Dave Thaler --- external/bpf_conformance | 2 +- src/asm_unmarshal.cpp | 28 +++++++++++++++++----------- src/test/test_conformance.cpp | 25 ++++++++++++++++++++----- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/external/bpf_conformance b/external/bpf_conformance index fe414a7f0..13de786ef 160000 --- a/external/bpf_conformance +++ b/external/bpf_conformance @@ -1 +1 @@ -Subproject commit fe414a7f063dc68d506c6368e4e0c31ffb1f2584 +Subproject commit 13de786efe55fb9c456561cf3ca1de4f51f590de diff --git a/src/asm_unmarshal.cpp b/src/asm_unmarshal.cpp index 102f1fa80..f11697bef 100644 --- a/src/asm_unmarshal.cpp +++ b/src/asm_unmarshal.cpp @@ -87,28 +87,20 @@ struct Unmarshaller { explicit Unmarshaller(vector>& notes, const program_info& info) : notes{notes}, info{info} { note_next_pc(); } auto getAluOp(size_t pc, ebpf_inst inst) -> std::variant { + // First handle instructions that support a non-zero offset. switch (inst.opcode & INST_ALU_OP_MASK) { - case INST_ALU_OP_ADD: return Bin::Op::ADD; - case INST_ALU_OP_SUB: return Bin::Op::SUB; - case INST_ALU_OP_MUL: return Bin::Op::MUL; case INST_ALU_OP_DIV: switch (inst.offset) { case 0: return Bin::Op::UDIV; case 1: return Bin::Op::SDIV; default: throw InvalidInstruction{pc, "invalid ALU op 0x30"}; } - case INST_ALU_OP_OR: return Bin::Op::OR; - case INST_ALU_OP_AND: return Bin::Op::AND; - case INST_ALU_OP_LSH: return Bin::Op::LSH; - case INST_ALU_OP_RSH: return Bin::Op::RSH; - case INST_ALU_OP_NEG: return Un::Op::NEG; case INST_ALU_OP_MOD: switch (inst.offset) { case 0: return Bin::Op::UMOD; case 1: return Bin::Op::SMOD; default: throw InvalidInstruction{pc, "invalid ALU op 0x90"}; } - case INST_ALU_OP_XOR: return Bin::Op::XOR; case INST_ALU_OP_MOV: switch (inst.offset) { case 0: return Bin::Op::MOV; @@ -117,6 +109,22 @@ struct Unmarshaller { case 32: return Bin::Op::MOVSX32; default: throw InvalidInstruction{pc, "invalid ALU op 0xb0"}; } + } + + // All the rest require a zero offset. + if (inst.offset != 0) + throw InvalidInstruction{pc, "nonzero offset for register alu op"}; + + switch (inst.opcode & INST_ALU_OP_MASK) { + case INST_ALU_OP_ADD: return Bin::Op::ADD; + case INST_ALU_OP_SUB: return Bin::Op::SUB; + case INST_ALU_OP_MUL: return Bin::Op::MUL; + case INST_ALU_OP_OR: return Bin::Op::OR; + case INST_ALU_OP_AND: return Bin::Op::AND; + case INST_ALU_OP_LSH: return Bin::Op::LSH; + case INST_ALU_OP_RSH: return Bin::Op::RSH; + case INST_ALU_OP_NEG: return Un::Op::NEG; + case INST_ALU_OP_XOR: return Bin::Op::XOR; case INST_ALU_OP_ARSH: if ((inst.opcode & INST_CLS_MASK) == INST_CLS_ALU) note("arsh32 is not allowed"); @@ -150,8 +158,6 @@ struct Unmarshaller { uint64_t zero_extend(int32_t imm) { return (uint64_t)(uint32_t)imm; } auto getBinValue(pc_t pc, ebpf_inst inst) -> Value { - if (inst.offset != 0) - throw InvalidInstruction{pc, "nonzero offset for register alu op"}; if (inst.opcode & INST_SRC_REG) { if (inst.imm != 0) throw InvalidInstruction{pc, "nonzero imm for register alu op"}; diff --git a/src/test/test_conformance.cpp b/src/test/test_conformance.cpp index 73d3e6c5c..c7a681cfb 100644 --- a/src/test/test_conformance.cpp +++ b/src/test/test_conformance.cpp @@ -13,7 +13,7 @@ void test_conformance(std::string filename, bpf_conformance_test_result_t expect std::filesystem::path plugin_path = test_path.remove_filename().append("conformance_check" + extension.string()).string(); std::map> result = - bpf_conformance(test_files, plugin_path, {}, {}, {}, bpf_conformance_test_CPU_version_t::v3, + bpf_conformance(test_files, plugin_path, {}, {}, {}, bpf_conformance_test_CPU_version_t::v4, bpf_conformance_list_instructions_t::LIST_INSTRUCTIONS_NONE, true); for (auto file : test_files) { auto& [file_result, reason] = result[file]; @@ -34,21 +34,21 @@ void test_conformance(std::string filename, bpf_conformance_test_result_t expect // legitimate programs from being usable. #define TEST_CONFORMANCE_VERIFICATION_FAILED(filename) \ TEST_CASE("conformance_check " filename, "[conformance]") { \ - test_conformance(filename, bpf_conformance_test_result_t::TEST_RESULT_FAIL, "Verification failed"); \ + test_conformance(filename, bpf_conformance_test_result_t::TEST_RESULT_ERROR, "Verification failed"); \ } // Any tests that return top are safe, but are not as precise as they // could be and so may prevent legitimate programs from being usable. #define TEST_CONFORMANCE_TOP(filename) \ TEST_CASE("conformance_check " filename, "[conformance]") { \ - test_conformance(filename, bpf_conformance_test_result_t::TEST_RESULT_FAIL, "Couldn't determine r0 value"); \ + test_conformance(filename, bpf_conformance_test_result_t::TEST_RESULT_ERROR, "Couldn't determine r0 value"); \ } // Any tests that return a range are safe, but are not as precise as they // could be and so may prevent legitimate programs from being usable. #define TEST_CONFORMANCE_RANGE(filename, range) \ TEST_CASE("conformance_check " filename, "[conformance]") { \ - test_conformance(filename, bpf_conformance_test_result_t::TEST_RESULT_FAIL, "r0 value is range " range); \ + test_conformance(filename, bpf_conformance_test_result_t::TEST_RESULT_ERROR, "r0 value is range " range); \ } TEST_CONFORMANCE("add.data") @@ -74,8 +74,9 @@ TEST_CONFORMANCE("be16.data") TEST_CONFORMANCE("be32-high.data") TEST_CONFORMANCE("be32.data") TEST_CONFORMANCE("be64.data") +TEST_CONFORMANCE_VERIFICATION_FAILED("call_local.data") TEST_CONFORMANCE("call_unwind_fail.data") -TEST_CONFORMANCE("div-by-zero-reg.data") +TEST_CONFORMANCE("div32-by-zero-reg.data") TEST_CONFORMANCE("div32-high-divisor.data") TEST_CONFORMANCE("div32-imm.data") TEST_CONFORMANCE("div32-reg.data") @@ -149,6 +150,14 @@ TEST_CONFORMANCE_VERIFICATION_FAILED("lock_and.data") TEST_CONFORMANCE_VERIFICATION_FAILED("lock_and32.data") TEST_CONFORMANCE_VERIFICATION_FAILED("lock_cmpxchg.data") TEST_CONFORMANCE_VERIFICATION_FAILED("lock_cmpxchg32.data") +TEST_CONFORMANCE_VERIFICATION_FAILED("lock_fetch_add.data") +TEST_CONFORMANCE_VERIFICATION_FAILED("lock_fetch_add32.data") +TEST_CONFORMANCE_VERIFICATION_FAILED("lock_fetch_and.data") +TEST_CONFORMANCE_VERIFICATION_FAILED("lock_fetch_and32.data") +TEST_CONFORMANCE_VERIFICATION_FAILED("lock_fetch_or.data") +TEST_CONFORMANCE_VERIFICATION_FAILED("lock_fetch_or32.data") +TEST_CONFORMANCE_VERIFICATION_FAILED("lock_fetch_xor.data") +TEST_CONFORMANCE_VERIFICATION_FAILED("lock_fetch_xor32.data") TEST_CONFORMANCE_VERIFICATION_FAILED("lock_or.data") TEST_CONFORMANCE_VERIFICATION_FAILED("lock_or32.data") TEST_CONFORMANCE_VERIFICATION_FAILED("lock_xchg.data") @@ -195,6 +204,12 @@ TEST_CONFORMANCE("rsh64-imm-neg.data") TEST_CONFORMANCE("rsh64-reg.data") TEST_CONFORMANCE("rsh64-reg-high.data") TEST_CONFORMANCE("rsh64-reg-neg.data") +TEST_CONFORMANCE("sdiv32-by-zero-reg.data") +TEST_CONFORMANCE("sdiv32-imm.data") +TEST_CONFORMANCE("sdiv32-reg.data") +TEST_CONFORMANCE("sdiv64-by-zero-reg.data") +TEST_CONFORMANCE("sdiv64-imm.data") +TEST_CONFORMANCE("sdiv64-reg.data") TEST_CONFORMANCE("stack.data") TEST_CONFORMANCE("stb.data") TEST_CONFORMANCE("stdw.data")