From b46d41cea1f26d595a286278fc65047b544e8625 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 30 Apr 2024 02:51:03 +0200 Subject: [PATCH 001/143] major changes due to difference between RISC-V and x64. Updated versions of intercept.c and assembly files still need to be pushed. A lot of clean up to do --- src/disasm_wrapper.c | 148 ++++++++------- src/intercept.h | 23 ++- src/intercept_desc.c | 18 +- src/patcher.c | 423 ++++++++++++++++++++++++++++--------------- 4 files changed, 385 insertions(+), 227 deletions(-) diff --git a/src/disasm_wrapper.c b/src/disasm_wrapper.c index acb7d0f..8fc0e5a 100644 --- a/src/disasm_wrapper.c +++ b/src/disasm_wrapper.c @@ -90,7 +90,7 @@ intercept_disasm_init(const unsigned char *begin, const unsigned char *end) * Initialize the disassembler. * The handle here must be passed to capstone each time it is used. */ - if (cs_open(CS_ARCH_X86, CS_MODE_64, &context->handle) != CS_ERR_OK) + if (cs_open(CS_ARCH_RISCV, CS_MODE_RISCV64, &context->handle) != CS_ERR_OK) xabort("cs_open"); /* @@ -145,9 +145,8 @@ check_op(struct intercept_disasm_result *result, cs_x86_op *op, */ const unsigned char *rip = code + result->length; - if (op->type == X86_OP_REG) { - if (op->reg == X86_REG_IP || - op->reg == X86_REG_RIP) { + if (op->type == RISCV_OP_REG) { + if (op->reg == X86_REG_IP || op->reg == X86_REG_RIP) { /* * Example: mov %rip, %rax */ @@ -207,23 +206,23 @@ struct intercept_disasm_result intercept_disasm_next_instruction(struct intercept_disasm_context *context, const unsigned char *code) { - static const unsigned char endbr64[] = {0xf3, 0x0f, 0x1e, 0xfa}; + //static const unsigned char endbr64[] = {0xf3, 0x0f, 0x1e, 0xfa}; // no endbr equivalent in RISC-V struct intercept_disasm_result result = {.address = code, 0, }; const unsigned char *start = code; size_t size = (size_t)(context->end - code + 1); uint64_t address = (uint64_t)code; - if (size >= sizeof(endbr64) && - memcmp(code, endbr64, sizeof(endbr64)) == 0) { - result.is_set = true; - result.is_endbr = true; - result.length = 4; -#ifndef NDEBUG - result.mnemonic = "endbr64"; -#endif - return result; - } +// if (size >= sizeof(endbr64) && +// memcmp(code, endbr64, sizeof(endbr64)) == 0) { +// result.is_set = true; +// result.is_endbr = true; +// result.length = 4; +// #ifndef NDEBUG +// result.mnemonic = "endbr64"; +// #endif +// return result; +// } if (!cs_disasm_iter(context->handle, &start, &size, &address, context->insn)) { @@ -234,50 +233,67 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, assert(result.length != 0); - result.is_syscall = (context->insn->id == X86_INS_SYSCALL); - result.is_call = (context->insn->id == X86_INS_CALL); - result.is_ret = (context->insn->id == X86_INS_RET); - result.is_rel_jump = false; - result.is_indirect_jump = false; + result.is_syscall = (context->insn->id == RISCV_INS_ECALL); + // result.is_call = (context->insn->id == RISCV_INS_JAL || + // context->insn->id == RISCV_INS_JALR); + // result.is_ret = (context->insn->id == RISCV_INS_JALR); // jalr รจ usata sia per ret che per le chiamate, per asserire o meno queste variabili servono verifiche diverse + // result.is_rel_jump = false; + // result.is_indirect_jump = false; #ifndef NDEBUG result.mnemonic = context->insn->mnemonic; #endif switch (context->insn->id) { - case X86_INS_JAE: - case X86_INS_JA: - case X86_INS_JBE: - case X86_INS_JB: - case X86_INS_JCXZ: - case X86_INS_JECXZ: - case X86_INS_JE: - case X86_INS_JGE: - case X86_INS_JG: - case X86_INS_JLE: - case X86_INS_JL: - case X86_INS_JMP: - case X86_INS_JNE: - case X86_INS_JNO: - case X86_INS_JNP: - case X86_INS_JNS: - case X86_INS_JO: - case X86_INS_JP: - case X86_INS_JRCXZ: - case X86_INS_JS: - case X86_INS_LOOP: - case X86_INS_CALL: + case RISCV_INS_BEQ: // these are jumps and their destination is calculated as PC + offset; + case RISCV_INS_BGE: + case RISCV_INS_BGEU: + case RISCV_INS_BLT: + case RISCV_INS_BLTU: + case RISCV_INS_BNE: + case RISCV_INS_JAL: + result.has_ip_relative_opr = true; result.is_jump = true; - assert(context->insn->detail->x86.op_count == 1); break; - case X86_INS_NOP: - result.is_nop = true; + case RISCV_INS_AUIPC: + result.has_ip_relative_opr = true; + break; + case RISCV_INS_JALR: + result.is_ret = true; + cs_riscv_op *op; + for (uint8_t op_i = 0; result.is_ret && + op_i < context->insn->detail->riscv.op_count; ++op_i) { + op = context->insn->detail->riscv.operands + op_i; + switch (op->type) { + case RISCV_OP_REG: + if (op->reg != RISCV_REG_ZERO || op->reg != RISCV_REG_RA) { + result.is_ret = false; + } + break; + case RISCV_OP_IMM: + if (op->imm != 0) { + result.is_ret = false; + } + break; + case RISCV_OP_MEM: + if (op->mem.base != RISCV_REG_RA || op->mem.disp != 0) { + result.is_ret = false; + } + break; + default: + result.is_ret = false; + break; + } + } + if (!result.is_ret) { + result.is_jump = true; + } break; default: result.is_jump = false; + result.has_ip_relative_opr = false; break; } - result.has_ip_relative_opr = false; /* * Loop over all operands of the instruction currently being decoded. @@ -293,26 +309,26 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, * be relocated ( including relative jumps, which naturally also * rely on the RIP register ). */ - for (uint8_t op_i = 0; - op_i < context->insn->detail->x86.op_count; ++op_i) - check_op(&result, context->insn->detail->x86.operands + op_i, - code); - - result.is_lea_rip = (context->insn->id == X86_INS_LEA && - result.has_ip_relative_opr); - - if (result.is_lea_rip) { - /* - * Extract the four bits from the encoding, which - * specify the destination register. - */ - - /* one bit from the REX prefix */ - result.arg_register_bits = ((code[0] & 4) << 1); - - /* three bits from the ModRM byte */ - result.arg_register_bits |= ((code[2] >> 3) & 7); - } + // for (uint8_t op_i = 0; // needed? PC isn't usable as operand in RISC-V, so you know if instruction it's PC-relative from the instruction itself + // op_i < context->insn->detail->x86.op_count; ++op_i) + // check_op(&result, context->insn->detail->x86.operands + op_i, + // code); + + // result.is_lea_rip = (context->insn->id == X86_INS_LEA && // no LEA instruction equivalent in RISC-V machine language + // result.has_ip_relative_opr); + // + // if (result.is_lea_rip) { + // /* + // * Extract the four bits from the encoding, which + // * specify the destination register. + // */ + // + // /* one bit from the REX prefix */ + // result.arg_register_bits = ((code[0] & 4) << 1); + // + // /* three bits from the ModRM byte */ + // result.arg_register_bits |= ((code[2] >> 3) & 7); + // } result.is_set = true; diff --git a/src/intercept.h b/src/intercept.h index 2edfd29..a8a2fe7 100644 --- a/src/intercept.h +++ b/src/intercept.h @@ -202,14 +202,21 @@ void mprotect_asm_wrappers(void); */ void activate_patches(struct intercept_desc *desc); -#define SYSCALL_INS_SIZE 2 -#define JUMP_INS_SIZE 5 -#define CALL_OPCODE 0xe8 -#define JMP_OPCODE 0xe9 -#define SHORT_JMP_OPCODE 0xeb -#define PUSH_IMM_OPCODE 0x68 -#define NOP_OPCODE 0x90 -#define INT3_OPCODE 0xCC +#define ECALL_INS_SIZE 4 +/* + * 16 bytes are actually needed to write 4 instructions. The 1st one decreases + * sp value, the 2nd one stores one tmp reg into the stack, the 3rd one uses the + * saved register to write part of the destination address and the 4th one is + * actually the jump summing its immediate value to the just wrote register to + * calculate desination of the jump + */ +#define JUMP_INS_SIZE 16 +// #define CALL_OPCODE 0xe8 +// #define JMP_OPCODE 0xe9 +// #define SHORT_JMP_OPCODE 0xeb +// #define PUSH_IMM_OPCODE 0x68 +// #define NOP_OPCODE 0x90 +// #define INT3_OPCODE 0xCC bool is_overwritable_nop(const struct intercept_disasm_result *ins); diff --git a/src/intercept_desc.c b/src/intercept_desc.c index 2d083ec..1136edb 100644 --- a/src/intercept_desc.c +++ b/src/intercept_desc.c @@ -353,8 +353,7 @@ find_jumps_in_section_rela(struct intercept_desc *desc, Elf64_Shdr *section, for (size_t i = 0; i < sym_count; ++i) { switch (ELF64_R_TYPE(syms[i].r_info)) { - case R_X86_64_RELATIVE: - case R_X86_64_RELATIVE64: + case R_RISCV_RELATIVE: /* Relocation type: "Adjust by program base" */ debug_dump("jump target: %lx\n", @@ -431,7 +430,8 @@ add_new_patch(struct intercept_desc *desc) bool is_overwritable_nop(const struct intercept_disasm_result *ins) { - return ins->is_nop && ins->length >= 2 + 5; + // return ins->is_nop && ins->length >= 2 + 5; + return false; // dummy function: NOP are 4 bytes on RISC-V } /* @@ -483,11 +483,11 @@ crawl_text(struct intercept_desc *desc) continue; } - if (result.has_ip_relative_opr) - mark_jump(desc, result.rip_ref_addr); + // if (result.has_ip_relative_opr) + // mark_jump(desc, result.rip_ref_addr); - if (is_overwritable_nop(&result)) - mark_nop(desc, code, result.length); + // if (is_overwritable_nop(&result)) // NOP is overwritable if its size is >= 7 bytes; + // mark_nop(desc, code, result.length); // RISC-V NOPs are fixed to 4-byte length, so it's never overwritable /* * Generate a new patch description, if: @@ -523,7 +523,7 @@ crawl_text(struct intercept_desc *desc) patch->preceding_ins_2 = prevs[0]; patch->preceding_ins = prevs[1]; patch->following_ins = result; - patch->syscall_addr = code - SYSCALL_INS_SIZE; + patch->syscall_addr = code - ECALL_INS_SIZE; ptrdiff_t syscall_offset = patch->syscall_addr - (desc->text_start - desc->text_offset); @@ -702,7 +702,7 @@ find_syscalls(struct intercept_desc *desc) (uintptr_t)desc->text_start, (uintptr_t)desc->text_end); allocate_jump_table(desc); - allocate_nop_table(desc); + // allocate_nop_table(desc); // should be able to ditch without any loss, since RISC-V could not use NOPs as x86_64 intended to for (Elf64_Half i = 0; i < desc->symbol_tables.count; ++i) find_jumps_in_section_syms(desc, diff --git a/src/patcher.c b/src/patcher.c index a82aecf..50d701c 100644 --- a/src/patcher.c +++ b/src/patcher.c @@ -80,42 +80,33 @@ #include -/* The size of a trampoline jump, jmp instruction + pointer */ -enum { TRAMPOLINE_SIZE = 6 + 8 }; +/* The size of a trampoline jump, 64-bit address loading process into a register + * (which requires 14 instructions to encode directly in machine code) + JALR. + */ +enum { TRAMPOLINE_SIZE = 15 * 4 }; static void create_wrapper(struct patch_desc *patch, unsigned char **dst); /* * create_absolute_jump(from, to) - * Create an indirect jump, with the pointer right next to the instruction. - * - * jmp *0(%rip) * - * This uses up 6 bytes for the jump instruction, and another 8 bytes - * for the pointer right after the instruction. */ static unsigned char * create_absolute_jump(unsigned char *from, void *to) { - *from++ = 0xff; /* opcode of RIP based indirect jump */ - *from++ = 0x25; /* opcode of RIP based indirect jump */ - *from++ = 0; /* 32 bit zero offset */ - *from++ = 0; /* this means zero relative to the value */ - *from++ = 0; /* of RIP, which during the execution of the jump */ - *from++ = 0; /* points to right after the jump instruction */ - - unsigned char *d = (unsigned char *)&to; - - *from++ = d[0]; /* so, this is where (RIP + 0) points to, */ - *from++ = d[1]; /* jump reads the destination address */ - *from++ = d[2]; /* from here */ - *from++ = d[3]; - *from++ = d[4]; - *from++ = d[5]; - *from++ = d[6]; - *from++ = d[7]; - - return from; + uint32_t *instructions = (uint32_t)from; + create_load_uint64t_into_a6(from,(uint64_t)value); + instructions[5] = 0x7ffff337; + instructions[6] = 0x7ff06393; + instructions[7] = 0x00139393; + instructions[8] = 0x0013e393; + instructions[9] = 0x00736333; + instructions[10] = 0x00131313; + instructions[11] = 0x00136313; + instructions[12] = 0x0062f2b3; + instructions[13] = 0x00586833; + instructions[14] = 0x00080067; + return instructions + 15; } /* @@ -307,26 +298,22 @@ static void check_surrounding_instructions(struct intercept_desc *desc, struct patch_desc *patch) { - patch->uses_prev_ins = patch->preceding_ins.is_lea_rip || - (is_copiable_before_syscall(patch->preceding_ins) && + patch->uses_prev_ins = (is_copiable_before_syscall(patch->preceding_ins) && !is_overwritable_nop(&patch->preceding_ins) && !has_jump(desc, patch->syscall_addr)); if (patch->uses_prev_ins) { - patch->uses_prev_ins_2 = patch->preceding_ins_2.is_lea_rip || - (patch->uses_prev_ins && + patch->uses_prev_ins_2 = (patch->uses_prev_ins && is_copiable_before_syscall(patch->preceding_ins_2) && !is_overwritable_nop(&patch->preceding_ins_2) && - !has_jump(desc, patch->syscall_addr - - patch->preceding_ins.length)); + !has_jump(desc, patch->syscall_addr - patch->preceding_ins.length)); } else { patch->uses_prev_ins_2 = false; } - patch->uses_next_ins = patch->following_ins.is_lea_rip || - (is_copiable_after_syscall(patch->following_ins) && + patch->uses_next_ins = (is_copiable_after_syscall(patch->following_ins) && !is_overwritable_nop(&patch->following_ins) && - !has_jump(desc, patch->syscall_addr + SYSCALL_INS_SIZE)); + !has_jump(desc, patch->syscall_addr + ECALL_INS_SIZE)); } /* @@ -354,37 +341,37 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) debug_dump("patching %s:0x%lx\n", desc->path, patch->syscall_addr - desc->base_addr); - assign_nop_trampoline(desc, patch, &next_nop_i); - - if (patch->uses_nop_trampoline) { - /* - * The preferred option it to use a 5 byte relative - * jump in a padding space between symbols in libc. - * If such padding space is found, a 2 byte short - * jump is enough for jumping to it, thus no - * instructions other than the syscall - * itself need to be overwritten. - */ - patch->uses_prev_ins = false; - patch->uses_prev_ins_2 = false; - patch->uses_next_ins = false; - patch->dst_jmp_patch = - patch->nop_trampoline.address + 2; - /* - * The first two bytes of the nop are used for - * something else, see the explanation - * at is_overwritable_nop in intercept_desc.c - */ - - /* - * Return to libc: - * just jump to instruction right after the place - * where the syscall instruction was originally. - */ - patch->return_address = - patch->syscall_addr + SYSCALL_INS_SIZE; - - } else { + // assign_nop_trampoline(desc, patch, &next_nop_i); // useless since NOPs aren't usable as x64 intended to + + // if (patch->uses_nop_trampoline) { // always false; can ditch the entire if branch + // /* + // * The preferred option it to use a 5 byte relative + // * jump in a padding space between symbols in libc. + // * If such padding space is found, a 2 byte short + // * jump is enough for jumping to it, thus no + // * instructions other than the syscall + // * itself need to be overwritten. + // */ + // patch->uses_prev_ins = false; + // patch->uses_prev_ins_2 = false; + // patch->uses_next_ins = false; + // patch->dst_jmp_patch = + // patch->nop_trampoline.address + 2; + // /* + // * The first two bytes of the nop are used for + // * something else, see the explanation + // * at is_overwritable_nop in intercept_desc.c + // */ + // + // /* + // * Return to libc: + // * just jump to instruction right after the place + // * where the syscall instruction was originally. + // */ + // patch->return_address = + // patch->syscall_addr + SYSCALL_INS_SIZE; + // + // } else { /* * No padding space is available, so check the * instructions surrounding the syscall instruction. @@ -400,11 +387,11 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) * Count the number of overwritable bytes * in the variable length. * Sum up the bytes that can be overwritten. - * The 2 bytes of the syscall instruction can + * The 4 bytes of the ecall instruction can * be overwritten definitely, so length starts - * as SYSCALL_INS_SIZE ( 2 bytes ). + * as ECALL_INS_SIZE ( 4 bytes ). */ - unsigned length = SYSCALL_INS_SIZE; + unsigned length = ECALL_INS_SIZE; patch->dst_jmp_patch = patch->syscall_addr; @@ -448,25 +435,25 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) * the syscall. */ patch->return_address = patch->syscall_addr + - SYSCALL_INS_SIZE + + ECALL_INS_SIZE + patch->following_ins.length; - } else { - /* - * Address of the syscall instruction - * plus 2 bytes - * - * adds up to: - * - * the address of the first instruction after - * the syscall ( just like in the case of - * using padding bytes ). - */ - patch->return_address = - patch->syscall_addr + SYSCALL_INS_SIZE; - } + } //else { // if patch->uses_next_ins is false this else branch is not important since length won't be enough nevertheless + // /* + // * Address of the syscall instruction + // * plus 2 bytes + // * + // * adds up to: + // * + // * the address of the first instruction after + // * the syscall ( just like in the case of + // * using padding bytes ). + // */ + // patch->return_address = + // patch->syscall_addr + ECALL_INS_SIZE; + // } /* - * If the length is at least 5, then a jump instruction + * If the length is at least 16, then a jump instruction * with a 32 bit displacement can fit. * * Otherwise give up @@ -483,7 +470,7 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) xabort("not enough space for patching" " around syscal"); } - } + // } mark_jump(desc, patch->return_address); @@ -538,9 +525,9 @@ init_patcher(void) * * XXX check for ZMM registers, and save/restore them! */ - extern bool has_ymm_registers(void); - - intercept_routine_must_save_ymm = has_ymm_registers(); + // extern bool has_ymm_registers(void); + // + // intercept_routine_must_save_ymm = has_ymm_registers(); } /* @@ -581,6 +568,66 @@ create_movabs_r11(unsigned char *code, uint64_t value) return create_movabs(code, value, 11); } +/* + * create_ret_from_template + * Write a RET instruction (encoded as JALR) to return to patch->return_address. + * This is possible as long patch->return_address is saved to ra in the first + * place when jumping to trampoline when intercepting the system call. This is + * not explicitly written at the end of intercept_template.S since the fourth + * overwritten instruction has to be relocated before RET. + */ +static unsigned char * +create_ret_from_template(unsigned char *code) +{ + *((uint32_t)code) = 0x00008067; // jalr zero, ra, 0 + return code + 4; +} + +/* + * create_load_uint64t_into_a6 + * Generates the first 5 instructions (LUI,ADDI,SLLI,LUI,ADDI) of a convoluted + * 14 instructions sequence that assign a 64 bit constant to a register. + * See intercept_template.S for the following 9 at + * intercept_asm_wrapper_patch_desc_addr (an equal sequence is placed at + * intercept_asm_wrapper_wrapper_level1_addr as well). + */ +static void +create_load_uint64t_into_a6(uint8_t *code, uint64_t value) +{ + + uint32_t *instructions = (uint32_t *)code; + uint32_t upper_32 = (value & 0xffffffff00000000) >> 32; + uint32_t lower_32 = (uint32_t)value; + + uint32_t lui_imm_field = upper_32 & 0xfffff000; + uint32_t addi_imm_field = 0; + if (upper_32 % 4096 != 0) { + addi_imm_field = upper_32 - lui_imm_field; + if (addi_imm_field > 2047) { + lui_imm_field += 4096; + addi_imm_field = -(4096 - addi_imm_field); + } + } + + instructions[0] = 0x00000837 | lui_imm_field; // lui a6, 0x..... + instructions[1] = 0x00080813 | (addi_imm_field << 20); // addi a6, a6, 0x... + instructions[2] = 0x02081813; // slli a6, a6, 32 // could ditch this line as long its placeholder in intercept_template.S isn't different at all + + lui_imm_field = lower_32 & 0xfffff000; + addi_imm_field = 0; + if (lower_32 % 4096 != 0) { + addi_imm_field = lower_32 - lui_imm_field; + if (addi_imm_field > 2047) { + lui_imm_field += 4096; + addi_imm_field = -(4096 - addi_imm_field); + } + } + + instructions[3] = 0x000002b7 | lui_imm_field; // lui t0, 0x..... + instructions[4] = 0x00028293 | (addi_imm_field << 20); // addi t0, t0, 0x... + +} + /* * relocate_instruction * Places an instruction equivalent to `ins` to the memory location at `dst`. @@ -591,19 +638,19 @@ static unsigned char * relocate_instruction(unsigned char *dst, const struct intercept_disasm_result *ins) { - if (ins->is_lea_rip) { - /* - * Substitue a "lea $offset(%rip), %reg" instruction - * by a movabs instruction, to achieve the same effect. - * The result of the lea calculation is already calculated - * in the rip_ref_addr variable. - */ - return create_movabs(dst, (uint64_t)ins->rip_ref_addr, - ins->arg_register_bits); - } else { + // if (ins->is_lea_rip) { + // /* + // * Substitue a "lea $offset(%rip), %reg" instruction + // * by a movabs instruction, to achieve the same effect. + // * The result of the lea calculation is already calculated + // * in the rip_ref_addr variable. + // */ + // return create_movabs(dst, (uint64_t)ins->rip_ref_addr, + // ins->arg_register_bits); + // } else { memcpy(dst, ins->address, ins->length); return dst + ins->length; - } + // } } /* @@ -623,15 +670,19 @@ create_wrapper(struct patch_desc *patch, unsigned char **dst) /* Copy the previous instruction(s) */ if (patch->uses_prev_ins) { - if (patch->uses_prev_ins_2) - *dst = relocate_instruction(*dst, - &patch->preceding_ins_2); + if (patch->uses_prev_ins_2) { + *((uint32_t *)(*dst)) = 0x00013283; // ld t0, 0(sp) + *dst += 4; + *((uint32_t *)(*dst)) = 0x00810113; // addi sp, sp, 8 + *dst += 4; + *dst = relocate_instruction(*dst, &patch->preceding_ins_2); + } *dst = relocate_instruction(*dst, &patch->preceding_ins); } memcpy(*dst, intercept_asm_wrapper_tmpl, asm_wrapper_tmpl_size); - create_movabs_r11(*dst + o_patch_desc_addr, (uintptr_t)patch); - create_movabs_r11(*dst + o_wrapper_level1_addr, + create_load_uint64t_into_a6(*dst + o_patch_desc_addr, (uintptr_t)patch); // why the uintptr_t cast? What if the address is not representable on 32 bit? + create_load_uint64t_into_a6(*dst + o_wrapper_level1_addr, (uintptr_t)&intercept_wrapper); *dst += asm_wrapper_tmpl_size; @@ -639,7 +690,8 @@ create_wrapper(struct patch_desc *patch, unsigned char **dst) if (patch->uses_next_ins) *dst = relocate_instruction(*dst, &patch->following_ins); - *dst = create_absolute_jump(*dst, patch->return_address); + // *dst = create_absolute_jump(*dst, patch->return_address); // since ra is updated with patch->return_address by JALR when jumping to trampoline, writing RET is enough + *dst = create_ret_from_template(*dst); } /* @@ -669,6 +721,91 @@ after_nop(const struct range *nop) return nop->address + nop->size; } +/* + * create_j(from, to) + * Create a 4 byte JAL instruction jumping to address to, by overwriting + * code starting at address from, if trampoline displacement is within + or - + * 1 MiB. Otherwise create a 2 instructions sequence (LUI + JALR) which allows + * to reach trampoline if its displacement is within -2 GiB or JALR_MAX_OFFSET, + * which is (+2 GiB - 2050 Bytes). + */ +void +create_j(unsigned char *from, void *to) +{ + /* + * The operand is the difference between the + * instruction pointer pointing to the instruction + * just after the call, and the to address. + */ + ptrdiff_t delta = ((unsigned char *)to) - from; + uint32_t *instructions = (uint32_t)from; + uint32_t ebreak = 0x00100073; // ebreak instruction + debug_dump("%p: svc -> b %ld\t# %p\n", from, delta, to); + + const ptrdiff_t JAL_OFFSET = 1 << 20; + const ptrdiff_t JALR_MAX_OFFSET = 2147481598; // ((2^31-1)-4095)+(2^11-1) == 0x7ffff000 + 0x7ff + const ptrdiff_t JALR_MIN_OFFSET = -2147483648; // (-2^31) == -0x80000000 + + if ((delta & 0x1) != 0) { + + xabort("create_j misaligned instruction fetch exception"); + + } else if ((delta <= JAL_OFFSET-2) || (delta >= -JAL_OFFSET)) { + /* delta can be encoded in a single jal instruction */ + + /* halving offset value, since RISC-V doubles the immediate value of jal */ + delta >>= 1; + + /* extracting 20 bits to be encoded in jal instruction */ + uint32_t tmp = (uint32_t) delta & 0x000fffff; + uint32_t jal = 0x0000006f; /* jal instruction with offset = 0 */ + jal |= ((tmp & 0x3ff) << 21); /* shifting imm[9:0] into jal[30:21] */ + jal |= ((tmp & 0x400) << 10); /* shifting imm[10] into jal[20] */ + jal |= ((tmp & 0x7f800) << 1); /* shifting imm[18:11] into jal[19:12] */ + jal |= ((tmp & 0x80000) << 12); /* shifting imm[19] into jal[31] */ + + // *((uint32_t *)from) = jal; replaced by following lines + instructions[0] = jal; + instructions[1] = ebreak; + instructions[2] = ebreak; + instructions[3] = ebreak; + + } else if (delta <= JALR_MAX_OFFSET || delta >= JALR_MIN_OFFSET) { + + uint32_t lui = 0x000002b7; // encoding t0 as rd + uint32_t jalr = 0x00028067; // encoding zero as rd and t0 as rs1 + uint32_t jalr_imm_field = 0; + uint32_t lui_imm_field = (uint32_t)delta & 0xfffff000; // offset[31:12] + + /* + * if the offset is not a multiple of 4096 the 12 least significant bits + * of its value must be set by adding the correct immediate value contained + * in jalr imm field to the rs1 value which is set by lui instruction + * preceding jalr + */ + if ((uint32_t)delta % 4096 != 0) { + jalr_imm_field = (uint32_t)delta - lui_imm_field; + if (jalr_imm_field > 2046) { + lui_imm_field += 4096; + jalr_imm_field = -(4096 - jalr_imm_field); + } + } + lui |= lui_imm_field; + jalr |= (jalr_imm_field << 20); + + instructions[0] = lui; // lui t0, 0x..... + instructions[1] = jalr; // jalr zero, t0, 0x... + instructions[2] = ebreak; + instructions[3] = ebreak; + // *((uint32_t *)from) = lui; // lui t0, 0x..... + // from += 4; + // *(uint32_t *)from) = jalr; // jalr zero, t0, 0x... + + } else { + xabort("create_j distance check"); + } +} + /* * activate_patches() * Loop over all the patches, and and overwrite each syscall. @@ -714,51 +851,49 @@ activate_patches(struct intercept_desc *desc) check_trampoline_usage(desc); /* jump - escape the text segment */ - create_jump(JMP_OPCODE, - patch->dst_jmp_patch, desc->next_trampoline); + create_j(patch->dst_jmp_patch, desc->next_trampoline); /* jump - escape the 2 GB range of the text segment */ desc->next_trampoline = create_absolute_jump( desc->next_trampoline, patch->asm_wrapper); } else { - create_jump(JMP_OPCODE, - patch->dst_jmp_patch, patch->asm_wrapper); + create_j(patch->dst_jmp_patch, patch->asm_wrapper); } - if (patch->uses_nop_trampoline) { - /* - * Create a mini trampoline jump. - * The first two bytes of the NOP instruction are - * overwritten by a short jump instruction - * (with 8 bit displacement), to make sure whenever - * this the execution reaches the address where this - * NOP resided originally, it continues uninterrupted. - * The rest of the bytes occupied by this instruction - * are used as an mini extra trampoline table. - * - * See also: the is_overwritable_nop function in - * the intercept_desc.c source file. - */ - - /* jump from syscall to mini trampoline */ - create_short_jump(patch->syscall_addr, - patch->dst_jmp_patch); - - /* - * Short jump to next instruction, skipping the newly - * created trampoline jump. - */ - create_short_jump(patch->nop_trampoline.address, - after_nop(&patch->nop_trampoline)); - } else { - unsigned char *byte; - - for (byte = patch->dst_jmp_patch + JUMP_INS_SIZE; - byte < patch->return_address; - ++byte) { - *byte = INT3_OPCODE; - } - } + // if (patch->uses_nop_trampoline) { + // /* + // * Create a mini trampoline jump. + // * The first two bytes of the NOP instruction are + // * overwritten by a short jump instruction + // * (with 8 bit displacement), to make sure whenever + // * this the execution reaches the address where this + // * NOP resided originally, it continues uninterrupted. + // * The rest of the bytes occupied by this instruction + // * are used as an mini extra trampoline table. + // * + // * See also: the is_overwritable_nop function in + // * the intercept_desc.c source file. + // */ + // + // /* jump from syscall to mini trampoline */ + // create_short_jump(patch->syscall_addr, + // patch->dst_jmp_patch); + // + // /* + // * Short jump to next instruction, skipping the newly + // * created trampoline jump. + // */ + // create_short_jump(patch->nop_trampoline.address, + // after_nop(&patch->nop_trampoline)); + // } else { + // unsigned char *byte; + // + // for (byte = patch->dst_jmp_patch + JUMP_INS_SIZE; + // byte < patch->return_address; + // ++byte) { + // *byte = INT3_OPCODE; + // } + // } } mprotect_no_intercept(first_page, size, From 402a3374fb4f7ac4c03d8f7ed7829965cf135edc Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 1 May 2024 03:58:01 +0200 Subject: [PATCH 002/143] Trampoline doesn't prematurely clobber used registers anymore --- src/patcher.c | 81 ++++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/src/patcher.c b/src/patcher.c index 50d701c..402879b 100644 --- a/src/patcher.c +++ b/src/patcher.c @@ -82,8 +82,12 @@ /* The size of a trampoline jump, 64-bit address loading process into a register * (which requires 14 instructions to encode directly in machine code) + JALR. + * These are preceeded and succeeded by storing and restoring of tmp registers + * used for the creation of the absolute jump. We can't clobber them since two + * instructions that were placed before the original ecall still must be + * executed. */ -enum { TRAMPOLINE_SIZE = 15 * 4 }; +enum { TRAMPOLINE_SIZE = 23 * 4 }; static void create_wrapper(struct patch_desc *patch, unsigned char **dst); @@ -95,18 +99,26 @@ static unsigned char * create_absolute_jump(unsigned char *from, void *to) { uint32_t *instructions = (uint32_t)from; - create_load_uint64t_into_a6(from,(uint64_t)value); - instructions[5] = 0x7ffff337; - instructions[6] = 0x7ff06393; - instructions[7] = 0x00139393; - instructions[8] = 0x0013e393; - instructions[9] = 0x00736333; - instructions[10] = 0x00131313; - instructions[11] = 0x00136313; - instructions[12] = 0x0062f2b3; - instructions[13] = 0x00586833; - instructions[14] = 0x00080067; - return instructions + 15; + instructions[0] = 0xfe810113; // addi sp, sp, -24 + instructions[1] = 0x00613023; // sd t1, 0(sp) + instructions[2] = 0x00713423; // sd t2, 8(sp) + instructions[3] = 0x01c13823; // sd t3, 16(sp) + create_load_uint64t_into_t0(instructions + 4,(uint64_t)value); + instructions[9] = 0x7ffff337; // lui t1, 0x7ffff + instructions[10] = 0x7ff06393; // ori t2, zero, 0x7ff + instructions[11] = 0x00139393; // slli t2, t2, 1 + instructions[12] = 0x0013e393; // ori t2, t2, 1 + instructions[13] = 0x00736333; // or t1, t1, t2 + instructions[14] = 0x00131313; // slli t1, t1, 1 + instructions[15] = 0x00136313; // ori t1, t1, 1 + instructions[16] = 0x006e7e33; // and t3, t3, t1 + instructions[17] = 0x01c2e2b3; // or t0, t0, t3 + instructions[18] = 0x00013303; // ld t1, 0(sp) + instructions[19] = 0x00813383; // ld t2, 8(sp) + instructions[20] = 0x01013e03; // ld t3, 16(sp) + instructions[21] = 0x01810113; // addi sp, sp, 24 + instructions[22] = 0x00028067; // jalr zero, t0, 0 + return instructions + 23; } /* @@ -584,7 +596,7 @@ create_ret_from_template(unsigned char *code) } /* - * create_load_uint64t_into_a6 + * create_load_uint64t_into_t0 * Generates the first 5 instructions (LUI,ADDI,SLLI,LUI,ADDI) of a convoluted * 14 instructions sequence that assign a 64 bit constant to a register. * See intercept_template.S for the following 9 at @@ -592,7 +604,7 @@ create_ret_from_template(unsigned char *code) * intercept_asm_wrapper_wrapper_level1_addr as well). */ static void -create_load_uint64t_into_a6(uint8_t *code, uint64_t value) +create_load_uint64t_into_t0(uint8_t *code, uint64_t value) { uint32_t *instructions = (uint32_t *)code; @@ -609,9 +621,9 @@ create_load_uint64t_into_a6(uint8_t *code, uint64_t value) } } - instructions[0] = 0x00000837 | lui_imm_field; // lui a6, 0x..... - instructions[1] = 0x00080813 | (addi_imm_field << 20); // addi a6, a6, 0x... - instructions[2] = 0x02081813; // slli a6, a6, 32 // could ditch this line as long its placeholder in intercept_template.S isn't different at all + instructions[0] = 0x000002b7 | lui_imm_field; // lui t0, 0x..... + instructions[1] = 0x00028293 | (addi_imm_field << 20); // addi t0, t0, 0x... + instructions[2] = 0x02029293; // slli t0, t0, 32 // could ditch this line as long its placeholder in intercept_template.S isn't different at all lui_imm_field = lower_32 & 0xfffff000; addi_imm_field = 0; @@ -623,8 +635,8 @@ create_load_uint64t_into_a6(uint8_t *code, uint64_t value) } } - instructions[3] = 0x000002b7 | lui_imm_field; // lui t0, 0x..... - instructions[4] = 0x00028293 | (addi_imm_field << 20); // addi t0, t0, 0x... + instructions[3] = 0x00000e37 | lui_imm_field; // lui t3, 0x..... + instructions[4] = 0x000e0e13 | (addi_imm_field << 20); // addi t3, t3, 0x... } @@ -667,6 +679,7 @@ create_wrapper(struct patch_desc *patch, unsigned char **dst) { /* Create a new copy of the template */ patch->asm_wrapper = *dst; + uint32_t *instructions = (uint32_t *)(*dst); /* Copy the previous instruction(s) */ if (patch->uses_prev_ins) { @@ -681,8 +694,8 @@ create_wrapper(struct patch_desc *patch, unsigned char **dst) } memcpy(*dst, intercept_asm_wrapper_tmpl, asm_wrapper_tmpl_size); - create_load_uint64t_into_a6(*dst + o_patch_desc_addr, (uintptr_t)patch); // why the uintptr_t cast? What if the address is not representable on 32 bit? - create_load_uint64t_into_a6(*dst + o_wrapper_level1_addr, + create_load_uint64t_into_t0(*dst + o_patch_desc_addr, (uintptr_t)patch); // why the uintptr_t cast? What if the address is not representable on 32 bit? + create_load_uint64t_into_t0(*dst + o_wrapper_level1_addr, (uintptr_t)&intercept_wrapper); *dst += asm_wrapper_tmpl_size; @@ -739,7 +752,7 @@ create_j(unsigned char *from, void *to) */ ptrdiff_t delta = ((unsigned char *)to) - from; uint32_t *instructions = (uint32_t)from; - uint32_t ebreak = 0x00100073; // ebreak instruction + uint32_t nop = 0x00000013; // nop instruction debug_dump("%p: svc -> b %ld\t# %p\n", from, delta, to); const ptrdiff_t JAL_OFFSET = 1 << 20; @@ -758,22 +771,21 @@ create_j(unsigned char *from, void *to) /* extracting 20 bits to be encoded in jal instruction */ uint32_t tmp = (uint32_t) delta & 0x000fffff; - uint32_t jal = 0x0000006f; /* jal instruction with offset = 0 */ + uint32_t jal = 0x000000ef; /* jal instruction with offset = 0 and rd = ra */ jal |= ((tmp & 0x3ff) << 21); /* shifting imm[9:0] into jal[30:21] */ jal |= ((tmp & 0x400) << 10); /* shifting imm[10] into jal[20] */ jal |= ((tmp & 0x7f800) << 1); /* shifting imm[18:11] into jal[19:12] */ jal |= ((tmp & 0x80000) << 12); /* shifting imm[19] into jal[31] */ - // *((uint32_t *)from) = jal; replaced by following lines instructions[0] = jal; - instructions[1] = ebreak; - instructions[2] = ebreak; - instructions[3] = ebreak; + instructions[1] = nop; + instructions[2] = nop; + instructions[3] = nop; } else if (delta <= JALR_MAX_OFFSET || delta >= JALR_MIN_OFFSET) { uint32_t lui = 0x000002b7; // encoding t0 as rd - uint32_t jalr = 0x00028067; // encoding zero as rd and t0 as rs1 + uint32_t jalr = 0x000280e7; // encoding ra as rd and t0 as rs1 uint32_t jalr_imm_field = 0; uint32_t lui_imm_field = (uint32_t)delta & 0xfffff000; // offset[31:12] @@ -793,13 +805,10 @@ create_j(unsigned char *from, void *to) lui |= lui_imm_field; jalr |= (jalr_imm_field << 20); - instructions[0] = lui; // lui t0, 0x..... - instructions[1] = jalr; // jalr zero, t0, 0x... - instructions[2] = ebreak; - instructions[3] = ebreak; - // *((uint32_t *)from) = lui; // lui t0, 0x..... - // from += 4; - // *(uint32_t *)from) = jalr; // jalr zero, t0, 0x... + instructions[0] = 0xff810113; // addi sp, sp, -8 + instructions[1] = 0x00513023; // sd t0, 0(sp) + instructions[2] = lui; // lui t0, 0x..... + instructions[3] = jalr; // jalr ra, t0, 0x... } else { xabort("create_j distance check"); From 3efb0e344cae6d078ff876ae70fa54d45e16707c Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 1 May 2024 05:18:46 +0200 Subject: [PATCH 003/143] sp value changes now keep it 16-byte boundary aligned --- src/patcher.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/patcher.c b/src/patcher.c index 402879b..329725e 100644 --- a/src/patcher.c +++ b/src/patcher.c @@ -99,7 +99,7 @@ static unsigned char * create_absolute_jump(unsigned char *from, void *to) { uint32_t *instructions = (uint32_t)from; - instructions[0] = 0xfe810113; // addi sp, sp, -24 + instructions[0] = 0xff010113; // addi sp, sp, -16 instructions[1] = 0x00613023; // sd t1, 0(sp) instructions[2] = 0x00713423; // sd t2, 8(sp) instructions[3] = 0x01c13823; // sd t3, 16(sp) @@ -116,7 +116,7 @@ create_absolute_jump(unsigned char *from, void *to) instructions[18] = 0x00013303; // ld t1, 0(sp) instructions[19] = 0x00813383; // ld t2, 8(sp) instructions[20] = 0x01013e03; // ld t3, 16(sp) - instructions[21] = 0x01810113; // addi sp, sp, 24 + instructions[21] = 0x01010113; // addi sp, sp, 16 instructions[22] = 0x00028067; // jalr zero, t0, 0 return instructions + 23; } @@ -503,7 +503,7 @@ size_t asm_wrapper_tmpl_size; static ptrdiff_t o_patch_desc_addr; static ptrdiff_t o_wrapper_level1_addr; -bool intercept_routine_must_save_ymm; +bool intercept_routine_must_save_ymm = false; // temporarily hardcoded /* * init_patcher @@ -684,9 +684,9 @@ create_wrapper(struct patch_desc *patch, unsigned char **dst) /* Copy the previous instruction(s) */ if (patch->uses_prev_ins) { if (patch->uses_prev_ins_2) { - *((uint32_t *)(*dst)) = 0x00013283; // ld t0, 0(sp) + *((uint32_t *)(*dst)) = 0x00813283; // ld t0, 8(sp) *dst += 4; - *((uint32_t *)(*dst)) = 0x00810113; // addi sp, sp, 8 + *((uint32_t *)(*dst)) = 0x01010113; // addi sp, sp, 16 *dst += 4; *dst = relocate_instruction(*dst, &patch->preceding_ins_2); } @@ -805,8 +805,8 @@ create_j(unsigned char *from, void *to) lui |= lui_imm_field; jalr |= (jalr_imm_field << 20); - instructions[0] = 0xff810113; // addi sp, sp, -8 - instructions[1] = 0x00513023; // sd t0, 0(sp) + instructions[0] = 0xff010113; // addi sp, sp, -16 + instructions[1] = 0x00513423; // sd t0, 8(sp) instructions[2] = lui; // lui t0, 0x..... instructions[3] = jalr; // jalr ra, t0, 0x... From ce40f2f1faa87e5a446f4e991d99788a167e35b7 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 2 May 2024 17:58:48 +0200 Subject: [PATCH 004/143] Now instruction following ecall must not use ra as operand to be able to be patched --- src/disasm_wrapper.c | 200 +++++++++++++++++++++++-------------------- src/disasm_wrapper.h | 3 + src/patcher.c | 159 +++++++++++++++++----------------- 3 files changed, 192 insertions(+), 170 deletions(-) diff --git a/src/disasm_wrapper.c b/src/disasm_wrapper.c index 8fc0e5a..c57d15c 100644 --- a/src/disasm_wrapper.c +++ b/src/disasm_wrapper.c @@ -135,67 +135,67 @@ intercept_disasm_destroy(struct intercept_disasm_context *context) * check_op - checks a single operand of an instruction, looking * for RIP relative addressing. */ -static void -check_op(struct intercept_disasm_result *result, cs_x86_op *op, - const unsigned char *code) -{ - /* - * the address the RIP register is going to contain during the - * execution of this instruction - */ - const unsigned char *rip = code + result->length; - - if (op->type == RISCV_OP_REG) { - if (op->reg == X86_REG_IP || op->reg == X86_REG_RIP) { - /* - * Example: mov %rip, %rax - */ - result->has_ip_relative_opr = true; - result->rip_disp = 0; - result->rip_ref_addr = rip; - } - if (result->is_jump) { - /* - * Example: jmp *(%rax) - */ - /* - * An indirect jump can't have arguments other - * than a register - therefore the asserts. - * ( I'm 99.99% sure this is true ) - */ - assert(!result->is_rel_jump); - result->is_indirect_jump = true; - } - } else if (op->type == X86_OP_MEM) { - if (op->mem.base == X86_REG_IP || - op->mem.base == X86_REG_RIP || - op->mem.index == X86_REG_IP || - op->mem.index == X86_REG_RIP || - result->is_jump) { - result->has_ip_relative_opr = true; - assert(!result->is_indirect_jump); - - if (result->is_jump) - result->is_rel_jump = true; - - assert(op->mem.disp <= INT32_MAX); - assert(op->mem.disp >= INT32_MIN); - - result->rip_disp = (int32_t)op->mem.disp; - result->rip_ref_addr = rip + result->rip_disp; - } - } else if (op->type == X86_OP_IMM) { - if (result->is_jump) { - assert(!result->is_indirect_jump); - result->has_ip_relative_opr = true; - result->is_rel_jump = true; - result->rip_ref_addr = (void *)op->imm; - - result->rip_disp = - (int32_t)((unsigned char *)op->imm - rip); - } - } -} +// static void +// check_op(struct intercept_disasm_result *result, cs_x86_op *op, +// const unsigned char *code) +// { +// /* +// * the address the RIP register is going to contain during the +// * execution of this instruction +// */ +// const unsigned char *rip = code + result->length; +// +// if (op->type == RISCV_OP_REG) { +// if (op->reg == X86_REG_IP || op->reg == X86_REG_RIP) { +// /* +// * Example: mov %rip, %rax +// */ +// result->has_ip_relative_opr = true; +// result->rip_disp = 0; +// result->rip_ref_addr = rip; +// } +// if (result->is_jump) { +// /* +// * Example: jmp *(%rax) +// */ +// /* +// * An indirect jump can't have arguments other +// * than a register - therefore the asserts. +// * ( I'm 99.99% sure this is true ) +// */ +// assert(!result->is_rel_jump); +// result->is_indirect_jump = true; +// } +// } else if (op->type == X86_OP_MEM) { +// if (op->mem.base == X86_REG_IP || +// op->mem.base == X86_REG_RIP || +// op->mem.index == X86_REG_IP || +// op->mem.index == X86_REG_RIP || +// result->is_jump) { +// result->has_ip_relative_opr = true; +// assert(!result->is_indirect_jump); +// +// if (result->is_jump) +// result->is_rel_jump = true; +// +// assert(op->mem.disp <= INT32_MAX); +// assert(op->mem.disp >= INT32_MIN); +// +// result->rip_disp = (int32_t)op->mem.disp; +// result->rip_ref_addr = rip + result->rip_disp; +// } +// } else if (op->type == X86_OP_IMM) { +// if (result->is_jump) { +// assert(!result->is_indirect_jump); +// result->has_ip_relative_opr = true; +// result->is_rel_jump = true; +// result->rip_ref_addr = (void *)op->imm; +// +// result->rip_disp = +// (int32_t)((unsigned char *)op->imm - rip); +// } +// } +// } /* * intercept_disasm_next_instruction - Examines a single instruction @@ -244,7 +244,7 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, #endif switch (context->insn->id) { - case RISCV_INS_BEQ: // these are jumps and their destination is calculated as PC + offset; + case RISCV_INS_BEQ: // PC-relative jumps case RISCV_INS_BGE: case RISCV_INS_BGEU: case RISCV_INS_BLT: @@ -258,39 +258,57 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, result.has_ip_relative_opr = true; break; case RISCV_INS_JALR: - result.is_ret = true; - cs_riscv_op *op; - for (uint8_t op_i = 0; result.is_ret && - op_i < context->insn->detail->riscv.op_count; ++op_i) { - op = context->insn->detail->riscv.operands + op_i; - switch (op->type) { - case RISCV_OP_REG: - if (op->reg != RISCV_REG_ZERO || op->reg != RISCV_REG_RA) { - result.is_ret = false; - } - break; - case RISCV_OP_IMM: - if (op->imm != 0) { - result.is_ret = false; - } - break; - case RISCV_OP_MEM: - if (op->mem.base != RISCV_REG_RA || op->mem.disp != 0) { - result.is_ret = false; - } - break; - default: - result.is_ret = false; - break; - } - } - if (!result.is_ret) { - result.is_jump = true; - } + result.is_jump = true; + // result.is_ret = true; + // cs_riscv_op *op; + // for (uint8_t op_i = 0; result.is_ret && + // op_i < context->insn->detail->riscv.op_count; ++op_i) { + // op = context->insn->detail->riscv.operands + op_i; + // switch (op->type) { + // case RISCV_OP_REG: + // if (op->reg != RISCV_REG_ZERO || op->reg != RISCV_REG_RA) { + // result.is_ret = false; + // } + // break; + // case RISCV_OP_IMM: + // if (op->imm != 0) { + // result.is_ret = false; + // } + // break; + // case RISCV_OP_MEM: + // if (op->mem.base != RISCV_REG_RA || op->mem.disp != 0) { + // result.is_ret = false; + // } + // break; + // default: + // result.is_ret = false; + // break; + // } + // } + // if (!result.is_ret) { + // result.is_jump = true; + // } break; default: result.is_jump = false; result.has_ip_relative_opr = false; + result.uses_ra = false; + cs_riscv_op *op; + for (uint8_t op_i = 0; !result.uses_ra && + op_i < context->insn->detail->riscv.op_count; ++op_i) { + op = context->insn->detail->riscv.operands + op_i; + switch (op->type) { + case RISCV_OP_REG: + result.uses_ra = op->reg == RISCV_REG_RA; + break; + case RISCV_OP_MEM: + result.uses_ra = op->mem.base == RISCV_REG_RA; + break; + default: + //result.is_ret = false; + break; + } + } break; } diff --git a/src/disasm_wrapper.h b/src/disasm_wrapper.h index 52e1d31..119d17f 100644 --- a/src/disasm_wrapper.h +++ b/src/disasm_wrapper.h @@ -67,6 +67,9 @@ struct intercept_disasm_result { /* as of now this only refers to endbr64 */ bool is_endbr; + /* Flag marking if ra is one of the operands of the instruction */ + bool uses_ra; + /* * Flag marking lea instructions setting a 64 bit register to a * RIP relative address. They can be relocated -- but by simple memcpy. diff --git a/src/patcher.c b/src/patcher.c index 329725e..20d9cbe 100644 --- a/src/patcher.c +++ b/src/patcher.c @@ -220,43 +220,43 @@ is_nop_in_range(unsigned char *address, const struct range *nop) * This routine essentially initializes the uses_nop_trampoline and * the nop_trampoline fields of a struct patch_desc. */ -static void -assign_nop_trampoline(struct intercept_desc *desc, - struct patch_desc *patch, - size_t *next_nop_i) -{ - struct range *nop = desc->nop_table + *next_nop_i; - - if (*next_nop_i >= desc->nop_count) { - patch->uses_nop_trampoline = false; - return; /* no more nops available */ - } - - /* - * Consider a nop instruction, to use as trampoline, but only - * if a two byte jump in the place of the syscall can jump - * to the proposed trampoline. Check if the nop is: - * 1) at an address too low - * 2) close enough for a two byte jump - * 3) at an address too high - */ - - if (is_nop_in_range(patch->syscall_addr, nop)) { - patch->uses_nop_trampoline = true; - patch->nop_trampoline = *nop; - ++(*next_nop_i); - return; /* found a nop in range to use as trampoline */ - } - - if (nop->address > patch->syscall_addr) { - patch->uses_nop_trampoline = false; - return; /* nop is too far ahead */ - } - - /* nop is too far behind, try the next nop */ - ++(*next_nop_i); - assign_nop_trampoline(desc, patch, next_nop_i); -} +// static void +// assign_nop_trampoline(struct intercept_desc *desc, +// struct patch_desc *patch, +// size_t *next_nop_i) +// { +// struct range *nop = desc->nop_table + *next_nop_i; +// +// if (*next_nop_i >= desc->nop_count) { +// patch->uses_nop_trampoline = false; +// return; /* no more nops available */ +// } +// +// /* +// * Consider a nop instruction, to use as trampoline, but only +// * if a two byte jump in the place of the syscall can jump +// * to the proposed trampoline. Check if the nop is: +// * 1) at an address too low +// * 2) close enough for a two byte jump +// * 3) at an address too high +// */ +// +// if (is_nop_in_range(patch->syscall_addr, nop)) { +// patch->uses_nop_trampoline = true; +// patch->nop_trampoline = *nop; +// ++(*next_nop_i); +// return; /* found a nop in range to use as trampoline */ +// } +// +// if (nop->address > patch->syscall_addr) { +// patch->uses_nop_trampoline = false; +// return; /* nop is too far ahead */ +// } +// +// /* nop is too far behind, try the next nop */ +// ++(*next_nop_i); +// assign_nop_trampoline(desc, patch, next_nop_i); +// } /* * is_copiable_before_syscall @@ -296,7 +296,8 @@ is_copiable_after_syscall(struct intercept_disasm_result ins) ins.is_rel_jump || ins.is_jump || ins.is_endbr || - ins.is_syscall); + ins.is_syscall || + ins.uses_ra); } @@ -549,36 +550,36 @@ init_patcher(void) * the reg_bits value must contain the X86 encoding of the register. * Returns a pointer to the char right after the generated instruction. */ -static unsigned char * -create_movabs(unsigned char *code, uint64_t value, unsigned char reg_bits) -{ - assert(reg_bits < 16); - - unsigned char *bytes = (unsigned char *)&value; - - *code++ = 0x48 | (reg_bits >> 3); /* REX prefix */ - *code++ = 0xb8 | (reg_bits & 7); /* opcode */ - *code++ = bytes[0]; - *code++ = bytes[1]; - *code++ = bytes[2]; - *code++ = bytes[3]; - *code++ = bytes[4]; - *code++ = bytes[5]; - *code++ = bytes[6]; - *code++ = bytes[7]; - - return code; -} +// static unsigned char * +// create_movabs(unsigned char *code, uint64_t value, unsigned char reg_bits) +// { +// assert(reg_bits < 16); +// +// unsigned char *bytes = (unsigned char *)&value; +// +// *code++ = 0x48 | (reg_bits >> 3); /* REX prefix */ +// *code++ = 0xb8 | (reg_bits & 7); /* opcode */ +// *code++ = bytes[0]; +// *code++ = bytes[1]; +// *code++ = bytes[2]; +// *code++ = bytes[3]; +// *code++ = bytes[4]; +// *code++ = bytes[5]; +// *code++ = bytes[6]; +// *code++ = bytes[7]; +// +// return code; +// } /* * create_movabs_r11 * Generates a movabs instruction moving a value into the R11 register. */ -static unsigned char * -create_movabs_r11(unsigned char *code, uint64_t value) -{ - return create_movabs(code, value, 11); -} +// static unsigned char * +// create_movabs_r11(unsigned char *code, uint64_t value) +// { +// return create_movabs(code, value, 11); +// } /* * create_ret_from_template @@ -712,27 +713,27 @@ create_wrapper(struct patch_desc *patch, unsigned char **dst) * Generates a 2 byte jump instruction. The to address must be reachable * using an 8 bit displacement. */ -static void -create_short_jump(unsigned char *from, unsigned char *to) -{ - ptrdiff_t d = to - (from + 2); - - if (d < - 128 || d > 127) - xabort("create_short_jump distance check"); - - from[0] = SHORT_JMP_OPCODE; - from[1] = (unsigned char)((char)d); -} +// static void +// create_short_jump(unsigned char *from, unsigned char *to) +// { +// ptrdiff_t d = to - (from + 2); +// +// if (d < - 128 || d > 127) +// xabort("create_short_jump distance check"); +// +// from[0] = SHORT_JMP_OPCODE; +// from[1] = (unsigned char)((char)d); +// } /* * after_nop -- get the address of the instruction * following the nop. */ -static unsigned char * -after_nop(const struct range *nop) -{ - return nop->address + nop->size; -} +// static unsigned char * +// after_nop(const struct range *nop) +// { +// return nop->address + nop->size; +// } /* * create_j(from, to) From 0a206ab3d09707e3a552386bbd7c48912794d623 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 2 May 2024 19:10:49 +0200 Subject: [PATCH 005/143] context and its references are now coherent with RISC-V and stack layout in intercept_wrapper --- src/intercept.c | 56 +++++++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/src/intercept.c b/src/intercept.c index efda03a..6773077 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -112,29 +112,17 @@ void __attribute__((noreturn)) xlongjmp(long rip, long rsp, long rax); * AVX instructions. */ struct context { + long ra; + long t[5]; + long sp; struct patch_desc *patch_desc; - long rip; - long r15; - long r14; - long r13; - long r12; - long r10; - long r9; - long r8; - long rsp; - long rbp; - long rdi; - long rsi; - long rbx; - long rdx; - long rax; - char padd[0x200 - 0x168]; /* see: stack layout in intercept_wrapper.s */ - long SIMD[16][8]; /* 8 SSE, 8 AVX, or 16 AVX512 registers */ + long a[8]; + double ft[12]; + double fa[8]; }; struct wrapper_ret { - long rax; - long rdx; + long a[2]; }; /* Should all objects be patched, or only libc and libpthread? */ @@ -593,13 +581,13 @@ xabort_on_syserror(long syscall_result, const char *msg) static void get_syscall_in_context(struct context *context, struct syscall_desc *sys) { - sys->nr = (int)context->rax; /* ignore higher 32 bits */ - sys->args[0] = context->rdi; - sys->args[1] = context->rsi; - sys->args[2] = context->rdx; - sys->args[3] = context->r10; - sys->args[4] = context->r8; - sys->args[5] = context->r9; + sys->nr = (int)context->a[7]; /* ignore higher 32 bits */ + sys->args[0] = context->a[0]; + sys->args[1] = context->a[1]; + sys->args[2] = context->a[2]; + sys->args[3] = context->a[3]; + sys->args[4] = context->a[4]; + sys->args[5] = context->a[5]; } /* @@ -644,7 +632,7 @@ intercept_routine(struct context *context) get_syscall_in_context(context, &desc); if (handle_magic_syscalls(&desc, &result) == 0) - return (struct wrapper_ret){.rax = result, .rdx = 1 }; + return (struct wrapper_ret){.a[0] = result, .a[1] = 1 }; intercept_log_syscall(patch, &desc, UNKNOWN, 0); @@ -660,7 +648,7 @@ intercept_routine(struct context *context) if (desc.nr == SYS_vfork || desc.nr == SYS_rt_sigreturn) { /* can't handle these syscalls the normal way */ - return (struct wrapper_ret){.rax = context->rax, .rdx = 0 }; + return (struct wrapper_ret){.a[0] = context->a[7], .a[1] = 0 }; } if (forward_to_kernel) { @@ -678,13 +666,13 @@ intercept_routine(struct context *context) */ if (desc.nr == SYS_clone && desc.args[1] != 0) { return (struct wrapper_ret){ - .rax = context->rax, .rdx = 2 }; + .a[0] = context->a[7], .a[1] = 2 }; } #ifdef SYS_clone3 else if (desc.nr == SYS_clone3 && ((struct clone_args *)desc.args[0])->stack != 0) { return (struct wrapper_ret){ - .rax = context->rax, .rdx = 2 }; + .a[0] = context->a[7], .a[1] = 2 }; } #endif else @@ -699,7 +687,7 @@ intercept_routine(struct context *context) intercept_log_syscall(patch, &desc, KNOWN, result); - return (struct wrapper_ret){ .rax = result, .rdx = 1 }; + return (struct wrapper_ret){ .a[0] = result, .a[1] = 1 }; } /* @@ -710,13 +698,13 @@ intercept_routine(struct context *context) struct wrapper_ret intercept_routine_post_clone(struct context *context) { - if (context->rax == 0) { + if (context->a[7] == 0) { if (intercept_hook_point_clone_child != NULL) intercept_hook_point_clone_child(); } else { if (intercept_hook_point_clone_parent != NULL) - intercept_hook_point_clone_parent(context->rax); + intercept_hook_point_clone_parent(context->a[7]); } - return (struct wrapper_ret){.rax = context->rax, .rdx = 1 }; + return (struct wrapper_ret){.a[0] = context->a[7], .a[1] = 1 }; } From 1ca3f2794910b53c7e7fa50fad9aea5623a008b8 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 2 May 2024 20:04:42 +0200 Subject: [PATCH 006/143] Assembly files now follow the correct logic. Clone should now be handled as intended --- src/intercept_template.S | 269 +++++++++++++++------------ src/intercept_wrapper.S | 393 ++++++++++++++++----------------------- src/util.S | 108 +++++------ 3 files changed, 368 insertions(+), 402 deletions(-) diff --git a/src/intercept_template.S b/src/intercept_template.S index 70f60d8..8e213ee 100644 --- a/src/intercept_template.S +++ b/src/intercept_template.S @@ -1,116 +1,153 @@ -/* - * Copyright 2016-2017, Intel Corporation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * intercept_template.s -- see asm_wrapper.md - */ - -.global intercept_asm_wrapper_tmpl; -.hidden intercept_asm_wrapper_tmpl; -.global intercept_asm_wrapper_patch_desc_addr; -.hidden intercept_asm_wrapper_patch_desc_addr; -.global intercept_asm_wrapper_wrapper_level1_addr; -.hidden intercept_asm_wrapper_wrapper_level1_addr; -.global intercept_asm_wrapper_tmpl_end; -.hidden intercept_asm_wrapper_tmpl_end; - -.text - -/* - * Locals on the stack: - * 0(%rsp) the original value of %rsp, in the code around the syscall - * 8(%rsp) the pointer to the struct patch_desc instance - * - * The %rcx register controls which C function to call in intercept.c: - * - * if %rcx == 0 then call intercept_routine - * if %rcx == 1 then intercept_routine_post_clone - * - * This value in %rcx is passed to the function intercep_wrapper. - * - * - * Note: the subq instruction allocating stack for locals must not - * ruin the stack alignment. It must round up the number of bytes - * needed for locals. - */ -intercept_asm_wrapper_tmpl: - movq $0x0, %rcx /* choose intercept_routine */ - -0: movq %rsp, %r11 /* remember original rsp */ - subq $0x80, %rsp /* avoid the red zone */ - andq $-16, %rsp /* align the stack */ - subq $0x20, %rsp /* allocate stack for some locals */ - movq %r11, (%rsp) /* orignal rsp on stack */ -intercept_asm_wrapper_patch_desc_addr: - movabsq $0x000000000000, %r11 - movq %r11, 0x8 (%rsp) /* patch_desc pointer on stack */ -intercept_asm_wrapper_wrapper_level1_addr: - movabsq $0x000000000000, %r11 - callq *%r11 /* call intercept_wrapper */ - movq (%rsp), %rsp /* restore original rsp */ - /* - * The intercept_wrapper function did restore all registers to their - * original state, except for rax, rsp, rip, and r11. - * - * If r11 is zero, rax contains a syscall number, and that syscall - * is executed here. - * If r11 is 1, rax contains the return value of the hooked syscall. - * If r11 is 2, a clone syscall is executed here. - */ - cmp $0x0, %r11 - je 2f - cmp $0x1, %r11 - je 3f - cmp $0x2, %r11 - je 1f - - hlt /* r11 value is invalid? */ - -1: - /* execute the clone syscall in its original context */ - syscall - movq $0x1, %rcx /* choose intercept_routine_post_clone */ - /* - * Now goto 0, and call the C function named - * intercept_routine_post_clone both in the parent thread, adn the - * child thread. - */ - jmp 0b - -2: - syscall -3: -intercept_asm_wrapper_tmpl_end: - /* - * This template must be appended here with a - * jump back to the intercepted code. - */ + # + # Copyright 2016-2024, Intel Corporation + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions + # are met: + # + # * Redistributions of source code must retain the above copyright + # notice, this list of conditions and the following disclaimer. + # + # * Redistributions in binary form must reproduce the above copyright + # notice, this list of conditions and the following disclaimer in + # the documentation and/or other materials provided with the + # distribution. + # + # * Neither the name of the copyright holder nor the names of its + # contributors may be used to endorse or promote products derived + # from this software without specific prior written permission. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + # + + # intercept_template.s -- see asm_wrapper.md + + .globl intercept_asm_wrapper_tmpl + # .local intercept_asm_wrapper_tmpl # x64 uses .hidden - how to port to RISC-V? + .globl intercept_asm_wrapper_patch_desc_addr + # .local intercept_asm_wrapper_patch_desc_addr + .globl intercept_asm_wrapper_wrapper_level1_addr + # .local intercept_asm_wrapper_wrapper_level1_addr + .globl intercept_asm_wrapper_tmpl_end + # .local intercept_asm_wrapper_tmpl_end + + .text + + # ld t0, 0(sp) + # addi sp, sp, 16 + # preceding_ins_2 + # preceding_ins + intercept_asm_wrapper_tmpl: + li t5, 0 # choose intercept_routine + l0: + bnez t5, l3 + mv t6, sp # remember original sp + j l4 + l3: + ld t6, 0(sp) # we cloned, so save actual original sp + l4: + addi sp, sp, -32 # allocate stack for some locals + sd t6, 0(sp) # original sp on stack + sd ra, 16(sp) # patch->return_address on stack + sd s0, 24(sp) # following conventions by saving s0 on stack since we use it + bnez t5, intercept_asm_wrapper_patch_desc_addr + li s0, 0 # s0 as flag: 1 if we are going for post_clone, 0 otherwise + intercept_asm_wrapper_patch_desc_addr: + # load patch_desc address in t0 + + # the 5 following instructions are placeholders for the correct ones which are + # overwritten in machine language by create_load_uint64t_into_t0() + lui t0, 0x00000 + addi t0, t0, 0x000 + slli t0, t0, 32 + lui t3, 0x00000 + addi t3, t3, 0x000 + + # the 9 following instructions load the 64-bit address in t0 + lui t1, 0x7ffff + ori t2, zero, 0x7ff + slli t2, t2, 1 + ori t2, t2, 1 + or t1, t1, t2 + slli t1, t1, 1 + ori t1, t1, 1 + and t3, t3, t1 + or t0, t0, t3 + + sd t0, 8(sp) # patch_desc pointer on stack + intercept_asm_wrapper_wrapper_level1_addr: + # load intercept_wrapper address in t0 + + # the 5 following instructions are placeholders for the correct ones which are + # written in machine language in create_load_uint64t_into_t0() in patcher.c + lui t0, 0x00000 + ori t0, t0, 0x000 + slli t0, t0, 32 + lui t3, 0x00000 + ori t3, t3, 0x000 + + # the 9 following instructions load the 64-bit address in t0 + lui t1, 0x7ffff + ori t2, zero, 0x7ff + slli t2, t2, 1 + ori t2, t2, 1 + or t1, t1, t2 + slli t1, t1, 1 + ori t1, t1, 1 + and t3, t3, t1 + or t0, t0, t3 + + # calling intercept_wrapper + jalr ra, t0, 0 + + + # The intercept_wrapper function did restore all registers to their + # original state, except for a0, sp and t6. + # + # If t6 is zero, rax contains a syscall number, and that syscall + # is executed here. + # If t6 is 1, rax contains the return value of the hooked syscall. + # If t6 is 2, a clone syscall is executed here. + + beqz t6, l2 + li t0, 1 + beq t6, t0, restore_sp + li t0, 2 + beq t6, t0, l1 + + li a7, 94 # exit_group if t6 contains an invalid value, namely different from + ecall # 0, 1 or 2 + + l1: + mv a7, a0 + ecall + li t5, 1 # choose intercept_routine_post_clone + li s0, 1 # flag to signal we cloned, restoring sp will require adding 64 + j l0 + l2: + mv a7, a0 + ecall + restore_sp: + beqz s0, l5 + addi sp, sp, 32 + l5: + ld ra, 16(sp) + ld s0, 24(sp) + addi sp, sp, 32 + + intercept_asm_wrapper_tmpl_end: + # This template must be appended here with a + # jump back to the intercepted code. + + # following_ins # !can't use ra as operand! need to check after disassembly + # jalr zero, ra, 0 diff --git a/src/intercept_wrapper.S b/src/intercept_wrapper.S index 7291a17..65ec8e2 100644 --- a/src/intercept_wrapper.S +++ b/src/intercept_wrapper.S @@ -1,232 +1,161 @@ -/* - * Copyright 2016-2017, Intel Corporation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * intercept_wrapper.s -- see asm_wrapper.md - */ - -/* the function in this file */ -.global intercept_wrapper -.hidden intercept_wrapper -.type intercept_wrapper, @function - -/* the C function in intercept.c */ -.global intercept_routine -.hidden intercept_routine -.type intercept_routine, @function - -/* the other C function in intercept.c, called right after cloning a thread */ -.global intercept_routine_post_clone -.hidden intercept_routine_post_clone -.type intercept_routine_post_clone, @function - -/* The boolean indicating whether YMM registers must saved */ -.global intercept_routine_must_save_ymm -.hidden intercept_routine_must_save_ymm - -.text - -/* - * Local stack layout: - * - * 0x448(%rsp) -- return address, to the generated asm wrapper - * Arguments recieved on stack: - * 0x450(%rsp) -- original value of rsp - * 0x458(%rsp) -- pointer to a struct patch_desc instance - * Locals on stack: - * 0xe8(%rsp) - 0x168(%rsp) -- saved GPRs - * 0x200(%rsp) - 0x400(%rsp) -- saved SIMD registers - * - * A pointer to these saved register is passed to intercept_routine, so the - * layout of `struct context` must match this part of the stack layout. - * - * Other arguments: - * %rcx -- which C function to call - */ -intercept_wrapper: - .cfi_startproc - - /* - * Stack size used locally: 0x448 bytes. - * - * This size assumes the stack pointer was correctly aligned before - * executing the call instruction calling this function. The return - * address pushed to the stack uses 8 bytes. This gives the equation: - * - * new_rsp = original_rsp - 8 - 0x448 == original_rsp - 0x450 - * The number 0x450 is a multiple of 16, so the stack is still correctly - * aligned. It is very easy to forget about this when making changes to this - * code. - */ - subq $0x448, %rsp - .cfi_def_cfa_offset 0x0 - - /* Save all GPRs on the stack */ - movq %rax, 0x160 (%rsp) - .cfi_offset 0, 0x160 - movq %rdx, 0x158 (%rsp) - .cfi_offset 1, 0x158 - /* rcx is already clobbered, no reason to save it */ - movq %rbx, 0x150 (%rsp) - .cfi_offset 3, 0x150 - movq %rsi, 0x148 (%rsp) - .cfi_offset 4, 0x148 - movq %rdi, 0x140 (%rsp) - .cfi_offset 5, 0x140 - movq %rbp, 0x138 (%rsp) - .cfi_offset 6, 0x138 - movq 0x450 (%rsp), %r11 /* fetch original value of rsp */ - movq %r11, 0x130 (%rsp) - .cfi_offset 7, 0x130 - movq %r8, 0x128 (%rsp) - .cfi_offset 8, 0x128 - movq %r9, 0x120 (%rsp) - .cfi_offset 9, 0x120 - movq %r10, 0x118 (%rsp) - .cfi_offset 10, -0x118 - /* r11 is already clobbered, no reason to save it */ - movq %r12, 0x110 (%rsp) - .cfi_offset 12, 0x110 - movq %r13, 0x108 (%rsp) - .cfi_offset 13, 0x108 - movq %r14, 0x100 (%rsp) - .cfi_offset 14, 0x100 - movq %r15, 0xf8 (%rsp) - .cfi_offset 15, 0xf8 - movq 0x458 (%rsp), %r11 /* fetch pointer to patch_desc */ - movq %r11, 0xe8 (%rsp) - movq (%r11), %r11 /* fetch original value of rip */ - movq %r11, 0xf0 (%rsp) - .cfi_offset 16, 0xf0 - - movb intercept_routine_must_save_ymm (%rip), %al - test %al, %al - jz 0f - - /* - * Save the YMM registers. - * Use vmovups. Must not use vmovaps, since 32 byte alignment is not - * guaranteed. - * One could just align the stack for this, but that would need - * more explanation in comments in other places about why overaligned - * stack is needed. - */ - vmovups %ymm0, 0x3c0 (%rsp) - vmovups %ymm1, 0x380 (%rsp) - vmovups %ymm2, 0x340 (%rsp) - vmovups %ymm3, 0x300 (%rsp) - vmovups %ymm4, 0x2c0 (%rsp) - vmovups %ymm5, 0x280 (%rsp) - vmovups %ymm6, 0x240 (%rsp) - vmovups %ymm7, 0x200 (%rsp) - jmp 1f - -0: - /* Save the XMM registers. */ - movaps %xmm0, 0x3c0 (%rsp) - movaps %xmm1, 0x380 (%rsp) - movaps %xmm2, 0x340 (%rsp) - movaps %xmm3, 0x300 (%rsp) - movaps %xmm4, 0x2c0 (%rsp) - movaps %xmm5, 0x280 (%rsp) - movaps %xmm6, 0x240 (%rsp) - movaps %xmm7, 0x200 (%rsp) - -1: - /* argument passed to intercept_routine */ - leaq 0xe8 (%rsp), %rdi - - cmp $0x1, %rcx /* which function should be called? */ - je 0f - call intercept_routine - jmp 1f -0: call intercept_routine_post_clone -1: - /* - * At this point, the return value of the C - * function (a struct wrapper_ret instance) is in rax, rdx. - * - * This function doesn't use these values for anything, just - * forwards them to the higher level wrapper function, generated - * from the template. - */ - - movq %rdx, %r11 - /* - * At this point, the return values of this asm function - * are in rax, r11. - * - * Restore the other registers, and return. - */ - - movb intercept_routine_must_save_ymm (%rip), %dl - test %dl, %dl - jz 0f - - vmovups 0x3c0 (%rsp), %ymm0 - vmovups 0x380 (%rsp), %ymm1 - vmovups 0x340 (%rsp), %ymm2 - vmovups 0x300 (%rsp), %ymm3 - vmovups 0x2c0 (%rsp), %ymm4 - vmovups 0x280 (%rsp), %ymm5 - vmovups 0x240 (%rsp), %ymm6 - vmovups 0x200 (%rsp), %ymm7 - jmp 1f - -0: - movaps 0x3c0 (%rsp), %xmm0 - movaps 0x380 (%rsp), %xmm1 - movaps 0x340 (%rsp), %xmm2 - movaps 0x300 (%rsp), %xmm3 - movaps 0x2c0 (%rsp), %xmm4 - movaps 0x280 (%rsp), %xmm5 - movaps 0x240 (%rsp), %xmm6 - movaps 0x200 (%rsp), %xmm7 - -1: - movq 0x158 (%rsp), %rdx - movq 0x150 (%rsp), %rbx - movq 0x148 (%rsp), %rsi - movq 0x140 (%rsp), %rdi - movq 0x138 (%rsp), %rbp - movq 0x128 (%rsp), %r8 - movq 0x120 (%rsp), %r9 - movq 0x118 (%rsp), %r10 - movq 0x110 (%rsp), %r12 - movq 0x108 (%rsp), %r13 - movq 0x100 (%rsp), %r14 - movq 0xf8 (%rsp), %r15 - - addq $0x448, %rsp - - retq - .cfi_endproc +# +# Copyright 2016-2024, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + + # intercept_wrapper.s -- see asm_wrapper.md + + # the function in this file + .globl intercept_wrapper + # .local intercept_wrapper # again, how to translate .hidden from x86_64? + .type intercept_wrapper, @function + + # the C function in intercept.c + .globl intercept_routine + # .local intercept_routine + .type intercept_routine, @function + + # the other C function in intercept.c, called right after cloning a thread + .globl intercept_routine_post_clone + # .local intercept_routine_post_clone + .type intercept_routine_post_clone, @function + + .text + + intercept_wrapper: + # Decreasing sp to allocate needed space to save caller-saved registers but + # t5 and t6 which are already clobbered, original sp value around the ecall + # and patch_desc pointer + addi sp, sp, -288 + # Saving temporary and function arguments registers, which are both + # caller-saved onto the stack + sd ra, 0(sp) + sd t0, 8(sp) + sd t1, 16(sp) + sd t2, 24(sp) + sd t3, 32(sp) + sd t4, 40(sp) + + # fetching original value of sp + ld t6, 288(sp) + sd t6, 48(sp) + + # fetching pointer to patch_desc + ld t6, 296(sp) + sd t6, 56(sp) + + sd a0, 64(sp) + sd a1, 72(sp) + sd a2, 80(sp) + sd a3, 88(sp) + sd a4, 96(sp) + sd a5, 104(sp) + sd a6, 112(sp) + sd a7, 120(sp) + sd ft0, 128(sp) + sd ft1, 136(sp) + sd ft2, 144(sp) + sd ft3, 152(sp) + sd ft4, 160(sp) + sd ft5, 168(sp) + sd ft6, 176(sp) + sd ft7, 184(sp) + sd ft8, 192(sp) + sd ft9, 200(sp) + sd ft10, 208(sp) + sd ft11, 216(sp) + sd fa0, 224(sp) + sd fa1, 232(sp) + sd fa2, 240(sp) + sd fa3, 248(sp) + sd fa4, 256(sp) + sd fa5, 264(sp) + sd fa6, 272(sp) + sd fa7, 280(sp) + + # argument passed to intercept_routine + mv a0, sp + + li t0, 1 + beq t5, t0, l0 # which function should be called? + + jal intercept_routine + j l1 + l0: + jal intercept_routine_post_clone + l1: + + # At this point, the return value of the C + # function (a struct wrapper_ret instance) is in a0, a1. + # + # This function doesn't use these values for anything, just + # forwards them to the higher level wrapper function, generated + # from the template. + + mv t6, a1 + + # Restoring temporary and funcion arguments registers + ld ra, 0(sp) + ld t0, 8(sp) + ld t1, 16(sp) + ld t2, 24(sp) + ld t3, 32(sp) + ld t4, 40(sp) + # no point in restoring in context values at 48(sp), 56(sp) and 64(sp) + ld a1, 72(sp) + ld a2, 80(sp) + ld a3, 88(sp) + ld a4, 96(sp) + ld a5, 104(sp) + ld a6, 112(sp) + ld a7, 120(sp) + ld ft0, 128(sp) + ld ft1, 136(sp) + ld ft2, 144(sp) + ld ft3, 152(sp) + ld ft4, 160(sp) + ld ft5, 168(sp) + ld ft6, 176(sp) + ld ft7, 184(sp) + ld ft8, 192(sp) + ld ft9, 200(sp) + ld ft10, 208(sp) + ld ft11, 216(sp) + ld fa0, 224(sp) + ld fa1, 232(sp) + ld fa2, 240(sp) + ld fa3, 248(sp) + ld fa4, 256(sp) + ld fa5, 264(sp) + ld fa6, 272(sp) + ld fa7, 280(sp) + # Increasing sp to its original value + addi sp, sp, 288 + ret diff --git a/src/util.S b/src/util.S index 4b375c8..22020ec 100644 --- a/src/util.S +++ b/src/util.S @@ -1,67 +1,67 @@ -/* - * Copyright 2016-2017, Intel Corporation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +# +# Copyright 2016-2024, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# -.global has_ymm_registers; -.hidden has_ymm_registers; +.globl has_ymm_registers +# .local has_ymm_registers # what does .hidden mean in x86_64? .type has_ymm_registers, @function -.global syscall_no_intercept; +.globl syscall_no_intercept; .type syscall_no_intercept, @function .text has_ymm_registers: - .cfi_startproc - pushq %rbx - movq $0x1, %rax - cpuid - movq %rcx, %rax - shrq $28, %rax - andq $1, %rax - popq %rbx - retq - .cfi_endproc - + # .cfi_startproc + # pushq %rbx + # movq $0x1, %rax + # cpuid + # movq %rcx, %rax + # shrq $28, %rax + # andq $1, %rax + # popq %rbx + # retq + # .cfi_endproc .size has_ymm_registers, .-has_ymm_registers syscall_no_intercept: - movq %rdi, %rax /* convert from linux ABI calling */ - movq %rsi, %rdi /* convention to syscall calling convention */ - movq %rdx, %rsi - movq %rcx, %rdx - movq %r8, %r10 - movq %r9, %r8 - movq 8(%rsp), %r9 - syscall - ret + # converting from RISC-V calling conventions to RISC-V Linux calling conventions + mv a7, a0 + mv a0, a1 + mv a1, a2 + mv a2, a3 + mv a3, a4 + mv a4, a5 + mv a5, a6 + ecall + ret .size syscall_no_intercept, .-syscall_no_intercept From d1cb7a8d2030dba0bb23c083e5eda206f5752a2f Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 5 Jun 2024 04:18:28 +0200 Subject: [PATCH 007/143] pattern1 work in progress --- test/mock_trampoline_table.S | 75 +++++++++++------------------------- test/pattern1.in.S | 7 ++-- test/pattern1.out.S | 21 +++++----- 3 files changed, 39 insertions(+), 64 deletions(-) diff --git a/test/mock_trampoline_table.S b/test/mock_trampoline_table.S index c97bcee..2c9599b 100644 --- a/test/mock_trampoline_table.S +++ b/test/mock_trampoline_table.S @@ -49,60 +49,31 @@ # cases -- the only thing that matters, is to have these at predictable # addresses. -.intel_syntax noprefix - -.global trampoline_table; -.global trampoline_table_end; +.globl trampoline_table; +.globl trampoline_table_end; .data trampoline_table: -dst0: jmp [rip] - .space 8, 0 -dst1: jmp [rip] - .space 8, 0 -dst2: jmp [rip] - .space 8, 0 -dst3: jmp [rip] - .space 8, 0 -dst4: jmp [rip] - .space 8, 0 -dst5: jmp [rip] - .space 8, 0 -dst6: jmp [rip] - .space 8, 0 -dst7: jmp [rip] - .space 8, 0 -dst8: jmp [rip] - .space 8, 0 -dst9: jmp [rip] - .space 8, 0 -dst10: jmp [rip] - .space 8, 0 -dst11: jmp [rip] - .space 8, 0 -dst12: jmp [rip] - .space 8, 0 -dst13: jmp [rip] - .space 8, 0 -dst14: jmp [rip] - .space 8, 0 -dst15: jmp [rip] - .space 8, 0 -dst16: jmp [rip] - .space 8, 0 -dst17: jmp [rip] - .space 8, 0 -dst18: jmp [rip] - .space 8, 0 -dst19: jmp [rip] - .space 8, 0 -dst20: jmp [rip] - .space 8, 0 -dst21: jmp [rip] - .space 8, 0 -dst22: jmp [rip] - .space 8, 0 -dst23: jmp [rip] - .space 8, 0 +dst0: + addi sp, sp, -16 + sd t1, 0(sp) + sd t2, 8(sp) + sd t3, 16(sp) + .space 20, 0 + lui t1, 0x7ffff + ori t2, zero, 0x7ff + slli t2, t2, 1 + ori t2, t2, 1 + or t1, t1, t2 + slli t1, t1, 1 + ori t1, t1, 1 + and t3, t3, t1 + or t0, t0, t3 + ld t1, 0(sp) + ld t2, 8(sp) + ld t3, 16(sp) + addi sp, sp, 16 + jalr zero, t0, 0 + trampoline_table_end: diff --git a/test/pattern1.in.S b/test/pattern1.in.S index 561c89f..64ff8b6 100644 --- a/test/pattern1.in.S +++ b/test/pattern1.in.S @@ -43,7 +43,8 @@ .text text_start: - mov rax, 1 - syscall - cmp rax, -1 + addi a7, zero, 1 + addi a7, a7, zero + ecall + addi zero, zero, zero text_end: diff --git a/test/pattern1.out.S b/test/pattern1.out.S index 333175a..ce21883 100644 --- a/test/pattern1.out.S +++ b/test/pattern1.out.S @@ -41,13 +41,16 @@ .text text_start: - jmp dst0 - int3 - int3 - int3 - int3 - int3 - int3 - int3 - int3 + jal dst0 + addi zero, zero, 0 # nop + addi zero, zero, 0 # nop + addi zero, zero, 0 # nop + + #otherwise + + # addi sp, sp, -16 + # sd t0, 8(sp) + # lui t0, 0x..... + # jalr ra, t0, 0x... + text_end: From 07af3783e02fb8a33d58405f392eb77502e5fbf4 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 11 Jun 2024 12:28:27 +0200 Subject: [PATCH 008/143] code cleanup --- src/disasm_wrapper.c | 150 +---------------------------- src/patcher.c | 220 +------------------------------------------ 2 files changed, 4 insertions(+), 366 deletions(-) diff --git a/src/disasm_wrapper.c b/src/disasm_wrapper.c index c57d15c..2ad699f 100644 --- a/src/disasm_wrapper.c +++ b/src/disasm_wrapper.c @@ -131,72 +131,6 @@ intercept_disasm_destroy(struct intercept_disasm_context *context) xmunmap(context, sizeof(*context)); } -/* - * check_op - checks a single operand of an instruction, looking - * for RIP relative addressing. - */ -// static void -// check_op(struct intercept_disasm_result *result, cs_x86_op *op, -// const unsigned char *code) -// { -// /* -// * the address the RIP register is going to contain during the -// * execution of this instruction -// */ -// const unsigned char *rip = code + result->length; -// -// if (op->type == RISCV_OP_REG) { -// if (op->reg == X86_REG_IP || op->reg == X86_REG_RIP) { -// /* -// * Example: mov %rip, %rax -// */ -// result->has_ip_relative_opr = true; -// result->rip_disp = 0; -// result->rip_ref_addr = rip; -// } -// if (result->is_jump) { -// /* -// * Example: jmp *(%rax) -// */ -// /* -// * An indirect jump can't have arguments other -// * than a register - therefore the asserts. -// * ( I'm 99.99% sure this is true ) -// */ -// assert(!result->is_rel_jump); -// result->is_indirect_jump = true; -// } -// } else if (op->type == X86_OP_MEM) { -// if (op->mem.base == X86_REG_IP || -// op->mem.base == X86_REG_RIP || -// op->mem.index == X86_REG_IP || -// op->mem.index == X86_REG_RIP || -// result->is_jump) { -// result->has_ip_relative_opr = true; -// assert(!result->is_indirect_jump); -// -// if (result->is_jump) -// result->is_rel_jump = true; -// -// assert(op->mem.disp <= INT32_MAX); -// assert(op->mem.disp >= INT32_MIN); -// -// result->rip_disp = (int32_t)op->mem.disp; -// result->rip_ref_addr = rip + result->rip_disp; -// } -// } else if (op->type == X86_OP_IMM) { -// if (result->is_jump) { -// assert(!result->is_indirect_jump); -// result->has_ip_relative_opr = true; -// result->is_rel_jump = true; -// result->rip_ref_addr = (void *)op->imm; -// -// result->rip_disp = -// (int32_t)((unsigned char *)op->imm - rip); -// } -// } -// } - /* * intercept_disasm_next_instruction - Examines a single instruction * in a text section. This is only a wrapper around capstone specific code, @@ -211,18 +145,7 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, struct intercept_disasm_result result = {.address = code, 0, }; const unsigned char *start = code; size_t size = (size_t)(context->end - code + 1); - uint64_t address = (uint64_t)code; - -// if (size >= sizeof(endbr64) && -// memcmp(code, endbr64, sizeof(endbr64)) == 0) { -// result.is_set = true; -// result.is_endbr = true; -// result.length = 4; -// #ifndef NDEBUG -// result.mnemonic = "endbr64"; -// #endif -// return result; -// } + uint64_t address = (uint64_t)code if (!cs_disasm_iter(context->handle, &start, &size, &address, context->insn)) { @@ -234,11 +157,6 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, assert(result.length != 0); result.is_syscall = (context->insn->id == RISCV_INS_ECALL); - // result.is_call = (context->insn->id == RISCV_INS_JAL || - // context->insn->id == RISCV_INS_JALR); - // result.is_ret = (context->insn->id == RISCV_INS_JALR); // jalr รจ usata sia per ret che per le chiamate, per asserire o meno queste variabili servono verifiche diverse - // result.is_rel_jump = false; - // result.is_indirect_jump = false; #ifndef NDEBUG result.mnemonic = context->insn->mnemonic; #endif @@ -259,35 +177,6 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, break; case RISCV_INS_JALR: result.is_jump = true; - // result.is_ret = true; - // cs_riscv_op *op; - // for (uint8_t op_i = 0; result.is_ret && - // op_i < context->insn->detail->riscv.op_count; ++op_i) { - // op = context->insn->detail->riscv.operands + op_i; - // switch (op->type) { - // case RISCV_OP_REG: - // if (op->reg != RISCV_REG_ZERO || op->reg != RISCV_REG_RA) { - // result.is_ret = false; - // } - // break; - // case RISCV_OP_IMM: - // if (op->imm != 0) { - // result.is_ret = false; - // } - // break; - // case RISCV_OP_MEM: - // if (op->mem.base != RISCV_REG_RA || op->mem.disp != 0) { - // result.is_ret = false; - // } - // break; - // default: - // result.is_ret = false; - // break; - // } - // } - // if (!result.is_ret) { - // result.is_jump = true; - // } break; default: result.is_jump = false; @@ -305,49 +194,12 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, result.uses_ra = op->mem.base == RISCV_REG_RA; break; default: - //result.is_ret = false; break; } } break; } - - /* - * Loop over all operands of the instruction currently being decoded. - * These operands are decoded by capstone, and described in the - * context->insn->detail->x86.operands array. - * - * This operand checking serves multiple purposes: - * The destination of any jumping instruction is found here, - * The instructions using RIP relative addressing are found by this - * loop, e.g.: mov %rax, 0x36eb55d(%rip) - * - * Any instruction relying on the value of the RIP register can not - * be relocated ( including relative jumps, which naturally also - * rely on the RIP register ). - */ - // for (uint8_t op_i = 0; // needed? PC isn't usable as operand in RISC-V, so you know if instruction it's PC-relative from the instruction itself - // op_i < context->insn->detail->x86.op_count; ++op_i) - // check_op(&result, context->insn->detail->x86.operands + op_i, - // code); - - // result.is_lea_rip = (context->insn->id == X86_INS_LEA && // no LEA instruction equivalent in RISC-V machine language - // result.has_ip_relative_opr); - // - // if (result.is_lea_rip) { - // /* - // * Extract the four bits from the encoding, which - // * specify the destination register. - // */ - // - // /* one bit from the REX prefix */ - // result.arg_register_bits = ((code[0] & 4) << 1); - // - // /* three bits from the ModRM byte */ - // result.arg_register_bits |= ((code[2] >> 3) & 7); - // } - result.is_set = true; return result; diff --git a/src/patcher.c b/src/patcher.c index 20d9cbe..d33b105 100644 --- a/src/patcher.c +++ b/src/patcher.c @@ -90,6 +90,7 @@ enum { TRAMPOLINE_SIZE = 23 * 4 }; static void create_wrapper(struct patch_desc *patch, unsigned char **dst); +static unsigned char *create_absolute_jump(unsigned char *from, void *to); /* * create_absolute_jump(from, to) @@ -103,7 +104,6 @@ create_absolute_jump(unsigned char *from, void *to) instructions[1] = 0x00613023; // sd t1, 0(sp) instructions[2] = 0x00713423; // sd t2, 8(sp) instructions[3] = 0x01c13823; // sd t3, 16(sp) - create_load_uint64t_into_t0(instructions + 4,(uint64_t)value); instructions[9] = 0x7ffff337; // lui t1, 0x7ffff instructions[10] = 0x7ff06393; // ori t2, zero, 0x7ff instructions[11] = 0x00139393; // slli t2, t2, 1 @@ -118,6 +118,7 @@ create_absolute_jump(unsigned char *from, void *to) instructions[20] = 0x01013e03; // ld t3, 16(sp) instructions[21] = 0x01010113; // addi sp, sp, 16 instructions[22] = 0x00028067; // jalr zero, t0, 0 + create_load_uint64t_into_t0(instructions + 4,(uint64_t)value); // writes 5 instructions starting from instructions[4] return instructions + 23; } @@ -209,55 +210,6 @@ is_nop_in_range(unsigned char *address, const struct range *nop) return reach_min <= dst && dst <= reach_max; } -/* - * assign_nop_trampoline - * Looks for a NOP instruction close to a syscall instruction to be patched. - * The struct patch_desc argument specifies where the particular syscall - * instruction resides, and the struct intercept_desc argument of course - * already contains information about NOPs, collected by the find_syscalls - * routine. - * - * This routine essentially initializes the uses_nop_trampoline and - * the nop_trampoline fields of a struct patch_desc. - */ -// static void -// assign_nop_trampoline(struct intercept_desc *desc, -// struct patch_desc *patch, -// size_t *next_nop_i) -// { -// struct range *nop = desc->nop_table + *next_nop_i; -// -// if (*next_nop_i >= desc->nop_count) { -// patch->uses_nop_trampoline = false; -// return; /* no more nops available */ -// } -// -// /* -// * Consider a nop instruction, to use as trampoline, but only -// * if a two byte jump in the place of the syscall can jump -// * to the proposed trampoline. Check if the nop is: -// * 1) at an address too low -// * 2) close enough for a two byte jump -// * 3) at an address too high -// */ -// -// if (is_nop_in_range(patch->syscall_addr, nop)) { -// patch->uses_nop_trampoline = true; -// patch->nop_trampoline = *nop; -// ++(*next_nop_i); -// return; /* found a nop in range to use as trampoline */ -// } -// -// if (nop->address > patch->syscall_addr) { -// patch->uses_nop_trampoline = false; -// return; /* nop is too far ahead */ -// } -// -// /* nop is too far behind, try the next nop */ -// ++(*next_nop_i); -// assign_nop_trampoline(desc, patch, next_nop_i); -// } - /* * is_copiable_before_syscall * checks if an instruction found before a syscall instruction @@ -354,37 +306,6 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) debug_dump("patching %s:0x%lx\n", desc->path, patch->syscall_addr - desc->base_addr); - // assign_nop_trampoline(desc, patch, &next_nop_i); // useless since NOPs aren't usable as x64 intended to - - // if (patch->uses_nop_trampoline) { // always false; can ditch the entire if branch - // /* - // * The preferred option it to use a 5 byte relative - // * jump in a padding space between symbols in libc. - // * If such padding space is found, a 2 byte short - // * jump is enough for jumping to it, thus no - // * instructions other than the syscall - // * itself need to be overwritten. - // */ - // patch->uses_prev_ins = false; - // patch->uses_prev_ins_2 = false; - // patch->uses_next_ins = false; - // patch->dst_jmp_patch = - // patch->nop_trampoline.address + 2; - // /* - // * The first two bytes of the nop are used for - // * something else, see the explanation - // * at is_overwritable_nop in intercept_desc.c - // */ - // - // /* - // * Return to libc: - // * just jump to instruction right after the place - // * where the syscall instruction was originally. - // */ - // patch->return_address = - // patch->syscall_addr + SYSCALL_INS_SIZE; - // - // } else { /* * No padding space is available, so check the * instructions surrounding the syscall instruction. @@ -450,20 +371,7 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) patch->return_address = patch->syscall_addr + ECALL_INS_SIZE + patch->following_ins.length; - } //else { // if patch->uses_next_ins is false this else branch is not important since length won't be enough nevertheless - // /* - // * Address of the syscall instruction - // * plus 2 bytes - // * - // * adds up to: - // * - // * the address of the first instruction after - // * the syscall ( just like in the case of - // * using padding bytes ). - // */ - // patch->return_address = - // patch->syscall_addr + ECALL_INS_SIZE; - // } + } /* * If the length is at least 16, then a jump instruction @@ -483,7 +391,6 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) xabort("not enough space for patching" " around syscal"); } - // } mark_jump(desc, patch->return_address); @@ -529,57 +436,8 @@ init_patcher(void) o_patch_desc_addr = &intercept_asm_wrapper_patch_desc_addr - begin; o_wrapper_level1_addr = &intercept_asm_wrapper_wrapper_level1_addr - begin; - - /* - * has_ymm_registers -- checks if AVX instructions are supported, - * thus YMM registers can be used on this CPU. - * - * this function is implemented in util.s - * - * XXX check for ZMM registers, and save/restore them! - */ - // extern bool has_ymm_registers(void); - // - // intercept_routine_must_save_ymm = has_ymm_registers(); } -/* - * create_movabs - * Generates a movabs instruction, that assigns a 64 bit constant to - * the 64 general purpose register. - * the reg_bits value must contain the X86 encoding of the register. - * Returns a pointer to the char right after the generated instruction. - */ -// static unsigned char * -// create_movabs(unsigned char *code, uint64_t value, unsigned char reg_bits) -// { -// assert(reg_bits < 16); -// -// unsigned char *bytes = (unsigned char *)&value; -// -// *code++ = 0x48 | (reg_bits >> 3); /* REX prefix */ -// *code++ = 0xb8 | (reg_bits & 7); /* opcode */ -// *code++ = bytes[0]; -// *code++ = bytes[1]; -// *code++ = bytes[2]; -// *code++ = bytes[3]; -// *code++ = bytes[4]; -// *code++ = bytes[5]; -// *code++ = bytes[6]; -// *code++ = bytes[7]; -// -// return code; -// } - -/* - * create_movabs_r11 - * Generates a movabs instruction moving a value into the R11 register. - */ -// static unsigned char * -// create_movabs_r11(unsigned char *code, uint64_t value) -// { -// return create_movabs(code, value, 11); -// } /* * create_ret_from_template @@ -651,19 +509,8 @@ static unsigned char * relocate_instruction(unsigned char *dst, const struct intercept_disasm_result *ins) { - // if (ins->is_lea_rip) { - // /* - // * Substitue a "lea $offset(%rip), %reg" instruction - // * by a movabs instruction, to achieve the same effect. - // * The result of the lea calculation is already calculated - // * in the rip_ref_addr variable. - // */ - // return create_movabs(dst, (uint64_t)ins->rip_ref_addr, - // ins->arg_register_bits); - // } else { memcpy(dst, ins->address, ins->length); return dst + ins->length; - // } } /* @@ -708,33 +555,6 @@ create_wrapper(struct patch_desc *patch, unsigned char **dst) *dst = create_ret_from_template(*dst); } -/* - * create_short_jump - * Generates a 2 byte jump instruction. The to address must be reachable - * using an 8 bit displacement. - */ -// static void -// create_short_jump(unsigned char *from, unsigned char *to) -// { -// ptrdiff_t d = to - (from + 2); -// -// if (d < - 128 || d > 127) -// xabort("create_short_jump distance check"); -// -// from[0] = SHORT_JMP_OPCODE; -// from[1] = (unsigned char)((char)d); -// } - -/* - * after_nop -- get the address of the instruction - * following the nop. - */ -// static unsigned char * -// after_nop(const struct range *nop) -// { -// return nop->address + nop->size; -// } - /* * create_j(from, to) * Create a 4 byte JAL instruction jumping to address to, by overwriting @@ -870,40 +690,6 @@ activate_patches(struct intercept_desc *desc) create_j(patch->dst_jmp_patch, patch->asm_wrapper); } - // if (patch->uses_nop_trampoline) { - // /* - // * Create a mini trampoline jump. - // * The first two bytes of the NOP instruction are - // * overwritten by a short jump instruction - // * (with 8 bit displacement), to make sure whenever - // * this the execution reaches the address where this - // * NOP resided originally, it continues uninterrupted. - // * The rest of the bytes occupied by this instruction - // * are used as an mini extra trampoline table. - // * - // * See also: the is_overwritable_nop function in - // * the intercept_desc.c source file. - // */ - // - // /* jump from syscall to mini trampoline */ - // create_short_jump(patch->syscall_addr, - // patch->dst_jmp_patch); - // - // /* - // * Short jump to next instruction, skipping the newly - // * created trampoline jump. - // */ - // create_short_jump(patch->nop_trampoline.address, - // after_nop(&patch->nop_trampoline)); - // } else { - // unsigned char *byte; - // - // for (byte = patch->dst_jmp_patch + JUMP_INS_SIZE; - // byte < patch->return_address; - // ++byte) { - // *byte = INT3_OPCODE; - // } - // } } mprotect_no_intercept(first_page, size, From b5499ccddf7fff96e2972698448a1e75bfbae773 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 11 Jun 2024 15:04:00 +0200 Subject: [PATCH 009/143] pointer small fix --- src/patcher.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/patcher.c b/src/patcher.c index d33b105..98391b0 100644 --- a/src/patcher.c +++ b/src/patcher.c @@ -118,7 +118,7 @@ create_absolute_jump(unsigned char *from, void *to) instructions[20] = 0x01013e03; // ld t3, 16(sp) instructions[21] = 0x01010113; // addi sp, sp, 16 instructions[22] = 0x00028067; // jalr zero, t0, 0 - create_load_uint64t_into_t0(instructions + 4,(uint64_t)value); // writes 5 instructions starting from instructions[4] + create_load_uint64t_into_t0(instructions + 4,(uint64_t)to); // writes 5 instructions starting from instructions[4] return instructions + 23; } @@ -450,7 +450,7 @@ init_patcher(void) static unsigned char * create_ret_from_template(unsigned char *code) { - *((uint32_t)code) = 0x00008067; // jalr zero, ra, 0 + *((uint32_t *)code) = 0x00008067; // jalr zero, ra, 0 return code + 4; } From 8b4ce8d3c634dce5ce01ccad0144bb59a542870d Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 12 Jun 2024 15:08:01 +0200 Subject: [PATCH 010/143] small pointer fix and added prototype of a function --- src/patcher.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/patcher.c b/src/patcher.c index 98391b0..75f2310 100644 --- a/src/patcher.c +++ b/src/patcher.c @@ -90,7 +90,7 @@ enum { TRAMPOLINE_SIZE = 23 * 4 }; static void create_wrapper(struct patch_desc *patch, unsigned char **dst); -static unsigned char *create_absolute_jump(unsigned char *from, void *to); +static void create_load_uint64t_into_t0(uint8_t *code, uint64_t value); /* * create_absolute_jump(from, to) @@ -99,7 +99,7 @@ static unsigned char *create_absolute_jump(unsigned char *from, void *to); static unsigned char * create_absolute_jump(unsigned char *from, void *to) { - uint32_t *instructions = (uint32_t)from; + uint32_t *instructions = (uint32_t *)from; instructions[0] = 0xff010113; // addi sp, sp, -16 instructions[1] = 0x00613023; // sd t1, 0(sp) instructions[2] = 0x00713423; // sd t2, 8(sp) From d6572cc70b34c402b29ccbbab739570f8a9771ed Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 12 Jun 2024 15:51:37 +0200 Subject: [PATCH 011/143] small fix, code cleanup and disabled CMake PERFORM_STYLE_CHECKS and TREAT_WARNING_AS_ERRORS flags --- CMakeLists.txt | 6 +-- src/intercept_desc.c | 37 ---------------- src/patcher.c | 42 +----------------- src/syscall_formats.c | 99 ++++++++++++++++++++----------------------- 4 files changed, 52 insertions(+), 132 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc3ee60..71ff641 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,11 +41,11 @@ if(",${CMAKE_SOURCE_DIR}," STREQUAL ",${CMAKE_BINARY_DIR},") endif() option(PERFORM_STYLE_CHECKS - "check coding style, license headers (requires perl)" ON) + "check coding style, license headers (requires perl)" OFF) option(BUILD_TESTS "build and enable tests" ON) option(BUILD_EXAMPLES "build examples" ON) option(TREAT_WARNINGS_AS_ERRORS - "make the build fail on any warnings during compilation, or linking" ON) + "make the build fail on any warnings during compilation, or linking" OFF) option(EXPECT_SPURIOUS_SYSCALLS "account for some unexpected syscalls in tests - enable while using sanitizers, gcov" OFF) option(STATIC_CAPSTONE "statically link libcapstone into the shared library" OFF) @@ -216,7 +216,7 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall - "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake") + "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake") add_subdirectory(doc) diff --git a/src/intercept_desc.c b/src/intercept_desc.c index 1136edb..d6cc506 100644 --- a/src/intercept_desc.c +++ b/src/intercept_desc.c @@ -404,36 +404,6 @@ add_new_patch(struct intercept_desc *desc) return &(desc->items[desc->count++]); } -/* - * is_overwritable_nop - * Check if an instruction just disassembled is a NOP that can be - * used for placing an extra jump instruction into it. - * See the nop_trampoline usage in the patcher.c source file. - * This instruction is usable only if it occupies at least seven bytes. - * Two are needed for a short jump, and another 5 bytes for a trampoline - * jump with 32 bit displacement. - * - * As in (where XXXX represents a 32 bit displacement): - * Before After - * _______ _______ - * address of NOP instruction -> | NOP | | JMP | <- jumps to next - * | | | +8 | instruction - * | | | JMP | <- 5 bytes of payload - * | | | X | - * | | | X | - * | | | X | - * | | | X | - * | | | | - * address of next instruction -> ------- ------- - * - */ -bool -is_overwritable_nop(const struct intercept_disasm_result *ins) -{ - // return ins->is_nop && ins->length >= 2 + 5; - return false; // dummy function: NOP are 4 bytes on RISC-V -} - /* * crawl_text * Crawl the text section, disassembling it all. @@ -483,12 +453,6 @@ crawl_text(struct intercept_desc *desc) continue; } - // if (result.has_ip_relative_opr) - // mark_jump(desc, result.rip_ref_addr); - - // if (is_overwritable_nop(&result)) // NOP is overwritable if its size is >= 7 bytes; - // mark_nop(desc, code, result.length); // RISC-V NOPs are fixed to 4-byte length, so it's never overwritable - /* * Generate a new patch description, if: * - Information is available about a syscalls place @@ -702,7 +666,6 @@ find_syscalls(struct intercept_desc *desc) (uintptr_t)desc->text_start, (uintptr_t)desc->text_end); allocate_jump_table(desc); - // allocate_nop_table(desc); // should be able to ditch without any loss, since RISC-V could not use NOPs as x86_64 intended to for (Elf64_Half i = 0; i < desc->symbol_tables.count; ++i) find_jumps_in_section_syms(desc, diff --git a/src/patcher.c b/src/patcher.c index 75f2310..de0ea15 100644 --- a/src/patcher.c +++ b/src/patcher.c @@ -175,41 +175,6 @@ check_trampoline_usage(const struct intercept_desc *desc) xabort("trampoline space not enough"); } -/* - * is_nop_in_range - checks if NOP is sufficiently close to address, to be - * reachable by a jmp having a 8 bit displacement. - */ -static bool -is_nop_in_range(unsigned char *address, const struct range *nop) -{ - /* - * Planning to put a 5 byte jump starting at the third byte - * of the nop instruction. The syscall should jump to this - * trampoline jump. - */ - unsigned char *dst = nop->address + 2; - /* - * Planning to put a two byte jump in the place of the syscall - * instruction, that is going to jump relative to the value of - * RIP during execution, which points to the next instruction, - * at address + 2. - */ - unsigned char *src = address + 2; - - /* - * How far can this short jump instruction jump, considering - * the one byte singed displacement? - */ - unsigned char *reach_min = src - 128; - unsigned char *reach_max = src + 127; - - /* - * Can a two byte jump reach the proposed destination? - * I.e.: is dst in the [reach_min, reach_max] range? - */ - return reach_min <= dst && dst <= reach_max; -} - /* * is_copiable_before_syscall * checks if an instruction found before a syscall instruction @@ -264,20 +229,17 @@ check_surrounding_instructions(struct intercept_desc *desc, struct patch_desc *patch) { patch->uses_prev_ins = (is_copiable_before_syscall(patch->preceding_ins) && - !is_overwritable_nop(&patch->preceding_ins) && !has_jump(desc, patch->syscall_addr)); if (patch->uses_prev_ins) { patch->uses_prev_ins_2 = (patch->uses_prev_ins && is_copiable_before_syscall(patch->preceding_ins_2) && - !is_overwritable_nop(&patch->preceding_ins_2) && !has_jump(desc, patch->syscall_addr - patch->preceding_ins.length)); } else { patch->uses_prev_ins_2 = false; } patch->uses_next_ins = (is_copiable_after_syscall(patch->following_ins) && - !is_overwritable_nop(&patch->following_ins) && !has_jump(desc, patch->syscall_addr + ECALL_INS_SIZE)); } @@ -360,7 +322,7 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) /* * Address of the syscall instruction - * plus 2 bytes + * plus 4 bytes * plus the length of the following instruction * * adds up to: @@ -572,7 +534,7 @@ create_j(unsigned char *from, void *to) * just after the call, and the to address. */ ptrdiff_t delta = ((unsigned char *)to) - from; - uint32_t *instructions = (uint32_t)from; + uint32_t *instructions = (uint32_t *)from; uint32_t nop = 0x00000013; // nop instruction debug_dump("%p: svc -> b %ld\t# %p\n", from, delta, to); diff --git a/src/syscall_formats.c b/src/syscall_formats.c index eba064e..cfd3aea 100644 --- a/src/syscall_formats.c +++ b/src/syscall_formats.c @@ -1,3 +1,4 @@ + /* * Copyright 2017, Intel Corporation * @@ -43,12 +44,12 @@ static const struct syscall_format formats[] = { SARGS(read, rdec, arg_fd, arg_buf_out, arg_dec), SARGS(write, rdec, arg_fd, arg_buf_in, arg_dec), - SARGS(open, rdec, arg_cstr, arg_open_flags), + // SARGS(open, rdec, arg_cstr, arg_open_flags), SARGS(close, rdec, arg_fd), - SARGS(stat, rdec, arg_cstr, arg_pointer), + // SARGS(stat, rdec, arg_cstr, arg_pointer), SARGS(fstat, rdec, arg_fd, arg_pointer), - SARGS(lstat, rdec, arg_cstr, arg_pointer), - SARGS(poll, rdec, arg_pointer, arg_, arg_), + // SARGS(lstat, rdec, arg_cstr, arg_pointer), + // SARGS(poll, rdec, arg_pointer, arg_, arg_), SARGS(lseek, rdec, arg_fd, arg_dec, arg_seek_whence), SARGS(mmap, rpointer, arg_pointer, arg_, arg_, arg_, arg_fd, arg_), SARGS(mprotect, rdec, arg_pointer, arg_, arg_), @@ -62,9 +63,9 @@ static const struct syscall_format formats[] = { SARGS(pwrite64, rdec, arg_fd, arg_buf_in, arg_dec, arg_dec), SARGS(readv, rdec, arg_fd, arg_pointer, arg_dec), SARGS(writev, rdec, arg_fd, arg_pointer, arg_dec), - SARGS(access, rdec, arg_cstr, arg_access_mode), - SARGS(pipe, rdec, arg_2fds), - SARGS(select, rdec, arg_dec32, arg_pointer, arg_pointer, arg_pointer, arg_pointer), + // SARGS(access, rdec, arg_cstr, arg_access_mode), + // SARGS(pipe, rdec, arg_2fds), + // SARGS(select, rdec, arg_dec32, arg_pointer, arg_pointer, arg_pointer, arg_pointer), SARGS(sched_yield, rdec, arg_none), SARGS(mremap, rpointer, arg_pointer, arg_dec, arg_dec, arg_dec32, arg_), SARGS(msync, rdec, arg_pointer, arg_dec, arg_dec32), @@ -74,11 +75,11 @@ static const struct syscall_format formats[] = { SARGS(shmat, rhex, arg_, arg_, arg_), SARGS(shmctl, rdec, arg_, arg_, arg_), SARGS(dup, rdec, arg_fd), - SARGS(dup2, rdec, arg_fd, arg_fd), - SARGS(pause, rdec, arg_none), + // SARGS(dup2, rdec, arg_fd, arg_fd), + // SARGS(pause, rdec, arg_none), SARGS(nanosleep, rdec, arg_, arg_), SARGS(getitimer, rdec, arg_, arg_), - SARGS(alarm, rdec, arg_), + // SARGS(alarm, rdec, arg_), SARGS(setitimer, rdec, arg_, arg_, arg_), SARGS(getpid, rdec, arg_none), SARGS(sendfile, rdec, arg_fd, arg_fd, arg_, arg_), @@ -98,8 +99,8 @@ static const struct syscall_format formats[] = { SARGS(setsockopt, rdec, arg_fd, arg_, arg_, arg_, arg_), SARGS(getsockopt, rdec, arg_fd, arg_, arg_, arg_, arg_), SARGS(clone, rdec, arg_clone_flags, arg_pointer, arg_pointer, arg_pointer, arg_), - SARGS(fork, rdec, arg_none), - SARGS(vfork, rdec, arg_none), + // SARGS(fork, rdec, arg_none), + // SARGS(vfork, rdec, arg_none), SARGS(execve, rdec, arg_, arg_, arg_), SARGS(exit, rnoreturn, arg_), SARGS(wait4, rdec, arg_dec, arg_, arg_, arg_), @@ -119,23 +120,23 @@ static const struct syscall_format formats[] = { SARGS(fdatasync, rdec, arg_fd), SARGS(truncate, rdec, arg_cstr, arg_), SARGS(ftruncate, rdec, arg_fd, arg_), - SARGS(getdents, rdec, arg_fd, arg_, arg_), + // SARGS(getdents, rdec, arg_fd, arg_, arg_), SARGS(getcwd, rdec, arg_, arg_), SARGS(chdir, rdec, arg_cstr), SARGS(fchdir, rdec, arg_fd), - SARGS(rename, rdec, arg_cstr, arg_cstr), - SARGS(mkdir, rdec, arg_cstr, arg_oct_mode), - SARGS(rmdir, rdec, arg_cstr), - SARGS(creat, rdec, arg_cstr, arg_oct_mode), - SARGS(link, rdec, arg_cstr, arg_cstr), - SARGS(unlink, rdec, arg_cstr), - SARGS(symlink, rdec, arg_cstr, arg_cstr), - SARGS(readlink, rdec, arg_cstr, arg_buf_out, arg_dec), - SARGS(chmod, rdec, arg_cstr, arg_oct_mode), + // SARGS(rename, rdec, arg_cstr, arg_cstr), + // SARGS(mkdir, rdec, arg_cstr, arg_oct_mode), + // SARGS(rmdir, rdec, arg_cstr), + // SARGS(creat, rdec, arg_cstr, arg_oct_mode), + // SARGS(link, rdec, arg_cstr, arg_cstr), + // SARGS(unlink, rdec, arg_cstr), + // SARGS(symlink, rdec, arg_cstr, arg_cstr), + // SARGS(readlink, rdec, arg_cstr, arg_buf_out, arg_dec), + // SARGS(chmod, rdec, arg_cstr, arg_oct_mode), SARGS(fchmod, rdec, arg_fd, arg_oct_mode), - SARGS(chown, rdec, arg_cstr, arg_, arg_), + // SARGS(chown, rdec, arg_cstr, arg_, arg_), SARGS(fchown, rdec, arg_fd, arg_, arg_), - SARGS(lchown, rdec, arg_cstr, arg_, arg_), + // SARGS(lchown, rdec, arg_cstr, arg_, arg_), SARGS(umask, rmode, arg_oct_mode), SARGS(gettimeofday, rdec, arg_, arg_), SARGS(getrlimit, rdec, arg_, arg_), @@ -151,7 +152,7 @@ static const struct syscall_format formats[] = { SARGS(geteuid, rdec, arg_none), SARGS(getegid, rdec, arg_none), SARGS(setpgid, rdec, arg_none), - SARGS(getpgrp, rdec, arg_none), + // SARGS(getpgrp, rdec, arg_none), SARGS(setsid, rdec, arg_none), SARGS(setreuid, rdec, arg_, arg_), SARGS(setregid, rdec, arg_, arg_), @@ -172,14 +173,14 @@ static const struct syscall_format formats[] = { SARGS(rt_sigqueueinfo, rdec, arg_, arg_, arg_), SARGS(rt_sigsuspend, rdec, arg_, arg_), SARGS(sigaltstack, rdec, arg_, arg_), - SARGS(utime, rdec, arg_cstr, arg_), - SARGS(mknod, rdec, arg_cstr, arg_, arg_), - SARGS(uselib, rdec, arg_cstr), + // SARGS(utime, rdec, arg_cstr, arg_), + // SARGS(mknod, rdec, arg_cstr, arg_, arg_), + // SARGS(uselib, rdec, arg_cstr), SARGS(personality, rdec, arg_), - SARGS(ustat, rdec, arg_, arg_), + // SARGS(ustat, rdec, arg_, arg_), SARGS(statfs, rdec, arg_cstr, arg_), SARGS(fstatfs, rdec, arg_fd, arg_), - SARGS(sysfs, rdec, arg_, arg_, arg_), + // SARGS(sysfs, rdec, arg_, arg_, arg_), SARGS(getpriority, rdec, arg_, arg_), SARGS(setpriority, rdec, arg_, arg_, arg_), SARGS(sched_setparam, rdec, arg_, arg_), @@ -194,11 +195,11 @@ static const struct syscall_format formats[] = { SARGS(mlockall, rdec, arg_), SARGS(munlockall, rdec, arg_none), SARGS(vhangup, rdec, arg_none), - SARGS(modify_ldt, rdec, arg_, arg_, arg_), + // SARGS(modify_ldt, rdec, arg_, arg_, arg_), SARGS(pivot_root, rdec, arg_cstr, arg_), - SARGS(_sysctl, rdec, arg_), + // SARGS(_sysctl, rdec, arg_), SARGS(prctl, rdec, arg_, arg_, arg_, arg_, arg_), - SARGS(arch_prctl, rdec, arg_, arg_, arg_), + // SARGS(arch_prctl, rdec, arg_, arg_, arg_), SARGS(adjtimex, rdec, arg_), SARGS(setrlimit, rdec, arg_, arg_), SARGS(chroot, rdec, arg_cstr), @@ -212,8 +213,8 @@ static const struct syscall_format formats[] = { SARGS(reboot, rdec, arg_, arg_, arg_, arg_), SARGS(sethostname, rdec, arg_, arg_), SARGS(setdomainname, rdec, arg_, arg_), - SARGS(iopl, rdec, arg_), - SARGS(ioperm, rdec, arg_, arg_, arg_), + // SARGS(iopl, rdec, arg_), + // SARGS(ioperm, rdec, arg_, arg_, arg_), SARGS(gettid, rdec, arg_none), SARGS(readahead, rdec, arg_fd, arg_dec, arg_dec), SARGS(setxattr, rdec, arg_cstr, arg_cstr, arg_buf_in, arg_dec, arg_), @@ -229,19 +230,19 @@ static const struct syscall_format formats[] = { SARGS(lremovexattr, rdec, arg_cstr, arg_cstr), SARGS(fremovexattr, rdec, arg_fd, arg_cstr), SARGS(tkill, rdec, arg_, arg_), - SARGS(time, rdec, arg_), + // SARGS(time, rdec, arg_), SARGS(futex, rdec, arg_, arg_, arg_, arg_, arg_, arg_), SARGS(sched_setaffinity, rdec, arg_, arg_, arg_), SARGS(sched_getaffinity, rdec, arg_, arg_, arg_), - SARGS(set_thread_area, rdec, arg_), + // SARGS(set_thread_area, rdec, arg_), SARGS(io_setup, rdec, arg_, arg_), SARGS(io_destroy, rdec, arg_), SARGS(io_getevents, rdec, arg_, arg_, arg_, arg_, arg_), SARGS(io_submit, rdec, arg_, arg_, arg_), SARGS(io_cancel, rdec, arg_, arg_, arg_), - SARGS(get_thread_area, rdec, arg_), + // SARGS(get_thread_area, rdec, arg_), SARGS(lookup_dcookie, rdec, arg_, arg_, arg_), - SARGS(epoll_create, rdec, arg_), + // SARGS(epoll_create, rdec, arg_), SARGS(getdents64, rdec, arg_fd, arg_, arg_), SARGS(set_tid_address, rdec, arg_), SARGS(semtimedop, rdec, arg_, arg_, arg_, arg_), @@ -256,10 +257,10 @@ static const struct syscall_format formats[] = { SARGS(clock_getres, rdec, arg_, arg_), SARGS(clock_nanosleep, rdec, arg_, arg_, arg_, arg_), SARGS(exit_group, rnoreturn, arg_), - SARGS(epoll_wait, rdec, arg_fd, arg_, arg_, arg_), + // SARGS(epoll_wait, rdec, arg_fd, arg_, arg_, arg_), SARGS(epoll_ctl, rdec, arg_fd, arg_, arg_fd, arg_), SARGS(tgkill, rdec, arg_, arg_, arg_), - SARGS(utimes, rdec, arg_cstr, arg_), + // SARGS(utimes, rdec, arg_cstr, arg_), SARGS(mbind, rdec, arg_, arg_, arg_, arg_, arg_), SARGS(set_mempolicy, rdec, arg_, arg_, arg_), SARGS(get_mempolicy, rdec, arg_, arg_, arg_, arg_, arg_), @@ -276,7 +277,7 @@ static const struct syscall_format formats[] = { SARGS(keyctl, rdec, arg_, arg_, arg_, arg_, arg_), SARGS(ioprio_set, rdec, arg_, arg_, arg_), SARGS(ioprio_get, rdec, arg_, arg_), - SARGS(inotify_init, rdec, arg_none), + // SARGS(inotify_init, rdec, arg_none), SARGS(inotify_add_watch, rdec, arg_fd, arg_cstr, arg_), SARGS(inotify_rm_watch, rdec, arg_fd, arg_), SARGS(migrate_pages, rdec, arg_, arg_, arg_, arg_), @@ -284,10 +285,10 @@ static const struct syscall_format formats[] = { SARGS(mkdirat, rdec, arg_atfd, arg_cstr, arg_oct_mode), SARGS(mknodat, rdec, arg_atfd, arg_cstr, arg_oct_mode, arg_), SARGS(fchownat, rdec, arg_atfd, arg_cstr, arg_, arg_, arg_), - SARGS(futimesat, rdec, arg_atfd, arg_cstr, arg_), + // SARGS(futimesat, rdec, arg_atfd, arg_cstr, arg_), SARGS(newfstatat, rdec, arg_atfd, arg_cstr, arg_, arg_), SARGS(unlinkat, rdec, arg_atfd, arg_cstr, arg_), - SARGS(renameat, rdec, arg_atfd, arg_cstr, arg_atfd, arg_cstr), + SARGS(renameat2, rdec, arg_atfd, arg_cstr, arg_atfd, arg_cstr), SARGS(linkat, rdec, arg_atfd, arg_cstr, arg_atfd, arg_cstr, arg_), SARGS(symlinkat, rdec, arg_cstr, arg_atfd, arg_cstr), SARGS(readlinkat, rdec, arg_atfd, arg_cstr, arg_buf_out, arg_dec), @@ -305,9 +306,9 @@ static const struct syscall_format formats[] = { SARGS(move_pages, rdec, arg_, arg_, arg_, arg_, arg_, arg_), SARGS(utimensat, rdec, arg_atfd, arg_cstr, arg_, arg_), SARGS(epoll_pwait, rdec, arg_fd, arg_, arg_, arg_, arg_, arg_), - SARGS(signalfd, rdec, arg_fd, arg_, arg_), + // SARGS(signalfd, rdec, arg_fd, arg_, arg_), SARGS(timerfd_create, rdec, arg_, arg_), - SARGS(eventfd, rdec, arg_), + // SARGS(eventfd, rdec, arg_), SARGS(fallocate, rdec, arg_fd, arg_, arg_, arg_), SARGS(timerfd_settime, rdec, arg_fd, arg_, arg_, arg_), SARGS(timerfd_gettime, rdec, arg_fd, arg_), @@ -396,9 +397,6 @@ static const struct syscall_format formats[] = { #undef SARGS -static struct syscall_format open_with_o_creat = {.name = "open", rdec, - {arg_cstr, arg_open_flags, arg_oct_mode}}; - static struct syscall_format openat_with_o_creat = {.name = "openat", rdec, {arg_atfd, arg_cstr, arg_open_flags, arg_oct_mode}}; @@ -450,9 +448,6 @@ get_syscall_format(const struct syscall_desc *desc) if (formats[desc->nr].name == NULL) return &unkown; - if (desc->nr == SYS_open && oflags_refer_mode_arg((int)desc->args[1])) - return &open_with_o_creat; - if (desc->nr == SYS_openat && oflags_refer_mode_arg((int)desc->args[2])) return &openat_with_o_creat; From 463eafafa502749ba7a70224d6df8bade283af61 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 12 Jun 2024 15:53:35 +0200 Subject: [PATCH 012/143] Created one more simple test --- test/intercept_sys_write_2.c | 55 ++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 test/intercept_sys_write_2.c diff --git a/test/intercept_sys_write_2.c b/test/intercept_sys_write_2.c new file mode 100644 index 0000000..898e3ff --- /dev/null +++ b/test/intercept_sys_write_2.c @@ -0,0 +1,55 @@ +#include "libsyscall_intercept_hook_point.h" +#include +#include +#include +#include // Include for the write function +#include + +static int +hook(long syscall_number, + long arg0, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long *result) +{ + (void)arg0; + (void)arg2; + (void)arg3; + (void)arg4; + (void)arg5; + (void)result; + + if (syscall_number == SYS_write) { + const char interc[] = "intercepted_"; + const char *src = interc; + + /* write(fd, buf, len) */ + size_t len = (size_t)arg2; + char *buf = (char *)arg1; + +#ifdef EXPECT_SPURIOUS_SYSCALLS + if (strcmp(buf, "original_syscall") != 0) + return 1; +#endif + + if (len > sizeof(interc)) { + while (*src != '\0') + *buf++ = *src++; + } + } + + return 1; +} + +static __attribute__((constructor)) void +init(void) +{ + intercept_hook_point = hook; +} + +int main() { + char buf[128] = "original_syscall"; + write(1, buf, strlen(buf)); + printf("\n"); + return 0; +} From 8390aade62aff86545768f41cd5b18c8030e0feb Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 12 Jun 2024 17:39:32 +0200 Subject: [PATCH 013/143] deleted SYS_vfork references and substituted SYS_open with SYS_openat --- src/disasm_wrapper.c | 2 +- src/intercept.c | 2 +- src/intercept_desc.c | 4 +- src/intercept_log.c | 2 +- src/intercept_wrapper.S | 80 ++++++++++++++++++------------------ test/intercept_sys_write_2.c | 2 +- 6 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/disasm_wrapper.c b/src/disasm_wrapper.c index 2ad699f..b14e99e 100644 --- a/src/disasm_wrapper.c +++ b/src/disasm_wrapper.c @@ -145,7 +145,7 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, struct intercept_disasm_result result = {.address = code, 0, }; const unsigned char *start = code; size_t size = (size_t)(context->end - code + 1); - uint64_t address = (uint64_t)code + uint64_t address = (uint64_t)code; if (!cs_disasm_iter(context->handle, &start, &size, &address, context->insn)) { diff --git a/src/intercept.c b/src/intercept.c index 6773077..1756a2b 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -646,7 +646,7 @@ intercept_routine(struct context *context) desc.args[5], &result); - if (desc.nr == SYS_vfork || desc.nr == SYS_rt_sigreturn) { + if (desc.nr == SYS_rt_sigreturn) { /* can't handle these syscalls the normal way */ return (struct wrapper_ret){.a[0] = context->a[7], .a[1] = 0 }; } diff --git a/src/intercept_desc.c b/src/intercept_desc.c index d6cc506..9c78552 100644 --- a/src/intercept_desc.c +++ b/src/intercept_desc.c @@ -62,7 +62,7 @@ open_orig_file(const struct intercept_desc *desc) { int fd; - fd = syscall_no_intercept(SYS_open, desc->path, O_RDONLY); + fd = syscall_no_intercept(SYS_openat, AT_FDCWD, desc->path, O_RDONLY); xabort_on_syserror(fd, __func__); @@ -525,7 +525,7 @@ get_min_address(void) min_address = 0x10000; /* best guess */ - int fd = syscall_no_intercept(SYS_open, "/proc/sys/vm/mmap_min_addr", + int fd = syscall_no_intercept(SYS_openat, AT_FDCWD, "/proc/sys/vm/mmap_min_addr", O_RDONLY); if (fd >= 0) { diff --git a/src/intercept_log.c b/src/intercept_log.c index 03ec4d4..c0f69f1 100644 --- a/src/intercept_log.c +++ b/src/intercept_log.c @@ -830,7 +830,7 @@ intercept_setup_log(const char *path, const char *trunc) intercept_log_close(); /* in case a log was already open */ - log_fd = (int)syscall_no_intercept(SYS_open, full_path, flags, 0700); + log_fd = (int)syscall_no_intercept(SYS_openat, AT_FDCWD, full_path, flags, 0700); xabort_on_syserror(log_fd, "opening log"); } diff --git a/src/intercept_wrapper.S b/src/intercept_wrapper.S index 65ec8e2..8db7990 100644 --- a/src/intercept_wrapper.S +++ b/src/intercept_wrapper.S @@ -79,26 +79,26 @@ sd a5, 104(sp) sd a6, 112(sp) sd a7, 120(sp) - sd ft0, 128(sp) - sd ft1, 136(sp) - sd ft2, 144(sp) - sd ft3, 152(sp) - sd ft4, 160(sp) - sd ft5, 168(sp) - sd ft6, 176(sp) - sd ft7, 184(sp) - sd ft8, 192(sp) - sd ft9, 200(sp) - sd ft10, 208(sp) - sd ft11, 216(sp) - sd fa0, 224(sp) - sd fa1, 232(sp) - sd fa2, 240(sp) - sd fa3, 248(sp) - sd fa4, 256(sp) - sd fa5, 264(sp) - sd fa6, 272(sp) - sd fa7, 280(sp) + fsd ft0, 128(sp) + fsd ft1, 136(sp) + fsd ft2, 144(sp) + fsd ft3, 152(sp) + fsd ft4, 160(sp) + fsd ft5, 168(sp) + fsd ft6, 176(sp) + fsd ft7, 184(sp) + fsd ft8, 192(sp) + fsd ft9, 200(sp) + fsd ft10, 208(sp) + fsd ft11, 216(sp) + fsd fa0, 224(sp) + fsd fa1, 232(sp) + fsd fa2, 240(sp) + fsd fa3, 248(sp) + fsd fa4, 256(sp) + fsd fa5, 264(sp) + fsd fa6, 272(sp) + fsd fa7, 280(sp) # argument passed to intercept_routine mv a0, sp @@ -136,26 +136,26 @@ ld a5, 104(sp) ld a6, 112(sp) ld a7, 120(sp) - ld ft0, 128(sp) - ld ft1, 136(sp) - ld ft2, 144(sp) - ld ft3, 152(sp) - ld ft4, 160(sp) - ld ft5, 168(sp) - ld ft6, 176(sp) - ld ft7, 184(sp) - ld ft8, 192(sp) - ld ft9, 200(sp) - ld ft10, 208(sp) - ld ft11, 216(sp) - ld fa0, 224(sp) - ld fa1, 232(sp) - ld fa2, 240(sp) - ld fa3, 248(sp) - ld fa4, 256(sp) - ld fa5, 264(sp) - ld fa6, 272(sp) - ld fa7, 280(sp) + fld ft0, 128(sp) + fld ft1, 136(sp) + fld ft2, 144(sp) + fld ft3, 152(sp) + fld ft4, 160(sp) + fld ft5, 168(sp) + fld ft6, 176(sp) + fld ft7, 184(sp) + fld ft8, 192(sp) + fld ft9, 200(sp) + fld ft10, 208(sp) + fld ft11, 216(sp) + fld fa0, 224(sp) + fld fa1, 232(sp) + fld fa2, 240(sp) + fld fa3, 248(sp) + fld fa4, 256(sp) + fld fa5, 264(sp) + fld fa6, 272(sp) + fld fa7, 280(sp) # Increasing sp to its original value addi sp, sp, 288 ret diff --git a/test/intercept_sys_write_2.c b/test/intercept_sys_write_2.c index 898e3ff..d252328 100644 --- a/test/intercept_sys_write_2.c +++ b/test/intercept_sys_write_2.c @@ -2,7 +2,7 @@ #include #include #include -#include // Include for the write function +#include #include static int From 165b36d20ac8a259c32067c822ed1fabc4ac1b59 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Mon, 16 Sep 2024 13:38:37 +0200 Subject: [PATCH 014/143] Correctly patching 490 out of 492 ecall in libc. To do: debug return to libc from asm_template --- src/disasm_wrapper.c | 22 +++++- src/disasm_wrapper.h | 3 + src/intercept.c | 4 +- src/intercept_desc.c | 1 + src/intercept_template.S | 28 ++++---- src/patcher.c | 127 ++++++++++++++++++++--------------- test/intercept_sys_write_2.c | 3 +- 7 files changed, 118 insertions(+), 70 deletions(-) diff --git a/src/disasm_wrapper.c b/src/disasm_wrapper.c index b14e99e..ac26150 100644 --- a/src/disasm_wrapper.c +++ b/src/disasm_wrapper.c @@ -90,7 +90,7 @@ intercept_disasm_init(const unsigned char *begin, const unsigned char *end) * Initialize the disassembler. * The handle here must be passed to capstone each time it is used. */ - if (cs_open(CS_ARCH_RISCV, CS_MODE_RISCV64, &context->handle) != CS_ERR_OK) + if (cs_open(CS_ARCH_RISCV, CS_MODE_RISCV64 | CS_MODE_RISCVC, &context->handle) != CS_ERR_OK) xabort("cs_open"); /* @@ -169,6 +169,10 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, case RISCV_INS_BLTU: case RISCV_INS_BNE: case RISCV_INS_JAL: + case RISCV_INS_C_J: + case RISCV_INS_C_JAL: + case RISCV_INS_C_BEQZ: + case RISCV_INS_C_BNEZ: result.has_ip_relative_opr = true; result.is_jump = true; break; @@ -176,6 +180,7 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, result.has_ip_relative_opr = true; break; case RISCV_INS_JALR: + case RISCV_INS_C_JALR: result.is_jump = true; break; default: @@ -197,6 +202,21 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, break; } } + result.uses_t6 = false; + for (uint8_t op_i = 0; !result.uses_t6 && + op_i < context->insn->detail->riscv.op_count; ++op_i) { + op = context->insn->detail->riscv.operands + op_i; + switch (op->type) { + case RISCV_OP_REG: + result.uses_t6 = op->reg == RISCV_REG_T6; + break; + case RISCV_OP_MEM: + result.uses_t6 = op->mem.base == RISCV_REG_T6; + break; + default: + break; + } + } break; } diff --git a/src/disasm_wrapper.h b/src/disasm_wrapper.h index 119d17f..61dca3a 100644 --- a/src/disasm_wrapper.h +++ b/src/disasm_wrapper.h @@ -70,6 +70,9 @@ struct intercept_disasm_result { /* Flag marking if ra is one of the operands of the instruction */ bool uses_ra; + /* Flag marking if t6 is one of the operands of the instruction*/ + bool uses_t6; + /* * Flag marking lea instructions setting a 64 bit register to a * RIP relative address. They can be relocated -- but by simple memcpy. diff --git a/src/intercept.c b/src/intercept.c index 1756a2b..b352ab1 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -631,6 +631,8 @@ intercept_routine(struct context *context) get_syscall_in_context(context, &desc); + debug_dump("ra: %lx", context->ra); + if (handle_magic_syscalls(&desc, &result) == 0) return (struct wrapper_ret){.a[0] = result, .a[1] = 1 }; @@ -686,7 +688,7 @@ intercept_routine(struct context *context) } intercept_log_syscall(patch, &desc, KNOWN, result); - + debug_dump("intercepted ecall -> returning to asm_wrapper - result: %ld\n",result); return (struct wrapper_ret){ .a[0] = result, .a[1] = 1 }; } diff --git a/src/intercept_desc.c b/src/intercept_desc.c index 9c78552..7c99a9b 100644 --- a/src/intercept_desc.c +++ b/src/intercept_desc.c @@ -449,6 +449,7 @@ crawl_text(struct intercept_desc *desc) result = intercept_disasm_next_instruction(context, code); if (result.length == 0) { + debug_dump("code pointer:0x%lx\n",code); ++code; continue; } diff --git a/src/intercept_template.S b/src/intercept_template.S index 8e213ee..b4f481b 100644 --- a/src/intercept_template.S +++ b/src/intercept_template.S @@ -59,7 +59,7 @@ addi sp, sp, -32 # allocate stack for some locals sd t6, 0(sp) # original sp on stack sd ra, 16(sp) # patch->return_address on stack - sd s0, 24(sp) # following conventions by saving s0 on stack since we use it + sd s0, 24(sp) # follows conventions by saving s0 on stack since we use it bnez t5, intercept_asm_wrapper_patch_desc_addr li s0, 0 # s0 as flag: 1 if we are going for post_clone, 0 otherwise intercept_asm_wrapper_patch_desc_addr: @@ -67,11 +67,12 @@ # the 5 following instructions are placeholders for the correct ones which are # overwritten in machine language by create_load_uint64t_into_t0() - lui t0, 0x00000 - addi t0, t0, 0x000 - slli t0, t0, 32 - lui t3, 0x00000 - addi t3, t3, 0x000 + .space 20, 0 + #lui t0, 0x00000 + #addi t0, t0, 0x000 + #slli t0, t0, 32 + #lui t3, 0x00000 + #addi t3, t3, 0x000 # the 9 following instructions load the 64-bit address in t0 lui t1, 0x7ffff @@ -90,11 +91,12 @@ # the 5 following instructions are placeholders for the correct ones which are # written in machine language in create_load_uint64t_into_t0() in patcher.c - lui t0, 0x00000 - ori t0, t0, 0x000 - slli t0, t0, 32 - lui t3, 0x00000 - ori t3, t3, 0x000 + .space 20, 0 + #lui t0, 0x00000 + #ori t0, t0, 0x000 + #slli t0, t0, 32 + #lui t3, 0x00000 + #ori t3, t3, 0x000 # the 9 following instructions load the 64-bit address in t0 lui t1, 0x7ffff @@ -114,9 +116,9 @@ # The intercept_wrapper function did restore all registers to their # original state, except for a0, sp and t6. # - # If t6 is zero, rax contains a syscall number, and that syscall + # If t6 is zero, a0 contains a syscall number, and that syscall # is executed here. - # If t6 is 1, rax contains the return value of the hooked syscall. + # If t6 is 1, a0 contains the return value of the hooked syscall. # If t6 is 2, a clone syscall is executed here. beqz t6, l2 diff --git a/src/patcher.c b/src/patcher.c index de0ea15..e862529 100644 --- a/src/patcher.c +++ b/src/patcher.c @@ -100,7 +100,7 @@ static unsigned char * create_absolute_jump(unsigned char *from, void *to) { uint32_t *instructions = (uint32_t *)from; - instructions[0] = 0xff010113; // addi sp, sp, -16 + instructions[0] = 0xfe010113; // addi sp, sp, -32 instructions[1] = 0x00613023; // sd t1, 0(sp) instructions[2] = 0x00713423; // sd t2, 8(sp) instructions[3] = 0x01c13823; // sd t3, 16(sp) @@ -116,10 +116,10 @@ create_absolute_jump(unsigned char *from, void *to) instructions[18] = 0x00013303; // ld t1, 0(sp) instructions[19] = 0x00813383; // ld t2, 8(sp) instructions[20] = 0x01013e03; // ld t3, 16(sp) - instructions[21] = 0x01010113; // addi sp, sp, 16 + instructions[21] = 0x02010113; // addi sp, sp, 32 instructions[22] = 0x00028067; // jalr zero, t0, 0 - create_load_uint64t_into_t0(instructions + 4,(uint64_t)to); // writes 5 instructions starting from instructions[4] - return instructions + 23; + create_load_uint64t_into_t0((uint8_t *)(instructions + 4),(uint64_t)to); // writes 5 instructions starting from instructions[4] + return (unsigned char *)(instructions + 23); } /* @@ -192,7 +192,8 @@ is_copiable_before_syscall(struct intercept_disasm_result ins) ins.is_jump || ins.is_ret || ins.is_endbr || - ins.is_syscall); + ins.is_syscall || + ins.uses_t6); } /* @@ -264,9 +265,12 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) size_t next_nop_i = 0; for (unsigned patch_i = 0; patch_i < desc->count; ++patch_i) { + if (patch_i == 283 || patch_i == 285) { + continue; + } struct patch_desc *patch = desc->items + patch_i; - debug_dump("patching %s:0x%lx\n", desc->path, - patch->syscall_addr - desc->base_addr); + debug_dump("patching %s:0x%lx - patch_number: %u\n", desc->path, + patch->syscall_addr - desc->base_addr, patch_i); /* * No padding space is available, so check the @@ -293,7 +297,7 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) /* * If the preceding instruction is relocatable, - * add its length. Also, the the instruction right + * add its length. Also, the instruction right * before that. */ if (patch->uses_prev_ins) { @@ -301,7 +305,7 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) patch->dst_jmp_patch -= patch->preceding_ins.length; - if (patch->uses_prev_ins_2) { + if (patch->uses_prev_ins_2 && (length < JUMP_INS_SIZE)) { length += patch->preceding_ins_2.length; patch->dst_jmp_patch -= patch->preceding_ins_2.length; @@ -317,7 +321,7 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) * is overwritten, the returning jump must jump to * the instruction after it. */ - if (patch->uses_next_ins) { + if (patch->uses_next_ins && (length < JUMP_INS_SIZE)) { length += patch->following_ins.length; /* @@ -333,6 +337,8 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) patch->return_address = patch->syscall_addr + ECALL_INS_SIZE + patch->following_ins.length; + } else { + patch->return_address = patch->syscall_addr + ECALL_INS_SIZE; } /* @@ -444,7 +450,7 @@ create_load_uint64t_into_t0(uint8_t *code, uint64_t value) instructions[0] = 0x000002b7 | lui_imm_field; // lui t0, 0x..... instructions[1] = 0x00028293 | (addi_imm_field << 20); // addi t0, t0, 0x... - instructions[2] = 0x02029293; // slli t0, t0, 32 // could ditch this line as long its placeholder in intercept_template.S isn't different at all + instructions[2] = 0x02029293; // slli t0, t0, 32 lui_imm_field = lower_32 & 0xfffff000; addi_imm_field = 0; @@ -494,10 +500,10 @@ create_wrapper(struct patch_desc *patch, unsigned char **dst) /* Copy the previous instruction(s) */ if (patch->uses_prev_ins) { if (patch->uses_prev_ins_2) { - *((uint32_t *)(*dst)) = 0x00813283; // ld t0, 8(sp) - *dst += 4; - *((uint32_t *)(*dst)) = 0x01010113; // addi sp, sp, 16 - *dst += 4; + //*((uint32_t *)(*dst)) = 0x00813283; // ld t0, 8(sp) + //*dst += 4; + //*((uint32_t *)(*dst)) = 0x01010113; // addi sp, sp, 16 + //*dst += 4;/**/ *dst = relocate_instruction(*dst, &patch->preceding_ins_2); } *dst = relocate_instruction(*dst, &patch->preceding_ins); @@ -536,7 +542,7 @@ create_j(unsigned char *from, void *to) ptrdiff_t delta = ((unsigned char *)to) - from; uint32_t *instructions = (uint32_t *)from; uint32_t nop = 0x00000013; // nop instruction - debug_dump("%p: svc -> b %ld\t# %p\n", from, delta, to); + debug_dump("%p: ecall -> jalr %ld\t# %p\n", from, delta, to); const ptrdiff_t JAL_OFFSET = 1 << 20; const ptrdiff_t JALR_MAX_OFFSET = 2147481598; // ((2^31-1)-4095)+(2^11-1) == 0x7ffff000 + 0x7ff @@ -546,52 +552,50 @@ create_j(unsigned char *from, void *to) xabort("create_j misaligned instruction fetch exception"); - } else if ((delta <= JAL_OFFSET-2) || (delta >= -JAL_OFFSET)) { - /* delta can be encoded in a single jal instruction */ - - /* halving offset value, since RISC-V doubles the immediate value of jal */ - delta >>= 1; - - /* extracting 20 bits to be encoded in jal instruction */ - uint32_t tmp = (uint32_t) delta & 0x000fffff; - uint32_t jal = 0x000000ef; /* jal instruction with offset = 0 and rd = ra */ - jal |= ((tmp & 0x3ff) << 21); /* shifting imm[9:0] into jal[30:21] */ - jal |= ((tmp & 0x400) << 10); /* shifting imm[10] into jal[20] */ - jal |= ((tmp & 0x7f800) << 1); /* shifting imm[18:11] into jal[19:12] */ - jal |= ((tmp & 0x80000) << 12); /* shifting imm[19] into jal[31] */ - - instructions[0] = jal; - instructions[1] = nop; - instructions[2] = nop; - instructions[3] = nop; - - } else if (delta <= JALR_MAX_OFFSET || delta >= JALR_MIN_OFFSET) { - - uint32_t lui = 0x000002b7; // encoding t0 as rd - uint32_t jalr = 0x000280e7; // encoding ra as rd and t0 as rs1 + } //else if ((delta <= JAL_OFFSET-2) || (delta >= -JAL_OFFSET)) { + // /* delta can be encoded in a single jal instruction */ + // + // /* halving offset value, since RISC-V doubles the immediate value of jal */ + // delta >>= 1; + // + // /* extracting 20 bits to be encoded in jal instruction */ + // uint32_t tmp = (uint32_t) delta & 0x000fffff; + // uint32_t jal = 0x000000ef; /* jal instruction with offset = 0 and rd = ra */ + // jal |= ((tmp & 0x3ff) << 21); /* shifting imm[9:0] into jal[30:21] */ + // jal |= ((tmp & 0x400) << 10); /* shifting imm[10] into jal[20] */ + // jal |= ((tmp & 0x7f800) << 1); /* shifting imm[18:11] into jal[19:12] */ + // jal |= ((tmp & 0x80000) << 12); /* shifting imm[19] into jal[31] */ + // + // instructions[0] = jal; + // instructions[1] = nop; + // } + else if (delta <= JALR_MAX_OFFSET && delta >= JALR_MIN_OFFSET) { + + uint32_t auipc = 0x00000f97; // encoding t6 as rd + uint32_t jalr = 0x000f80e7; // encoding ra as rd and t6 as rs1 uint32_t jalr_imm_field = 0; - uint32_t lui_imm_field = (uint32_t)delta & 0xfffff000; // offset[31:12] + uint32_t auipc_imm_field = (uint32_t)delta & 0xfffff000; // offset[31:12] /* * if the offset is not a multiple of 4096 the 12 least significant bits * of its value must be set by adding the correct immediate value contained - * in jalr imm field to the rs1 value which is set by lui instruction + * in jalr imm field to the rs1 value which is set by auipc instruction * preceding jalr */ if ((uint32_t)delta % 4096 != 0) { - jalr_imm_field = (uint32_t)delta - lui_imm_field; - if (jalr_imm_field > 2046) { - lui_imm_field += 4096; - jalr_imm_field = -(4096 - jalr_imm_field); - } - } - lui |= lui_imm_field; - jalr |= (jalr_imm_field << 20); + jalr_imm_field = (uint32_t)delta - auipc_imm_field; + if (jalr_imm_field > 2046) { + auipc_imm_field += 4096; + jalr_imm_field = -(4096 - jalr_imm_field); + } + } + auipc |= auipc_imm_field; + jalr |= (jalr_imm_field << 20); - instructions[0] = 0xff010113; // addi sp, sp, -16 - instructions[1] = 0x00513423; // sd t0, 8(sp) - instructions[2] = lui; // lui t0, 0x..... - instructions[3] = jalr; // jalr ra, t0, 0x... + // instructions[0] = 0xff010113; // addi sp, sp, -16 + // instructions[1] = 0x00513423; // sd t0, 8(sp) + instructions[0] = auipc; // auipc t6, 0x..... + instructions[1] = jalr; // jalr ra, t6, 0x... } else { xabort("create_j distance check"); @@ -600,7 +604,7 @@ create_j(unsigned char *from, void *to) /* * activate_patches() - * Loop over all the patches, and and overwrite each syscall. + * Loop over all the patches, and overwrite each syscall. */ void activate_patches(struct intercept_desc *desc) @@ -619,7 +623,12 @@ activate_patches(struct intercept_desc *desc) "mprotect PROT_READ | PROT_WRITE | PROT_EXEC"); for (unsigned i = 0; i < desc->count; ++i) { + if (i == 283 || i == 285) { + continue; + } const struct patch_desc *patch = desc->items + i; + debug_dump("activating patch at dst_jmp_patch:0x%lx - patch->return_address :0x%lx - patch_n:%u\n", + patch->dst_jmp_patch-desc->base_addr,patch->return_address-desc->base_addr,i); if (patch->dst_jmp_patch < desc->text_start || patch->dst_jmp_patch > desc->text_end) @@ -645,6 +654,16 @@ activate_patches(struct intercept_desc *desc) /* jump - escape the text segment */ create_j(patch->dst_jmp_patch, desc->next_trampoline); + /* + * if patch is 10 bytes long, fill the last two + * with c.nop instruction. Template will return there, + * c.nop will make advance PC and .so execution will + * continue normally + */ + if (patch->return_address - patch->dst_jmp_patch == 2) { + *(uint16_t *)(patch->dst_jmp_patch + 8) = 0x0001; // c.nop + } + /* jump - escape the 2 GB range of the text segment */ desc->next_trampoline = create_absolute_jump( desc->next_trampoline, patch->asm_wrapper); diff --git a/test/intercept_sys_write_2.c b/test/intercept_sys_write_2.c index d252328..5846b03 100644 --- a/test/intercept_sys_write_2.c +++ b/test/intercept_sys_write_2.c @@ -48,8 +48,9 @@ init(void) } int main() { - char buf[128] = "original_syscall"; + char buf[128] = "original_syscall\n"; write(1, buf, strlen(buf)); + printf("correctly returned to libc from asm_template\n"); printf("\n"); return 0; } From db7244ff6c8d84393ec1e0873241751473fc6aa4 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 1 Oct 2024 17:45:27 +0200 Subject: [PATCH 015/143] ECALL can now be successfully patched even with just 6 overwritable bytes if ISA compressed module is supported. TO DO: more testing --- src/intercept.h | 18 +++- src/patcher.c | 189 +++++++++++++++++++++++------------ test/intercept_sys_read.c | 46 +++++++++ test/intercept_sys_write_2.c | 3 - 4 files changed, 190 insertions(+), 66 deletions(-) create mode 100644 test/intercept_sys_read.c diff --git a/src/intercept.h b/src/intercept.h index a8a2fe7..e51d69f 100644 --- a/src/intercept.h +++ b/src/intercept.h @@ -111,6 +111,22 @@ struct patch_desc { bool uses_nop_trampoline; + /* + * Flag marking if the patch has just 6 relocatable bytes. If true + * an auipc+c.jalr sequence is needed to perform a jump to the trampoline + */ + bool needs_compressed_ins; + + /* + * Flag marking if the patch is 10 bytes long. If true, two 32 bits + * instructions and one compressed 16 bit instruction has been selected + * for patching, but since 8 bytes are enough a 2 byte padding is needed. + * It will be provided by a c.nop instruction. If compressed instructions + * are not supported this will never happen since the patch can just be 8 + * bytes long (or 4, in case of failure) + */ + bool padding_is_needed; + struct range nop_trampoline; }; @@ -210,7 +226,7 @@ void activate_patches(struct intercept_desc *desc); * actually the jump summing its immediate value to the just wrote register to * calculate desination of the jump */ -#define JUMP_INS_SIZE 16 +#define JUMP_INS_SIZE 8 // #define CALL_OPCODE 0xe8 // #define JMP_OPCODE 0xe9 // #define SHORT_JMP_OPCODE 0xeb diff --git a/src/patcher.c b/src/patcher.c index e862529..fc50f61 100644 --- a/src/patcher.c +++ b/src/patcher.c @@ -79,6 +79,9 @@ #include #include +#include + +#define COMPAT_HWCAP_ISA_C (1 << ('C' - 'A')) /* The size of a trampoline jump, 64-bit address loading process into a register * (which requires 14 instructions to encode directly in machine code) + JALR. @@ -91,6 +94,7 @@ enum { TRAMPOLINE_SIZE = 23 * 4 }; static void create_wrapper(struct patch_desc *patch, unsigned char **dst); static void create_load_uint64t_into_t0(uint8_t *code, uint64_t value); +static void create_load_uint64t_into_t6(uint8_t *code, uint64_t value); /* * create_absolute_jump(from, to) @@ -112,13 +116,13 @@ create_absolute_jump(unsigned char *from, void *to) instructions[14] = 0x00131313; // slli t1, t1, 1 instructions[15] = 0x00136313; // ori t1, t1, 1 instructions[16] = 0x006e7e33; // and t3, t3, t1 - instructions[17] = 0x01c2e2b3; // or t0, t0, t3 + instructions[17] = 0x01cfefb3; // or t6, t6, t3 instructions[18] = 0x00013303; // ld t1, 0(sp) instructions[19] = 0x00813383; // ld t2, 8(sp) instructions[20] = 0x01013e03; // ld t3, 16(sp) instructions[21] = 0x02010113; // addi sp, sp, 32 - instructions[22] = 0x00028067; // jalr zero, t0, 0 - create_load_uint64t_into_t0((uint8_t *)(instructions + 4),(uint64_t)to); // writes 5 instructions starting from instructions[4] + instructions[22] = 0x000f8067; // jalr zero, t6, 0 + create_load_uint64t_into_t6((uint8_t *)(instructions + 4),(uint64_t)to); // writes 5 instructions starting from instructions[4] return (unsigned char *)(instructions + 23); } @@ -215,7 +219,7 @@ is_copiable_after_syscall(struct intercept_disasm_result ins) ins.is_jump || ins.is_endbr || ins.is_syscall || - ins.uses_ra); + ins.uses_ra); } @@ -257,17 +261,14 @@ check_surrounding_instructions(struct intercept_desc *desc, * * This is all based on the information collected by the routine * find_syscalls, which does the disassembling, finding jump destinations, - * finding padding bytes, etc.. + * finding padding bytes, etc... */ void create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) { - size_t next_nop_i = 0; - + short min_treshold = JUMP_INS_SIZE; + bool c_isa_supported = getauxval(AT_HWCAP) & COMPAT_HWCAP_ISA_C; for (unsigned patch_i = 0; patch_i < desc->count; ++patch_i) { - if (patch_i == 283 || patch_i == 285) { - continue; - } struct patch_desc *patch = desc->items + patch_i; debug_dump("patching %s:0x%lx - patch_number: %u\n", desc->path, patch->syscall_addr - desc->base_addr, patch_i); @@ -293,6 +294,8 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) */ unsigned length = ECALL_INS_SIZE; + patch->needs_compressed_ins = false; + patch->padding_is_needed = false; patch->dst_jmp_patch = patch->syscall_addr; /* @@ -341,13 +344,31 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) patch->return_address = patch->syscall_addr + ECALL_INS_SIZE; } + if (length > JUMP_INS_SIZE) { + patch->padding_is_needed = true; + patch->return_address -= (length - JUMP_INS_SIZE); + } + /* - * If the length is at least 16, then a jump instruction - * with a 32 bit displacement can fit. + * Check if compressed instructions module is supported by the CPU. + * If yes, 6 bytes are enough to place an auipc+c.jalr sequence. + * If the length of the patch is exactly 6 bytes, then we assert + * the flag marking the need of said sequence. + * + * If length is less than minimum needed bytes (value depending on + * ISA C module being supported or not), give up. * - * Otherwise give up + * TO DO: creating an environment variable marking if all ECALLs + * must be patchable for success or if we could just skip the + * unpatchable ones. */ - if (length < JUMP_INS_SIZE) { + if (c_isa_supported) { + if (length == 6) { + patch->needs_compressed_ins = true; + } + min_treshold = 6; + } + if (length < min_treshold) { char buffer[0x1000]; int l = snprintf(buffer, sizeof(buffer), @@ -356,8 +377,13 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) patch->syscall_offset); intercept_log(buffer, (size_t)l); + debug_dump("unintercepted syscall at: %s 0x%lx\n", + desc->path, + patch->syscall_offset); +#ifdef ABORT_ON_FAILURE xabort("not enough space for patching" " around syscal"); +#endif } mark_jump(desc, patch->return_address); @@ -464,7 +490,42 @@ create_load_uint64t_into_t0(uint8_t *code, uint64_t value) instructions[3] = 0x00000e37 | lui_imm_field; // lui t3, 0x..... instructions[4] = 0x000e0e13 | (addi_imm_field << 20); // addi t3, t3, 0x... +} + +static void +create_load_uint64t_into_t6(uint8_t *code, uint64_t value) +{ + + uint32_t *instructions = (uint32_t *)code; + uint32_t upper_32 = (value & 0xffffffff00000000) >> 32; + uint32_t lower_32 = (uint32_t)value; + + uint32_t lui_imm_field = upper_32 & 0xfffff000; + uint32_t addi_imm_field = 0; + if (upper_32 % 4096 != 0) { + addi_imm_field = upper_32 - lui_imm_field; + if (addi_imm_field > 2047) { + lui_imm_field += 4096; + addi_imm_field = -(4096 - addi_imm_field); + } + } + + instructions[0] = 0x00000fb7 | lui_imm_field; // lui t6, 0x..... + instructions[1] = 0x000f8f93 | (addi_imm_field << 20); // addi t6, t6, 0x... + instructions[2] = 0x020f9f93; // slli t6, t6, 32 + + lui_imm_field = lower_32 & 0xfffff000; + addi_imm_field = 0; + if (lower_32 % 4096 != 0) { + addi_imm_field = lower_32 - lui_imm_field; + if (addi_imm_field > 2047) { + lui_imm_field += 4096; + addi_imm_field = -(4096 - addi_imm_field); + } + } + instructions[3] = 0x00000e37 | lui_imm_field; // lui t3, 0x..... + instructions[4] = 0x000e0e13 | (addi_imm_field << 20); // addi t3, t3, 0x... } /* @@ -500,10 +561,6 @@ create_wrapper(struct patch_desc *patch, unsigned char **dst) /* Copy the previous instruction(s) */ if (patch->uses_prev_ins) { if (patch->uses_prev_ins_2) { - //*((uint32_t *)(*dst)) = 0x00813283; // ld t0, 8(sp) - //*dst += 4; - //*((uint32_t *)(*dst)) = 0x01010113; // addi sp, sp, 16 - //*dst += 4;/**/ *dst = relocate_instruction(*dst, &patch->preceding_ins_2); } *dst = relocate_instruction(*dst, &patch->preceding_ins); @@ -552,27 +609,11 @@ create_j(unsigned char *from, void *to) xabort("create_j misaligned instruction fetch exception"); - } //else if ((delta <= JAL_OFFSET-2) || (delta >= -JAL_OFFSET)) { - // /* delta can be encoded in a single jal instruction */ - // - // /* halving offset value, since RISC-V doubles the immediate value of jal */ - // delta >>= 1; - // - // /* extracting 20 bits to be encoded in jal instruction */ - // uint32_t tmp = (uint32_t) delta & 0x000fffff; - // uint32_t jal = 0x000000ef; /* jal instruction with offset = 0 and rd = ra */ - // jal |= ((tmp & 0x3ff) << 21); /* shifting imm[9:0] into jal[30:21] */ - // jal |= ((tmp & 0x400) << 10); /* shifting imm[10] into jal[20] */ - // jal |= ((tmp & 0x7f800) << 1); /* shifting imm[18:11] into jal[19:12] */ - // jal |= ((tmp & 0x80000) << 12); /* shifting imm[19] into jal[31] */ - // - // instructions[0] = jal; - // instructions[1] = nop; - // } - else if (delta <= JALR_MAX_OFFSET && delta >= JALR_MIN_OFFSET) { - - uint32_t auipc = 0x00000f97; // encoding t6 as rd - uint32_t jalr = 0x000f80e7; // encoding ra as rd and t6 as rs1 + } + if (delta <= JALR_MAX_OFFSET && delta >= JALR_MIN_OFFSET) { + + uint32_t auipc = 0x00000f97; // auipc t6, 0x..... + uint32_t jalr = 0x000f80e7; // jalr ra, t6, 0x... uint32_t jalr_imm_field = 0; uint32_t auipc_imm_field = (uint32_t)delta & 0xfffff000; // offset[31:12] @@ -591,17 +632,35 @@ create_j(unsigned char *from, void *to) } auipc |= auipc_imm_field; jalr |= (jalr_imm_field << 20); - - // instructions[0] = 0xff010113; // addi sp, sp, -16 - // instructions[1] = 0x00513423; // sd t0, 8(sp) instructions[0] = auipc; // auipc t6, 0x..... instructions[1] = jalr; // jalr ra, t6, 0x... - } else { xabort("create_j distance check"); } } +void +create_c_j(unsigned char *from, void *to) { + ptrdiff_t delta = ((unsigned char *)to) - from; + debug_dump("%p: ecall -> c.jalr %ld\t# %p\n", from, delta, to); + const ptrdiff_t AUIPC_MAX_OFFSET = 2147479552; + const ptrdiff_t AUIPC_MIN_OFFSET = -2147483648; + if ((delta & 0xfff) != 0) { + xabort("create_c_j misaligned instruction fetch exception"); + } + if (delta >= AUIPC_MIN_OFFSET && delta <= AUIPC_MAX_OFFSET) { + uint32_t auipc = 0x00000f97; // auipc t6, 0x..... + uint16_t c_jalr = 0x9f82; // c.jalr t6 + uint32_t auipc_imm_field = (uint32_t)delta & 0xfffff000; // offset[31:12] + auipc |= auipc_imm_field; + *(uint32_t *)from = auipc; + *(uint16_t *)(from + 4) = c_jalr; + } else { + xabort("create_c_j distance check"); + } + +} + /* * activate_patches() * Loop over all the patches, and overwrite each syscall. @@ -623,12 +682,10 @@ activate_patches(struct intercept_desc *desc) "mprotect PROT_READ | PROT_WRITE | PROT_EXEC"); for (unsigned i = 0; i < desc->count; ++i) { - if (i == 283 || i == 285) { - continue; - } const struct patch_desc *patch = desc->items + i; - debug_dump("activating patch at dst_jmp_patch:0x%lx - patch->return_address :0x%lx - patch_n:%u\n", - patch->dst_jmp_patch-desc->base_addr,patch->return_address-desc->base_addr,i); + debug_dump("\nactivating patch at dst_jmp_patch: 0x%lx - patch->return_address: 0x%lx - patch_n:%u\n" + "patch_absolute_return_address: %p\n", + patch->dst_jmp_patch-desc->base_addr,patch->return_address-desc->base_addr,i,patch->return_address); if (patch->dst_jmp_patch < desc->text_start || patch->dst_jmp_patch > desc->text_end) @@ -650,23 +707,31 @@ activate_patches(struct intercept_desc *desc) * jump to the asm_wrapper. */ check_trampoline_usage(desc); + if (!patch->needs_compressed_ins) { - /* jump - escape the text segment */ - create_j(patch->dst_jmp_patch, desc->next_trampoline); + /* jump - escape the text segment */ + create_j(patch->dst_jmp_patch, desc->next_trampoline); - /* - * if patch is 10 bytes long, fill the last two - * with c.nop instruction. Template will return there, - * c.nop will make advance PC and .so execution will - * continue normally - */ - if (patch->return_address - patch->dst_jmp_patch == 2) { - *(uint16_t *)(patch->dst_jmp_patch + 8) = 0x0001; // c.nop - } + /* + * if patch is 10 bytes long, fill the last two + * with c.nop instruction. Template will return there, + * c.nop will make advance PC and .so execution will + * continue normally + */ + if (patch->padding_is_needed) { + *(uint16_t *)patch->return_address = 0x0001; + } - /* jump - escape the 2 GB range of the text segment */ - desc->next_trampoline = create_absolute_jump( - desc->next_trampoline, patch->asm_wrapper); + /* jump - escape the 2 GB range of the text segment */ + desc->next_trampoline = create_absolute_jump( + desc->next_trampoline, patch->asm_wrapper); + } else { + const int rem = (desc->next_trampoline - patch->dst_jmp_patch) % 4096; + if (rem) { + desc->next_trampoline += 4096 - rem; + } + create_c_j(patch->dst_jmp_patch, desc->next_trampoline); + } } else { create_j(patch->dst_jmp_patch, patch->asm_wrapper); } diff --git a/test/intercept_sys_read.c b/test/intercept_sys_read.c new file mode 100644 index 0000000..d8dbf72 --- /dev/null +++ b/test/intercept_sys_read.c @@ -0,0 +1,46 @@ +#include "libsyscall_intercept_hook_point.h" +#include +#include +#include +#include +#include + + +static int hook(long syscall_number, + long arg0, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long *result) +{ + (void)arg3; + (void)arg4; + (void)arg5; + (void)result; + + if (syscall_number == SYS_read) { + char *buf = (char *)arg1; + size_t len = (size_t)arg2; + const char interc[] = "intercepted_read\n"; + const char *src = interc; + + if (len > sizeof(interc)) { + *result = 0; + while (*src != '\0') + *buf++ = *src++; + *result += 1; + } + return 0; + } + return 1; +} + +static __attribute__((constructor)) void init(void) +{ + intercept_hook_point = hook; +} + +int main() { + char buf[128]; + read(0, buf, sizeof(buf)); + write(1, buf, strlen(buf)); // Should print "intercepted_read" +} diff --git a/test/intercept_sys_write_2.c b/test/intercept_sys_write_2.c index 5846b03..e544d5f 100644 --- a/test/intercept_sys_write_2.c +++ b/test/intercept_sys_write_2.c @@ -50,7 +50,4 @@ init(void) int main() { char buf[128] = "original_syscall\n"; write(1, buf, strlen(buf)); - printf("correctly returned to libc from asm_template\n"); - printf("\n"); - return 0; } From 316483802bc7af0910cf397fae146422c8270cea Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Fri, 4 Oct 2024 10:39:41 +0000 Subject: [PATCH 016/143] added simple openat interception test --- CMakeLists.txt | 4 ++-- test/intercept_sys_open.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 test/intercept_sys_open.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 71ff641..e5906ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,8 +84,8 @@ set(SOURCES_ASM src/intercept_wrapper.S) -include_directories(include) -link_directories(${capstone_LIBRARY_DIRS}) +include_directories(include "/usr/local/include/capstone") +link_directories("/usr/local/lib/capstone") set(CMAKE_POSITION_INDEPENDENT_CODE ON) diff --git a/test/intercept_sys_open.c b/test/intercept_sys_open.c new file mode 100644 index 0000000..828d773 --- /dev/null +++ b/test/intercept_sys_open.c @@ -0,0 +1,34 @@ +#include "libsyscall_intercept_hook_point.h" +#include +#include +#include +#include +#include +#include + + +static int hook(long syscall_number, + long arg0, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long *result) +{ + if (syscall_number == SYS_openat) { + write(1,"Proof of openat interception\n",29); + } + return 1; +} + +static __attribute__((constructor)) void init(void) +{ + intercept_hook_point = hook; +} + +int main() { + int fd = openat(AT_FDCWD,"non_existing_original_file.txt", O_RDONLY); + if (fd >= 0) { + write(1, "Success: File opened\n", 21); + } else { + write(1, "Failure: File not opened\n", 25); + } +} From dc0bde703e52c8e059d2364543599afb210cf72c Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 10 Oct 2024 22:38:25 +0200 Subject: [PATCH 017/143] Commented out useless debug_dump calls --- src/intercept.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/intercept.c b/src/intercept.c index b352ab1..6198824 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -631,7 +631,7 @@ intercept_routine(struct context *context) get_syscall_in_context(context, &desc); - debug_dump("ra: %lx", context->ra); + // debug_dump("ra: %lx", context->ra); if (handle_magic_syscalls(&desc, &result) == 0) return (struct wrapper_ret){.a[0] = result, .a[1] = 1 }; @@ -688,7 +688,7 @@ intercept_routine(struct context *context) } intercept_log_syscall(patch, &desc, KNOWN, result); - debug_dump("intercepted ecall -> returning to asm_wrapper - result: %ld\n",result); + // debug_dump("intercepted ecall -> returning to asm_wrapper - result: %ld\n",result); return (struct wrapper_ret){ .a[0] = result, .a[1] = 1 }; } From fc2c796823aa719160ca7a72c5c48c3f9edb1f55 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 10 Oct 2024 22:40:06 +0200 Subject: [PATCH 018/143] changed two flags and corrected link_directories --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e5906ca..7b721f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,8 +42,8 @@ endif() option(PERFORM_STYLE_CHECKS "check coding style, license headers (requires perl)" OFF) -option(BUILD_TESTS "build and enable tests" ON) -option(BUILD_EXAMPLES "build examples" ON) +option(BUILD_TESTS "build and enable tests" OFF) +option(BUILD_EXAMPLES "build examples" OFF) option(TREAT_WARNINGS_AS_ERRORS "make the build fail on any warnings during compilation, or linking" OFF) option(EXPECT_SPURIOUS_SYSCALLS @@ -85,7 +85,7 @@ set(SOURCES_ASM include_directories(include "/usr/local/include/capstone") -link_directories("/usr/local/lib/capstone") +link_directories("/usr/local/lib") set(CMAKE_POSITION_INDEPENDENT_CODE ON) From eed7bdd752ff214c0135d4e882f2fc814aadaab8 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 11 Oct 2024 00:14:41 +0200 Subject: [PATCH 019/143] added trampoline creation in 6 byte patch case --- src/patcher.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/patcher.c b/src/patcher.c index fc50f61..2c5e21c 100644 --- a/src/patcher.c +++ b/src/patcher.c @@ -716,7 +716,7 @@ activate_patches(struct intercept_desc *desc) * if patch is 10 bytes long, fill the last two * with c.nop instruction. Template will return there, * c.nop will make advance PC and .so execution will - * continue normally + * normally take back control */ if (patch->padding_is_needed) { *(uint16_t *)patch->return_address = 0x0001; @@ -731,6 +731,9 @@ activate_patches(struct intercept_desc *desc) desc->next_trampoline += 4096 - rem; } create_c_j(patch->dst_jmp_patch, desc->next_trampoline); + + desc->next_trampoline = create_absolute_jump( + desc->next_trampoline, patch->asm_wrapper); } } else { create_j(patch->dst_jmp_patch, patch->asm_wrapper); From 8a51ff9b2189c6121cabf729a1ac5751fa331628 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 24 Oct 2024 18:15:15 +0200 Subject: [PATCH 020/143] updated .gitignore and one assembly test --- .gitignore | 3 ++ test/fcntl64_test.c | 31 +++++++++++++++ test/mock_trampoline_table.S | 75 ++++++++++++++++++++++++------------ test/pattern1.in.S | 8 ++-- test/pattern1.out.S | 20 +++------- 5 files changed, 94 insertions(+), 43 deletions(-) create mode 100644 test/fcntl64_test.c diff --git a/.gitignore b/.gitignore index 58d5f50..b098388 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ tags /.settings /build-deb /syscall_intercept-*.tar.gz +build/ +.idea/ +cmake-build-debug/ diff --git a/test/fcntl64_test.c b/test/fcntl64_test.c new file mode 100644 index 0000000..0bbee6f --- /dev/null +++ b/test/fcntl64_test.c @@ -0,0 +1,31 @@ +#include "libsyscall_intercept_hook_point.h" +#include +#include +#include +#include +#include +#include + +static int +hook(long syscall_number, + long arg0, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long *result) +{ + if (syscall_number == SYS_fcntl) { + write(1,"Proof of fcntl64 interception\n",30); + } + return 1; +} + +static __attribute__((constructor)) void +init(void) +{ + intercept_hook_point = hook; +} + +int main() { + int fd = openat(AT_FDCWD, "intercepting_original_file.txt", O_RDONLY); + int fd_dup = fcntl(fd, F_DUPFD, 0); +} diff --git a/test/mock_trampoline_table.S b/test/mock_trampoline_table.S index 2c9599b..4215a47 100644 --- a/test/mock_trampoline_table.S +++ b/test/mock_trampoline_table.S @@ -45,35 +45,62 @@ # trampoline table has the same format, each mock entry has the same size as # as such a trampoline jump would have. Since these patched syscalls are # never executed in these low level tests, these jumps don't need to be -# real functioning jumps, thus their destination is ".space 8, 0" in all +# real functioning jumps, thus their destination is ".space 92, 0" in all # cases -- the only thing that matters, is to have these at predictable # addresses. -.globl trampoline_table; -.globl trampoline_table_end; +.global trampoline_table; +.global trampoline_table_end; .data trampoline_table: dst0: - addi sp, sp, -16 - sd t1, 0(sp) - sd t2, 8(sp) - sd t3, 16(sp) - .space 20, 0 - lui t1, 0x7ffff - ori t2, zero, 0x7ff - slli t2, t2, 1 - ori t2, t2, 1 - or t1, t1, t2 - slli t1, t1, 1 - ori t1, t1, 1 - and t3, t3, t1 - or t0, t0, t3 - ld t1, 0(sp) - ld t2, 8(sp) - ld t3, 16(sp) - addi sp, sp, 16 - jalr zero, t0, 0 - -trampoline_table_end: + .space 92, 0 +dst1: + .space 92, 0 +dst2: + .space 92, 0 +dst3: + .space 92, 0 +dst4: + .space 92, 0 +dst5: + .space 92, 0 +dst6: + .space 92, 0 +dst7: + .space 92, 0 +dst8: + .space 92, 0 +dst9: + .space 92, 0 +dst10: + .space 92, 0 +dst11: + .space 92, 0 +dst12: + .space 92, 0 +dst13: + .space 92, 0 +dst14: + .space 92, 0 +dst15: + .space 92, 0 +dst16: + .space 92, 0 +dst17: + .space 92, 0 +dst18: + .space 92, 0 +dst19: + .space 92, 0 +dst20: + .space 92, 0 +dst21: + .space 92, 0 +dst22: + .space 92, 0 +dst23: + .space 92, 0 +trampoline_table_end: \ No newline at end of file diff --git a/test/pattern1.in.S b/test/pattern1.in.S index 64ff8b6..fd00ebc 100644 --- a/test/pattern1.in.S +++ b/test/pattern1.in.S @@ -33,18 +33,18 @@ # A simple test with a single syscall instruction. # -.intel_syntax noprefix - .global text_start; .global text_end; -#include "mock_trampoline_table.S" +.include "mock_trampoline_table.S" .text text_start: addi a7, zero, 1 addi a7, a7, zero + c.mv t2, t1 + c.mv t0, t1 ecall - addi zero, zero, zero + c.mv t3, a0 text_end: diff --git a/test/pattern1.out.S b/test/pattern1.out.S index ce21883..30b2ea7 100644 --- a/test/pattern1.out.S +++ b/test/pattern1.out.S @@ -31,26 +31,16 @@ # see pattern1.in.S -.intel_syntax noprefix - .global text_start; .global text_end; -#include "mock_trampoline_table.S" +.include "mock_trampoline_table.S" .text text_start: - jal dst0 - addi zero, zero, 0 # nop - addi zero, zero, 0 # nop - addi zero, zero, 0 # nop - - #otherwise - - # addi sp, sp, -16 - # sd t0, 8(sp) - # lui t0, 0x..... - # jalr ra, t0, 0x... - + addi a7, zero, 1 + addi a7, a7, zero + jal dst0 + c.mv t3, a0 text_end: From 2db363e6cfc8eb2ede5256022523d12abb3859f1 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 24 Oct 2024 18:45:52 +0200 Subject: [PATCH 021/143] test/CMakeLists.txt test push --- test/CMakeLists.txt | 508 ++++++++++++++++++++++---------------------- 1 file changed, 254 insertions(+), 254 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5452223..f4ed2d8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -49,41 +49,41 @@ target_link_libraries(asm_pattern PRIVATE ${CMAKE_DL_LIBS} ${capstone_LDFLAGS}) set(asm_patterns - nosyscall - pattern1 - pattern2 - pattern3 - pattern4 - pattern_loop - pattern_loop2 - pattern_symbol_boundary0 - pattern_symbol_boundary1 - pattern_symbol_boundary2 - pattern_symbol_boundary3 - pattern_nop_padding0 - pattern_nop_padding1 - pattern_nop_padding2 - pattern_nop_padding3 - pattern_nop_padding4 - pattern_nop_padding5 - pattern_nop_padding6 - pattern_nop_padding7 - pattern_nop_padding8 - pattern_nop_padding9 - pattern_lea_rip_rdi - pattern_lea_rip_r12) - -try_compile(ASSEMBLER_SUPPORTS_ENDBR64 ${CMAKE_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/pattern_endbr64.in.S - CMAKE_FLAGS "-DCMAKE_ASM_LINK_EXECUTABLE='echo skip linking'") -if(ASSEMBLER_SUPPORTS_ENDBR64) - list(APPEND asm_patterns pattern_endbr64) -endif() - -set(asm_patterns_failing - pattern_double_syscall - pattern_rets - pattern_jmps) +# nosyscall + pattern1) +# pattern2 +# pattern3 +# pattern4 +# pattern_loop +# pattern_loop2 +# pattern_symbol_boundary0 +# pattern_symbol_boundary1 +# pattern_symbol_boundary2 +# pattern_symbol_boundary3 +# pattern_nop_padding0 +# pattern_nop_padding1 +# pattern_nop_padding2 +# pattern_nop_padding3 +# pattern_nop_padding4 +# pattern_nop_padding5 +# pattern_nop_padding6 +# pattern_nop_padding7 +# pattern_nop_padding8 +# pattern_nop_padding9 +# pattern_lea_rip_rdi +# pattern_lea_rip_r12) + +#try_compile(ASSEMBLER_SUPPORTS_ENDBR64 ${CMAKE_BINARY_DIR} +# ${CMAKE_CURRENT_SOURCE_DIR}/pattern_endbr64.in.S +# CMAKE_FLAGS "-DCMAKE_ASM_LINK_EXECUTABLE='echo skip linking'") +#if(ASSEMBLER_SUPPORTS_ENDBR64) +# list(APPEND asm_patterns pattern_endbr64) +#endif() + +#set(asm_patterns_failing +# pattern_double_syscall +# pattern_rets +# pattern_jmps) macro(add_asm_test test_name failing) add_library(${test_name}.in SHARED ${test_name}.in.S) @@ -116,228 +116,228 @@ foreach(name ${asm_patterns}) add_asm_test(${name} FALSE) endforeach() -foreach(name ${asm_patterns_failing}) - add_asm_test(${name} TRUE) -endforeach() +#foreach(name ${asm_patterns_failing}) +# add_asm_test(${name} TRUE) +#endforeach() set(CHECK_LOG_COMMON_ARGS -DMATCH_SCRIPT=${PROJECT_SOURCE_DIR}/utils/match.pl -DEXPECT_SPURIOUS_SYSCALLS=${EXPECT_SPURIOUS_SYSCALLS} -P ${CMAKE_CURRENT_SOURCE_DIR}/check_log.cmake) -add_executable(fork_logging fork_logging.c) -add_test(NAME "fork_logging" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DTEST_NAME=logging - -DLIB_FILE=$ - -DTEST_PROG=$ - -DTEST_PROG_ARG=${CMAKE_CURRENT_SOURCE_DIR}/fork_logging.c - -DHAS_SECOND_LOG=1 - -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0.log.match - -DSECOND_MATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0_child.log.match - ${CHECK_LOG_COMMON_ARGS}) - -add_library(hook_test_preload_o OBJECT hook_test_preload.c) - -add_executable(hook_test hook_test.c) - -add_library(hook_test_preload_with_shared SHARED - $) -target_link_libraries(hook_test_preload_with_shared PRIVATE syscall_intercept_shared) -add_test(NAME "hook_with_shared" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DTEST_NAME=hook - -DLIB_FILE=$ - -DTEST_PROG=$ - -DTEST_PROG_ARG=None - -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept1.log.match - ${CHECK_LOG_COMMON_ARGS}) - -add_library(hook_test_preload_with_static SHARED - $) -target_link_libraries(hook_test_preload_with_static PRIVATE syscall_intercept_static) -add_test(NAME "hook_with_static" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DTEST_NAME=hook - -DLIB_FILE=$ - -DTEST_PROG=$ - -DTEST_PROG_ARG=None - -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept1.log.match - ${CHECK_LOG_COMMON_ARGS}) - - -add_library(hook_test_clone_preload SHARED hook_test_clone_preload.c) -target_link_libraries(hook_test_clone_preload PRIVATE syscall_intercept_shared) -add_test(NAME "hook_clone" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DTEST_NAME=hook_clone - -DLIB_FILE=$ - -DTEST_PROG=$ - -DTEST_PROG_ARG=${CMAKE_CURRENT_SOURCE_DIR}/fork_logging.c - -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0.log.match - -DHAS_SECOND_LOG=1 - -DSECOND_MATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0_child.log.match - ${CHECK_LOG_COMMON_ARGS}) - -add_executable(filter_test filter_test.c) -target_link_libraries(filter_test PRIVATE syscall_intercept_shared) - -add_test(NAME "filter_none" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DTEST_PROG=$ - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -set_tests_properties("filter_none" - PROPERTIES PASS_REGULAR_EXPRESSION "hooked - allowed") - -add_test(NAME "filter_positive" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DFILTER=$ - -DTEST_PROG=$ - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -set_tests_properties("filter_positive" - PROPERTIES PASS_REGULAR_EXPRESSION "hooked - allowed") - -add_test(NAME "filter_negative" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DFILTER=non_matching_filter - -DTEST_PROG=$ - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -set_tests_properties("filter_negative" - PROPERTIES PASS_REGULAR_EXPRESSION "disallowed") - -# the filter is a substring of the executable name -add_test(NAME "filter_negative_substring0" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DFILTER_PLUS_ONECHAR=$ - -DTEST_PROG=$ - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -set_tests_properties("filter_negative_substring0" - PROPERTIES PASS_REGULAR_EXPRESSION "disallowed") - -# the executable name is a substring of the filter -add_test(NAME "filter_negative_substring1" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DFILTER=A$ - -DTEST_PROG=$ - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -set_tests_properties("filter_negative_substring1" - PROPERTIES PASS_REGULAR_EXPRESSION "disallowed") - -add_executable(test_clone_thread test_clone_thread.c) -target_link_libraries(test_clone_thread PRIVATE ${CMAKE_THREAD_LIBS_INIT}) -add_library(test_clone_thread_preload SHARED test_clone_thread_preload.c) -target_link_libraries(test_clone_thread_preload PRIVATE syscall_intercept_shared) -add_test(NAME "clone_thread" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DFILTER=${test_clone_thread_filename} - -DTEST_PROG=$ - -DLIB_FILE=$ - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -set_tests_properties("clone_thread" - PROPERTIES PASS_REGULAR_EXPRESSION "clone_hook_child called") - -add_library(intercept_sys_write SHARED intercept_sys_write.c) -target_link_libraries(intercept_sys_write PRIVATE syscall_intercept_shared) - -add_executable(executable_with_syscall_pie executable_with_syscall.S) -if(HAS_NOUNUSEDARG) - target_compile_options(executable_with_syscall_pie BEFORE - PRIVATE "-Wno-unused-command-line-argument") -endif() -set_target_properties(executable_with_syscall_pie - PROPERTIES POSITION_INDEPENDENT_CODE True) -if(HAS_ARG_PIE) - target_compile_options(executable_with_syscall_pie PRIVATE "-pie") - target_link_libraries(executable_with_syscall_pie PRIVATE "-pie") -endif() - -add_executable(executable_with_syscall_no_pie executable_with_syscall.S) -if(HAS_NOUNUSEDARG) - target_compile_options(executable_with_syscall_no_pie BEFORE - PRIVATE "-Wno-unused-command-line-argument") -endif() -set_target_properties(executable_with_syscall_no_pie - PROPERTIES POSITION_INDEPENDENT_CODE False) -if(HAS_ARG_NOPIE) - target_compile_options(executable_with_syscall_no_pie PRIVATE "-nopie") - target_link_libraries(executable_with_syscall_no_pie PRIVATE "-nopie") -elseif(HAS_ARG_NO_PIE) - target_compile_options(executable_with_syscall_no_pie PRIVATE "-no-pie") - target_link_libraries(executable_with_syscall_no_pie PRIVATE "-no-pie") -endif() - -add_test(NAME "prog_pie_intercept_libc_only" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DTEST_PROG=$ - -DLIB_FILE=$ - -DTEST_PROG_ARGS=original_syscall - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -set_tests_properties("prog_pie_intercept_libc_only" - PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") - -add_test(NAME "prog_no_pie_intercept_libc_only" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DTEST_PROG=$ - -DLIB_FILE=$ - -DTEST_PROG_ARGS=original_syscall - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -set_tests_properties("prog_no_pie_intercept_libc_only" - PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") - -add_test(NAME "prog_pie_intercept_all" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DINTERCEPT_ALL=1 - -DTEST_PROG=$ - -DLIB_FILE=$ - -DTEST_PROG_ARGS=original_syscall - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -set_tests_properties("prog_pie_intercept_all" - PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") - -add_test(NAME "prog_no_pie_intercept_all" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DINTERCEPT_ALL=1 - -DTEST_PROG=$ - -DLIB_FILE=$ - -DTEST_PROG_ARGS=original_syscall - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -set_tests_properties("prog_no_pie_intercept_all" - PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") - -add_executable(vfork_logging vfork_logging.c) -add_test(NAME "vfork_logging" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DTEST_PROG=$ - -DLIB_FILE=$ - -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept2.log.match - -DTEST_NAME=vfork_logging - ${CHECK_LOG_COMMON_ARGS}) -set_tests_properties("vfork_logging" - PROPERTIES PASS_REGULAR_EXPRESSION "in_child_created_using_vfork") - - -add_executable(syscall_format syscall_format.c) -target_link_libraries(syscall_format PRIVATE syscall_intercept_shared) -add_test(NAME "syscall_format_logging" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DTEST_PROG=$ - -DLIB_FILE= - -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/syscall_format.log.match - -DTEST_NAME=syscall_format_logging - ${CHECK_LOG_COMMON_ARGS}) +#add_executable(fork_logging fork_logging.c) +#add_test(NAME "fork_logging" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DTEST_NAME=logging +# -DLIB_FILE=$ +# -DTEST_PROG=$ +# -DTEST_PROG_ARG=${CMAKE_CURRENT_SOURCE_DIR}/fork_logging.c +# -DHAS_SECOND_LOG=1 +# -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0.log.match +# -DSECOND_MATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0_child.log.match +# ${CHECK_LOG_COMMON_ARGS}) + +#add_library(hook_test_preload_o OBJECT hook_test_preload.c) + +#add_executable(hook_test hook_test.c) +# +#add_library(hook_test_preload_with_shared SHARED +# $) +#target_link_libraries(hook_test_preload_with_shared PRIVATE syscall_intercept_shared) +#add_test(NAME "hook_with_shared" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DTEST_NAME=hook +# -DLIB_FILE=$ +# -DTEST_PROG=$ +# -DTEST_PROG_ARG=None +# -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept1.log.match +# ${CHECK_LOG_COMMON_ARGS}) + +#add_library(hook_test_preload_with_static SHARED +# $) +#target_link_libraries(hook_test_preload_with_static PRIVATE syscall_intercept_static) +#add_test(NAME "hook_with_static" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DTEST_NAME=hook +# -DLIB_FILE=$ +# -DTEST_PROG=$ +# -DTEST_PROG_ARG=None +# -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept1.log.match +# ${CHECK_LOG_COMMON_ARGS}) + + +#add_library(hook_test_clone_preload SHARED hook_test_clone_preload.c) +#target_link_libraries(hook_test_clone_preload PRIVATE syscall_intercept_shared) +#add_test(NAME "hook_clone" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DTEST_NAME=hook_clone +# -DLIB_FILE=$ +# -DTEST_PROG=$ +# -DTEST_PROG_ARG=${CMAKE_CURRENT_SOURCE_DIR}/fork_logging.c +# -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0.log.match +# -DHAS_SECOND_LOG=1 +# -DSECOND_MATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0_child.log.match +# ${CHECK_LOG_COMMON_ARGS}) + +#add_executable(filter_test filter_test.c) +#target_link_libraries(filter_test PRIVATE syscall_intercept_shared) +# +#add_test(NAME "filter_none" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DTEST_PROG=$ +# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +#set_tests_properties("filter_none" +# PROPERTIES PASS_REGULAR_EXPRESSION "hooked - allowed") +# +#add_test(NAME "filter_positive" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DFILTER=$ +# -DTEST_PROG=$ +# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +#set_tests_properties("filter_positive" +# PROPERTIES PASS_REGULAR_EXPRESSION "hooked - allowed") +# +#add_test(NAME "filter_negative" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DFILTER=non_matching_filter +# -DTEST_PROG=$ +# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +#set_tests_properties("filter_negative" +# PROPERTIES PASS_REGULAR_EXPRESSION "disallowed") +# +## the filter is a substring of the executable name +#add_test(NAME "filter_negative_substring0" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DFILTER_PLUS_ONECHAR=$ +# -DTEST_PROG=$ +# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +#set_tests_properties("filter_negative_substring0" +# PROPERTIES PASS_REGULAR_EXPRESSION "disallowed") +# +## the executable name is a substring of the filter +#add_test(NAME "filter_negative_substring1" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DFILTER=A$ +# -DTEST_PROG=$ +# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +#set_tests_properties("filter_negative_substring1" +# PROPERTIES PASS_REGULAR_EXPRESSION "disallowed") +# +#add_executable(test_clone_thread test_clone_thread.c) +#target_link_libraries(test_clone_thread PRIVATE ${CMAKE_THREAD_LIBS_INIT}) +#add_library(test_clone_thread_preload SHARED test_clone_thread_preload.c) +#target_link_libraries(test_clone_thread_preload PRIVATE syscall_intercept_shared) +#add_test(NAME "clone_thread" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DFILTER=${test_clone_thread_filename} +# -DTEST_PROG=$ +# -DLIB_FILE=$ +# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +#set_tests_properties("clone_thread" +# PROPERTIES PASS_REGULAR_EXPRESSION "clone_hook_child called") +# +#add_library(intercept_sys_write SHARED intercept_sys_write.c) +#target_link_libraries(intercept_sys_write PRIVATE syscall_intercept_shared) +# +#add_executable(executable_with_syscall_pie executable_with_syscall.S) +#if(HAS_NOUNUSEDARG) +# target_compile_options(executable_with_syscall_pie BEFORE +# PRIVATE "-Wno-unused-command-line-argument") +#endif() +#set_target_properties(executable_with_syscall_pie +# PROPERTIES POSITION_INDEPENDENT_CODE True) +#if(HAS_ARG_PIE) +# target_compile_options(executable_with_syscall_pie PRIVATE "-pie") +# target_link_libraries(executable_with_syscall_pie PRIVATE "-pie") +#endif() +# +#add_executable(executable_with_syscall_no_pie executable_with_syscall.S) +#if(HAS_NOUNUSEDARG) +# target_compile_options(executable_with_syscall_no_pie BEFORE +# PRIVATE "-Wno-unused-command-line-argument") +#endif() +#set_target_properties(executable_with_syscall_no_pie +# PROPERTIES POSITION_INDEPENDENT_CODE False) +#if(HAS_ARG_NOPIE) +# target_compile_options(executable_with_syscall_no_pie PRIVATE "-nopie") +# target_link_libraries(executable_with_syscall_no_pie PRIVATE "-nopie") +#elseif(HAS_ARG_NO_PIE) +# target_compile_options(executable_with_syscall_no_pie PRIVATE "-no-pie") +# target_link_libraries(executable_with_syscall_no_pie PRIVATE "-no-pie") +#endif() +# +#add_test(NAME "prog_pie_intercept_libc_only" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DTEST_PROG=$ +# -DLIB_FILE=$ +# -DTEST_PROG_ARGS=original_syscall +# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +#set_tests_properties("prog_pie_intercept_libc_only" +# PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") +# +#add_test(NAME "prog_no_pie_intercept_libc_only" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DTEST_PROG=$ +# -DLIB_FILE=$ +# -DTEST_PROG_ARGS=original_syscall +# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +#set_tests_properties("prog_no_pie_intercept_libc_only" +# PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") +# +#add_test(NAME "prog_pie_intercept_all" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DINTERCEPT_ALL=1 +# -DTEST_PROG=$ +# -DLIB_FILE=$ +# -DTEST_PROG_ARGS=original_syscall +# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +#set_tests_properties("prog_pie_intercept_all" +# PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") +# +#add_test(NAME "prog_no_pie_intercept_all" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DINTERCEPT_ALL=1 +# -DTEST_PROG=$ +# -DLIB_FILE=$ +# -DTEST_PROG_ARGS=original_syscall +# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +#set_tests_properties("prog_no_pie_intercept_all" +# PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") +# +#add_executable(vfork_logging vfork_logging.c) +#add_test(NAME "vfork_logging" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DTEST_PROG=$ +# -DLIB_FILE=$ +# -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept2.log.match +# -DTEST_NAME=vfork_logging +# ${CHECK_LOG_COMMON_ARGS}) +#set_tests_properties("vfork_logging" +# PROPERTIES PASS_REGULAR_EXPRESSION "in_child_created_using_vfork") +# +# +#add_executable(syscall_format syscall_format.c) +#target_link_libraries(syscall_format PRIVATE syscall_intercept_shared) +#add_test(NAME "syscall_format_logging" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DTEST_PROG=$ +# -DLIB_FILE= +# -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/syscall_format.log.match +# -DTEST_NAME=syscall_format_logging +# ${CHECK_LOG_COMMON_ARGS}) From a864c327dad91c4007f5093d50e317e9c50d7126 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 24 Oct 2024 18:54:12 +0200 Subject: [PATCH 022/143] restored original version of test/CMakeLists.txt --- test/CMakeLists.txt | 508 ++++++++++++++++++++++---------------------- 1 file changed, 254 insertions(+), 254 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f4ed2d8..5452223 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -49,41 +49,41 @@ target_link_libraries(asm_pattern PRIVATE ${CMAKE_DL_LIBS} ${capstone_LDFLAGS}) set(asm_patterns -# nosyscall - pattern1) -# pattern2 -# pattern3 -# pattern4 -# pattern_loop -# pattern_loop2 -# pattern_symbol_boundary0 -# pattern_symbol_boundary1 -# pattern_symbol_boundary2 -# pattern_symbol_boundary3 -# pattern_nop_padding0 -# pattern_nop_padding1 -# pattern_nop_padding2 -# pattern_nop_padding3 -# pattern_nop_padding4 -# pattern_nop_padding5 -# pattern_nop_padding6 -# pattern_nop_padding7 -# pattern_nop_padding8 -# pattern_nop_padding9 -# pattern_lea_rip_rdi -# pattern_lea_rip_r12) - -#try_compile(ASSEMBLER_SUPPORTS_ENDBR64 ${CMAKE_BINARY_DIR} -# ${CMAKE_CURRENT_SOURCE_DIR}/pattern_endbr64.in.S -# CMAKE_FLAGS "-DCMAKE_ASM_LINK_EXECUTABLE='echo skip linking'") -#if(ASSEMBLER_SUPPORTS_ENDBR64) -# list(APPEND asm_patterns pattern_endbr64) -#endif() - -#set(asm_patterns_failing -# pattern_double_syscall -# pattern_rets -# pattern_jmps) + nosyscall + pattern1 + pattern2 + pattern3 + pattern4 + pattern_loop + pattern_loop2 + pattern_symbol_boundary0 + pattern_symbol_boundary1 + pattern_symbol_boundary2 + pattern_symbol_boundary3 + pattern_nop_padding0 + pattern_nop_padding1 + pattern_nop_padding2 + pattern_nop_padding3 + pattern_nop_padding4 + pattern_nop_padding5 + pattern_nop_padding6 + pattern_nop_padding7 + pattern_nop_padding8 + pattern_nop_padding9 + pattern_lea_rip_rdi + pattern_lea_rip_r12) + +try_compile(ASSEMBLER_SUPPORTS_ENDBR64 ${CMAKE_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/pattern_endbr64.in.S + CMAKE_FLAGS "-DCMAKE_ASM_LINK_EXECUTABLE='echo skip linking'") +if(ASSEMBLER_SUPPORTS_ENDBR64) + list(APPEND asm_patterns pattern_endbr64) +endif() + +set(asm_patterns_failing + pattern_double_syscall + pattern_rets + pattern_jmps) macro(add_asm_test test_name failing) add_library(${test_name}.in SHARED ${test_name}.in.S) @@ -116,228 +116,228 @@ foreach(name ${asm_patterns}) add_asm_test(${name} FALSE) endforeach() -#foreach(name ${asm_patterns_failing}) -# add_asm_test(${name} TRUE) -#endforeach() +foreach(name ${asm_patterns_failing}) + add_asm_test(${name} TRUE) +endforeach() set(CHECK_LOG_COMMON_ARGS -DMATCH_SCRIPT=${PROJECT_SOURCE_DIR}/utils/match.pl -DEXPECT_SPURIOUS_SYSCALLS=${EXPECT_SPURIOUS_SYSCALLS} -P ${CMAKE_CURRENT_SOURCE_DIR}/check_log.cmake) -#add_executable(fork_logging fork_logging.c) -#add_test(NAME "fork_logging" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DTEST_NAME=logging -# -DLIB_FILE=$ -# -DTEST_PROG=$ -# -DTEST_PROG_ARG=${CMAKE_CURRENT_SOURCE_DIR}/fork_logging.c -# -DHAS_SECOND_LOG=1 -# -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0.log.match -# -DSECOND_MATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0_child.log.match -# ${CHECK_LOG_COMMON_ARGS}) - -#add_library(hook_test_preload_o OBJECT hook_test_preload.c) - -#add_executable(hook_test hook_test.c) -# -#add_library(hook_test_preload_with_shared SHARED -# $) -#target_link_libraries(hook_test_preload_with_shared PRIVATE syscall_intercept_shared) -#add_test(NAME "hook_with_shared" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DTEST_NAME=hook -# -DLIB_FILE=$ -# -DTEST_PROG=$ -# -DTEST_PROG_ARG=None -# -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept1.log.match -# ${CHECK_LOG_COMMON_ARGS}) - -#add_library(hook_test_preload_with_static SHARED -# $) -#target_link_libraries(hook_test_preload_with_static PRIVATE syscall_intercept_static) -#add_test(NAME "hook_with_static" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DTEST_NAME=hook -# -DLIB_FILE=$ -# -DTEST_PROG=$ -# -DTEST_PROG_ARG=None -# -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept1.log.match -# ${CHECK_LOG_COMMON_ARGS}) - - -#add_library(hook_test_clone_preload SHARED hook_test_clone_preload.c) -#target_link_libraries(hook_test_clone_preload PRIVATE syscall_intercept_shared) -#add_test(NAME "hook_clone" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DTEST_NAME=hook_clone -# -DLIB_FILE=$ -# -DTEST_PROG=$ -# -DTEST_PROG_ARG=${CMAKE_CURRENT_SOURCE_DIR}/fork_logging.c -# -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0.log.match -# -DHAS_SECOND_LOG=1 -# -DSECOND_MATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0_child.log.match -# ${CHECK_LOG_COMMON_ARGS}) - -#add_executable(filter_test filter_test.c) -#target_link_libraries(filter_test PRIVATE syscall_intercept_shared) -# -#add_test(NAME "filter_none" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DTEST_PROG=$ -# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -#set_tests_properties("filter_none" -# PROPERTIES PASS_REGULAR_EXPRESSION "hooked - allowed") -# -#add_test(NAME "filter_positive" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DFILTER=$ -# -DTEST_PROG=$ -# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -#set_tests_properties("filter_positive" -# PROPERTIES PASS_REGULAR_EXPRESSION "hooked - allowed") -# -#add_test(NAME "filter_negative" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DFILTER=non_matching_filter -# -DTEST_PROG=$ -# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -#set_tests_properties("filter_negative" -# PROPERTIES PASS_REGULAR_EXPRESSION "disallowed") -# -## the filter is a substring of the executable name -#add_test(NAME "filter_negative_substring0" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DFILTER_PLUS_ONECHAR=$ -# -DTEST_PROG=$ -# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -#set_tests_properties("filter_negative_substring0" -# PROPERTIES PASS_REGULAR_EXPRESSION "disallowed") -# -## the executable name is a substring of the filter -#add_test(NAME "filter_negative_substring1" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DFILTER=A$ -# -DTEST_PROG=$ -# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -#set_tests_properties("filter_negative_substring1" -# PROPERTIES PASS_REGULAR_EXPRESSION "disallowed") -# -#add_executable(test_clone_thread test_clone_thread.c) -#target_link_libraries(test_clone_thread PRIVATE ${CMAKE_THREAD_LIBS_INIT}) -#add_library(test_clone_thread_preload SHARED test_clone_thread_preload.c) -#target_link_libraries(test_clone_thread_preload PRIVATE syscall_intercept_shared) -#add_test(NAME "clone_thread" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DFILTER=${test_clone_thread_filename} -# -DTEST_PROG=$ -# -DLIB_FILE=$ -# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -#set_tests_properties("clone_thread" -# PROPERTIES PASS_REGULAR_EXPRESSION "clone_hook_child called") -# -#add_library(intercept_sys_write SHARED intercept_sys_write.c) -#target_link_libraries(intercept_sys_write PRIVATE syscall_intercept_shared) -# -#add_executable(executable_with_syscall_pie executable_with_syscall.S) -#if(HAS_NOUNUSEDARG) -# target_compile_options(executable_with_syscall_pie BEFORE -# PRIVATE "-Wno-unused-command-line-argument") -#endif() -#set_target_properties(executable_with_syscall_pie -# PROPERTIES POSITION_INDEPENDENT_CODE True) -#if(HAS_ARG_PIE) -# target_compile_options(executable_with_syscall_pie PRIVATE "-pie") -# target_link_libraries(executable_with_syscall_pie PRIVATE "-pie") -#endif() -# -#add_executable(executable_with_syscall_no_pie executable_with_syscall.S) -#if(HAS_NOUNUSEDARG) -# target_compile_options(executable_with_syscall_no_pie BEFORE -# PRIVATE "-Wno-unused-command-line-argument") -#endif() -#set_target_properties(executable_with_syscall_no_pie -# PROPERTIES POSITION_INDEPENDENT_CODE False) -#if(HAS_ARG_NOPIE) -# target_compile_options(executable_with_syscall_no_pie PRIVATE "-nopie") -# target_link_libraries(executable_with_syscall_no_pie PRIVATE "-nopie") -#elseif(HAS_ARG_NO_PIE) -# target_compile_options(executable_with_syscall_no_pie PRIVATE "-no-pie") -# target_link_libraries(executable_with_syscall_no_pie PRIVATE "-no-pie") -#endif() -# -#add_test(NAME "prog_pie_intercept_libc_only" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DTEST_PROG=$ -# -DLIB_FILE=$ -# -DTEST_PROG_ARGS=original_syscall -# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -#set_tests_properties("prog_pie_intercept_libc_only" -# PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") -# -#add_test(NAME "prog_no_pie_intercept_libc_only" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DTEST_PROG=$ -# -DLIB_FILE=$ -# -DTEST_PROG_ARGS=original_syscall -# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -#set_tests_properties("prog_no_pie_intercept_libc_only" -# PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") -# -#add_test(NAME "prog_pie_intercept_all" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DINTERCEPT_ALL=1 -# -DTEST_PROG=$ -# -DLIB_FILE=$ -# -DTEST_PROG_ARGS=original_syscall -# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -#set_tests_properties("prog_pie_intercept_all" -# PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") -# -#add_test(NAME "prog_no_pie_intercept_all" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DINTERCEPT_ALL=1 -# -DTEST_PROG=$ -# -DLIB_FILE=$ -# -DTEST_PROG_ARGS=original_syscall -# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -#set_tests_properties("prog_no_pie_intercept_all" -# PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") -# -#add_executable(vfork_logging vfork_logging.c) -#add_test(NAME "vfork_logging" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DTEST_PROG=$ -# -DLIB_FILE=$ -# -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept2.log.match -# -DTEST_NAME=vfork_logging -# ${CHECK_LOG_COMMON_ARGS}) -#set_tests_properties("vfork_logging" -# PROPERTIES PASS_REGULAR_EXPRESSION "in_child_created_using_vfork") -# -# -#add_executable(syscall_format syscall_format.c) -#target_link_libraries(syscall_format PRIVATE syscall_intercept_shared) -#add_test(NAME "syscall_format_logging" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DTEST_PROG=$ -# -DLIB_FILE= -# -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/syscall_format.log.match -# -DTEST_NAME=syscall_format_logging -# ${CHECK_LOG_COMMON_ARGS}) +add_executable(fork_logging fork_logging.c) +add_test(NAME "fork_logging" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DTEST_NAME=logging + -DLIB_FILE=$ + -DTEST_PROG=$ + -DTEST_PROG_ARG=${CMAKE_CURRENT_SOURCE_DIR}/fork_logging.c + -DHAS_SECOND_LOG=1 + -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0.log.match + -DSECOND_MATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0_child.log.match + ${CHECK_LOG_COMMON_ARGS}) + +add_library(hook_test_preload_o OBJECT hook_test_preload.c) + +add_executable(hook_test hook_test.c) + +add_library(hook_test_preload_with_shared SHARED + $) +target_link_libraries(hook_test_preload_with_shared PRIVATE syscall_intercept_shared) +add_test(NAME "hook_with_shared" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DTEST_NAME=hook + -DLIB_FILE=$ + -DTEST_PROG=$ + -DTEST_PROG_ARG=None + -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept1.log.match + ${CHECK_LOG_COMMON_ARGS}) + +add_library(hook_test_preload_with_static SHARED + $) +target_link_libraries(hook_test_preload_with_static PRIVATE syscall_intercept_static) +add_test(NAME "hook_with_static" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DTEST_NAME=hook + -DLIB_FILE=$ + -DTEST_PROG=$ + -DTEST_PROG_ARG=None + -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept1.log.match + ${CHECK_LOG_COMMON_ARGS}) + + +add_library(hook_test_clone_preload SHARED hook_test_clone_preload.c) +target_link_libraries(hook_test_clone_preload PRIVATE syscall_intercept_shared) +add_test(NAME "hook_clone" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DTEST_NAME=hook_clone + -DLIB_FILE=$ + -DTEST_PROG=$ + -DTEST_PROG_ARG=${CMAKE_CURRENT_SOURCE_DIR}/fork_logging.c + -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0.log.match + -DHAS_SECOND_LOG=1 + -DSECOND_MATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept0_child.log.match + ${CHECK_LOG_COMMON_ARGS}) + +add_executable(filter_test filter_test.c) +target_link_libraries(filter_test PRIVATE syscall_intercept_shared) + +add_test(NAME "filter_none" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DTEST_PROG=$ + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +set_tests_properties("filter_none" + PROPERTIES PASS_REGULAR_EXPRESSION "hooked - allowed") + +add_test(NAME "filter_positive" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DFILTER=$ + -DTEST_PROG=$ + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +set_tests_properties("filter_positive" + PROPERTIES PASS_REGULAR_EXPRESSION "hooked - allowed") + +add_test(NAME "filter_negative" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DFILTER=non_matching_filter + -DTEST_PROG=$ + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +set_tests_properties("filter_negative" + PROPERTIES PASS_REGULAR_EXPRESSION "disallowed") + +# the filter is a substring of the executable name +add_test(NAME "filter_negative_substring0" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DFILTER_PLUS_ONECHAR=$ + -DTEST_PROG=$ + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +set_tests_properties("filter_negative_substring0" + PROPERTIES PASS_REGULAR_EXPRESSION "disallowed") + +# the executable name is a substring of the filter +add_test(NAME "filter_negative_substring1" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DFILTER=A$ + -DTEST_PROG=$ + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +set_tests_properties("filter_negative_substring1" + PROPERTIES PASS_REGULAR_EXPRESSION "disallowed") + +add_executable(test_clone_thread test_clone_thread.c) +target_link_libraries(test_clone_thread PRIVATE ${CMAKE_THREAD_LIBS_INIT}) +add_library(test_clone_thread_preload SHARED test_clone_thread_preload.c) +target_link_libraries(test_clone_thread_preload PRIVATE syscall_intercept_shared) +add_test(NAME "clone_thread" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DFILTER=${test_clone_thread_filename} + -DTEST_PROG=$ + -DLIB_FILE=$ + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +set_tests_properties("clone_thread" + PROPERTIES PASS_REGULAR_EXPRESSION "clone_hook_child called") + +add_library(intercept_sys_write SHARED intercept_sys_write.c) +target_link_libraries(intercept_sys_write PRIVATE syscall_intercept_shared) + +add_executable(executable_with_syscall_pie executable_with_syscall.S) +if(HAS_NOUNUSEDARG) + target_compile_options(executable_with_syscall_pie BEFORE + PRIVATE "-Wno-unused-command-line-argument") +endif() +set_target_properties(executable_with_syscall_pie + PROPERTIES POSITION_INDEPENDENT_CODE True) +if(HAS_ARG_PIE) + target_compile_options(executable_with_syscall_pie PRIVATE "-pie") + target_link_libraries(executable_with_syscall_pie PRIVATE "-pie") +endif() + +add_executable(executable_with_syscall_no_pie executable_with_syscall.S) +if(HAS_NOUNUSEDARG) + target_compile_options(executable_with_syscall_no_pie BEFORE + PRIVATE "-Wno-unused-command-line-argument") +endif() +set_target_properties(executable_with_syscall_no_pie + PROPERTIES POSITION_INDEPENDENT_CODE False) +if(HAS_ARG_NOPIE) + target_compile_options(executable_with_syscall_no_pie PRIVATE "-nopie") + target_link_libraries(executable_with_syscall_no_pie PRIVATE "-nopie") +elseif(HAS_ARG_NO_PIE) + target_compile_options(executable_with_syscall_no_pie PRIVATE "-no-pie") + target_link_libraries(executable_with_syscall_no_pie PRIVATE "-no-pie") +endif() + +add_test(NAME "prog_pie_intercept_libc_only" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DTEST_PROG=$ + -DLIB_FILE=$ + -DTEST_PROG_ARGS=original_syscall + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +set_tests_properties("prog_pie_intercept_libc_only" + PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") + +add_test(NAME "prog_no_pie_intercept_libc_only" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DTEST_PROG=$ + -DLIB_FILE=$ + -DTEST_PROG_ARGS=original_syscall + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +set_tests_properties("prog_no_pie_intercept_libc_only" + PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") + +add_test(NAME "prog_pie_intercept_all" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DINTERCEPT_ALL=1 + -DTEST_PROG=$ + -DLIB_FILE=$ + -DTEST_PROG_ARGS=original_syscall + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +set_tests_properties("prog_pie_intercept_all" + PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") + +add_test(NAME "prog_no_pie_intercept_all" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DINTERCEPT_ALL=1 + -DTEST_PROG=$ + -DLIB_FILE=$ + -DTEST_PROG_ARGS=original_syscall + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +set_tests_properties("prog_no_pie_intercept_all" + PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") + +add_executable(vfork_logging vfork_logging.c) +add_test(NAME "vfork_logging" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DTEST_PROG=$ + -DLIB_FILE=$ + -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept2.log.match + -DTEST_NAME=vfork_logging + ${CHECK_LOG_COMMON_ARGS}) +set_tests_properties("vfork_logging" + PROPERTIES PASS_REGULAR_EXPRESSION "in_child_created_using_vfork") + + +add_executable(syscall_format syscall_format.c) +target_link_libraries(syscall_format PRIVATE syscall_intercept_shared) +add_test(NAME "syscall_format_logging" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DTEST_PROG=$ + -DLIB_FILE= + -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/syscall_format.log.match + -DTEST_NAME=syscall_format_logging + ${CHECK_LOG_COMMON_ARGS}) From 76e7e5c0973ae9f285c58712e791711d01930992 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Mon, 30 Dec 2024 12:44:28 +0100 Subject: [PATCH 023/143] Fixed relocation bug and fixed bug for leaves procedure; now returning to libc with absolute jump instead of ret --- src/patcher.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/patcher.c b/src/patcher.c index 2c5e21c..d5d28df 100644 --- a/src/patcher.c +++ b/src/patcher.c @@ -85,7 +85,7 @@ /* The size of a trampoline jump, 64-bit address loading process into a register * (which requires 14 instructions to encode directly in machine code) + JALR. - * These are preceeded and succeeded by storing and restoring of tmp registers + * These are preceded and succeeded by storing and restoring of tmp registers * used for the creation of the absolute jump. We can't clobber them since two * instructions that were placed before the original ecall still must be * executed. @@ -219,6 +219,7 @@ is_copiable_after_syscall(struct intercept_disasm_result ins) ins.is_jump || ins.is_endbr || ins.is_syscall || + ins.uses_t6 || ins.uses_ra); } @@ -312,6 +313,12 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) length += patch->preceding_ins_2.length; patch->dst_jmp_patch -= patch->preceding_ins_2.length; + } else { + /* + * If it could be used but is not necessary we need + * to set the flag to false so that it's not relocated + */ + patch->uses_prev_ins_2 = false; } } @@ -341,12 +348,17 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) ECALL_INS_SIZE + patch->following_ins.length; } else { + /* + * If it could be used but is not necessary we need + * to set the flag to false so that it's not relocated + */ + patch->uses_next_ins = false; patch->return_address = patch->syscall_addr + ECALL_INS_SIZE; } if (length > JUMP_INS_SIZE) { patch->padding_is_needed = true; - patch->return_address -= (length - JUMP_INS_SIZE); + // patch->return_address -= (length - JUMP_INS_SIZE); } /* @@ -380,10 +392,8 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) debug_dump("unintercepted syscall at: %s 0x%lx\n", desc->path, patch->syscall_offset); -#ifdef ABORT_ON_FAILURE xabort("not enough space for patching" " around syscal"); -#endif } mark_jump(desc, patch->return_address); @@ -556,7 +566,6 @@ create_wrapper(struct patch_desc *patch, unsigned char **dst) { /* Create a new copy of the template */ patch->asm_wrapper = *dst; - uint32_t *instructions = (uint32_t *)(*dst); /* Copy the previous instruction(s) */ if (patch->uses_prev_ins) { @@ -576,15 +585,15 @@ create_wrapper(struct patch_desc *patch, unsigned char **dst) if (patch->uses_next_ins) *dst = relocate_instruction(*dst, &patch->following_ins); - // *dst = create_absolute_jump(*dst, patch->return_address); // since ra is updated with patch->return_address by JALR when jumping to trampoline, writing RET is enough - *dst = create_ret_from_template(*dst); + *dst = create_absolute_jump(*dst, patch->return_address); + // *dst = create_ret_from_template(*dst); } /* * create_j(from, to) * Create a 4 byte JAL instruction jumping to address to, by overwriting * code starting at address from, if trampoline displacement is within + or - - * 1 MiB. Otherwise create a 2 instructions sequence (LUI + JALR) which allows + * 1 MiB. Otherwise, create a 2 instructions sequence (LUI + JALR) which allows * to reach trampoline if its displacement is within -2 GiB or JALR_MAX_OFFSET, * which is (+2 GiB - 2050 Bytes). */ @@ -598,10 +607,8 @@ create_j(unsigned char *from, void *to) */ ptrdiff_t delta = ((unsigned char *)to) - from; uint32_t *instructions = (uint32_t *)from; - uint32_t nop = 0x00000013; // nop instruction debug_dump("%p: ecall -> jalr %ld\t# %p\n", from, delta, to); - const ptrdiff_t JAL_OFFSET = 1 << 20; const ptrdiff_t JALR_MAX_OFFSET = 2147481598; // ((2^31-1)-4095)+(2^11-1) == 0x7ffff000 + 0x7ff const ptrdiff_t JALR_MIN_OFFSET = -2147483648; // (-2^31) == -0x80000000 @@ -613,7 +620,7 @@ create_j(unsigned char *from, void *to) if (delta <= JALR_MAX_OFFSET && delta >= JALR_MIN_OFFSET) { uint32_t auipc = 0x00000f97; // auipc t6, 0x..... - uint32_t jalr = 0x000f80e7; // jalr ra, t6, 0x... + uint32_t jalr = 0x000f8067; // jalr zero, t6, 0x... uint32_t jalr_imm_field = 0; uint32_t auipc_imm_field = (uint32_t)delta & 0xfffff000; // offset[31:12] @@ -633,7 +640,7 @@ create_j(unsigned char *from, void *to) auipc |= auipc_imm_field; jalr |= (jalr_imm_field << 20); instructions[0] = auipc; // auipc t6, 0x..... - instructions[1] = jalr; // jalr ra, t6, 0x... + instructions[1] = jalr; // jalr zero, t6, 0x... } else { xabort("create_j distance check"); } @@ -650,11 +657,11 @@ create_c_j(unsigned char *from, void *to) { } if (delta >= AUIPC_MIN_OFFSET && delta <= AUIPC_MAX_OFFSET) { uint32_t auipc = 0x00000f97; // auipc t6, 0x..... - uint16_t c_jalr = 0x9f82; // c.jalr t6 + uint16_t c_jr = 0x8f82; // c.jr t6 uint32_t auipc_imm_field = (uint32_t)delta & 0xfffff000; // offset[31:12] auipc |= auipc_imm_field; *(uint32_t *)from = auipc; - *(uint16_t *)(from + 4) = c_jalr; + *(uint16_t *)(from + 4) = c_jr; } else { xabort("create_c_j distance check"); } @@ -719,7 +726,7 @@ activate_patches(struct intercept_desc *desc) * normally take back control */ if (patch->padding_is_needed) { - *(uint16_t *)patch->return_address = 0x0001; + *(uint16_t *)patch->return_address = 0x0001; // c.nop } /* jump - escape the 2 GB range of the text segment */ From dbb453826978f91af3673fd33b6333fc22767558 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Mon, 30 Dec 2024 14:17:53 +0100 Subject: [PATCH 024/143] added some tests --- .gitignore | 1 + test/example.c | 38 ++++++++++++++++++++++++++++++++++++++ test/intercept_sys_open.c | 17 +++++++++-------- test/intercept_sys_read.c | 6 ------ test/openat_test.c | 14 ++++++++++++++ test/read_test.c | 8 ++++++++ test/write_test.c | 7 +++++++ 7 files changed, 77 insertions(+), 14 deletions(-) create mode 100644 test/example.c create mode 100644 test/openat_test.c create mode 100644 test/read_test.c create mode 100644 test/write_test.c diff --git a/.gitignore b/.gitignore index b098388..01cee36 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ tags build/ .idea/ cmake-build-debug/ +test/*.so diff --git a/test/example.c b/test/example.c new file mode 100644 index 0000000..541eb3b --- /dev/null +++ b/test/example.c @@ -0,0 +1,38 @@ +#include "libsyscall_intercept_hook_point.h" +#include +#include + +static int +hook(long syscall_number, + long arg0, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long *result) +{ + if (syscall_number == SYS_getdents) { + /* + * Prevent the application from + * using the getdents syscall. From + * the point of view of the calling + * process, it is as if the kernel + * would return the ENOTSUP error + * code from the syscall. + */ + *result = -ENOTSUP; + return 0; + } else { + /* + * Ignore any other syscalls + * i.e.: pass them on to the kernel + * as would normally happen. + */ + return 1; + } +} + +static __attribute__((constructor)) void +init(void) +{ + // Set up the callback function + intercept_hook_point = hook; +} \ No newline at end of file diff --git a/test/intercept_sys_open.c b/test/intercept_sys_open.c index 828d773..9c062d0 100644 --- a/test/intercept_sys_open.c +++ b/test/intercept_sys_open.c @@ -24,11 +24,12 @@ static __attribute__((constructor)) void init(void) intercept_hook_point = hook; } -int main() { - int fd = openat(AT_FDCWD,"non_existing_original_file.txt", O_RDONLY); - if (fd >= 0) { - write(1, "Success: File opened\n", 21); - } else { - write(1, "Failure: File not opened\n", 25); - } -} +//int main() { +// int fd = openat(AT_FDCWD,"non_existing_original_file.txt", O_RDONLY); +// if (fd >= 0) { +// write(1, "Success: File opened\n", 21); +// } else { +// write(1, "Specified file doesn't exist - Test is ok if previous line is:\n" +// "\"Proof of openat interception\"\n", 25); +// } +//} diff --git a/test/intercept_sys_read.c b/test/intercept_sys_read.c index d8dbf72..e07e798 100644 --- a/test/intercept_sys_read.c +++ b/test/intercept_sys_read.c @@ -38,9 +38,3 @@ static __attribute__((constructor)) void init(void) { intercept_hook_point = hook; } - -int main() { - char buf[128]; - read(0, buf, sizeof(buf)); - write(1, buf, strlen(buf)); // Should print "intercepted_read" -} diff --git a/test/openat_test.c b/test/openat_test.c new file mode 100644 index 0000000..1816d34 --- /dev/null +++ b/test/openat_test.c @@ -0,0 +1,14 @@ +#include +#include +#include + +int main() { + int fd = openat(AT_FDCWD,"non_existing_original_file.txt", O_RDONLY); + char buf[128] = "Specified file doesn't exist - Test is ok if previous line is:\n" + "\"Proof of openat interception\"\n"; + if (fd >= 0) { + write(1, "Success: File opened\n", 21); + } else { + write(1, buf, strlen(buf)); + } +} \ No newline at end of file diff --git a/test/read_test.c b/test/read_test.c new file mode 100644 index 0000000..0239dde --- /dev/null +++ b/test/read_test.c @@ -0,0 +1,8 @@ +#include +#include + +int main() { + char buf[128]; + read(0, buf, sizeof(buf)); + write(1, buf, strlen(buf)); // Should print "intercepted_read" +} \ No newline at end of file diff --git a/test/write_test.c b/test/write_test.c new file mode 100644 index 0000000..1ee552c --- /dev/null +++ b/test/write_test.c @@ -0,0 +1,7 @@ +#include +#include + +int main() { + char buf[128] = "original_syscall\n"; + write(1, buf, strlen(buf)); +} \ No newline at end of file From 0f6f411d99659732f361cb974c2147cbb936b0ec Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Mon, 30 Dec 2024 15:25:09 +0100 Subject: [PATCH 025/143] some more tests --- test/intercept_sys_open_2.c | 34 +++++++++++++++++++++++++++ test/intercept_sys_read_2.c | 46 +++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 test/intercept_sys_open_2.c create mode 100644 test/intercept_sys_read_2.c diff --git a/test/intercept_sys_open_2.c b/test/intercept_sys_open_2.c new file mode 100644 index 0000000..f55f987 --- /dev/null +++ b/test/intercept_sys_open_2.c @@ -0,0 +1,34 @@ +#include "libsyscall_intercept_hook_point.h" +#include +#include +#include +#include +#include +#include + + +static int hook(long syscall_number, + long arg0, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long *result) +{ + if (syscall_number == SYS_openat) { + write(1,"Proof of openat interception\n",29); + } + return 1; +} + +static __attribute__((constructor)) void init(void) +{ + intercept_hook_point = hook; +} + +int main() { + int fd = openat(AT_FDCWD,"non_existing_original_file.txt", O_RDONLY); + if (fd >= 0) { + write(1, "Success: File opened\n", 21); + } else { + write(1, "Failure: File not opened\n", 25); + } +} diff --git a/test/intercept_sys_read_2.c b/test/intercept_sys_read_2.c new file mode 100644 index 0000000..c3abcd8 --- /dev/null +++ b/test/intercept_sys_read_2.c @@ -0,0 +1,46 @@ +#include "libsyscall_intercept_hook_point.h" +#include +#include +#include +#include +#include + + +static int hook(long syscall_number, + long arg0, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long *result) +{ + (void)arg3; + (void)arg4; + (void)arg5; + (void)result; + + if (syscall_number == SYS_read) { + char *buf = (char *)arg1; + size_t len = (size_t)arg2; + const char interc[] = "intercepted_read\n"; + const char *src = interc; + + if (len > sizeof(interc)) { + *result = 0; + while (*src != '\0') + *buf++ = *src++; + *result += 1; + } + return 0; + } + return 1; +} + +static __attribute__((constructor)) void init(void) +{ + intercept_hook_point = hook; +} + +int main() { + char buf[128]; + read(0, buf, sizeof(buf)); + write(1, buf, strlen(buf)); // Should print "intercepted_read" +} \ No newline at end of file From 2f88c94f141bdcd58a819cc996f4720c2ed77d7e Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Mon, 30 Dec 2024 15:42:40 +0100 Subject: [PATCH 026/143] corrected some more tests --- test/intercept_sys_read.c | 5 ++++- test/intercept_sys_read_2.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/test/intercept_sys_read.c b/test/intercept_sys_read.c index e07e798..c1a18e7 100644 --- a/test/intercept_sys_read.c +++ b/test/intercept_sys_read.c @@ -25,9 +25,12 @@ static int hook(long syscall_number, if (len > sizeof(interc)) { *result = 0; - while (*src != '\0') + while (*src != '\0') { *buf++ = *src++; *result += 1; + } + *buf = '\0'; + *result += 1; } return 0; } diff --git a/test/intercept_sys_read_2.c b/test/intercept_sys_read_2.c index c3abcd8..5889044 100644 --- a/test/intercept_sys_read_2.c +++ b/test/intercept_sys_read_2.c @@ -25,8 +25,11 @@ static int hook(long syscall_number, if (len > sizeof(interc)) { *result = 0; - while (*src != '\0') + while (*src != '\0') { *buf++ = *src++; + *result += 1; + } + *buf = '\0'; *result += 1; } return 0; From 93ec7113aa3f270cb9457f0e4e16204cb1c6dd4f Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Mon, 30 Dec 2024 16:03:47 +0100 Subject: [PATCH 027/143] example.c test corrected --- test/example.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/example.c b/test/example.c index 541eb3b..bf9e2b3 100644 --- a/test/example.c +++ b/test/example.c @@ -9,7 +9,7 @@ hook(long syscall_number, long arg4, long arg5, long *result) { - if (syscall_number == SYS_getdents) { + if (syscall_number == SYS_getdents64) { /* * Prevent the application from * using the getdents syscall. From From 8962c5caff43d287be1b446db24a71dc0cba80f5 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 3 Jan 2025 22:05:45 +0100 Subject: [PATCH 028/143] c.nop placement bug solved --- src/patcher.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/patcher.c b/src/patcher.c index d5d28df..e651d91 100644 --- a/src/patcher.c +++ b/src/patcher.c @@ -719,15 +719,15 @@ activate_patches(struct intercept_desc *desc) /* jump - escape the text segment */ create_j(patch->dst_jmp_patch, desc->next_trampoline); - /* - * if patch is 10 bytes long, fill the last two - * with c.nop instruction. Template will return there, - * c.nop will make advance PC and .so execution will - * normally take back control - */ - if (patch->padding_is_needed) { - *(uint16_t *)patch->return_address = 0x0001; // c.nop - } + // /* + // * if patch is 10 bytes long, fill the last two + // * with c.nop instruction. Template will return there, + // * c.nop will make advance PC and .so execution will + // * normally take back control + // */ + // if (patch->padding_is_needed) { + // *(uint16_t *)patch->return_address = 0x0001; // c.nop + // } /* jump - escape the 2 GB range of the text segment */ desc->next_trampoline = create_absolute_jump( From 3e7d0e502bd277a281cce38137f788668d6d5d37 Mon Sep 17 00:00:00 2001 From: GlassOfWhiskey Date: Sat, 4 Jan 2025 09:50:28 +0100 Subject: [PATCH 029/143] Cleaning arch-specific dependencies --- CMakeLists.txt | 25 ++- src/arch/riscv/disasm_wrapper.c | 136 ++++++++++++++++ src/arch/riscv/intercept_template.S | 165 +++++++++++++++++++ src/arch/riscv/intercept_wrapper.S | 167 +++++++++++++++++++ src/arch/riscv/util.S | 50 ++++++ src/arch/x86_64/disasm_wrapper.c | 232 +++++++++++++++++++++++++++ src/arch/x86_64/intercept_template.S | 116 ++++++++++++++ src/arch/x86_64/intercept_wrapper.S | 232 +++++++++++++++++++++++++++ src/arch/x86_64/util.S | 67 ++++++++ src/disasm_wrapper.c | 109 ++----------- src/intercept_desc.c | 44 ++++- src/intercept_template.S | 155 ------------------ src/intercept_wrapper.S | 161 ------------------- src/util.S | 67 -------- 14 files changed, 1239 insertions(+), 487 deletions(-) create mode 100644 src/arch/riscv/disasm_wrapper.c create mode 100644 src/arch/riscv/intercept_template.S create mode 100644 src/arch/riscv/intercept_wrapper.S create mode 100644 src/arch/riscv/util.S create mode 100644 src/arch/x86_64/disasm_wrapper.c create mode 100644 src/arch/x86_64/intercept_template.S create mode 100644 src/arch/x86_64/intercept_wrapper.S create mode 100644 src/arch/x86_64/util.S delete mode 100644 src/intercept_template.S delete mode 100644 src/intercept_wrapper.S delete mode 100644 src/util.S diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b721f5..0c710b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,11 +78,26 @@ set(SOURCES_C src/magic_syscalls.c src/syscall_formats.c) -set(SOURCES_ASM - src/intercept_template.S - src/util.S - src/intercept_wrapper.S) - +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86(_64)?)$") + set(SOURCES_C "${SOURCES_C}" + src/arch/x86_64/disasm_wrapper.c) + + set(SOURCES_ASM + src/arch/x86_64/intercept_template.S + src/arch/x86_64/intercept_wrapper.S + src/arch/x86_64/util.S + ) +elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv(32|64))$") + set(SOURCES_C "${SOURCES_C}" + src/arch/riscv/disasm_wrapper.c + ) + + set(SOURCES_ASM + src/arch/riscv/intercept_template.S + src/arch/riscv/intercept_wrapper.S + src/arch/riscv/util.S + ) +endif() include_directories(include "/usr/local/include/capstone") link_directories("/usr/local/lib") diff --git a/src/arch/riscv/disasm_wrapper.c b/src/arch/riscv/disasm_wrapper.c new file mode 100644 index 0000000..f940a77 --- /dev/null +++ b/src/arch/riscv/disasm_wrapper.c @@ -0,0 +1,136 @@ +/* + * Copyright 2016-2020, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "../../disasm_wrapper.h" + +#include "../../capstone_wrapper.h" + +struct intercept_disasm_context { + csh handle; + cs_insn *insn; + const unsigned char *begin; + const unsigned char *end; +}; + +/* + * intercept_disasm_next_instruction - Examines a single instruction + * in a text section. This is only a wrapper around capstone specific code, + * collecting data that can be used later to make decisions about patching. + */ +struct intercept_disasm_result +intercept_disasm_next_instruction(struct intercept_disasm_context *context, + const unsigned char *code) +{ + struct intercept_disasm_result result = {.address = code, 0, }; + const unsigned char *start = code; + size_t size = (size_t)(context->end - code + 1); + uint64_t address = (uint64_t)code; + + if (!cs_disasm_iter(context->handle, &start, &size, + &address, context->insn)) { + return result; + } + + result.length = context->insn->size; + + assert(result.length != 0); + + result.is_syscall = (context->insn->id == RISCV_INS_ECALL); +#ifndef NDEBUG + result.mnemonic = context->insn->mnemonic; +#endif + + switch (context->insn->id) { + case RISCV_INS_BEQ: // PC-relative jumps + case RISCV_INS_BGE: + case RISCV_INS_BGEU: + case RISCV_INS_BLT: + case RISCV_INS_BLTU: + case RISCV_INS_BNE: + case RISCV_INS_JAL: + case RISCV_INS_C_J: + case RISCV_INS_C_JAL: + case RISCV_INS_C_BEQZ: + case RISCV_INS_C_BNEZ: + result.has_ip_relative_opr = true; + result.is_jump = true; + break; + case RISCV_INS_AUIPC: + result.has_ip_relative_opr = true; + break; + case RISCV_INS_JALR: + case RISCV_INS_C_JALR: + result.is_jump = true; + break; + default: + result.is_jump = false; + result.has_ip_relative_opr = false; + result.uses_ra = false; + cs_riscv_op *op; + for (uint8_t op_i = 0; !result.uses_ra && + op_i < context->insn->detail->riscv.op_count; ++op_i) { + op = context->insn->detail->riscv.operands + op_i; + switch (op->type) { + case RISCV_OP_REG: + result.uses_ra = op->reg == RISCV_REG_RA; + break; + case RISCV_OP_MEM: + result.uses_ra = op->mem.base == RISCV_REG_RA; + break; + default: + break; + } + } + result.uses_t6 = false; + for (uint8_t op_i = 0; !result.uses_t6 && + op_i < context->insn->detail->riscv.op_count; ++op_i) { + op = context->insn->detail->riscv.operands + op_i; + switch (op->type) { + case RISCV_OP_REG: + result.uses_t6 = op->reg == RISCV_REG_T6; + break; + case RISCV_OP_MEM: + result.uses_t6 = op->mem.base == RISCV_REG_T6; + break; + default: + break; + } + } + break; + } + + result.is_set = true; + + return result; +} diff --git a/src/arch/riscv/intercept_template.S b/src/arch/riscv/intercept_template.S new file mode 100644 index 0000000..7166aa3 --- /dev/null +++ b/src/arch/riscv/intercept_template.S @@ -0,0 +1,165 @@ +/* + * Copyright 2016-2017, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * intercept_template.s -- see asm_wrapper.md + */ + +.globl intercept_asm_wrapper_tmpl +.globl intercept_asm_wrapper_patch_desc_addr +.globl intercept_asm_wrapper_wrapper_level1_addr +.globl intercept_asm_wrapper_tmpl_end + +.text + +/* + * ld t0, 0(sp) + * addi sp, sp, 16 + * preceding_ins_2 + * preceding_ins + */ +intercept_asm_wrapper_tmpl: + li t5, 0 # choose intercept_routine +l0: + bnez t5, l3 + mv t6, sp # remember original sp + j l4 +l3: + ld t6, 0(sp) # we cloned, so save actual original sp +l4: + addi sp, sp, -32 # allocate stack for some locals + sd t6, 0(sp) # original sp on stack + sd ra, 16(sp) # patch->return_address on stack + sd s0, 24(sp) # follows conventions by saving s0 on stack since we use it + bnez t5, intercept_asm_wrapper_patch_desc_addr + li s0, 0 # s0 as flag: 1 if we are going for post_clone, 0 otherwise +intercept_asm_wrapper_patch_desc_addr: + /* load patch_desc address in t0 */ + + /* + * the 5 following instructions are placeholders for the correct ones which are + * overwritten in machine language by create_load_uint64t_into_t0() + * + * lui t0, 0x00000 + * addi t0, t0, 0x000 + * slli t0, t0, 32 + * lui t3, 0x00000 + * addi t3, t3, 0x000 + */ + .space 20, 0 + + /* the 9 following instructions load the 64-bit address in t0 */ + lui t1, 0x7ffff + ori t2, zero, 0x7ff + slli t2, t2, 1 + ori t2, t2, 1 + or t1, t1, t2 + slli t1, t1, 1 + ori t1, t1, 1 + and t3, t3, t1 + or t0, t0, t3 + + sd t0, 8(sp) /* patch_desc pointer on stack */ +intercept_asm_wrapper_wrapper_level1_addr: + /* load intercept_wrapper address in t0 */ + + /* + * the 5 following instructions are placeholders for the correct ones which are + * written in machine language in create_load_uint64t_into_t0() in patcher.c + * + * lui t0, 0x00000 + * ori t0, t0, 0x000 + * slli t0, t0, 32 + * lui t3, 0x00000 + * ori t3, t3, 0x000 + * + */ + .space 20, 0 + + /* the 9 following instructions load the 64-bit address in t0 */ + lui t1, 0x7ffff + ori t2, zero, 0x7ff + slli t2, t2, 1 + ori t2, t2, 1 + or t1, t1, t2 + slli t1, t1, 1 + ori t1, t1, 1 + and t3, t3, t1 + or t0, t0, t3 + + /* calling intercept_wrapper */ + jalr ra, t0, 0 + + /* + * The intercept_wrapper function did restore all registers to their + * original state, except for a0, sp and t6. + * + * If t6 is zero, a0 contains a syscall number, and that syscall + * is executed here. + * If t6 is 1, a0 contains the return value of the hooked syscall. + * If t6 is 2, a clone syscall is executed here. + */ + beqz t6, l2 + li t0, 1 + beq t6, t0, restore_sp + li t0, 2 + beq t6, t0, l1 + + li a7, 94 /* exit_group if t6 contains an invalid value, namely different from */ + ecall /* 0, 1 or 2 */ +l1: + mv a7, a0 + ecall + li t5, 1 /* choose intercept_routine_post_clone */ + li s0, 1 /* flag to signal we cloned, restoring sp will require adding 64 */ + j l0 +l2: + mv a7, a0 + ecall +restore_sp: + beqz s0, l5 + addi sp, sp, 32 +l5: + ld ra, 16(sp) + ld s0, 24(sp) + addi sp, sp, 32 + +intercept_asm_wrapper_tmpl_end: + /* + * This template must be appended here with a + * jump back to the intercepted code. + */ + + /* + * following_ins # !can't use ra as operand! need to check after disassembly + * jalr zero, ra, 0 + */ diff --git a/src/arch/riscv/intercept_wrapper.S b/src/arch/riscv/intercept_wrapper.S new file mode 100644 index 0000000..f8a8e55 --- /dev/null +++ b/src/arch/riscv/intercept_wrapper.S @@ -0,0 +1,167 @@ +/* + * Copyright 2016-2017, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * intercept_wrapper.s -- see asm_wrapper.md + */ + +/* the function in this file */ +.globl intercept_wrapper +.type intercept_wrapper, @function + +/* the C function in intercept.c */ +.globl intercept_routine +.type intercept_routine, @function + +/* the other C function in intercept.c, called right after cloning a thread */ +.globl intercept_routine_post_clone +.type intercept_routine_post_clone, @function + +.text + +intercept_wrapper: + /* + * Decreasing sp to allocate needed space to save caller-saved registers but + * t5 and t6 which are already clobbered, original sp value around the ecall + * and patch_desc pointer + */ + addi sp, sp, -288 + + /* + * Saving temporary and function arguments registers, which are both + * caller-saved onto the stack + */ + sd ra, 0(sp) + sd t0, 8(sp) + sd t1, 16(sp) + sd t2, 24(sp) + sd t3, 32(sp) + sd t4, 40(sp) + + /* fetching original value of sp */ + ld t6, 288(sp) + sd t6, 48(sp) + + /* fetching pointer to patch_desc */ + ld t6, 296(sp) + sd t6, 56(sp) + + sd a0, 64(sp) + sd a1, 72(sp) + sd a2, 80(sp) + sd a3, 88(sp) + sd a4, 96(sp) + sd a5, 104(sp) + sd a6, 112(sp) + sd a7, 120(sp) + fsd ft0, 128(sp) + fsd ft1, 136(sp) + fsd ft2, 144(sp) + fsd ft3, 152(sp) + fsd ft4, 160(sp) + fsd ft5, 168(sp) + fsd ft6, 176(sp) + fsd ft7, 184(sp) + fsd ft8, 192(sp) + fsd ft9, 200(sp) + fsd ft10, 208(sp) + fsd ft11, 216(sp) + fsd fa0, 224(sp) + fsd fa1, 232(sp) + fsd fa2, 240(sp) + fsd fa3, 248(sp) + fsd fa4, 256(sp) + fsd fa5, 264(sp) + fsd fa6, 272(sp) + fsd fa7, 280(sp) + + /* argument passed to intercept_routine */ + mv a0, sp + + li t0, 1 + beq t5, t0, l0 # which function should be called? + + jal intercept_routine + j l1 +l0: + jal intercept_routine_post_clone +l1: + /* + * At this point, the return value of the C + * function (a struct wrapper_ret instance) is in a0, a1. + * + * This function doesn't use these values for anything, just + * forwards them to the higher level wrapper function, generated + * from the template. + */ + mv t6, a1 + + /* Restoring temporary and funcion arguments registers */ + ld ra, 0(sp) + ld t0, 8(sp) + ld t1, 16(sp) + ld t2, 24(sp) + ld t3, 32(sp) + ld t4, 40(sp) + + /* no point in restoring in context values at 48(sp), 56(sp) and 64(sp) */ + ld a1, 72(sp) + ld a2, 80(sp) + ld a3, 88(sp) + ld a4, 96(sp) + ld a5, 104(sp) + ld a6, 112(sp) + ld a7, 120(sp) + fld ft0, 128(sp) + fld ft1, 136(sp) + fld ft2, 144(sp) + fld ft3, 152(sp) + fld ft4, 160(sp) + fld ft5, 168(sp) + fld ft6, 176(sp) + fld ft7, 184(sp) + fld ft8, 192(sp) + fld ft9, 200(sp) + fld ft10, 208(sp) + fld ft11, 216(sp) + fld fa0, 224(sp) + fld fa1, 232(sp) + fld fa2, 240(sp) + fld fa3, 248(sp) + fld fa4, 256(sp) + fld fa5, 264(sp) + fld fa6, 272(sp) + fld fa7, 280(sp) + + /* Increasing sp to its original value */ + addi sp, sp, 288 + ret diff --git a/src/arch/riscv/util.S b/src/arch/riscv/util.S new file mode 100644 index 0000000..c4a84f4 --- /dev/null +++ b/src/arch/riscv/util.S @@ -0,0 +1,50 @@ +/* + * Copyright 2016-2027, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +.globl syscall_no_intercept; +.type syscall_no_intercept, @function + +.text + +syscall_no_intercept: + /* converting from RISC-V calling conventions to RISC-V Linux calling conventions */ + mv a7, a0 + mv a0, a1 + mv a1, a2 + mv a2, a3 + mv a3, a4 + mv a4, a5 + mv a5, a6 + ecall + ret + +.size syscall_no_intercept, .-syscall_no_intercept diff --git a/src/arch/x86_64/disasm_wrapper.c b/src/arch/x86_64/disasm_wrapper.c new file mode 100644 index 0000000..d399c74 --- /dev/null +++ b/src/arch/x86_64/disasm_wrapper.c @@ -0,0 +1,232 @@ +/* + * Copyright 2016-2020, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "../../disasm_wrapper.h" + +#include "../../capstone_wrapper.h" + +struct intercept_disasm_context { + csh handle; + cs_insn *insn; + const unsigned char *begin; + const unsigned char *end; +}; + +/* + * check_op - checks a single operand of an instruction, looking + * for RIP relative addressing. + */ +static void +check_op(struct intercept_disasm_result *result, cs_x86_op *op, + const unsigned char *code) +{ + /* + * the address the RIP register is going to contain during the + * execution of this instruction + */ + const unsigned char *rip = code + result->length; + + if (op->type == X86_OP_REG) { + if (op->reg == X86_REG_IP || + op->reg == X86_REG_RIP) { + /* + * Example: mov %rip, %rax + */ + result->has_ip_relative_opr = true; + result->rip_disp = 0; + result->rip_ref_addr = rip; + } + if (result->is_jump) { + /* + * Example: jmp *(%rax) + */ + /* + * An indirect jump can't have arguments other + * than a register - therefore the asserts. + * ( I'm 99.99% sure this is true ) + */ + assert(!result->is_rel_jump); + result->is_indirect_jump = true; + } + } else if (op->type == X86_OP_MEM) { + if (op->mem.base == X86_REG_IP || + op->mem.base == X86_REG_RIP || + op->mem.index == X86_REG_IP || + op->mem.index == X86_REG_RIP || + result->is_jump) { + result->has_ip_relative_opr = true; + assert(!result->is_indirect_jump); + + if (result->is_jump) + result->is_rel_jump = true; + + assert(op->mem.disp <= INT32_MAX); + assert(op->mem.disp >= INT32_MIN); + + result->rip_disp = (int32_t)op->mem.disp; + result->rip_ref_addr = rip + result->rip_disp; + } + } else if (op->type == X86_OP_IMM) { + if (result->is_jump) { + assert(!result->is_indirect_jump); + result->has_ip_relative_opr = true; + result->is_rel_jump = true; + result->rip_ref_addr = (void *)op->imm; + + result->rip_disp = + (int32_t)((unsigned char *)op->imm - rip); + } + } +} + +/* + * intercept_disasm_next_instruction - Examines a single instruction + * in a text section. This is only a wrapper around capstone specific code, + * collecting data that can be used later to make decisions about patching. + */ +struct intercept_disasm_result +intercept_disasm_next_instruction(struct intercept_disasm_context *context, + const unsigned char *code) +{ + static const unsigned char endbr64[] = {0xf3, 0x0f, 0x1e, 0xfa}; + + struct intercept_disasm_result result = {.address = code, 0, }; + const unsigned char *start = code; + size_t size = (size_t)(context->end - code + 1); + uint64_t address = (uint64_t)code; + + if (size >= sizeof(endbr64) && + memcmp(code, endbr64, sizeof(endbr64)) == 0) { + result.is_set = true; + result.is_endbr = true; + result.length = 4; +#ifndef NDEBUG + result.mnemonic = "endbr64"; +#endif + return result; + } + + if (!cs_disasm_iter(context->handle, &start, &size, + &address, context->insn)) { + return result; + } + + result.length = context->insn->size; + + assert(result.length != 0); + + result.is_syscall = (context->insn->id == X86_INS_SYSCALL); + result.is_call = (context->insn->id == X86_INS_CALL); + result.is_ret = (context->insn->id == X86_INS_RET); + result.is_rel_jump = false; + result.is_indirect_jump = false; +#ifndef NDEBUG + result.mnemonic = context->insn->mnemonic; +#endif + + switch (context->insn->id) { + case X86_INS_JAE: + case X86_INS_JA: + case X86_INS_JBE: + case X86_INS_JB: + case X86_INS_JCXZ: + case X86_INS_JECXZ: + case X86_INS_JE: + case X86_INS_JGE: + case X86_INS_JG: + case X86_INS_JLE: + case X86_INS_JL: + case X86_INS_JMP: + case X86_INS_JNE: + case X86_INS_JNO: + case X86_INS_JNP: + case X86_INS_JNS: + case X86_INS_JO: + case X86_INS_JP: + case X86_INS_JRCXZ: + case X86_INS_JS: + case X86_INS_LOOP: + case X86_INS_CALL: + result.is_jump = true; + assert(context->insn->detail->x86.op_count == 1); + break; + case X86_INS_NOP: + result.is_nop = true; + break; + default: + result.is_jump = false; + break; + } + + result.has_ip_relative_opr = false; + + /* + * Loop over all operands of the instruction currently being decoded. + * These operands are decoded by capstone, and described in the + * context->insn->detail->x86.operands array. + * + * This operand checking serves multiple purposes: + * The destination of any jumping instruction is found here, + * The instructions using RIP relative addressing are found by this + * loop, e.g.: mov %rax, 0x36eb55d(%rip) + * + * Any instruction relying on the value of the RIP register can not + * be relocated ( including relative jumps, which naturally also + * rely on the RIP register ). + */ + for (uint8_t op_i = 0; + op_i < context->insn->detail->x86.op_count; ++op_i) + check_op(&result, context->insn->detail->x86.operands + op_i, + code); + + result.is_lea_rip = (context->insn->id == X86_INS_LEA && + result.has_ip_relative_opr); + + if (result.is_lea_rip) { + /* + * Extract the four bits from the encoding, which + * specify the destination register. + */ + + /* one bit from the REX prefix */ + result.arg_register_bits = ((code[0] & 4) << 1); + + /* three bits from the ModRM byte */ + result.arg_register_bits |= ((code[2] >> 3) & 7); + } + + result.is_set = true; + + return result; +} \ No newline at end of file diff --git a/src/arch/x86_64/intercept_template.S b/src/arch/x86_64/intercept_template.S new file mode 100644 index 0000000..70f60d8 --- /dev/null +++ b/src/arch/x86_64/intercept_template.S @@ -0,0 +1,116 @@ +/* + * Copyright 2016-2017, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * intercept_template.s -- see asm_wrapper.md + */ + +.global intercept_asm_wrapper_tmpl; +.hidden intercept_asm_wrapper_tmpl; +.global intercept_asm_wrapper_patch_desc_addr; +.hidden intercept_asm_wrapper_patch_desc_addr; +.global intercept_asm_wrapper_wrapper_level1_addr; +.hidden intercept_asm_wrapper_wrapper_level1_addr; +.global intercept_asm_wrapper_tmpl_end; +.hidden intercept_asm_wrapper_tmpl_end; + +.text + +/* + * Locals on the stack: + * 0(%rsp) the original value of %rsp, in the code around the syscall + * 8(%rsp) the pointer to the struct patch_desc instance + * + * The %rcx register controls which C function to call in intercept.c: + * + * if %rcx == 0 then call intercept_routine + * if %rcx == 1 then intercept_routine_post_clone + * + * This value in %rcx is passed to the function intercep_wrapper. + * + * + * Note: the subq instruction allocating stack for locals must not + * ruin the stack alignment. It must round up the number of bytes + * needed for locals. + */ +intercept_asm_wrapper_tmpl: + movq $0x0, %rcx /* choose intercept_routine */ + +0: movq %rsp, %r11 /* remember original rsp */ + subq $0x80, %rsp /* avoid the red zone */ + andq $-16, %rsp /* align the stack */ + subq $0x20, %rsp /* allocate stack for some locals */ + movq %r11, (%rsp) /* orignal rsp on stack */ +intercept_asm_wrapper_patch_desc_addr: + movabsq $0x000000000000, %r11 + movq %r11, 0x8 (%rsp) /* patch_desc pointer on stack */ +intercept_asm_wrapper_wrapper_level1_addr: + movabsq $0x000000000000, %r11 + callq *%r11 /* call intercept_wrapper */ + movq (%rsp), %rsp /* restore original rsp */ + /* + * The intercept_wrapper function did restore all registers to their + * original state, except for rax, rsp, rip, and r11. + * + * If r11 is zero, rax contains a syscall number, and that syscall + * is executed here. + * If r11 is 1, rax contains the return value of the hooked syscall. + * If r11 is 2, a clone syscall is executed here. + */ + cmp $0x0, %r11 + je 2f + cmp $0x1, %r11 + je 3f + cmp $0x2, %r11 + je 1f + + hlt /* r11 value is invalid? */ + +1: + /* execute the clone syscall in its original context */ + syscall + movq $0x1, %rcx /* choose intercept_routine_post_clone */ + /* + * Now goto 0, and call the C function named + * intercept_routine_post_clone both in the parent thread, adn the + * child thread. + */ + jmp 0b + +2: + syscall +3: +intercept_asm_wrapper_tmpl_end: + /* + * This template must be appended here with a + * jump back to the intercepted code. + */ diff --git a/src/arch/x86_64/intercept_wrapper.S b/src/arch/x86_64/intercept_wrapper.S new file mode 100644 index 0000000..7291a17 --- /dev/null +++ b/src/arch/x86_64/intercept_wrapper.S @@ -0,0 +1,232 @@ +/* + * Copyright 2016-2017, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * intercept_wrapper.s -- see asm_wrapper.md + */ + +/* the function in this file */ +.global intercept_wrapper +.hidden intercept_wrapper +.type intercept_wrapper, @function + +/* the C function in intercept.c */ +.global intercept_routine +.hidden intercept_routine +.type intercept_routine, @function + +/* the other C function in intercept.c, called right after cloning a thread */ +.global intercept_routine_post_clone +.hidden intercept_routine_post_clone +.type intercept_routine_post_clone, @function + +/* The boolean indicating whether YMM registers must saved */ +.global intercept_routine_must_save_ymm +.hidden intercept_routine_must_save_ymm + +.text + +/* + * Local stack layout: + * + * 0x448(%rsp) -- return address, to the generated asm wrapper + * Arguments recieved on stack: + * 0x450(%rsp) -- original value of rsp + * 0x458(%rsp) -- pointer to a struct patch_desc instance + * Locals on stack: + * 0xe8(%rsp) - 0x168(%rsp) -- saved GPRs + * 0x200(%rsp) - 0x400(%rsp) -- saved SIMD registers + * + * A pointer to these saved register is passed to intercept_routine, so the + * layout of `struct context` must match this part of the stack layout. + * + * Other arguments: + * %rcx -- which C function to call + */ +intercept_wrapper: + .cfi_startproc + + /* + * Stack size used locally: 0x448 bytes. + * + * This size assumes the stack pointer was correctly aligned before + * executing the call instruction calling this function. The return + * address pushed to the stack uses 8 bytes. This gives the equation: + * + * new_rsp = original_rsp - 8 - 0x448 == original_rsp - 0x450 + * The number 0x450 is a multiple of 16, so the stack is still correctly + * aligned. It is very easy to forget about this when making changes to this + * code. + */ + subq $0x448, %rsp + .cfi_def_cfa_offset 0x0 + + /* Save all GPRs on the stack */ + movq %rax, 0x160 (%rsp) + .cfi_offset 0, 0x160 + movq %rdx, 0x158 (%rsp) + .cfi_offset 1, 0x158 + /* rcx is already clobbered, no reason to save it */ + movq %rbx, 0x150 (%rsp) + .cfi_offset 3, 0x150 + movq %rsi, 0x148 (%rsp) + .cfi_offset 4, 0x148 + movq %rdi, 0x140 (%rsp) + .cfi_offset 5, 0x140 + movq %rbp, 0x138 (%rsp) + .cfi_offset 6, 0x138 + movq 0x450 (%rsp), %r11 /* fetch original value of rsp */ + movq %r11, 0x130 (%rsp) + .cfi_offset 7, 0x130 + movq %r8, 0x128 (%rsp) + .cfi_offset 8, 0x128 + movq %r9, 0x120 (%rsp) + .cfi_offset 9, 0x120 + movq %r10, 0x118 (%rsp) + .cfi_offset 10, -0x118 + /* r11 is already clobbered, no reason to save it */ + movq %r12, 0x110 (%rsp) + .cfi_offset 12, 0x110 + movq %r13, 0x108 (%rsp) + .cfi_offset 13, 0x108 + movq %r14, 0x100 (%rsp) + .cfi_offset 14, 0x100 + movq %r15, 0xf8 (%rsp) + .cfi_offset 15, 0xf8 + movq 0x458 (%rsp), %r11 /* fetch pointer to patch_desc */ + movq %r11, 0xe8 (%rsp) + movq (%r11), %r11 /* fetch original value of rip */ + movq %r11, 0xf0 (%rsp) + .cfi_offset 16, 0xf0 + + movb intercept_routine_must_save_ymm (%rip), %al + test %al, %al + jz 0f + + /* + * Save the YMM registers. + * Use vmovups. Must not use vmovaps, since 32 byte alignment is not + * guaranteed. + * One could just align the stack for this, but that would need + * more explanation in comments in other places about why overaligned + * stack is needed. + */ + vmovups %ymm0, 0x3c0 (%rsp) + vmovups %ymm1, 0x380 (%rsp) + vmovups %ymm2, 0x340 (%rsp) + vmovups %ymm3, 0x300 (%rsp) + vmovups %ymm4, 0x2c0 (%rsp) + vmovups %ymm5, 0x280 (%rsp) + vmovups %ymm6, 0x240 (%rsp) + vmovups %ymm7, 0x200 (%rsp) + jmp 1f + +0: + /* Save the XMM registers. */ + movaps %xmm0, 0x3c0 (%rsp) + movaps %xmm1, 0x380 (%rsp) + movaps %xmm2, 0x340 (%rsp) + movaps %xmm3, 0x300 (%rsp) + movaps %xmm4, 0x2c0 (%rsp) + movaps %xmm5, 0x280 (%rsp) + movaps %xmm6, 0x240 (%rsp) + movaps %xmm7, 0x200 (%rsp) + +1: + /* argument passed to intercept_routine */ + leaq 0xe8 (%rsp), %rdi + + cmp $0x1, %rcx /* which function should be called? */ + je 0f + call intercept_routine + jmp 1f +0: call intercept_routine_post_clone +1: + /* + * At this point, the return value of the C + * function (a struct wrapper_ret instance) is in rax, rdx. + * + * This function doesn't use these values for anything, just + * forwards them to the higher level wrapper function, generated + * from the template. + */ + + movq %rdx, %r11 + /* + * At this point, the return values of this asm function + * are in rax, r11. + * + * Restore the other registers, and return. + */ + + movb intercept_routine_must_save_ymm (%rip), %dl + test %dl, %dl + jz 0f + + vmovups 0x3c0 (%rsp), %ymm0 + vmovups 0x380 (%rsp), %ymm1 + vmovups 0x340 (%rsp), %ymm2 + vmovups 0x300 (%rsp), %ymm3 + vmovups 0x2c0 (%rsp), %ymm4 + vmovups 0x280 (%rsp), %ymm5 + vmovups 0x240 (%rsp), %ymm6 + vmovups 0x200 (%rsp), %ymm7 + jmp 1f + +0: + movaps 0x3c0 (%rsp), %xmm0 + movaps 0x380 (%rsp), %xmm1 + movaps 0x340 (%rsp), %xmm2 + movaps 0x300 (%rsp), %xmm3 + movaps 0x2c0 (%rsp), %xmm4 + movaps 0x280 (%rsp), %xmm5 + movaps 0x240 (%rsp), %xmm6 + movaps 0x200 (%rsp), %xmm7 + +1: + movq 0x158 (%rsp), %rdx + movq 0x150 (%rsp), %rbx + movq 0x148 (%rsp), %rsi + movq 0x140 (%rsp), %rdi + movq 0x138 (%rsp), %rbp + movq 0x128 (%rsp), %r8 + movq 0x120 (%rsp), %r9 + movq 0x118 (%rsp), %r10 + movq 0x110 (%rsp), %r12 + movq 0x108 (%rsp), %r13 + movq 0x100 (%rsp), %r14 + movq 0xf8 (%rsp), %r15 + + addq $0x448, %rsp + + retq + .cfi_endproc diff --git a/src/arch/x86_64/util.S b/src/arch/x86_64/util.S new file mode 100644 index 0000000..88e48ce --- /dev/null +++ b/src/arch/x86_64/util.S @@ -0,0 +1,67 @@ +/* + * Copyright 2016-2027, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +.global has_ymm_registers; +.hidden has_ymm_registers; +.type has_ymm_registers, @function + +.global syscall_no_intercept; +.type syscall_no_intercept, @function + +.text + +has_ymm_registers: + .cfi_startproc + pushq %rbx + movq $0x1, %rax + cpuid + movq %rcx, %rax + shrq $28, %rax + andq $1, %rax + popq %rbx + retq + .cfi_endproc + +.size has_ymm_registers, .-has_ymm_registers + +syscall_no_intercept: + movq %rdi, %rax /* convert from linux ABI calling */ + movq %rsi, %rdi /* convention to syscall calling convention */ + movq %rdx, %rsi + movq %rcx, %rdx + movq %r8, %r10 + movq %r9, %r8 + movq 8(%rsp), %r9 + syscall + ret + +.size syscall_no_intercept, .-syscall_no_intercept diff --git a/src/disasm_wrapper.c b/src/disasm_wrapper.c index ac26150..f8cc53c 100644 --- a/src/disasm_wrapper.c +++ b/src/disasm_wrapper.c @@ -42,11 +42,18 @@ #include "intercept_util.h" #include "disasm_wrapper.h" -#include -#include -#include #include "capstone_wrapper.h" +#if defined(__x86_64__) || defined(_M_X64) + #define CS_ARCH CS_ARCH_X86 + #define CS_MODE CS_MODE_64 +#elif defined(__riscv) + #define CS_ARCH CS_ARCH_RISCV + #define CS_MODE CS_MODE_RISCV64 | CS_MODE_RISCVC +#else + #error "Unsupported ISA" +#endif + struct intercept_disasm_context { csh handle; cs_insn *insn; @@ -90,7 +97,7 @@ intercept_disasm_init(const unsigned char *begin, const unsigned char *end) * Initialize the disassembler. * The handle here must be passed to capstone each time it is used. */ - if (cs_open(CS_ARCH_RISCV, CS_MODE_RISCV64 | CS_MODE_RISCVC, &context->handle) != CS_ERR_OK) + if (cs_open(CS_ARCH, CS_MODE, &context->handle) != CS_ERR_OK) xabort("cs_open"); /* @@ -130,97 +137,3 @@ intercept_disasm_destroy(struct intercept_disasm_context *context) cs_close(&context->handle); xmunmap(context, sizeof(*context)); } - -/* - * intercept_disasm_next_instruction - Examines a single instruction - * in a text section. This is only a wrapper around capstone specific code, - * collecting data that can be used later to make decisions about patching. - */ -struct intercept_disasm_result -intercept_disasm_next_instruction(struct intercept_disasm_context *context, - const unsigned char *code) -{ - //static const unsigned char endbr64[] = {0xf3, 0x0f, 0x1e, 0xfa}; // no endbr equivalent in RISC-V - - struct intercept_disasm_result result = {.address = code, 0, }; - const unsigned char *start = code; - size_t size = (size_t)(context->end - code + 1); - uint64_t address = (uint64_t)code; - - if (!cs_disasm_iter(context->handle, &start, &size, - &address, context->insn)) { - return result; - } - - result.length = context->insn->size; - - assert(result.length != 0); - - result.is_syscall = (context->insn->id == RISCV_INS_ECALL); -#ifndef NDEBUG - result.mnemonic = context->insn->mnemonic; -#endif - - switch (context->insn->id) { - case RISCV_INS_BEQ: // PC-relative jumps - case RISCV_INS_BGE: - case RISCV_INS_BGEU: - case RISCV_INS_BLT: - case RISCV_INS_BLTU: - case RISCV_INS_BNE: - case RISCV_INS_JAL: - case RISCV_INS_C_J: - case RISCV_INS_C_JAL: - case RISCV_INS_C_BEQZ: - case RISCV_INS_C_BNEZ: - result.has_ip_relative_opr = true; - result.is_jump = true; - break; - case RISCV_INS_AUIPC: - result.has_ip_relative_opr = true; - break; - case RISCV_INS_JALR: - case RISCV_INS_C_JALR: - result.is_jump = true; - break; - default: - result.is_jump = false; - result.has_ip_relative_opr = false; - result.uses_ra = false; - cs_riscv_op *op; - for (uint8_t op_i = 0; !result.uses_ra && - op_i < context->insn->detail->riscv.op_count; ++op_i) { - op = context->insn->detail->riscv.operands + op_i; - switch (op->type) { - case RISCV_OP_REG: - result.uses_ra = op->reg == RISCV_REG_RA; - break; - case RISCV_OP_MEM: - result.uses_ra = op->mem.base == RISCV_REG_RA; - break; - default: - break; - } - } - result.uses_t6 = false; - for (uint8_t op_i = 0; !result.uses_t6 && - op_i < context->insn->detail->riscv.op_count; ++op_i) { - op = context->insn->detail->riscv.operands + op_i; - switch (op->type) { - case RISCV_OP_REG: - result.uses_t6 = op->reg == RISCV_REG_T6; - break; - case RISCV_OP_MEM: - result.uses_t6 = op->mem.base == RISCV_REG_T6; - break; - default: - break; - } - } - break; - } - - result.is_set = true; - - return result; -} diff --git a/src/intercept_desc.c b/src/intercept_desc.c index 7c99a9b..e355dc4 100644 --- a/src/intercept_desc.c +++ b/src/intercept_desc.c @@ -353,6 +353,8 @@ find_jumps_in_section_rela(struct intercept_desc *desc, Elf64_Shdr *section, for (size_t i = 0; i < sym_count; ++i) { switch (ELF64_R_TYPE(syms[i].r_info)) { + case R_X86_64_RELATIVE: + case R_X86_64_RELATIVE64: case R_RISCV_RELATIVE: /* Relocation type: "Adjust by program base" */ @@ -404,6 +406,35 @@ add_new_patch(struct intercept_desc *desc) return &(desc->items[desc->count++]); } +/* + * is_overwritable_nop + * Check if an instruction just disassembled is a NOP that can be + * used for placing an extra jump instruction into it. + * See the nop_trampoline usage in the patcher.c source file. + * This instruction is usable only if it occupies at least seven bytes. + * Two are needed for a short jump, and another 5 bytes for a trampoline + * jump with 32 bit displacement. + * + * As in (where XXXX represents a 32 bit displacement): + * Before After + * _______ _______ + * address of NOP instruction -> | NOP | | JMP | <- jumps to next + * | | | +8 | instruction + * | | | JMP | <- 5 bytes of payload + * | | | X | + * | | | X | + * | | | X | + * | | | X | + * | | | | + * address of next instruction -> ------- ------- + * + */ +bool +is_overwritable_nop(const struct intercept_disasm_result *ins) +{ + return ins->is_nop && ins->length >= 2 + 5; +} + /* * crawl_text * Crawl the text section, disassembling it all. @@ -449,11 +480,18 @@ crawl_text(struct intercept_desc *desc) result = intercept_disasm_next_instruction(context, code); if (result.length == 0) { - debug_dump("code pointer:0x%lx\n",code); ++code; continue; } +#if defined(__x86_64__) || defined(_M_X64) + if (result.has_ip_relative_opr) + mark_jump(desc, result.rip_ref_addr); + + if (is_overwritable_nop(&result)) + mark_nop(desc, code, result.length); +#endif + /* * Generate a new patch description, if: * - Information is available about a syscalls place @@ -668,6 +706,10 @@ find_syscalls(struct intercept_desc *desc) (uintptr_t)desc->text_end); allocate_jump_table(desc); +#if defined(__x86_64__) || defined(_M_X64) + allocate_nop_table(desc); +#endif + for (Elf64_Half i = 0; i < desc->symbol_tables.count; ++i) find_jumps_in_section_syms(desc, desc->symbol_tables.headers + i, fd); diff --git a/src/intercept_template.S b/src/intercept_template.S deleted file mode 100644 index b4f481b..0000000 --- a/src/intercept_template.S +++ /dev/null @@ -1,155 +0,0 @@ - # - # Copyright 2016-2024, Intel Corporation - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions - # are met: - # - # * Redistributions of source code must retain the above copyright - # notice, this list of conditions and the following disclaimer. - # - # * Redistributions in binary form must reproduce the above copyright - # notice, this list of conditions and the following disclaimer in - # the documentation and/or other materials provided with the - # distribution. - # - # * Neither the name of the copyright holder nor the names of its - # contributors may be used to endorse or promote products derived - # from this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - # - - # intercept_template.s -- see asm_wrapper.md - - .globl intercept_asm_wrapper_tmpl - # .local intercept_asm_wrapper_tmpl # x64 uses .hidden - how to port to RISC-V? - .globl intercept_asm_wrapper_patch_desc_addr - # .local intercept_asm_wrapper_patch_desc_addr - .globl intercept_asm_wrapper_wrapper_level1_addr - # .local intercept_asm_wrapper_wrapper_level1_addr - .globl intercept_asm_wrapper_tmpl_end - # .local intercept_asm_wrapper_tmpl_end - - .text - - # ld t0, 0(sp) - # addi sp, sp, 16 - # preceding_ins_2 - # preceding_ins - intercept_asm_wrapper_tmpl: - li t5, 0 # choose intercept_routine - l0: - bnez t5, l3 - mv t6, sp # remember original sp - j l4 - l3: - ld t6, 0(sp) # we cloned, so save actual original sp - l4: - addi sp, sp, -32 # allocate stack for some locals - sd t6, 0(sp) # original sp on stack - sd ra, 16(sp) # patch->return_address on stack - sd s0, 24(sp) # follows conventions by saving s0 on stack since we use it - bnez t5, intercept_asm_wrapper_patch_desc_addr - li s0, 0 # s0 as flag: 1 if we are going for post_clone, 0 otherwise - intercept_asm_wrapper_patch_desc_addr: - # load patch_desc address in t0 - - # the 5 following instructions are placeholders for the correct ones which are - # overwritten in machine language by create_load_uint64t_into_t0() - .space 20, 0 - #lui t0, 0x00000 - #addi t0, t0, 0x000 - #slli t0, t0, 32 - #lui t3, 0x00000 - #addi t3, t3, 0x000 - - # the 9 following instructions load the 64-bit address in t0 - lui t1, 0x7ffff - ori t2, zero, 0x7ff - slli t2, t2, 1 - ori t2, t2, 1 - or t1, t1, t2 - slli t1, t1, 1 - ori t1, t1, 1 - and t3, t3, t1 - or t0, t0, t3 - - sd t0, 8(sp) # patch_desc pointer on stack - intercept_asm_wrapper_wrapper_level1_addr: - # load intercept_wrapper address in t0 - - # the 5 following instructions are placeholders for the correct ones which are - # written in machine language in create_load_uint64t_into_t0() in patcher.c - .space 20, 0 - #lui t0, 0x00000 - #ori t0, t0, 0x000 - #slli t0, t0, 32 - #lui t3, 0x00000 - #ori t3, t3, 0x000 - - # the 9 following instructions load the 64-bit address in t0 - lui t1, 0x7ffff - ori t2, zero, 0x7ff - slli t2, t2, 1 - ori t2, t2, 1 - or t1, t1, t2 - slli t1, t1, 1 - ori t1, t1, 1 - and t3, t3, t1 - or t0, t0, t3 - - # calling intercept_wrapper - jalr ra, t0, 0 - - - # The intercept_wrapper function did restore all registers to their - # original state, except for a0, sp and t6. - # - # If t6 is zero, a0 contains a syscall number, and that syscall - # is executed here. - # If t6 is 1, a0 contains the return value of the hooked syscall. - # If t6 is 2, a clone syscall is executed here. - - beqz t6, l2 - li t0, 1 - beq t6, t0, restore_sp - li t0, 2 - beq t6, t0, l1 - - li a7, 94 # exit_group if t6 contains an invalid value, namely different from - ecall # 0, 1 or 2 - - l1: - mv a7, a0 - ecall - li t5, 1 # choose intercept_routine_post_clone - li s0, 1 # flag to signal we cloned, restoring sp will require adding 64 - j l0 - l2: - mv a7, a0 - ecall - restore_sp: - beqz s0, l5 - addi sp, sp, 32 - l5: - ld ra, 16(sp) - ld s0, 24(sp) - addi sp, sp, 32 - - intercept_asm_wrapper_tmpl_end: - # This template must be appended here with a - # jump back to the intercepted code. - - # following_ins # !can't use ra as operand! need to check after disassembly - # jalr zero, ra, 0 diff --git a/src/intercept_wrapper.S b/src/intercept_wrapper.S deleted file mode 100644 index 8db7990..0000000 --- a/src/intercept_wrapper.S +++ /dev/null @@ -1,161 +0,0 @@ -# -# Copyright 2016-2024, Intel Corporation -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# -# * Neither the name of the copyright holder nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - - # intercept_wrapper.s -- see asm_wrapper.md - - # the function in this file - .globl intercept_wrapper - # .local intercept_wrapper # again, how to translate .hidden from x86_64? - .type intercept_wrapper, @function - - # the C function in intercept.c - .globl intercept_routine - # .local intercept_routine - .type intercept_routine, @function - - # the other C function in intercept.c, called right after cloning a thread - .globl intercept_routine_post_clone - # .local intercept_routine_post_clone - .type intercept_routine_post_clone, @function - - .text - - intercept_wrapper: - # Decreasing sp to allocate needed space to save caller-saved registers but - # t5 and t6 which are already clobbered, original sp value around the ecall - # and patch_desc pointer - addi sp, sp, -288 - # Saving temporary and function arguments registers, which are both - # caller-saved onto the stack - sd ra, 0(sp) - sd t0, 8(sp) - sd t1, 16(sp) - sd t2, 24(sp) - sd t3, 32(sp) - sd t4, 40(sp) - - # fetching original value of sp - ld t6, 288(sp) - sd t6, 48(sp) - - # fetching pointer to patch_desc - ld t6, 296(sp) - sd t6, 56(sp) - - sd a0, 64(sp) - sd a1, 72(sp) - sd a2, 80(sp) - sd a3, 88(sp) - sd a4, 96(sp) - sd a5, 104(sp) - sd a6, 112(sp) - sd a7, 120(sp) - fsd ft0, 128(sp) - fsd ft1, 136(sp) - fsd ft2, 144(sp) - fsd ft3, 152(sp) - fsd ft4, 160(sp) - fsd ft5, 168(sp) - fsd ft6, 176(sp) - fsd ft7, 184(sp) - fsd ft8, 192(sp) - fsd ft9, 200(sp) - fsd ft10, 208(sp) - fsd ft11, 216(sp) - fsd fa0, 224(sp) - fsd fa1, 232(sp) - fsd fa2, 240(sp) - fsd fa3, 248(sp) - fsd fa4, 256(sp) - fsd fa5, 264(sp) - fsd fa6, 272(sp) - fsd fa7, 280(sp) - - # argument passed to intercept_routine - mv a0, sp - - li t0, 1 - beq t5, t0, l0 # which function should be called? - - jal intercept_routine - j l1 - l0: - jal intercept_routine_post_clone - l1: - - # At this point, the return value of the C - # function (a struct wrapper_ret instance) is in a0, a1. - # - # This function doesn't use these values for anything, just - # forwards them to the higher level wrapper function, generated - # from the template. - - mv t6, a1 - - # Restoring temporary and funcion arguments registers - ld ra, 0(sp) - ld t0, 8(sp) - ld t1, 16(sp) - ld t2, 24(sp) - ld t3, 32(sp) - ld t4, 40(sp) - # no point in restoring in context values at 48(sp), 56(sp) and 64(sp) - ld a1, 72(sp) - ld a2, 80(sp) - ld a3, 88(sp) - ld a4, 96(sp) - ld a5, 104(sp) - ld a6, 112(sp) - ld a7, 120(sp) - fld ft0, 128(sp) - fld ft1, 136(sp) - fld ft2, 144(sp) - fld ft3, 152(sp) - fld ft4, 160(sp) - fld ft5, 168(sp) - fld ft6, 176(sp) - fld ft7, 184(sp) - fld ft8, 192(sp) - fld ft9, 200(sp) - fld ft10, 208(sp) - fld ft11, 216(sp) - fld fa0, 224(sp) - fld fa1, 232(sp) - fld fa2, 240(sp) - fld fa3, 248(sp) - fld fa4, 256(sp) - fld fa5, 264(sp) - fld fa6, 272(sp) - fld fa7, 280(sp) - # Increasing sp to its original value - addi sp, sp, 288 - ret diff --git a/src/util.S b/src/util.S deleted file mode 100644 index 22020ec..0000000 --- a/src/util.S +++ /dev/null @@ -1,67 +0,0 @@ -# -# Copyright 2016-2024, Intel Corporation -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# -# * Neither the name of the copyright holder nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -.globl has_ymm_registers -# .local has_ymm_registers # what does .hidden mean in x86_64? -.type has_ymm_registers, @function - -.globl syscall_no_intercept; -.type syscall_no_intercept, @function - -.text - -has_ymm_registers: - # .cfi_startproc - # pushq %rbx - # movq $0x1, %rax - # cpuid - # movq %rcx, %rax - # shrq $28, %rax - # andq $1, %rax - # popq %rbx - # retq - # .cfi_endproc -.size has_ymm_registers, .-has_ymm_registers - -syscall_no_intercept: - # converting from RISC-V calling conventions to RISC-V Linux calling conventions - mv a7, a0 - mv a0, a1 - mv a1, a2 - mv a2, a3 - mv a3, a4 - mv a4, a5 - mv a5, a6 - ecall - ret - -.size syscall_no_intercept, .-syscall_no_intercept From 2fa201b447d46af4ee42e7a35143d0168067d96b Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sat, 4 Jan 2025 21:45:27 +0100 Subject: [PATCH 030/143] temporary registers are now saved and restored as expected by libc --- src/arch/riscv/intercept_template.S | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/arch/riscv/intercept_template.S b/src/arch/riscv/intercept_template.S index 7166aa3..d4d2dc6 100644 --- a/src/arch/riscv/intercept_template.S +++ b/src/arch/riscv/intercept_template.S @@ -56,10 +56,14 @@ l0: l3: ld t6, 0(sp) # we cloned, so save actual original sp l4: - addi sp, sp, -32 # allocate stack for some locals + addi sp, sp, -64 # allocate stack for some locals sd t6, 0(sp) # original sp on stack sd ra, 16(sp) # patch->return_address on stack sd s0, 24(sp) # follows conventions by saving s0 on stack since we use it + sd t0, 32(sp) + sd t1, 40(sp) + sd t2, 48(sp) + sd t3, 56(sp) bnez t5, intercept_asm_wrapper_patch_desc_addr li s0, 0 # s0 as flag: 1 if we are going for post_clone, 0 otherwise intercept_asm_wrapper_patch_desc_addr: @@ -134,24 +138,28 @@ intercept_asm_wrapper_wrapper_level1_addr: li t0, 2 beq t6, t0, l1 - li a7, 94 /* exit_group if t6 contains an invalid value, namely different from */ - ecall /* 0, 1 or 2 */ + li a7, 94 /* exit_group if t6 contains an invalid value, */ + ecall /* namely different from 0, 1 or 2 */ l1: mv a7, a0 ecall li t5, 1 /* choose intercept_routine_post_clone */ - li s0, 1 /* flag to signal we cloned, restoring sp will require adding 64 */ + li s0, 1 /* flag to signal we cloned, restoring sp will require adding 128 */ j l0 l2: mv a7, a0 ecall restore_sp: beqz s0, l5 - addi sp, sp, 32 + addi sp, sp, 64 l5: ld ra, 16(sp) ld s0, 24(sp) - addi sp, sp, 32 + ld t0, 32(sp) + ld t1, 40(sp) + ld t2, 48(sp) + ld t3, 56(sp) + addi sp, sp, 64 intercept_asm_wrapper_tmpl_end: /* @@ -161,5 +169,5 @@ intercept_asm_wrapper_tmpl_end: /* * following_ins # !can't use ra as operand! need to check after disassembly - * jalr zero, ra, 0 + * create_absolute_jump(*dst, patch->return_address) */ From 02eb5fb694ea5e45f074e430f93619ab2b6d6534 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 9 Jan 2025 19:07:12 +0100 Subject: [PATCH 031/143] t5 is now correctly preserved across the interception --- src/arch/riscv/intercept_template.S | 5 ++++- src/intercept.c | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/arch/riscv/intercept_template.S b/src/arch/riscv/intercept_template.S index d4d2dc6..3dab6b0 100644 --- a/src/arch/riscv/intercept_template.S +++ b/src/arch/riscv/intercept_template.S @@ -48,6 +48,8 @@ * preceding_ins */ intercept_asm_wrapper_tmpl: + addi sp, sp -8 + sd t5, 0(sp) li t5, 0 # choose intercept_routine l0: bnez t5, l3 @@ -159,7 +161,8 @@ l5: ld t1, 40(sp) ld t2, 48(sp) ld t3, 56(sp) - addi sp, sp, 64 + ld t5, 64(sp) # t5 was saved at what currently can be accessed with 64(sp) + addi sp, sp, 72 intercept_asm_wrapper_tmpl_end: /* diff --git a/src/intercept.c b/src/intercept.c index 6198824..a87a192 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -659,7 +659,7 @@ intercept_routine(struct context *context) * that serves as the stack space of a new child thread. * If this is zero, the child thread uses the same address * as stack pointer as the parent does (e.g.: a copy of - * of the memory area after fork). + * the memory area after fork). * * The code at clone_wrapper only returns to this routine * in the parent thread. In the child thread, it calls From 951a8d878dadcf601cf3df96913f5040e314e1c1 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sat, 11 Jan 2025 14:09:08 +0100 Subject: [PATCH 032/143] Use of in following instruction is no more forbidding, added C.JR case, typo fix --- src/arch/riscv/disasm_wrapper.c | 29 +++++++++++++++-------------- src/arch/riscv/intercept_template.S | 2 +- src/patcher.c | 21 ++++++++++----------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/arch/riscv/disasm_wrapper.c b/src/arch/riscv/disasm_wrapper.c index f940a77..5ae0ccc 100644 --- a/src/arch/riscv/disasm_wrapper.c +++ b/src/arch/riscv/disasm_wrapper.c @@ -90,6 +90,7 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, result.has_ip_relative_opr = true; break; case RISCV_INS_JALR: + case RISCV_INS_C_JR: case RISCV_INS_C_JALR: result.is_jump = true; break; @@ -98,20 +99,20 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, result.has_ip_relative_opr = false; result.uses_ra = false; cs_riscv_op *op; - for (uint8_t op_i = 0; !result.uses_ra && - op_i < context->insn->detail->riscv.op_count; ++op_i) { - op = context->insn->detail->riscv.operands + op_i; - switch (op->type) { - case RISCV_OP_REG: - result.uses_ra = op->reg == RISCV_REG_RA; - break; - case RISCV_OP_MEM: - result.uses_ra = op->mem.base == RISCV_REG_RA; - break; - default: - break; - } - } +// for (uint8_t op_i = 0; !result.uses_ra && +// op_i < context->insn->detail->riscv.op_count; ++op_i) { +// op = context->insn->detail->riscv.operands + op_i; +// switch (op->type) { +// case RISCV_OP_REG: +// result.uses_ra = op->reg == RISCV_REG_RA; +// break; +// case RISCV_OP_MEM: +// result.uses_ra = op->mem.base == RISCV_REG_RA; +// break; +// default: +// break; +// } +// } result.uses_t6 = false; for (uint8_t op_i = 0; !result.uses_t6 && op_i < context->insn->detail->riscv.op_count; ++op_i) { diff --git a/src/arch/riscv/intercept_template.S b/src/arch/riscv/intercept_template.S index 3dab6b0..dea78cd 100644 --- a/src/arch/riscv/intercept_template.S +++ b/src/arch/riscv/intercept_template.S @@ -48,7 +48,7 @@ * preceding_ins */ intercept_asm_wrapper_tmpl: - addi sp, sp -8 + addi sp, sp, -8 sd t5, 0(sp) li t5, 0 # choose intercept_routine l0: diff --git a/src/patcher.c b/src/patcher.c index e651d91..1db4376 100644 --- a/src/patcher.c +++ b/src/patcher.c @@ -219,8 +219,7 @@ is_copiable_after_syscall(struct intercept_disasm_result ins) ins.is_jump || ins.is_endbr || ins.is_syscall || - ins.uses_t6 || - ins.uses_ra); + ins.uses_t6); } @@ -719,15 +718,15 @@ activate_patches(struct intercept_desc *desc) /* jump - escape the text segment */ create_j(patch->dst_jmp_patch, desc->next_trampoline); - // /* - // * if patch is 10 bytes long, fill the last two - // * with c.nop instruction. Template will return there, - // * c.nop will make advance PC and .so execution will - // * normally take back control - // */ - // if (patch->padding_is_needed) { - // *(uint16_t *)patch->return_address = 0x0001; // c.nop - // } + /* + * if patch is 10 bytes long, fill the last two + * with c.ebreak instruction. Template will jump back to the + * return address so c.ebreak will never be executed as long + * as the patching correctly the return jump from template. + */ + if (patch->padding_is_needed) { + *(uint16_t *)(patch->return_address-2) = 0x8002; // c.ebreak + } /* jump - escape the 2 GB range of the text segment */ desc->next_trampoline = create_absolute_jump( From ca2581ab3ff6af04caac9249b0afbb85a6f471dd Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Mon, 3 Feb 2025 17:09:47 +0100 Subject: [PATCH 033/143] Library is now architecture independent. It works on both x86_64 and RISC-V --- CMakeLists.txt | 7 +- src/arch/riscv/disasm_wrapper.c | 14 - src/arch/riscv/patcher.c | 753 +++++++++++++++++++++++++++++++ src/arch/x86_64/patcher.c | 767 ++++++++++++++++++++++++++++++++ src/intercept.c | 100 +++-- src/intercept.h | 54 ++- src/intercept_desc.c | 21 +- src/intercept_log.c | 7 +- src/patcher.c | 18 +- 9 files changed, 1662 insertions(+), 79 deletions(-) create mode 100644 src/arch/riscv/patcher.c create mode 100644 src/arch/x86_64/patcher.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c710b0..f99726f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,13 +74,14 @@ set(SOURCES_C src/intercept_desc.c src/intercept_log.c src/intercept_util.c - src/patcher.c +# src/patcher.c src/magic_syscalls.c src/syscall_formats.c) if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86(_64)?)$") set(SOURCES_C "${SOURCES_C}" - src/arch/x86_64/disasm_wrapper.c) + src/arch/x86_64/disasm_wrapper.c + src/arch/x86_64/patcher.c) set(SOURCES_ASM src/arch/x86_64/intercept_template.S @@ -90,7 +91,7 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86(_64)?)$") elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv(32|64))$") set(SOURCES_C "${SOURCES_C}" src/arch/riscv/disasm_wrapper.c - ) + src/arch/riscv/patcher.c) set(SOURCES_ASM src/arch/riscv/intercept_template.S diff --git a/src/arch/riscv/disasm_wrapper.c b/src/arch/riscv/disasm_wrapper.c index 5ae0ccc..43c8c72 100644 --- a/src/arch/riscv/disasm_wrapper.c +++ b/src/arch/riscv/disasm_wrapper.c @@ -99,20 +99,6 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, result.has_ip_relative_opr = false; result.uses_ra = false; cs_riscv_op *op; -// for (uint8_t op_i = 0; !result.uses_ra && -// op_i < context->insn->detail->riscv.op_count; ++op_i) { -// op = context->insn->detail->riscv.operands + op_i; -// switch (op->type) { -// case RISCV_OP_REG: -// result.uses_ra = op->reg == RISCV_REG_RA; -// break; -// case RISCV_OP_MEM: -// result.uses_ra = op->mem.base == RISCV_REG_RA; -// break; -// default: -// break; -// } -// } result.uses_t6 = false; for (uint8_t op_i = 0; !result.uses_t6 && op_i < context->insn->detail->riscv.op_count; ++op_i) { diff --git a/src/arch/riscv/patcher.c b/src/arch/riscv/patcher.c new file mode 100644 index 0000000..1723071 --- /dev/null +++ b/src/arch/riscv/patcher.c @@ -0,0 +1,753 @@ +/* + * Copyright 2016-2020, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * patcher.c -- patching a library + * + * Jumping from the subject library: + * + * /--------------------------\ + * | subject.so | + * | | + * | jmp to_trampoline_table | patched by activate_patches() + * /->| | | + * | \___|______________________/ + * | | + * | /---|--------------------------\ + * | | movabs %r11, wrapper_address | jmp generated by activate_patches() + * | | jmp *%r11 | This allows subject.so and + * | | | | libsyscall_intercept.so to be farther + * | \___|__________________________/ than 2 gigabytes from each other + * | | + * | /---|-----------------------------\ + * | | | libsyscall_intercept.so | + * | | | | + * | | /-|--------------------------\ | + * | | | | static unsigned char | | + * | | | | asm_wrapper_space[] | | + * | | | | in BSS | | wrapper routine + * | | | | | | generated into asm_wrapper_space + * | | | | | | by create_wrapper() + * | | |wrapper routine | | + * | | |calls C hook function ----------> intercept_routine in intercept.c + * | | |movabs %r11, return_address | | + * | | |jmp *%r11 | | + * | | \_|__________________________/ | + * | \___|_____________________________/ + * | | + * \______/ + * + */ + +#include "../../intercept.h" +#include "../../intercept_util.h" +#include "../../intercept_log.h" + +#include +#include +#include +#include +#include + +#include +#include + +#define COMPAT_HWCAP_ISA_C (1 << ('C' - 'A')) + +/* The size of a trampoline jump, 64-bit address loading process into a register + * (which requires 14 instructions to encode directly in machine code) + JALR. + * These are preceded and succeeded by storing and restoring of tmp registers + * used for the creation of the absolute jump. We can't clobber them since two + * instructions that were placed before the original ecall still must be + * executed. + */ +// enum { TRAMPOLINE_SIZE = 23 * 4 }; + +static void create_wrapper(struct patch_desc *patch, unsigned char **dst); +static void create_load_uint64t_into_t0(uint8_t *code, uint64_t value); +static void create_load_uint64t_into_t6(uint8_t *code, uint64_t value); + +/* + * create_absolute_jump(from, to) + * + */ +static unsigned char * +create_absolute_jump(unsigned char *from, void *to) +{ + uint32_t *instructions = (uint32_t *)from; + instructions[0] = 0xfe010113; // addi sp, sp, -32 + instructions[1] = 0x00613023; // sd t1, 0(sp) + instructions[2] = 0x00713423; // sd t2, 8(sp) + instructions[3] = 0x01c13823; // sd t3, 16(sp) + instructions[9] = 0x7ffff337; // lui t1, 0x7ffff + instructions[10] = 0x7ff06393; // ori t2, zero, 0x7ff + instructions[11] = 0x00139393; // slli t2, t2, 1 + instructions[12] = 0x0013e393; // ori t2, t2, 1 + instructions[13] = 0x00736333; // or t1, t1, t2 + instructions[14] = 0x00131313; // slli t1, t1, 1 + instructions[15] = 0x00136313; // ori t1, t1, 1 + instructions[16] = 0x006e7e33; // and t3, t3, t1 + instructions[17] = 0x01cfefb3; // or t6, t6, t3 + instructions[18] = 0x00013303; // ld t1, 0(sp) + instructions[19] = 0x00813383; // ld t2, 8(sp) + instructions[20] = 0x01013e03; // ld t3, 16(sp) + instructions[21] = 0x02010113; // addi sp, sp, 32 + instructions[22] = 0x000f8067; // jalr zero, t6, 0 + create_load_uint64t_into_t6((uint8_t *)(instructions + 4),(uint64_t)to); // writes 5 instructions starting from instructions[4] + return (unsigned char *)(instructions + 23); +} + +/* + * create_jump(opcode, from, to) + * Create a 5 byte jmp/call instruction jumping to address to, by overwriting + * code starting at address from. + */ +void +create_jump(unsigned char opcode, unsigned char *from, void *to) +{ + /* + * The operand is the difference between the + * instruction pointer pointing to the instruction + * just after the call, and the to address. + * Thus RIP seen by the call instruction is from + 5 + */ + ptrdiff_t delta = ((unsigned char *)to) - (from + JUMP_INS_SIZE); + + if (delta > ((ptrdiff_t)INT32_MAX) || delta < ((ptrdiff_t)INT32_MIN)) + xabort("create_jump distance check"); + + int32_t delta32 = (int32_t)delta; + unsigned char *d = (unsigned char *)&delta32; + + from[0] = opcode; + from[1] = d[0]; + from[2] = d[1]; + from[3] = d[2]; + from[4] = d[3]; +} + +/* + * check_trampoline_usage - + * Make sure the trampoline table allocated at the beginning of patching has + * enough space for all trampolines. This just aborts the process if the + * allocate space does not seem to be enough, but it can be fairly easy + * to implement more allocation here if such need would arise. + */ +static void +check_trampoline_usage(const struct intercept_desc *desc) +{ + if (!desc->uses_trampoline_table) + return; + + /* + * We might actually not have enough space for creating + * more trampolines. + */ + + size_t used = (size_t)(desc->next_trampoline - desc->trampoline_table); + + if (used + TRAMPOLINE_SIZE >= desc->trampoline_table_size) + xabort("trampoline space not enough"); +} + +/* + * is_copiable_before_syscall + * checks if an instruction found before a syscall instruction + * can be copied (and thus overwritten). + */ +static bool +is_copiable_before_syscall(struct intercept_disasm_result ins) +{ + if (!ins.is_set) + return false; + + return !(ins.has_ip_relative_opr || + ins.is_call || + ins.is_rel_jump || + ins.is_jump || + ins.is_ret || + ins.is_endbr || + ins.is_syscall || + ins.uses_t6); +} + +/* + * is_copiable_after_syscall + * checks if an instruction found after a syscall instruction + * can be copied (and thus overwritten). + * + * Notice: we allow the copy of ret instructions. + */ +static bool +is_copiable_after_syscall(struct intercept_disasm_result ins) +{ + if (!ins.is_set) + return false; + + return !(ins.has_ip_relative_opr || + ins.is_call || + ins.is_rel_jump || + ins.is_jump || + ins.is_endbr || + ins.is_syscall || + ins.uses_t6); +} + + +/* + * check_surrounding_instructions + * Sets up the following members in a patch_desc, based on + * instruction being relocatable or not: + * uses_prev_ins ; uses_prev_ins_2 ; uses_next_ins + */ +static void +check_surrounding_instructions(struct intercept_desc *desc, + struct patch_desc *patch) +{ + patch->uses_prev_ins = (is_copiable_before_syscall(patch->preceding_ins) && + !has_jump(desc, patch->syscall_addr)); + + if (patch->uses_prev_ins) { + patch->uses_prev_ins_2 = (patch->uses_prev_ins && + is_copiable_before_syscall(patch->preceding_ins_2) && + !has_jump(desc, patch->syscall_addr - patch->preceding_ins.length)); + } else { + patch->uses_prev_ins_2 = false; + } + + patch->uses_next_ins = (is_copiable_after_syscall(patch->following_ins) && + !has_jump(desc, patch->syscall_addr + SYSCALL_INS_SIZE)); +} + +/* + * create_patch_wrappers - create the custom assembly wrappers + * around each syscall to be intercepted. Well, actually, the + * function create_wrapper does that, so perhaps this function + * deserves a better name. + * What this function actually does, is figure out how to create + * a jump instruction in libc ( which bytes to overwrite ). + * If it successfully finds suitable bytes for hotpatching, + * then it determines the exact bytes to overwrite, and the exact + * address for jumping back to libc. + * + * This is all based on the information collected by the routine + * find_syscalls, which does the disassembling, finding jump destinations, + * finding padding bytes, etc... + */ +void +create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) +{ + short min_treshold = JUMP_INS_SIZE; + bool c_isa_supported = getauxval(AT_HWCAP) & COMPAT_HWCAP_ISA_C; + for (unsigned patch_i = 0; patch_i < desc->count; ++patch_i) { + struct patch_desc *patch = desc->items + patch_i; + debug_dump("patching %s:0x%lx - patch_number: %u\n", desc->path, + patch->syscall_addr - desc->base_addr, patch_i); + + /* + * No padding space is available, so check the + * instructions surrounding the syscall instruction. + * If they can be relocated, then they can be + * overwritten. Of course some instructions depend + * on the value of the RIP register, these can not + * be relocated. + */ + + check_surrounding_instructions(desc, patch); + + /* + * Count the number of overwritable bytes + * in the variable length. + * Sum up the bytes that can be overwritten. + * The 4 bytes of the ecall instruction can + * be overwritten definitely, so length starts + * as SYSCALL_INS_SIZE ( 4 bytes ). + */ + unsigned length = SYSCALL_INS_SIZE; + + patch->needs_compressed_ins = false; + patch->padding_is_needed = false; + patch->dst_jmp_patch = patch->syscall_addr; + + /* + * If the preceding instruction is relocatable, + * add its length. Also, the instruction right + * before that. + */ + if (patch->uses_prev_ins) { + length += patch->preceding_ins.length; + patch->dst_jmp_patch -= + patch->preceding_ins.length; + + if (patch->uses_prev_ins_2 && (length < JUMP_INS_SIZE)) { + length += patch->preceding_ins_2.length; + patch->dst_jmp_patch -= + patch->preceding_ins_2.length; + } else { + /* + * If it could be used but is not necessary we need + * to set the flag to false so that it's not relocated + */ + patch->uses_prev_ins_2 = false; + } + } + + /* + * If the following instruction is relocatable, + * add its length. This also affects the return address. + * Normally, the library would return to libc after + * handling the syscall by jumping to instruction + * right after the syscall. But if that instruction + * is overwritten, the returning jump must jump to + * the instruction after it. + */ + if (patch->uses_next_ins && (length < JUMP_INS_SIZE)) { + length += patch->following_ins.length; + + /* + * Address of the syscall instruction + * plus 4 bytes + * plus the length of the following instruction + * + * adds up to: + * + * the address of the second instruction after + * the syscall. + */ + patch->return_address = patch->syscall_addr + + SYSCALL_INS_SIZE + + patch->following_ins.length; + } else { + /* + * If it could be used but is not necessary we need + * to set the flag to false so that it's not relocated + */ + patch->uses_next_ins = false; + patch->return_address = patch->syscall_addr + SYSCALL_INS_SIZE; + } + + if (length > JUMP_INS_SIZE) { + patch->padding_is_needed = true; + // patch->return_address -= (length - JUMP_INS_SIZE); + } + + /* + * Check if compressed instructions module is supported by the CPU. + * If yes, 6 bytes are enough to place an auipc+c.jalr sequence. + * If the length of the patch is exactly 6 bytes, then we assert + * the flag marking the need of said sequence. + * + * If length is less than minimum needed bytes (value depending on + * ISA C module being supported or not), give up. + * + * TO DO: creating an environment variable marking if all ECALLs + * must be patchable for success or if we could just skip the + * unpatchable ones. + */ + if (c_isa_supported) { + if (length == 6) { + patch->needs_compressed_ins = true; + } + min_treshold = 6; + } + if (length < min_treshold) { + char buffer[0x1000]; + + int l = snprintf(buffer, sizeof(buffer), + "unintercepted syscall at: %s 0x%lx\n", + desc->path, + patch->syscall_offset); + + intercept_log(buffer, (size_t)l); + debug_dump("unintercepted syscall at: %s 0x%lx\n", + desc->path, + patch->syscall_offset); + xabort("not enough space for patching" + " around syscal"); + } + + mark_jump(desc, patch->return_address); + + create_wrapper(patch, dst); + } +} + +/* + * Referencing symbols defined in intercept_template.s + */ +extern unsigned char intercept_asm_wrapper_tmpl[]; +extern unsigned char intercept_asm_wrapper_tmpl_end; +extern unsigned char intercept_asm_wrapper_patch_desc_addr; +extern unsigned char intercept_asm_wrapper_wrapper_level1_addr; +extern unsigned char intercept_wrapper; + +size_t asm_wrapper_tmpl_size; +static ptrdiff_t o_patch_desc_addr; +static ptrdiff_t o_wrapper_level1_addr; + +bool intercept_routine_must_save_ymm = false; // temporarily hardcoded + +/* + * init_patcher + * Some variables need to be initialized before patching. + * This routine must be called once before patching any library. + */ +void +init_patcher(void) +{ + unsigned char *begin = &intercept_asm_wrapper_tmpl[0]; + + assert(&intercept_asm_wrapper_tmpl_end > begin); + assert(&intercept_asm_wrapper_patch_desc_addr > begin); + assert(&intercept_asm_wrapper_wrapper_level1_addr > begin); + assert(&intercept_asm_wrapper_patch_desc_addr < + &intercept_asm_wrapper_tmpl_end); + assert(&intercept_asm_wrapper_wrapper_level1_addr < + &intercept_asm_wrapper_tmpl_end); + + asm_wrapper_tmpl_size = + (size_t)(&intercept_asm_wrapper_tmpl_end - begin); + o_patch_desc_addr = &intercept_asm_wrapper_patch_desc_addr - begin; + o_wrapper_level1_addr = + &intercept_asm_wrapper_wrapper_level1_addr - begin; +} + + +/* + * create_ret_from_template + * Write a RET instruction (encoded as JALR) to return to patch->return_address. + * This is possible as long patch->return_address is saved to ra in the first + * place when jumping to trampoline when intercepting the system call. This is + * not explicitly written at the end of intercept_template.S since the fourth + * overwritten instruction has to be relocated before RET. + */ +static unsigned char * +create_ret_from_template(unsigned char *code) +{ + *((uint32_t *)code) = 0x00008067; // jalr zero, ra, 0 + return code + 4; +} + +/* + * create_load_uint64t_into_t0 + * Generates the first 5 instructions (LUI,ADDI,SLLI,LUI,ADDI) of a convoluted + * 14 instructions sequence that assign a 64 bit constant to a register. + * See intercept_template.S for the following 9 at + * intercept_asm_wrapper_patch_desc_addr (an equal sequence is placed at + * intercept_asm_wrapper_wrapper_level1_addr as well). + */ +static void +create_load_uint64t_into_t0(uint8_t *code, uint64_t value) +{ + + uint32_t *instructions = (uint32_t *)code; + uint32_t upper_32 = (value & 0xffffffff00000000) >> 32; + uint32_t lower_32 = (uint32_t)value; + + uint32_t lui_imm_field = upper_32 & 0xfffff000; + uint32_t addi_imm_field = 0; + if (upper_32 % 4096 != 0) { + addi_imm_field = upper_32 - lui_imm_field; + if (addi_imm_field > 2047) { + lui_imm_field += 4096; + addi_imm_field = -(4096 - addi_imm_field); + } + } + + instructions[0] = 0x000002b7 | lui_imm_field; // lui t0, 0x..... + instructions[1] = 0x00028293 | (addi_imm_field << 20); // addi t0, t0, 0x... + instructions[2] = 0x02029293; // slli t0, t0, 32 + + lui_imm_field = lower_32 & 0xfffff000; + addi_imm_field = 0; + if (lower_32 % 4096 != 0) { + addi_imm_field = lower_32 - lui_imm_field; + if (addi_imm_field > 2047) { + lui_imm_field += 4096; + addi_imm_field = -(4096 - addi_imm_field); + } + } + + instructions[3] = 0x00000e37 | lui_imm_field; // lui t3, 0x..... + instructions[4] = 0x000e0e13 | (addi_imm_field << 20); // addi t3, t3, 0x... +} + +static void +create_load_uint64t_into_t6(uint8_t *code, uint64_t value) +{ + + uint32_t *instructions = (uint32_t *)code; + uint32_t upper_32 = (value & 0xffffffff00000000) >> 32; + uint32_t lower_32 = (uint32_t)value; + + uint32_t lui_imm_field = upper_32 & 0xfffff000; + uint32_t addi_imm_field = 0; + if (upper_32 % 4096 != 0) { + addi_imm_field = upper_32 - lui_imm_field; + if (addi_imm_field > 2047) { + lui_imm_field += 4096; + addi_imm_field = -(4096 - addi_imm_field); + } + } + + instructions[0] = 0x00000fb7 | lui_imm_field; // lui t6, 0x..... + instructions[1] = 0x000f8f93 | (addi_imm_field << 20); // addi t6, t6, 0x... + instructions[2] = 0x020f9f93; // slli t6, t6, 32 + + lui_imm_field = lower_32 & 0xfffff000; + addi_imm_field = 0; + if (lower_32 % 4096 != 0) { + addi_imm_field = lower_32 - lui_imm_field; + if (addi_imm_field > 2047) { + lui_imm_field += 4096; + addi_imm_field = -(4096 - addi_imm_field); + } + } + + instructions[3] = 0x00000e37 | lui_imm_field; // lui t3, 0x..... + instructions[4] = 0x000e0e13 | (addi_imm_field << 20); // addi t3, t3, 0x... +} + +/* + * relocate_instruction + * Places an instruction equivalent to `ins` to the memory location at `dst`. + * Only handles instructions that can be copied verbatim, and some LEA + * instructions. + */ +static unsigned char * +relocate_instruction(unsigned char *dst, + const struct intercept_disasm_result *ins) +{ + memcpy(dst, ins->address, ins->length); + return dst + ins->length; +} + +/* + * create_wrapper + * Generates an assembly wrapper. Copies the template written in + * intercept_template.s, and generates the instructions specific + * to a particular syscall into the new copy. + * After this wrapper is created, a syscall can be replaced with a + * jump to this wrapper, and wrapper is going to call dest_routine + * (actually only after a call to mprotect_asm_wrappers). + */ +static void +create_wrapper(struct patch_desc *patch, unsigned char **dst) +{ + /* Create a new copy of the template */ + patch->asm_wrapper = *dst; + + /* Copy the previous instruction(s) */ + if (patch->uses_prev_ins) { + if (patch->uses_prev_ins_2) { + *dst = relocate_instruction(*dst, &patch->preceding_ins_2); + } + *dst = relocate_instruction(*dst, &patch->preceding_ins); + } + + memcpy(*dst, intercept_asm_wrapper_tmpl, asm_wrapper_tmpl_size); + create_load_uint64t_into_t0(*dst + o_patch_desc_addr, (uintptr_t)patch); // why the uintptr_t cast? What if the address is not representable on 32 bit? + create_load_uint64t_into_t0(*dst + o_wrapper_level1_addr, + (uintptr_t)&intercept_wrapper); + *dst += asm_wrapper_tmpl_size; + + /* Copy the following instruction */ + if (patch->uses_next_ins) + *dst = relocate_instruction(*dst, &patch->following_ins); + + *dst = create_absolute_jump(*dst, patch->return_address); + // *dst = create_ret_from_template(*dst); +} + +/* + * create_j(from, to) + * Create a 4 byte JAL instruction jumping to address to, by overwriting + * code starting at address from, if trampoline displacement is within + or - + * 1 MiB. Otherwise, create a 2 instructions sequence (LUI + JALR) which allows + * to reach trampoline if its displacement is within -2 GiB or JALR_MAX_OFFSET, + * which is (+2 GiB - 2050 Bytes). + */ +void +create_j(unsigned char *from, void *to) +{ + /* + * The operand is the difference between the + * instruction pointer pointing to the instruction + * just after the call, and the to address. + */ + ptrdiff_t delta = ((unsigned char *)to) - from; + uint32_t *instructions = (uint32_t *)from; + debug_dump("%p: ecall -> jalr %ld\t# %p\n", from, delta, to); + + const ptrdiff_t JALR_MAX_OFFSET = 2147481598; // ((2^31-1)-4095)+(2^11-1) = 0x7ffff000 + 0x7ff + const ptrdiff_t JALR_MIN_OFFSET = -2147483648; // (-2^31) = -0x80000000 + + if ((delta & 0x1) != 0) { + + xabort("create_j misaligned instruction fetch exception"); + + } + if (delta <= JALR_MAX_OFFSET && delta >= JALR_MIN_OFFSET) { + + uint32_t auipc = 0x00000f97; // auipc t6, 0x..... + uint32_t jalr = 0x000f8067; // jalr zero, t6, 0x... + uint32_t jalr_imm_field = 0; + uint32_t auipc_imm_field = (uint32_t)delta & 0xfffff000; // offset[31:12] + + /* + * if the offset is not a multiple of 4096 the 12 least significant bits + * of its value must be set by adding the correct immediate value contained + * in jalr imm field to the rs1 value which is set by auipc instruction + * preceding jalr + */ + if ((uint32_t)delta % 4096 != 0) { + jalr_imm_field = (uint32_t)delta - auipc_imm_field; + if (jalr_imm_field > 2046) { + auipc_imm_field += 4096; + jalr_imm_field = -(4096 - jalr_imm_field); + } + } + auipc |= auipc_imm_field; + jalr |= (jalr_imm_field << 20); + instructions[0] = auipc; // auipc t6, 0x..... + instructions[1] = jalr; // jalr zero, t6, 0x... + } else { + xabort("create_j distance check"); + } +} + +void +create_c_j(unsigned char *from, void *to) { + ptrdiff_t delta = ((unsigned char *)to) - from; + debug_dump("%p: ecall -> c.jalr %ld\t# %p\n", from, delta, to); + const ptrdiff_t AUIPC_MAX_OFFSET = 2147479552; + const ptrdiff_t AUIPC_MIN_OFFSET = -2147483648; + if ((delta & 0xfff) != 0) { + xabort("create_c_j misaligned instruction fetch exception"); + } + if (delta >= AUIPC_MIN_OFFSET && delta <= AUIPC_MAX_OFFSET) { + uint32_t auipc = 0x00000f97; // auipc t6, 0x..... + uint16_t c_jr = 0x8f82; // c.jr t6 + uint32_t auipc_imm_field = (uint32_t)delta & 0xfffff000; // offset[31:12] + auipc |= auipc_imm_field; + *(uint32_t *)from = auipc; + *(uint16_t *)(from + 4) = c_jr; + } else { + xabort("create_c_j distance check"); + } + +} + +/* + * activate_patches() + * Loop over all the patches, and overwrite each syscall. + */ +void +activate_patches(struct intercept_desc *desc) +{ + unsigned char *first_page; + size_t size; + + if (desc->count == 0) + return; + + first_page = round_down_address(desc->text_start); + size = (size_t)(desc->text_end - first_page); + + mprotect_no_intercept(first_page, size, + PROT_READ | PROT_WRITE | PROT_EXEC, + "mprotect PROT_READ | PROT_WRITE | PROT_EXEC"); + + for (unsigned i = 0; i < desc->count; ++i) { + const struct patch_desc *patch = desc->items + i; + debug_dump("\nactivating patch at dst_jmp_patch: 0x%lx - patch->return_address: 0x%lx - patch_n:%u\n" + "patch_absolute_return_address: %p\n", + patch->dst_jmp_patch-desc->base_addr,patch->return_address-desc->base_addr,i,patch->return_address); + + if (patch->dst_jmp_patch < desc->text_start || + patch->dst_jmp_patch > desc->text_end) + xabort("dst_jmp_patch outside text"); + + /* + * The dst_jmp_patch pointer contains the address where + * the actual jump instruction escaping the patched text + * segment should be written. + * This is either at the place of the original syscall + * instruction, or at some usable padding space close to + * it (an overwritable NOP instruction). + */ + + if (desc->uses_trampoline_table) { + /* + * First jump to the trampoline table, which + * should be in a 2 gigabyte range. From there, + * jump to the asm_wrapper. + */ + check_trampoline_usage(desc); + if (!patch->needs_compressed_ins) { + + /* jump - escape the text segment */ + create_j(patch->dst_jmp_patch, desc->next_trampoline); + + /* + * if patch is 10 bytes long, fill the last two + * with c.ebreak instruction. Template will jump back to the + * return address so c.ebreak will never be executed as long + * as the patching correctly the return jump from template. + */ + if (patch->padding_is_needed) { + *(uint16_t *)(patch->return_address-2) = 0x8002; // c.ebreak + } + + /* jump - escape the 2 GB range of the text segment */ + desc->next_trampoline = create_absolute_jump( + desc->next_trampoline, patch->asm_wrapper); + } else { + const int rem = (desc->next_trampoline - patch->dst_jmp_patch) % 4096; + if (rem) { + desc->next_trampoline += 4096 - rem; + } + create_c_j(patch->dst_jmp_patch, desc->next_trampoline); + + desc->next_trampoline = create_absolute_jump( + desc->next_trampoline, patch->asm_wrapper); + } + } else { + create_j(patch->dst_jmp_patch, patch->asm_wrapper); + } + + } + + mprotect_no_intercept(first_page, size, + PROT_READ | PROT_EXEC, + "mprotect PROT_READ | PROT_EXEC"); +} diff --git a/src/arch/x86_64/patcher.c b/src/arch/x86_64/patcher.c new file mode 100644 index 0000000..ab9c465 --- /dev/null +++ b/src/arch/x86_64/patcher.c @@ -0,0 +1,767 @@ +/* + * Copyright 2016-2020, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * patcher.c -- patching a library + * + * Jumping from the subject library: + * + * /--------------------------\ + * | subject.so | + * | | + * | jmp to_trampoline_table | patched by activate_patches() + * /->| | | + * | \___|______________________/ + * | | + * | /---|--------------------------\ + * | | movabs %r11, wrapper_address | jmp generated by activate_patches() + * | | jmp *%r11 | This allows subject.so and + * | | | | libsyscall_intercept.so to be farther + * | \___|__________________________/ than 2 gigabytes from each other + * | | + * | /---|-----------------------------\ + * | | | libsyscall_intercept.so | + * | | | | + * | | /-|--------------------------\ | + * | | | | static unsigned char | | + * | | | | asm_wrapper_space[] | | + * | | | | in BSS | | wrapper routine + * | | | | | | generated into asm_wrapper_space + * | | | | | | by create_wrapper() + * | | |wrapper routine | | + * | | |calls C hook function ----------> intercept_routine in intercept.c + * | | |movabs %r11, return_address | | + * | | |jmp *%r11 | | + * | | \_|__________________________/ | + * | \___|_____________________________/ + * | | + * \______/ + * + */ + +#include "../../intercept.h" +#include "../../intercept_util.h" +#include "../../intercept_log.h" + +#include +#include +#include +#include +#include + +#include + +/* The size of a trampoline jump, jmp instruction + pointer */ +//enum { TRAMPOLINE_SIZE = 6 + 8 }; + +static void create_wrapper(struct patch_desc *patch, unsigned char **dst); + +/* + * create_absolute_jump(from, to) + * Create an indirect jump, with the pointer right next to the instruction. + * + * jmp *0(%rip) + * + * This uses up 6 bytes for the jump instruction, and another 8 bytes + * for the pointer right after the instruction. + */ +static unsigned char * +create_absolute_jump(unsigned char *from, void *to) +{ + *from++ = 0xff; /* opcode of RIP based indirect jump */ + *from++ = 0x25; /* opcode of RIP based indirect jump */ + *from++ = 0; /* 32 bit zero offset */ + *from++ = 0; /* this means zero relative to the value */ + *from++ = 0; /* of RIP, which during the execution of the jump */ + *from++ = 0; /* points to right after the jump instruction */ + + unsigned char *d = (unsigned char *)&to; + + *from++ = d[0]; /* so, this is where (RIP + 0) points to, */ + *from++ = d[1]; /* jump reads the destination address */ + *from++ = d[2]; /* from here */ + *from++ = d[3]; + *from++ = d[4]; + *from++ = d[5]; + *from++ = d[6]; + *from++ = d[7]; + + return from; +} + +/* + * create_jump(opcode, from, to) + * Create a 5 byte jmp/call instruction jumping to address to, by overwriting + * code starting at address from. + */ +void +create_jump(unsigned char opcode, unsigned char *from, void *to) +{ + /* + * The operand is the difference between the + * instruction pointer pointing to the instruction + * just after the call, and the to address. + * Thus RIP seen by the call instruction is from + 5 + */ + ptrdiff_t delta = ((unsigned char *)to) - (from + JUMP_INS_SIZE); + + if (delta > ((ptrdiff_t)INT32_MAX) || delta < ((ptrdiff_t)INT32_MIN)) + xabort("create_jump distance check"); + + int32_t delta32 = (int32_t)delta; + unsigned char *d = (unsigned char *)&delta32; + + from[0] = opcode; + from[1] = d[0]; + from[2] = d[1]; + from[3] = d[2]; + from[4] = d[3]; +} + +/* + * check_trampoline_usage - + * Make sure the trampoline table allocated at the beginning of patching has + * enough space for all trampolines. This just aborts the process if the + * allocate space does not seem to be enough, but it can be fairly easy + * to implement more allocation here if such need would arise. + */ +static void +check_trampoline_usage(const struct intercept_desc *desc) +{ + if (!desc->uses_trampoline_table) + return; + + /* + * We might actually not have enough space for creating + * more trampolines. + */ + + size_t used = (size_t)(desc->next_trampoline - desc->trampoline_table); + + if (used + TRAMPOLINE_SIZE >= desc->trampoline_table_size) + xabort("trampoline space not enough"); +} + +/* + * is_nop_in_range - checks if NOP is sufficiently close to address, to be + * reachable by a jmp having a 8 bit displacement. + */ +static bool +is_nop_in_range(unsigned char *address, const struct range *nop) +{ + /* + * Planning to put a 5 byte jump starting at the third byte + * of the nop instruction. The syscall should jump to this + * trampoline jump. + */ + unsigned char *dst = nop->address + 2; + /* + * Planning to put a two byte jump in the place of the syscall + * instruction, that is going to jump relative to the value of + * RIP during execution, which points to the next instruction, + * at address + 2. + */ + unsigned char *src = address + 2; + + /* + * How far can this short jump instruction jump, considering + * the one byte singed displacement? + */ + unsigned char *reach_min = src - 128; + unsigned char *reach_max = src + 127; + + /* + * Can a two byte jump reach the proposed destination? + * I.e.: is dst in the [reach_min, reach_max] range? + */ + return reach_min <= dst && dst <= reach_max; +} + +/* + * assign_nop_trampoline + * Looks for a NOP instruction close to a syscall instruction to be patched. + * The struct patch_desc argument specifies where the particular syscall + * instruction resides, and the struct intercept_desc argument of course + * already contains information about NOPs, collected by the find_syscalls + * routine. + * + * This routine essentially initializes the uses_nop_trampoline and + * the nop_trampoline fields of a struct patch_desc. + */ +static void +assign_nop_trampoline(struct intercept_desc *desc, + struct patch_desc *patch, + size_t *next_nop_i) +{ + struct range *nop = desc->nop_table + *next_nop_i; + + if (*next_nop_i >= desc->nop_count) { + patch->uses_nop_trampoline = false; + return; /* no more nops available */ + } + + /* + * Consider a nop instruction, to use as trampoline, but only + * if a two byte jump in the place of the syscall can jump + * to the proposed trampoline. Check if the nop is: + * 1) at an address too low + * 2) close enough for a two byte jump + * 3) at an address too high + */ + + if (is_nop_in_range(patch->syscall_addr, nop)) { + patch->uses_nop_trampoline = true; + patch->nop_trampoline = *nop; + ++(*next_nop_i); + return; /* found a nop in range to use as trampoline */ + } + + if (nop->address > patch->syscall_addr) { + patch->uses_nop_trampoline = false; + return; /* nop is too far ahead */ + } + + /* nop is too far behind, try the next nop */ + ++(*next_nop_i); + assign_nop_trampoline(desc, patch, next_nop_i); +} + +/* + * is_copiable_before_syscall + * checks if an instruction found before a syscall instruction + * can be copied (and thus overwritten). + */ +static bool +is_copiable_before_syscall(struct intercept_disasm_result ins) +{ + if (!ins.is_set) + return false; + + return !(ins.has_ip_relative_opr || + ins.is_call || + ins.is_rel_jump || + ins.is_jump || + ins.is_ret || + ins.is_endbr || + ins.is_syscall); +} + +/* + * is_copiable_after_syscall + * checks if an instruction found after a syscall instruction + * can be copied (and thus overwritten). + * + * Notice: we allow the copy of ret instructions. + */ +static bool +is_copiable_after_syscall(struct intercept_disasm_result ins) +{ + if (!ins.is_set) + return false; + + return !(ins.has_ip_relative_opr || + ins.is_call || + ins.is_rel_jump || + ins.is_jump || + ins.is_endbr || + ins.is_syscall); +} + + +/* + * check_surrounding_instructions + * Sets up the following members in a patch_desc, based on + * instruction being relocateable or not: + * uses_prev_ins ; uses_prev_ins_2 ; uses_next_ins + */ +static void +check_surrounding_instructions(struct intercept_desc *desc, + struct patch_desc *patch) +{ + patch->uses_prev_ins = patch->preceding_ins.is_lea_rip || + (is_copiable_before_syscall(patch->preceding_ins) && + !is_overwritable_nop(&patch->preceding_ins) && + !has_jump(desc, patch->syscall_addr)); + + if (patch->uses_prev_ins) { + patch->uses_prev_ins_2 = patch->preceding_ins_2.is_lea_rip || + (patch->uses_prev_ins && + is_copiable_before_syscall(patch->preceding_ins_2) && + !is_overwritable_nop(&patch->preceding_ins_2) && + !has_jump(desc, patch->syscall_addr + - patch->preceding_ins.length)); + } else { + patch->uses_prev_ins_2 = false; + } + + patch->uses_next_ins = patch->following_ins.is_lea_rip || + (is_copiable_after_syscall(patch->following_ins) && + !is_overwritable_nop(&patch->following_ins) && + !has_jump(desc, patch->syscall_addr + SYSCALL_INS_SIZE)); +} + +/* + * create_patch_wrappers - create the custom assembly wrappers + * around each syscall to be intercepted. Well, actually, the + * function create_wrapper does that, so perhaps this function + * deserves a better name. + * What this function actually does, is figure out how to create + * a jump instruction in libc ( which bytes to overwrite ). + * If it successfully finds suitable bytes for hotpatching, + * then it determines the exact bytes to overwrite, and the exact + * address for jumping back to libc. + * + * This is all based on the information collected by the routine + * find_syscalls, which does the disassembling, finding jump destinations, + * finding padding bytes, etc.. + */ +void +create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) +{ + size_t next_nop_i = 0; + + for (unsigned patch_i = 0; patch_i < desc->count; ++patch_i) { + struct patch_desc *patch = desc->items + patch_i; + debug_dump("patching %s:0x%lx\n", desc->path, + patch->syscall_addr - desc->base_addr); + + assign_nop_trampoline(desc, patch, &next_nop_i); + + if (patch->uses_nop_trampoline) { + /* + * The preferred option it to use a 5 byte relative + * jump in a padding space between symbols in libc. + * If such padding space is found, a 2 byte short + * jump is enough for jumping to it, thus no + * instructions other than the syscall + * itself need to be overwritten. + */ + patch->uses_prev_ins = false; + patch->uses_prev_ins_2 = false; + patch->uses_next_ins = false; + patch->dst_jmp_patch = + patch->nop_trampoline.address + 2; + /* + * The first two bytes of the nop are used for + * something else, see the explanation + * at is_overwritable_nop in intercept_desc.c + */ + + /* + * Return to libc: + * just jump to instruction right after the place + * where the syscall instruction was originally. + */ + patch->return_address = + patch->syscall_addr + SYSCALL_INS_SIZE; + + } else { + /* + * No padding space is available, so check the + * instructions surrounding the syscall instruction. + * If they can be relocated, then they can be + * overwritten. Of course some instructions depend + * on the value of the RIP register, these can not + * be relocated. + */ + + check_surrounding_instructions(desc, patch); + + /* + * Count the number of overwritable bytes + * in the variable length. + * Sum up the bytes that can be overwritten. + * The 2 bytes of the syscall instruction can + * be overwritten definitely, so length starts + * as SYSCALL_INS_SIZE ( 2 bytes ). + */ + unsigned length = SYSCALL_INS_SIZE; + + patch->dst_jmp_patch = patch->syscall_addr; + + /* + * If the preceding instruction is relocatable, + * add its length. Also, the the instruction right + * before that. + */ + if (patch->uses_prev_ins) { + length += patch->preceding_ins.length; + patch->dst_jmp_patch -= + patch->preceding_ins.length; + + if (patch->uses_prev_ins_2) { + length += patch->preceding_ins_2.length; + patch->dst_jmp_patch -= + patch->preceding_ins_2.length; + } + } + + /* + * If the following instruction is relocatable, + * add its length. This also affects the return address. + * Normally, the library would return to libc after + * handling the syscall by jumping to instruction + * right after the syscall. But if that instruction + * is overwritten, the returning jump must jump to + * the instruction after it. + */ + if (patch->uses_next_ins) { + length += patch->following_ins.length; + + /* + * Address of the syscall instruction + * plus 2 bytes + * plus the length of the following instruction + * + * adds up to: + * + * the address of the second instruction after + * the syscall. + */ + patch->return_address = patch->syscall_addr + + SYSCALL_INS_SIZE + + patch->following_ins.length; + } else { + /* + * Address of the syscall instruction + * plus 2 bytes + * + * adds up to: + * + * the address of the first instruction after + * the syscall ( just like in the case of + * using padding bytes ). + */ + patch->return_address = + patch->syscall_addr + SYSCALL_INS_SIZE; + } + + /* + * If the length is at least 5, then a jump instruction + * with a 32 bit displacement can fit. + * + * Otherwise give up + */ + if (length < JUMP_INS_SIZE) { + char buffer[0x1000]; + + int l = snprintf(buffer, sizeof(buffer), + "unintercepted syscall at: %s 0x%lx\n", + desc->path, + patch->syscall_offset); + + intercept_log(buffer, (size_t)l); + xabort("not enough space for patching" + " around syscal"); + } + } + + mark_jump(desc, patch->return_address); + + create_wrapper(patch, dst); + } +} + +/* + * Referencing symbols defined in intercept_template.s + */ +extern unsigned char intercept_asm_wrapper_tmpl[]; +extern unsigned char intercept_asm_wrapper_tmpl_end; +extern unsigned char intercept_asm_wrapper_patch_desc_addr; +extern unsigned char intercept_asm_wrapper_wrapper_level1_addr; +extern unsigned char intercept_wrapper; + +size_t asm_wrapper_tmpl_size; +static ptrdiff_t o_patch_desc_addr; +static ptrdiff_t o_wrapper_level1_addr; + +bool intercept_routine_must_save_ymm; + +/* + * init_patcher + * Some variables need to be initialized before patching. + * This routine must be called once before patching any library. + */ +void +init_patcher(void) +{ + unsigned char *begin = &intercept_asm_wrapper_tmpl[0]; + + assert(&intercept_asm_wrapper_tmpl_end > begin); + assert(&intercept_asm_wrapper_patch_desc_addr > begin); + assert(&intercept_asm_wrapper_wrapper_level1_addr > begin); + assert(&intercept_asm_wrapper_patch_desc_addr < + &intercept_asm_wrapper_tmpl_end); + assert(&intercept_asm_wrapper_wrapper_level1_addr < + &intercept_asm_wrapper_tmpl_end); + + asm_wrapper_tmpl_size = + (size_t)(&intercept_asm_wrapper_tmpl_end - begin); + o_patch_desc_addr = &intercept_asm_wrapper_patch_desc_addr - begin; + o_wrapper_level1_addr = + &intercept_asm_wrapper_wrapper_level1_addr - begin; + + /* + * has_ymm_registers -- checks if AVX instructions are supported, + * thus YMM registers can be used on this CPU. + * + * this function is implemented in util.s + * + * XXX check for ZMM registers, and save/restore them! + */ + extern bool has_ymm_registers(void); + + intercept_routine_must_save_ymm = has_ymm_registers(); +} + +/* + * create_movabs + * Generates a movabs instruction, that assigns a 64 bit constant to + * the 64 general purpose register. + * the reg_bits value must contain the X86 encoding of the register. + * Returns a pointer to the char right after the generated instruction. + */ +static unsigned char * +create_movabs(unsigned char *code, uint64_t value, unsigned char reg_bits) +{ + assert(reg_bits < 16); + + unsigned char *bytes = (unsigned char *)&value; + + *code++ = 0x48 | (reg_bits >> 3); /* REX prefix */ + *code++ = 0xb8 | (reg_bits & 7); /* opcode */ + *code++ = bytes[0]; + *code++ = bytes[1]; + *code++ = bytes[2]; + *code++ = bytes[3]; + *code++ = bytes[4]; + *code++ = bytes[5]; + *code++ = bytes[6]; + *code++ = bytes[7]; + + return code; +} + +/* + * create_movabs_r11 + * Generates a movabs instruction moving a value into the R11 register. + */ +static unsigned char * +create_movabs_r11(unsigned char *code, uint64_t value) +{ + return create_movabs(code, value, 11); +} + +/* + * relocate_instruction + * Places an instruction equivalent to `ins` to the memory location at `dst`. + * Only handles instructions that can be copied verbatim, and some LEA + * instructions. + */ +static unsigned char * +relocate_instruction(unsigned char *dst, + const struct intercept_disasm_result *ins) +{ + if (ins->is_lea_rip) { + /* + * Substitue a "lea $offset(%rip), %reg" instruction + * by a movabs instruction, to achieve the same effect. + * The result of the lea calculation is already calculated + * in the rip_ref_addr variable. + */ + return create_movabs(dst, (uint64_t)ins->rip_ref_addr, + ins->arg_register_bits); + } else { + memcpy(dst, ins->address, ins->length); + return dst + ins->length; + } +} + +/* + * create_wrapper + * Generates an assembly wrapper. Copies the template written in + * intercept_template.s, and generates the instructions specific + * to a particular syscall into the new copy. + * After this wrapper is created, a syscall can be replaced with a + * jump to this wrapper, and wrapper is going to call dest_routine + * (actually only after a call to mprotect_asm_wrappers). + */ +static void +create_wrapper(struct patch_desc *patch, unsigned char **dst) +{ + /* Create a new copy of the template */ + patch->asm_wrapper = *dst; + + /* Copy the previous instruction(s) */ + if (patch->uses_prev_ins) { + if (patch->uses_prev_ins_2) + *dst = relocate_instruction(*dst, + &patch->preceding_ins_2); + *dst = relocate_instruction(*dst, &patch->preceding_ins); + } + + memcpy(*dst, intercept_asm_wrapper_tmpl, asm_wrapper_tmpl_size); + create_movabs_r11(*dst + o_patch_desc_addr, (uintptr_t)patch); + create_movabs_r11(*dst + o_wrapper_level1_addr, + (uintptr_t)&intercept_wrapper); + *dst += asm_wrapper_tmpl_size; + + /* Copy the following instruction */ + if (patch->uses_next_ins) + *dst = relocate_instruction(*dst, &patch->following_ins); + + *dst = create_absolute_jump(*dst, patch->return_address); +} + +/* + * create_short_jump + * Generates a 2 byte jump instruction. The to address must be reachable + * using an 8 bit displacement. + */ +static void +create_short_jump(unsigned char *from, unsigned char *to) +{ + ptrdiff_t d = to - (from + 2); + + if (d < - 128 || d > 127) + xabort("create_short_jump distance check"); + + from[0] = SHORT_JMP_OPCODE; + from[1] = (unsigned char)((char)d); +} + +/* + * after_nop -- get the address of the instruction + * following the nop. + */ +static unsigned char * +after_nop(const struct range *nop) +{ + return nop->address + nop->size; +} + +/* + * activate_patches() + * Loop over all the patches, and and overwrite each syscall. + */ +void +activate_patches(struct intercept_desc *desc) +{ + unsigned char *first_page; + size_t size; + + if (desc->count == 0) + return; + + first_page = round_down_address(desc->text_start); + size = (size_t)(desc->text_end - first_page); + + mprotect_no_intercept(first_page, size, + PROT_READ | PROT_WRITE | PROT_EXEC, + "mprotect PROT_READ | PROT_WRITE | PROT_EXEC"); + + for (unsigned i = 0; i < desc->count; ++i) { + const struct patch_desc *patch = desc->items + i; + + if (patch->dst_jmp_patch < desc->text_start || + patch->dst_jmp_patch > desc->text_end) + xabort("dst_jmp_patch outside text"); + + /* + * The dst_jmp_patch pointer contains the address where + * the actual jump instruction escaping the patched text + * segment should be written. + * This is either at the place of the original syscall + * instruction, or at some usable padding space close to + * it (an overwritable NOP instruction). + */ + + if (desc->uses_trampoline_table) { + /* + * First jump to the trampoline table, which + * should be in a 2 gigabyte range. From there, + * jump to the asm_wrapper. + */ + check_trampoline_usage(desc); + + /* jump - escape the text segment */ + create_jump(JMP_OPCODE, + patch->dst_jmp_patch, desc->next_trampoline); + + /* jump - escape the 2 GB range of the text segment */ + desc->next_trampoline = create_absolute_jump( + desc->next_trampoline, patch->asm_wrapper); + } else { + create_jump(JMP_OPCODE, + patch->dst_jmp_patch, patch->asm_wrapper); + } + + if (patch->uses_nop_trampoline) { + /* + * Create a mini trampoline jump. + * The first two bytes of the NOP instruction are + * overwritten by a short jump instruction + * (with 8 bit displacement), to make sure whenever + * this the execution reaches the address where this + * NOP resided originally, it continues uninterrupted. + * The rest of the bytes occupied by this instruction + * are used as an mini extra trampoline table. + * + * See also: the is_overwritable_nop function in + * the intercept_desc.c source file. + */ + + /* jump from syscall to mini trampoline */ + create_short_jump(patch->syscall_addr, + patch->dst_jmp_patch); + + /* + * Short jump to next instruction, skipping the newly + * created trampoline jump. + */ + create_short_jump(patch->nop_trampoline.address, + after_nop(&patch->nop_trampoline)); + } else { + unsigned char *byte; + + for (byte = patch->dst_jmp_patch + JUMP_INS_SIZE; + byte < patch->return_address; + ++byte) { + *byte = INT3_OPCODE; + } + } + } + + mprotect_no_intercept(first_page, size, + PROT_READ | PROT_EXEC, + "mprotect PROT_READ | PROT_EXEC"); +} \ No newline at end of file diff --git a/src/intercept.c b/src/intercept.c index a87a192..1ae8c59 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -104,26 +104,56 @@ static void log_header(void); void __attribute__((noreturn)) xlongjmp(long rip, long rsp, long rax); -/* - * Kernel can clobber rcx and r11 while serving a syscall, those are ignored - * The layout of this struct depends on the way the assembly wrapper saves - * register on the stack. - * Note: don't expect the SIMD array to be aligned for efficient use with - * AVX instructions. - */ -struct context { - long ra; - long t[5]; - long sp; - struct patch_desc *patch_desc; - long a[8]; - double ft[12]; - double fa[8]; -}; - -struct wrapper_ret { - long a[2]; -}; +#if defined(__x86_64__) || defined(_M_X64) + /* + * Kernel can clobber rcx and r11 while serving a syscall, those are ignored + * The layout of this struct depends on the way the assembly wrapper saves + * register on the stack. + * Note: don't expect the SIMD array to be aligned for efficient use with + * AVX instructions. + */ + struct context { + struct patch_desc *patch_desc; + long rip; + long r15; + long r14; + long r13; + long r12; + long r10; + long r9; + long r8; + long rsp; + long rbp; + long rdi; + long rsi; + long rbx; + long rdx; + long rax; + char padd[0x200 - 0x168]; /* see: stack layout in intercept_wrapper.s */ + long SIMD[16][8]; /* 8 SSE, 8 AVX, or 16 AVX512 registers */ + }; + + struct wrapper_ret { + long rax; + long rdx; + }; +#elif defined(__riscv) + struct context { + long ra; + long t[5]; + long sp; + struct patch_desc *patch_desc; + long a[8]; + double ft[12]; + double fa[8]; + }; + + struct wrapper_ret { + long a[2]; + }; +#else + #error "Unsupported ISA" +#endif /* Should all objects be patched, or only libc and libpthread? */ static bool patch_all_objs; @@ -581,13 +611,13 @@ xabort_on_syserror(long syscall_result, const char *msg) static void get_syscall_in_context(struct context *context, struct syscall_desc *sys) { - sys->nr = (int)context->a[7]; /* ignore higher 32 bits */ - sys->args[0] = context->a[0]; - sys->args[1] = context->a[1]; - sys->args[2] = context->a[2]; - sys->args[3] = context->a[3]; - sys->args[4] = context->a[4]; - sys->args[5] = context->a[5]; + sys->nr = (int)SYSCALL_NR; /* ignore higher 32 bits */ + sys->args[0] = FIRST_ARG_REG; + sys->args[1] = SECOND_ARG_REG; + sys->args[2] = THIRD_ARG_REG; + sys->args[3] = FOURTH_ARG_REG; + sys->args[4] = FIFTH_ARG_REG; + sys->args[5] = SIXTH_ARG_REG; } /* @@ -634,7 +664,7 @@ intercept_routine(struct context *context) // debug_dump("ra: %lx", context->ra); if (handle_magic_syscalls(&desc, &result) == 0) - return (struct wrapper_ret){.a[0] = result, .a[1] = 1 }; + return (struct wrapper_ret){FIRST_RET_REG = result, SECOND_RET_REG = 1 }; intercept_log_syscall(patch, &desc, UNKNOWN, 0); @@ -650,7 +680,7 @@ intercept_routine(struct context *context) if (desc.nr == SYS_rt_sigreturn) { /* can't handle these syscalls the normal way */ - return (struct wrapper_ret){.a[0] = context->a[7], .a[1] = 0 }; + return (struct wrapper_ret){FIRST_RET_REG = SYSCALL_NR, SECOND_RET_REG = 0 }; } if (forward_to_kernel) { @@ -668,13 +698,13 @@ intercept_routine(struct context *context) */ if (desc.nr == SYS_clone && desc.args[1] != 0) { return (struct wrapper_ret){ - .a[0] = context->a[7], .a[1] = 2 }; + FIRST_RET_REG = SYSCALL_NR, SECOND_RET_REG = 2 }; } #ifdef SYS_clone3 else if (desc.nr == SYS_clone3 && ((struct clone_args *)desc.args[0])->stack != 0) { return (struct wrapper_ret){ - .a[0] = context->a[7], .a[1] = 2 }; + FIRST_RET_REG = SYSCALL_NR, SECOND_RET_REG = 2 }; } #endif else @@ -689,7 +719,7 @@ intercept_routine(struct context *context) intercept_log_syscall(patch, &desc, KNOWN, result); // debug_dump("intercepted ecall -> returning to asm_wrapper - result: %ld\n",result); - return (struct wrapper_ret){ .a[0] = result, .a[1] = 1 }; + return (struct wrapper_ret){ FIRST_RET_REG = result, SECOND_RET_REG = 1 }; } /* @@ -700,13 +730,13 @@ intercept_routine(struct context *context) struct wrapper_ret intercept_routine_post_clone(struct context *context) { - if (context->a[7] == 0) { + if (SYSCALL_NR == 0) { if (intercept_hook_point_clone_child != NULL) intercept_hook_point_clone_child(); } else { if (intercept_hook_point_clone_parent != NULL) - intercept_hook_point_clone_parent(context->a[7]); + intercept_hook_point_clone_parent(SYSCALL_NR); } - return (struct wrapper_ret){.a[0] = context->a[7], .a[1] = 1 }; + return (struct wrapper_ret){FIRST_RET_REG = SYSCALL_NR, SECOND_RET_REG = 1 }; } diff --git a/src/intercept.h b/src/intercept.h index e51d69f..7c90e65 100644 --- a/src/intercept.h +++ b/src/intercept.h @@ -218,21 +218,45 @@ void mprotect_asm_wrappers(void); */ void activate_patches(struct intercept_desc *desc); -#define ECALL_INS_SIZE 4 -/* - * 16 bytes are actually needed to write 4 instructions. The 1st one decreases - * sp value, the 2nd one stores one tmp reg into the stack, the 3rd one uses the - * saved register to write part of the destination address and the 4th one is - * actually the jump summing its immediate value to the just wrote register to - * calculate desination of the jump - */ -#define JUMP_INS_SIZE 8 -// #define CALL_OPCODE 0xe8 -// #define JMP_OPCODE 0xe9 -// #define SHORT_JMP_OPCODE 0xeb -// #define PUSH_IMM_OPCODE 0x68 -// #define NOP_OPCODE 0x90 -// #define INT3_OPCODE 0xCC +#if defined(__x86_64__) || defined(_M_X64) + #define SYSCALL_INS_SIZE 2 + #define JUMP_INS_SIZE 5 + #define TRAMPOLINE_SIZE 14 + #define SYSCALL_NR context->rax + #define FIRST_ARG_REG context->rdi + #define SECOND_ARG_REG context->rsi + #define THIRD_ARG_REG context->rdx + #define FOURTH_ARG_REG context->r10 + #define FIFTH_ARG_REG context->r8 + #define SIXTH_ARG_REG context->r9 + #define FIRST_RET_REG .rax + #define SECOND_RET_REG .rdx + #define CALL_OPCODE 0xe8 + #define JMP_OPCODE 0xe9 + #define SHORT_JMP_OPCODE 0xeb + #define PUSH_IMM_OPCODE 0x68 + #define NOP_OPCODE 0x90 + #define INT3_OPCODE 0xCC +#elif defined(__riscv) + #define SYSCALL_INS_SIZE 4 + /* + * 8 bytes are needed to be able to perform + * a PC-relative jump with a 32-bit offset + */ + #define JUMP_INS_SIZE 8 + #define TRAMPOLINE_SIZE 92 + #define SYSCALL_NR context->a[7] + #define FIRST_ARG_REG context->a[0] + #define SECOND_ARG_REG context->a[1] + #define THIRD_ARG_REG context->a[2] + #define FOURTH_ARG_REG context->a[3] + #define FIFTH_ARG_REG context->a[4] + #define SIXTH_ARG_REG context->a[5] + #define FIRST_RET_REG .a[0] + #define SECOND_RET_REG .a[1] +#else + #error "Unsupported ISA" +#endif bool is_overwritable_nop(const struct intercept_disasm_result *ins); diff --git a/src/intercept_desc.c b/src/intercept_desc.c index e355dc4..40e1b87 100644 --- a/src/intercept_desc.c +++ b/src/intercept_desc.c @@ -61,8 +61,13 @@ static int open_orig_file(const struct intercept_desc *desc) { int fd; - +#if defined(__x86_64__) || defined(_M_X64) + fd = syscall_no_intercept(SYS_open, desc->path, O_RDONLY); +#elif defined(__riscv) fd = syscall_no_intercept(SYS_openat, AT_FDCWD, desc->path, O_RDONLY); +#else + #error "Unsupported ISA" +#endif xabort_on_syserror(fd, __func__); @@ -353,9 +358,14 @@ find_jumps_in_section_rela(struct intercept_desc *desc, Elf64_Shdr *section, for (size_t i = 0; i < sym_count; ++i) { switch (ELF64_R_TYPE(syms[i].r_info)) { +#if defined(__x86_64__) || defined(_M_X64) case R_X86_64_RELATIVE: case R_X86_64_RELATIVE64: +#elif defined(__riscv) case R_RISCV_RELATIVE: +#else + #error "Unsupported ISA" +#endif /* Relocation type: "Adjust by program base" */ debug_dump("jump target: %lx\n", @@ -526,7 +536,7 @@ crawl_text(struct intercept_desc *desc) patch->preceding_ins_2 = prevs[0]; patch->preceding_ins = prevs[1]; patch->following_ins = result; - patch->syscall_addr = code - ECALL_INS_SIZE; + patch->syscall_addr = code - SYSCALL_INS_SIZE; ptrdiff_t syscall_offset = patch->syscall_addr - (desc->text_start - desc->text_offset); @@ -564,8 +574,15 @@ get_min_address(void) min_address = 0x10000; /* best guess */ +#if defined(__x86_64__) || defined(_M_X64) + int fd = syscall_no_intercept(SYS_open, "/proc/sys/vm/mmap_min_addr", + O_RDONLY); +#elif defined(__riscv) int fd = syscall_no_intercept(SYS_openat, AT_FDCWD, "/proc/sys/vm/mmap_min_addr", O_RDONLY); +#else + #error "Unsupported ISA" +#endif if (fd >= 0) { char line[64]; diff --git a/src/intercept_log.c b/src/intercept_log.c index c0f69f1..37dcebe 100644 --- a/src/intercept_log.c +++ b/src/intercept_log.c @@ -830,8 +830,13 @@ intercept_setup_log(const char *path, const char *trunc) intercept_log_close(); /* in case a log was already open */ +#if defined(__x86_64__) || defined(_M_X64) + log_fd = (int)syscall_no_intercept(SYS_open, full_path, flags, 0700); +#elif defined(__riscv) log_fd = (int)syscall_no_intercept(SYS_openat, AT_FDCWD, full_path, flags, 0700); - +#else +#error "Unsupported ISA" +#endif xabort_on_syserror(log_fd, "opening log"); } diff --git a/src/patcher.c b/src/patcher.c index 1db4376..ac9d89c 100644 --- a/src/patcher.c +++ b/src/patcher.c @@ -90,7 +90,7 @@ * instructions that were placed before the original ecall still must be * executed. */ -enum { TRAMPOLINE_SIZE = 23 * 4 }; +// enum { TRAMPOLINE_SIZE = 23 * 4 }; static void create_wrapper(struct patch_desc *patch, unsigned char **dst); static void create_load_uint64t_into_t0(uint8_t *code, uint64_t value); @@ -226,7 +226,7 @@ is_copiable_after_syscall(struct intercept_disasm_result ins) /* * check_surrounding_instructions * Sets up the following members in a patch_desc, based on - * instruction being relocateable or not: + * instruction being relocatable or not: * uses_prev_ins ; uses_prev_ins_2 ; uses_next_ins */ static void @@ -245,7 +245,7 @@ check_surrounding_instructions(struct intercept_desc *desc, } patch->uses_next_ins = (is_copiable_after_syscall(patch->following_ins) && - !has_jump(desc, patch->syscall_addr + ECALL_INS_SIZE)); + !has_jump(desc, patch->syscall_addr + SYSCALL_INS_SIZE)); } /* @@ -290,9 +290,9 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) * Sum up the bytes that can be overwritten. * The 4 bytes of the ecall instruction can * be overwritten definitely, so length starts - * as ECALL_INS_SIZE ( 4 bytes ). + * as SYSCALL_INS_SIZE ( 4 bytes ). */ - unsigned length = ECALL_INS_SIZE; + unsigned length = SYSCALL_INS_SIZE; patch->needs_compressed_ins = false; patch->padding_is_needed = false; @@ -344,7 +344,7 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) * the syscall. */ patch->return_address = patch->syscall_addr + - ECALL_INS_SIZE + + SYSCALL_INS_SIZE + patch->following_ins.length; } else { /* @@ -352,7 +352,7 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) * to set the flag to false so that it's not relocated */ patch->uses_next_ins = false; - patch->return_address = patch->syscall_addr + ECALL_INS_SIZE; + patch->return_address = patch->syscall_addr + SYSCALL_INS_SIZE; } if (length > JUMP_INS_SIZE) { @@ -608,8 +608,8 @@ create_j(unsigned char *from, void *to) uint32_t *instructions = (uint32_t *)from; debug_dump("%p: ecall -> jalr %ld\t# %p\n", from, delta, to); - const ptrdiff_t JALR_MAX_OFFSET = 2147481598; // ((2^31-1)-4095)+(2^11-1) == 0x7ffff000 + 0x7ff - const ptrdiff_t JALR_MIN_OFFSET = -2147483648; // (-2^31) == -0x80000000 + const ptrdiff_t JALR_MAX_OFFSET = 2147481598; // ((2^31-1)-4095)+(2^11-1) = 0x7ffff000 + 0x7ff + const ptrdiff_t JALR_MIN_OFFSET = -2147483648; // (-2^31) = -0x80000000 if ((delta & 0x1) != 0) { From 2874db593492be97e834743d3b9f8226bc07c373 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Mon, 3 Feb 2025 17:46:50 +0100 Subject: [PATCH 034/143] Solved some warnings --- src/arch/riscv/patcher.c | 32 ++++++++++++++++---------------- src/intercept_desc.c | 2 ++ src/syscall_formats.c | 2 +- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/arch/riscv/patcher.c b/src/arch/riscv/patcher.c index 1723071..84fff9f 100644 --- a/src/arch/riscv/patcher.c +++ b/src/arch/riscv/patcher.c @@ -266,7 +266,7 @@ check_surrounding_instructions(struct intercept_desc *desc, void create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) { - short min_treshold = JUMP_INS_SIZE; + unsigned short min_treshold = JUMP_INS_SIZE; bool c_isa_supported = getauxval(AT_HWCAP) & COMPAT_HWCAP_ISA_C; for (unsigned patch_i = 0; patch_i < desc->count; ++patch_i) { struct patch_desc *patch = desc->items + patch_i; @@ -292,7 +292,7 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) * be overwritten definitely, so length starts * as SYSCALL_INS_SIZE ( 4 bytes ). */ - unsigned length = SYSCALL_INS_SIZE; + unsigned short length = SYSCALL_INS_SIZE; patch->needs_compressed_ins = false; patch->padding_is_needed = false; @@ -442,20 +442,20 @@ init_patcher(void) } -/* - * create_ret_from_template - * Write a RET instruction (encoded as JALR) to return to patch->return_address. - * This is possible as long patch->return_address is saved to ra in the first - * place when jumping to trampoline when intercepting the system call. This is - * not explicitly written at the end of intercept_template.S since the fourth - * overwritten instruction has to be relocated before RET. - */ -static unsigned char * -create_ret_from_template(unsigned char *code) -{ - *((uint32_t *)code) = 0x00008067; // jalr zero, ra, 0 - return code + 4; -} +///* +// * create_ret_from_template +// * Write a RET instruction (encoded as JALR) to return to patch->return_address. +// * This is possible as long patch->return_address is saved to ra in the first +// * place when jumping to trampoline when intercepting the system call. This is +// * not explicitly written at the end of intercept_template.S since the fourth +// * overwritten instruction has to be relocated before RET. +// */ +//static unsigned char * +//create_ret_from_template(unsigned char *code) +//{ +// *((uint32_t *)code) = 0x00008067; // jalr zero, ra, 0 +// return code + 4; +//} /* * create_load_uint64t_into_t0 diff --git a/src/intercept_desc.c b/src/intercept_desc.c index 40e1b87..9d28719 100644 --- a/src/intercept_desc.c +++ b/src/intercept_desc.c @@ -197,6 +197,7 @@ calculate_table_count(const struct intercept_desc *desc) return 1024; } +#if defined(__x86_64__) || defined(_M_X64) /* * allocate_nop_table - allocates desc->nop_table */ @@ -222,6 +223,7 @@ mark_nop(struct intercept_desc *desc, unsigned char *address, size_t size) desc->nop_table[desc->nop_count].size = size; desc->nop_count++; } +#endif /* * is_bit_set - check a bit in a bitmap diff --git a/src/syscall_formats.c b/src/syscall_formats.c index cfd3aea..535b36f 100644 --- a/src/syscall_formats.c +++ b/src/syscall_formats.c @@ -288,7 +288,7 @@ static const struct syscall_format formats[] = { // SARGS(futimesat, rdec, arg_atfd, arg_cstr, arg_), SARGS(newfstatat, rdec, arg_atfd, arg_cstr, arg_, arg_), SARGS(unlinkat, rdec, arg_atfd, arg_cstr, arg_), - SARGS(renameat2, rdec, arg_atfd, arg_cstr, arg_atfd, arg_cstr), + // SARGS(renameat2, rdec, arg_atfd, arg_cstr, arg_atfd, arg_cstr), SARGS(linkat, rdec, arg_atfd, arg_cstr, arg_atfd, arg_cstr, arg_), SARGS(symlinkat, rdec, arg_cstr, arg_atfd, arg_cstr), SARGS(readlinkat, rdec, arg_atfd, arg_cstr, arg_buf_out, arg_dec), From 971ab4ba4e3f4c0f16cc6048a4321ac84b8d1545 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Mon, 3 Feb 2025 17:51:07 +0100 Subject: [PATCH 035/143] Solved last warning --- src/intercept_desc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intercept_desc.c b/src/intercept_desc.c index 9d28719..2ba35ed 100644 --- a/src/intercept_desc.c +++ b/src/intercept_desc.c @@ -170,6 +170,7 @@ allocate_jump_table(struct intercept_desc *desc) desc->jump_table = xmmap_anon(bytes / 8 + 1); } +#if defined(__x86_64__) || defined(_M_X64) /* * calculate_table_count - estimate the number of entries * that might be used for nop table. @@ -197,7 +198,6 @@ calculate_table_count(const struct intercept_desc *desc) return 1024; } -#if defined(__x86_64__) || defined(_M_X64) /* * allocate_nop_table - allocates desc->nop_table */ From a8e6c3b01fc513073fbb5895f78b2b3759b84b94 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 4 Feb 2025 16:50:48 +0100 Subject: [PATCH 036/143] Corrected comment to RISC-V specific files --- src/arch/riscv/intercept_template.S | 12 +-- src/arch/riscv/intercept_wrapper.S | 2 + src/arch/riscv/patcher.c | 117 ++++++++-------------------- src/intercept.h | 4 +- 4 files changed, 42 insertions(+), 93 deletions(-) diff --git a/src/arch/riscv/intercept_template.S b/src/arch/riscv/intercept_template.S index dea78cd..73e95e3 100644 --- a/src/arch/riscv/intercept_template.S +++ b/src/arch/riscv/intercept_template.S @@ -42,8 +42,6 @@ .text /* - * ld t0, 0(sp) - * addi sp, sp, 16 * preceding_ins_2 * preceding_ins */ @@ -167,10 +165,8 @@ l5: intercept_asm_wrapper_tmpl_end: /* * This template must be appended here with a - * jump back to the intercepted code. - */ - - /* - * following_ins # !can't use ra as operand! need to check after disassembly - * create_absolute_jump(*dst, patch->return_address) + * jump back to the intercepted code, whic is written by + * create_absolute_jump(*dst, patch->return_address) in patcher.c + * + * following_ins */ diff --git a/src/arch/riscv/intercept_wrapper.S b/src/arch/riscv/intercept_wrapper.S index f8a8e55..3064ad2 100644 --- a/src/arch/riscv/intercept_wrapper.S +++ b/src/arch/riscv/intercept_wrapper.S @@ -46,6 +46,8 @@ .globl intercept_routine_post_clone .type intercept_routine_post_clone, @function +.globl is_v_extension_supported + .text intercept_wrapper: diff --git a/src/arch/riscv/patcher.c b/src/arch/riscv/patcher.c index 84fff9f..419b6bf 100644 --- a/src/arch/riscv/patcher.c +++ b/src/arch/riscv/patcher.c @@ -38,13 +38,13 @@ * /--------------------------\ * | subject.so | * | | - * | jmp to_trampoline_table | patched by activate_patches() + * | jr to_trampoline_table | patched by activate_patches() * /->| | | * | \___|______________________/ * | | * | /---|--------------------------\ - * | | movabs %r11, wrapper_address | jmp generated by activate_patches() - * | | jmp *%r11 | This allows subject.so and + * | | load wrapper_address into t6 | jr generated by activate_patches() + * | | jr t6 | This allows subject.so and * | | | | libsyscall_intercept.so to be farther * | \___|__________________________/ than 2 gigabytes from each other * | | @@ -59,8 +59,8 @@ * | | | | | | by create_wrapper() * | | |wrapper routine | | * | | |calls C hook function ----------> intercept_routine in intercept.c - * | | |movabs %r11, return_address | | - * | | |jmp *%r11 | | + * | | |load return address into t6 | | + * | | |jr t6 | | * | | \_|__________________________/ | * | \___|_____________________________/ * | | @@ -82,15 +82,7 @@ #include #define COMPAT_HWCAP_ISA_C (1 << ('C' - 'A')) - -/* The size of a trampoline jump, 64-bit address loading process into a register - * (which requires 14 instructions to encode directly in machine code) + JALR. - * These are preceded and succeeded by storing and restoring of tmp registers - * used for the creation of the absolute jump. We can't clobber them since two - * instructions that were placed before the original ecall still must be - * executed. - */ -// enum { TRAMPOLINE_SIZE = 23 * 4 }; +#define COMPAT_HWCAP_ISA_V (1 << ('V' - 'A')) static void create_wrapper(struct patch_desc *patch, unsigned char **dst); static void create_load_uint64t_into_t0(uint8_t *code, uint64_t value); @@ -98,7 +90,12 @@ static void create_load_uint64t_into_t6(uint8_t *code, uint64_t value); /* * create_absolute_jump(from, to) - * + * Writes the machine code of a trampoline at from jumping to to; 92 bytes are + * needed to make sure to correctly encoding a 64-bit constant into t6, + * whihch we assume being clobbered in the version 1.0 of the RISC-V porting. + * Auxiliary temporary registers must be saved and restored so that they are + * not clobbered as well. The conformation of the trampoline requires + * 4 bytes * 23 instructions. */ static unsigned char * create_absolute_jump(unsigned char *from, void *to) @@ -126,35 +123,6 @@ create_absolute_jump(unsigned char *from, void *to) return (unsigned char *)(instructions + 23); } -/* - * create_jump(opcode, from, to) - * Create a 5 byte jmp/call instruction jumping to address to, by overwriting - * code starting at address from. - */ -void -create_jump(unsigned char opcode, unsigned char *from, void *to) -{ - /* - * The operand is the difference between the - * instruction pointer pointing to the instruction - * just after the call, and the to address. - * Thus RIP seen by the call instruction is from + 5 - */ - ptrdiff_t delta = ((unsigned char *)to) - (from + JUMP_INS_SIZE); - - if (delta > ((ptrdiff_t)INT32_MAX) || delta < ((ptrdiff_t)INT32_MIN)) - xabort("create_jump distance check"); - - int32_t delta32 = (int32_t)delta; - unsigned char *d = (unsigned char *)&delta32; - - from[0] = opcode; - from[1] = d[0]; - from[2] = d[1]; - from[3] = d[2]; - from[4] = d[3]; -} - /* * check_trampoline_usage - * Make sure the trampoline table allocated at the beginning of patching has @@ -274,12 +242,10 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) patch->syscall_addr - desc->base_addr, patch_i); /* - * No padding space is available, so check the - * instructions surrounding the syscall instruction. - * If they can be relocated, then they can be - * overwritten. Of course some instructions depend - * on the value of the RIP register, these can not - * be relocated. + * Check the instructions surrounding the syscall instruction. + * If they can be relocated, then they can be overwritten. + * Of course some instructions depend on the value of the + * PC register, these can not be relocated. */ check_surrounding_instructions(desc, patch); @@ -334,7 +300,7 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) length += patch->following_ins.length; /* - * Address of the syscall instruction + * Address of the ecall instruction * plus 4 bytes * plus the length of the following instruction * @@ -355,6 +321,11 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) patch->return_address = patch->syscall_addr + SYSCALL_INS_SIZE; } + /* The following happens when we found 6 suitable bytes for + * rewriting and a 4-byte instruction is found after those, + * resulting in patch size being 10 bytes but just 8 are used so + * padding with a c.ebreak will be reasonable + */ if (length > JUMP_INS_SIZE) { patch->padding_is_needed = true; // patch->return_address -= (length - JUMP_INS_SIZE); @@ -368,10 +339,6 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) * * If length is less than minimum needed bytes (value depending on * ISA C module being supported or not), give up. - * - * TO DO: creating an environment variable marking if all ECALLs - * must be patchable for success or if we could just skip the - * unpatchable ones. */ if (c_isa_supported) { if (length == 6) { @@ -414,7 +381,7 @@ size_t asm_wrapper_tmpl_size; static ptrdiff_t o_patch_desc_addr; static ptrdiff_t o_wrapper_level1_addr; -bool intercept_routine_must_save_ymm = false; // temporarily hardcoded +bool is_v_extension_supported; /* * init_patcher @@ -439,28 +406,14 @@ init_patcher(void) o_patch_desc_addr = &intercept_asm_wrapper_patch_desc_addr - begin; o_wrapper_level1_addr = &intercept_asm_wrapper_wrapper_level1_addr - begin; -} - -///* -// * create_ret_from_template -// * Write a RET instruction (encoded as JALR) to return to patch->return_address. -// * This is possible as long patch->return_address is saved to ra in the first -// * place when jumping to trampoline when intercepting the system call. This is -// * not explicitly written at the end of intercept_template.S since the fourth -// * overwritten instruction has to be relocated before RET. -// */ -//static unsigned char * -//create_ret_from_template(unsigned char *code) -//{ -// *((uint32_t *)code) = 0x00008067; // jalr zero, ra, 0 -// return code + 4; -//} + is_v_extension_supported = getauxval(AT_HWCAP) & COMPAT_HWCAP_ISA_V; +} /* - * create_load_uint64t_into_t0 - * Generates the first 5 instructions (LUI,ADDI,SLLI,LUI,ADDI) of a convoluted - * 14 instructions sequence that assign a 64 bit constant to a register. + * create_load_uint64t_into_tn + * Generates the first 5 instructions (LUI,ADDI,SLLI,LUI,ADDI) of a + * 14 instructions sequence that loads a 64 bit constant into a register. * See intercept_template.S for the following 9 at * intercept_asm_wrapper_patch_desc_addr (an equal sequence is placed at * intercept_asm_wrapper_wrapper_level1_addr as well). @@ -555,8 +508,8 @@ relocate_instruction(unsigned char *dst, * create_wrapper * Generates an assembly wrapper. Copies the template written in * intercept_template.s, and generates the instructions specific - * to a particular syscall into the new copy. - * After this wrapper is created, a syscall can be replaced with a + * to a particular ecall into the new copy. + * After this wrapper is created, a ecall can be replaced with a * jump to this wrapper, and wrapper is going to call dest_routine * (actually only after a call to mprotect_asm_wrappers). */ @@ -590,9 +543,7 @@ create_wrapper(struct patch_desc *patch, unsigned char **dst) /* * create_j(from, to) - * Create a 4 byte JAL instruction jumping to address to, by overwriting - * code starting at address from, if trampoline displacement is within + or - - * 1 MiB. Otherwise, create a 2 instructions sequence (LUI + JALR) which allows + * Create an 8 byte instructions sequence (LUI + JALR) which allows * to reach trampoline if its displacement is within -2 GiB or JALR_MAX_OFFSET, * which is (+2 GiB - 2050 Bytes). */ @@ -669,7 +620,7 @@ create_c_j(unsigned char *from, void *to) { /* * activate_patches() - * Loop over all the patches, and overwrite each syscall. + * Loop over all the patches, and overwrite each ecall. */ void activate_patches(struct intercept_desc *desc) @@ -721,8 +672,8 @@ activate_patches(struct intercept_desc *desc) /* * if patch is 10 bytes long, fill the last two * with c.ebreak instruction. Template will jump back to the - * return address so c.ebreak will never be executed as long - * as the patching correctly the return jump from template. + * return address so c.ebreak will never be executed as long as + * the patching correctly writes the return jump from template. */ if (patch->padding_is_needed) { *(uint16_t *)(patch->return_address-2) = 0x8002; // c.ebreak diff --git a/src/intercept.h b/src/intercept.h index 7c90e65..8e1d669 100644 --- a/src/intercept.h +++ b/src/intercept.h @@ -221,7 +221,7 @@ void activate_patches(struct intercept_desc *desc); #if defined(__x86_64__) || defined(_M_X64) #define SYSCALL_INS_SIZE 2 #define JUMP_INS_SIZE 5 - #define TRAMPOLINE_SIZE 14 + #define TRAMPOLINE_SIZE 14 /* jmp instruction + pointer */ #define SYSCALL_NR context->rax #define FIRST_ARG_REG context->rdi #define SECOND_ARG_REG context->rsi @@ -244,7 +244,7 @@ void activate_patches(struct intercept_desc *desc); * a PC-relative jump with a 32-bit offset */ #define JUMP_INS_SIZE 8 - #define TRAMPOLINE_SIZE 92 + #define TRAMPOLINE_SIZE 92 /* see create_absolute_jump() in arch/riscv/patcher.c */ #define SYSCALL_NR context->a[7] #define FIRST_ARG_REG context->a[0] #define SECOND_ARG_REG context->a[1] From 3a9f3d75ab1ae0db1e6975c9446eb7f1608acba0 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 5 Feb 2025 14:21:10 +0100 Subject: [PATCH 037/143] Made architecture indepentent --- src/arch/riscv/disasm_wrapper.c | 8 +- src/arch/riscv/patcher.c | 12 +-- src/syscall_formats.c | 162 +++++++++++++++++++++++--------- 3 files changed, 127 insertions(+), 55 deletions(-) diff --git a/src/arch/riscv/disasm_wrapper.c b/src/arch/riscv/disasm_wrapper.c index 43c8c72..c3ca551 100644 --- a/src/arch/riscv/disasm_wrapper.c +++ b/src/arch/riscv/disasm_wrapper.c @@ -72,7 +72,8 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, #endif switch (context->insn->id) { - case RISCV_INS_BEQ: // PC-relative jumps + /* PC-relative jumps */ + case RISCV_INS_BEQ: case RISCV_INS_BGE: case RISCV_INS_BGEU: case RISCV_INS_BLT: @@ -92,12 +93,15 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, case RISCV_INS_JALR: case RISCV_INS_C_JR: case RISCV_INS_C_JALR: + case RISCV_INS_MRET: + case RISCV_INS_SRET: + case RISCV_INS_URET: result.is_jump = true; break; default: result.is_jump = false; result.has_ip_relative_opr = false; - result.uses_ra = false; +// result.uses_ra = false; cs_riscv_op *op; result.uses_t6 = false; for (uint8_t op_i = 0; !result.uses_t6 && diff --git a/src/arch/riscv/patcher.c b/src/arch/riscv/patcher.c index 419b6bf..7630dfa 100644 --- a/src/arch/riscv/patcher.c +++ b/src/arch/riscv/patcher.c @@ -159,11 +159,11 @@ is_copiable_before_syscall(struct intercept_disasm_result ins) return false; return !(ins.has_ip_relative_opr || - ins.is_call || +// ins.is_call || ins.is_rel_jump || ins.is_jump || - ins.is_ret || - ins.is_endbr || +// ins.is_ret || +// ins.is_endbr || ins.is_syscall || ins.uses_t6); } @@ -182,10 +182,10 @@ is_copiable_after_syscall(struct intercept_disasm_result ins) return false; return !(ins.has_ip_relative_opr || - ins.is_call || +// ins.is_call || ins.is_rel_jump || ins.is_jump || - ins.is_endbr || +// ins.is_endbr || ins.is_syscall || ins.uses_t6); } @@ -328,7 +328,6 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) */ if (length > JUMP_INS_SIZE) { patch->padding_is_needed = true; - // patch->return_address -= (length - JUMP_INS_SIZE); } /* @@ -538,7 +537,6 @@ create_wrapper(struct patch_desc *patch, unsigned char **dst) *dst = relocate_instruction(*dst, &patch->following_ins); *dst = create_absolute_jump(*dst, patch->return_address); - // *dst = create_ret_from_template(*dst); } /* diff --git a/src/syscall_formats.c b/src/syscall_formats.c index 535b36f..e3b754b 100644 --- a/src/syscall_formats.c +++ b/src/syscall_formats.c @@ -44,12 +44,18 @@ static const struct syscall_format formats[] = { SARGS(read, rdec, arg_fd, arg_buf_out, arg_dec), SARGS(write, rdec, arg_fd, arg_buf_in, arg_dec), - // SARGS(open, rdec, arg_cstr, arg_open_flags), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(open, rdec, arg_cstr, arg_open_flags), +#endif SARGS(close, rdec, arg_fd), - // SARGS(stat, rdec, arg_cstr, arg_pointer), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(stat, rdec, arg_cstr, arg_pointer), +#endif SARGS(fstat, rdec, arg_fd, arg_pointer), - // SARGS(lstat, rdec, arg_cstr, arg_pointer), - // SARGS(poll, rdec, arg_pointer, arg_, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(lstat, rdec, arg_cstr, arg_pointer), + SARGS(poll, rdec, arg_pointer, arg_, arg_), +#endif SARGS(lseek, rdec, arg_fd, arg_dec, arg_seek_whence), SARGS(mmap, rpointer, arg_pointer, arg_, arg_, arg_, arg_fd, arg_), SARGS(mprotect, rdec, arg_pointer, arg_, arg_), @@ -63,9 +69,11 @@ static const struct syscall_format formats[] = { SARGS(pwrite64, rdec, arg_fd, arg_buf_in, arg_dec, arg_dec), SARGS(readv, rdec, arg_fd, arg_pointer, arg_dec), SARGS(writev, rdec, arg_fd, arg_pointer, arg_dec), - // SARGS(access, rdec, arg_cstr, arg_access_mode), - // SARGS(pipe, rdec, arg_2fds), - // SARGS(select, rdec, arg_dec32, arg_pointer, arg_pointer, arg_pointer, arg_pointer), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(access, rdec, arg_cstr, arg_access_mode), + SARGS(pipe, rdec, arg_2fds), + SARGS(select, rdec, arg_dec32, arg_pointer, arg_pointer, arg_pointer, arg_pointer), +#endif SARGS(sched_yield, rdec, arg_none), SARGS(mremap, rpointer, arg_pointer, arg_dec, arg_dec, arg_dec32, arg_), SARGS(msync, rdec, arg_pointer, arg_dec, arg_dec32), @@ -75,11 +83,15 @@ static const struct syscall_format formats[] = { SARGS(shmat, rhex, arg_, arg_, arg_), SARGS(shmctl, rdec, arg_, arg_, arg_), SARGS(dup, rdec, arg_fd), - // SARGS(dup2, rdec, arg_fd, arg_fd), - // SARGS(pause, rdec, arg_none), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(dup2, rdec, arg_fd, arg_fd), + SARGS(pause, rdec, arg_none), +#endif SARGS(nanosleep, rdec, arg_, arg_), SARGS(getitimer, rdec, arg_, arg_), - // SARGS(alarm, rdec, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(alarm, rdec, arg_), +#endif SARGS(setitimer, rdec, arg_, arg_, arg_), SARGS(getpid, rdec, arg_none), SARGS(sendfile, rdec, arg_fd, arg_fd, arg_, arg_), @@ -99,8 +111,10 @@ static const struct syscall_format formats[] = { SARGS(setsockopt, rdec, arg_fd, arg_, arg_, arg_, arg_), SARGS(getsockopt, rdec, arg_fd, arg_, arg_, arg_, arg_), SARGS(clone, rdec, arg_clone_flags, arg_pointer, arg_pointer, arg_pointer, arg_), - // SARGS(fork, rdec, arg_none), - // SARGS(vfork, rdec, arg_none), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(fork, rdec, arg_none), + SARGS(vfork, rdec, arg_none), +#endif SARGS(execve, rdec, arg_, arg_, arg_), SARGS(exit, rnoreturn, arg_), SARGS(wait4, rdec, arg_dec, arg_, arg_, arg_), @@ -120,23 +134,31 @@ static const struct syscall_format formats[] = { SARGS(fdatasync, rdec, arg_fd), SARGS(truncate, rdec, arg_cstr, arg_), SARGS(ftruncate, rdec, arg_fd, arg_), - // SARGS(getdents, rdec, arg_fd, arg_, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(getdents, rdec, arg_fd, arg_, arg_), +#endif SARGS(getcwd, rdec, arg_, arg_), SARGS(chdir, rdec, arg_cstr), SARGS(fchdir, rdec, arg_fd), - // SARGS(rename, rdec, arg_cstr, arg_cstr), - // SARGS(mkdir, rdec, arg_cstr, arg_oct_mode), - // SARGS(rmdir, rdec, arg_cstr), - // SARGS(creat, rdec, arg_cstr, arg_oct_mode), - // SARGS(link, rdec, arg_cstr, arg_cstr), - // SARGS(unlink, rdec, arg_cstr), - // SARGS(symlink, rdec, arg_cstr, arg_cstr), - // SARGS(readlink, rdec, arg_cstr, arg_buf_out, arg_dec), - // SARGS(chmod, rdec, arg_cstr, arg_oct_mode), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(rename, rdec, arg_cstr, arg_cstr), + SARGS(mkdir, rdec, arg_cstr, arg_oct_mode), + SARGS(rmdir, rdec, arg_cstr), + SARGS(creat, rdec, arg_cstr, arg_oct_mode), + SARGS(link, rdec, arg_cstr, arg_cstr), + SARGS(unlink, rdec, arg_cstr), + SARGS(symlink, rdec, arg_cstr, arg_cstr), + SARGS(readlink, rdec, arg_cstr, arg_buf_out, arg_dec), + SARGS(chmod, rdec, arg_cstr, arg_oct_mode), +#endif SARGS(fchmod, rdec, arg_fd, arg_oct_mode), - // SARGS(chown, rdec, arg_cstr, arg_, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(chown, rdec, arg_cstr, arg_, arg_), +#endif SARGS(fchown, rdec, arg_fd, arg_, arg_), - // SARGS(lchown, rdec, arg_cstr, arg_, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(lchown, rdec, arg_cstr, arg_, arg_), +#endif SARGS(umask, rmode, arg_oct_mode), SARGS(gettimeofday, rdec, arg_, arg_), SARGS(getrlimit, rdec, arg_, arg_), @@ -152,7 +174,9 @@ static const struct syscall_format formats[] = { SARGS(geteuid, rdec, arg_none), SARGS(getegid, rdec, arg_none), SARGS(setpgid, rdec, arg_none), - // SARGS(getpgrp, rdec, arg_none), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(getpgrp, rdec, arg_none), +#endif SARGS(setsid, rdec, arg_none), SARGS(setreuid, rdec, arg_, arg_), SARGS(setregid, rdec, arg_, arg_), @@ -173,14 +197,20 @@ static const struct syscall_format formats[] = { SARGS(rt_sigqueueinfo, rdec, arg_, arg_, arg_), SARGS(rt_sigsuspend, rdec, arg_, arg_), SARGS(sigaltstack, rdec, arg_, arg_), - // SARGS(utime, rdec, arg_cstr, arg_), - // SARGS(mknod, rdec, arg_cstr, arg_, arg_), - // SARGS(uselib, rdec, arg_cstr), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(utime, rdec, arg_cstr, arg_), + SARGS(mknod, rdec, arg_cstr, arg_, arg_), + SARGS(uselib, rdec, arg_cstr), +#endif SARGS(personality, rdec, arg_), - // SARGS(ustat, rdec, arg_, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(ustat, rdec, arg_, arg_), +#endif SARGS(statfs, rdec, arg_cstr, arg_), SARGS(fstatfs, rdec, arg_fd, arg_), - // SARGS(sysfs, rdec, arg_, arg_, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(sysfs, rdec, arg_, arg_, arg_), +#endif SARGS(getpriority, rdec, arg_, arg_), SARGS(setpriority, rdec, arg_, arg_, arg_), SARGS(sched_setparam, rdec, arg_, arg_), @@ -195,11 +225,17 @@ static const struct syscall_format formats[] = { SARGS(mlockall, rdec, arg_), SARGS(munlockall, rdec, arg_none), SARGS(vhangup, rdec, arg_none), - // SARGS(modify_ldt, rdec, arg_, arg_, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(modify_ldt, rdec, arg_, arg_, arg_), +#endif SARGS(pivot_root, rdec, arg_cstr, arg_), - // SARGS(_sysctl, rdec, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(_sysctl, rdec, arg_), +#endif SARGS(prctl, rdec, arg_, arg_, arg_, arg_, arg_), - // SARGS(arch_prctl, rdec, arg_, arg_, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(arch_prctl, rdec, arg_, arg_, arg_), +#endif SARGS(adjtimex, rdec, arg_), SARGS(setrlimit, rdec, arg_, arg_), SARGS(chroot, rdec, arg_cstr), @@ -213,8 +249,10 @@ static const struct syscall_format formats[] = { SARGS(reboot, rdec, arg_, arg_, arg_, arg_), SARGS(sethostname, rdec, arg_, arg_), SARGS(setdomainname, rdec, arg_, arg_), - // SARGS(iopl, rdec, arg_), - // SARGS(ioperm, rdec, arg_, arg_, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(iopl, rdec, arg_), + SARGS(ioperm, rdec, arg_, arg_, arg_), +#endif SARGS(gettid, rdec, arg_none), SARGS(readahead, rdec, arg_fd, arg_dec, arg_dec), SARGS(setxattr, rdec, arg_cstr, arg_cstr, arg_buf_in, arg_dec, arg_), @@ -230,19 +268,27 @@ static const struct syscall_format formats[] = { SARGS(lremovexattr, rdec, arg_cstr, arg_cstr), SARGS(fremovexattr, rdec, arg_fd, arg_cstr), SARGS(tkill, rdec, arg_, arg_), - // SARGS(time, rdec, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(time, rdec, arg_), +#endif SARGS(futex, rdec, arg_, arg_, arg_, arg_, arg_, arg_), SARGS(sched_setaffinity, rdec, arg_, arg_, arg_), SARGS(sched_getaffinity, rdec, arg_, arg_, arg_), - // SARGS(set_thread_area, rdec, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(set_thread_area, rdec, arg_), +#endif SARGS(io_setup, rdec, arg_, arg_), SARGS(io_destroy, rdec, arg_), SARGS(io_getevents, rdec, arg_, arg_, arg_, arg_, arg_), SARGS(io_submit, rdec, arg_, arg_, arg_), SARGS(io_cancel, rdec, arg_, arg_, arg_), - // SARGS(get_thread_area, rdec, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(get_thread_area, rdec, arg_), +#endif SARGS(lookup_dcookie, rdec, arg_, arg_, arg_), - // SARGS(epoll_create, rdec, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(epoll_create, rdec, arg_), +#endif SARGS(getdents64, rdec, arg_fd, arg_, arg_), SARGS(set_tid_address, rdec, arg_), SARGS(semtimedop, rdec, arg_, arg_, arg_, arg_), @@ -257,10 +303,14 @@ static const struct syscall_format formats[] = { SARGS(clock_getres, rdec, arg_, arg_), SARGS(clock_nanosleep, rdec, arg_, arg_, arg_, arg_), SARGS(exit_group, rnoreturn, arg_), - // SARGS(epoll_wait, rdec, arg_fd, arg_, arg_, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(epoll_wait, rdec, arg_fd, arg_, arg_, arg_), +#endif SARGS(epoll_ctl, rdec, arg_fd, arg_, arg_fd, arg_), SARGS(tgkill, rdec, arg_, arg_, arg_), - // SARGS(utimes, rdec, arg_cstr, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(utimes, rdec, arg_cstr, arg_), +#endif SARGS(mbind, rdec, arg_, arg_, arg_, arg_, arg_), SARGS(set_mempolicy, rdec, arg_, arg_, arg_), SARGS(get_mempolicy, rdec, arg_, arg_, arg_, arg_, arg_), @@ -277,7 +327,9 @@ static const struct syscall_format formats[] = { SARGS(keyctl, rdec, arg_, arg_, arg_, arg_, arg_), SARGS(ioprio_set, rdec, arg_, arg_, arg_), SARGS(ioprio_get, rdec, arg_, arg_), - // SARGS(inotify_init, rdec, arg_none), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(inotify_init, rdec, arg_none), +#endif SARGS(inotify_add_watch, rdec, arg_fd, arg_cstr, arg_), SARGS(inotify_rm_watch, rdec, arg_fd, arg_), SARGS(migrate_pages, rdec, arg_, arg_, arg_, arg_), @@ -285,10 +337,14 @@ static const struct syscall_format formats[] = { SARGS(mkdirat, rdec, arg_atfd, arg_cstr, arg_oct_mode), SARGS(mknodat, rdec, arg_atfd, arg_cstr, arg_oct_mode, arg_), SARGS(fchownat, rdec, arg_atfd, arg_cstr, arg_, arg_, arg_), - // SARGS(futimesat, rdec, arg_atfd, arg_cstr, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(futimesat, rdec, arg_atfd, arg_cstr, arg_), +#endif SARGS(newfstatat, rdec, arg_atfd, arg_cstr, arg_, arg_), SARGS(unlinkat, rdec, arg_atfd, arg_cstr, arg_), - // SARGS(renameat2, rdec, arg_atfd, arg_cstr, arg_atfd, arg_cstr), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(renameat, rdec, arg_atfd, arg_cstr, arg_atfd, arg_cstr), +#endif SARGS(linkat, rdec, arg_atfd, arg_cstr, arg_atfd, arg_cstr, arg_), SARGS(symlinkat, rdec, arg_cstr, arg_atfd, arg_cstr), SARGS(readlinkat, rdec, arg_atfd, arg_cstr, arg_buf_out, arg_dec), @@ -306,9 +362,13 @@ static const struct syscall_format formats[] = { SARGS(move_pages, rdec, arg_, arg_, arg_, arg_, arg_, arg_), SARGS(utimensat, rdec, arg_atfd, arg_cstr, arg_, arg_), SARGS(epoll_pwait, rdec, arg_fd, arg_, arg_, arg_, arg_, arg_), - // SARGS(signalfd, rdec, arg_fd, arg_, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(signalfd, rdec, arg_fd, arg_, arg_), +#endif SARGS(timerfd_create, rdec, arg_, arg_), - // SARGS(eventfd, rdec, arg_), +#if defined(__x86_64__) || defined(_M_X64) + SARGS(eventfd, rdec, arg_), +#endif SARGS(fallocate, rdec, arg_fd, arg_, arg_, arg_), SARGS(timerfd_settime, rdec, arg_fd, arg_, arg_, arg_), SARGS(timerfd_gettime, rdec, arg_fd, arg_), @@ -397,6 +457,11 @@ static const struct syscall_format formats[] = { #undef SARGS +#if defined(__x86_64__) || defined(_M_X64) +static struct syscall_format open_with_o_creat = {.name = "open", rdec, + {arg_cstr, arg_open_flags, arg_oct_mode}}; +#endif + static struct syscall_format openat_with_o_creat = {.name = "openat", rdec, {arg_atfd, arg_cstr, arg_open_flags, arg_oct_mode}}; @@ -448,6 +513,11 @@ get_syscall_format(const struct syscall_desc *desc) if (formats[desc->nr].name == NULL) return &unkown; +#if defined(__x86_64__) || defined(_M_X64) + if (desc->nr == SYS_open && oflags_refer_mode_arg((int)desc->args[1])) + return &open_with_o_creat; +#endif + if (desc->nr == SYS_openat && oflags_refer_mode_arg((int)desc->args[2])) return &openat_with_o_creat; From 279be1982bfd050cff7427191c8da8ce95f78022 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 6 Feb 2025 10:28:24 +0100 Subject: [PATCH 038/143] Added missing syscall formats --- src/syscall_formats.c | 81 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/syscall_formats.c b/src/syscall_formats.c index e3b754b..492e557 100644 --- a/src/syscall_formats.c +++ b/src/syscall_formats.c @@ -452,6 +452,87 @@ static const struct syscall_format formats[] = { #ifdef SYS_pkey_free SARGS(pkey_free, rdec, arg_), #endif +#ifdef SYS_io_pgetevents + SARGS(io_pgetevents, rdec, arg_dec, arg_dec, arg_dec, arg_pointer, arg_pointer, arg_pointer), +#endif +#ifdef SYS_rseq + SARGS(rseq, rdec, arg_pointer, arg_dec32, arg_, arg_dec32), +#endif +#ifdef SYS_pidfd_send_signal + SARGS(pidfd_send_signal, rdec, arg_dec32, arg_dec32, arg_pointer, arg_), +#endif +#ifdef SYS_io_uring_setup + SARGS(io_uring_setup, rdec, arg_dec32, arg_pointer), +#endif +#ifdef SYS_io_uring_enter + SARGS(io_uring_enter, rdec, arg_fd, arg_dec32, arg_dec32, arg_, arg_pointer), +#endif +#ifdef SYS_io_uring_register + SARGS(io_uring_register, rdec, arg_fd, arg_, arg_pointer, arg_dec32), +#endif +#ifdef SYS_open_tree + SARGS(open_tree, rdec, arg_atfd, arg_cstr, arg_open_flags), +#endif +#ifdef SYS_move_mount + SARGS(move_mount, rdec, arg_fd, arg_cstr, arg_atfd, arg_cstr, arg_), +#endif +#ifdef SYS_fsopen + SARGS(fsopen, rdec, arg_cstr, arg_), +#endif +#ifdef SYS_fsconfig + SARGS(fsconfig, rdec, arg_pointer, arg_dec32, arg_cstr, arg_pointer, arg_), +#endif +#ifdef SYS_fsmount + SARGS(fsmount, rdec, arg_fd, arg_), +#endif +#ifdef SYS_fspick + SARGS(fspick, rdec, arg_atfd, arg_cstr, arg_), +#endif +#ifdef SYS_pidfd_open + SARGS(pidfd_open, rdec, arg_dec32, arg_), +#endif +#ifdef SYS_clone3 + SARGS(clone3, rdec, arg_pointer, arg_dec32), +#endif +#ifdef SYS_close_range + SARGS(close_range, rdec, arg_dec32, arg_dec32, arg_), +#endif +#ifdef SYS_openat2 + SARGS(openat2, rdec, arg_cstr, arg_pointer, arg_dec32), +#endif +#ifdef SYS_pidfd_getfd + SARGS(pidfd_getfd, rdec, arg_fd, arg_fd, arg_), +#endif +#ifdef SYS_faccessat2 + SARGS(faccessat2, rdec, arg_atfd, arg_cstr, arg_oct_mode, arg_), +#endif +#ifdef SYS_process_madvise + SARGS(process_madvise, rdec, arg_fd, arg_pointer, arg_dec32, arg_), +#endif +#ifdef SYS_epoll_pwait2 + SARGS(epoll_pwait2, rdec, arg_fd, arg_pointer, arg_dec32, arg_pointer, arg_pointer), +#endif +#ifdef SYS_mount_setattr + SARGS(mount_setattr, rdec, arg_fd, arg_cstr, arg_, arg_pointer, arg_dec32), +#endif +#ifdef SYS_quotactl_fd + SARGS(quotactl_fd, rdec, arg_fd, arg_dec32, arg_dec32, arg_pointer), +#endif +#ifdef SYS_landlock_create_ruleset + SARGS(landlock_create_ruleset, rdec, arg_pointer, arg_dec32, arg_), +#endif +#ifdef SYS_landlock_add_rule + SARGS(landlock_add_rule, rdec, arg_fd, arg_dec32, arg_pointer, arg_), +#endif +#ifdef SYS_landlock_restrict_self + SARGS(landlock_restrict_self, rdec, arg_fd, arg_), +#endif +#ifdef SYS_memfd_secret + SARGS(memfd_secret, rdec, arg_), +#endif +#ifdef SYS_process_mrelease + SARGS(process_mrelease, rdec, arg_fd, arg_) +#endif }; /* END CSTYLED */ From 808c0909c10e4fe3403ea50feaa937bbe8adcd73 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 6 Feb 2025 11:18:16 +0100 Subject: [PATCH 039/143] Fixed and enabled perl coding style check --- CMakeLists.txt | 4 ++-- src/arch/x86_64/disasm_wrapper.c | 2 +- src/arch/x86_64/patcher.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f99726f..31ce7ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,11 +41,11 @@ if(",${CMAKE_SOURCE_DIR}," STREQUAL ",${CMAKE_BINARY_DIR},") endif() option(PERFORM_STYLE_CHECKS - "check coding style, license headers (requires perl)" OFF) + "check coding style, license headers (requires perl)" ON) option(BUILD_TESTS "build and enable tests" OFF) option(BUILD_EXAMPLES "build examples" OFF) option(TREAT_WARNINGS_AS_ERRORS - "make the build fail on any warnings during compilation, or linking" OFF) + "make the build fail on any warnings during compilation, or linking" ON) option(EXPECT_SPURIOUS_SYSCALLS "account for some unexpected syscalls in tests - enable while using sanitizers, gcov" OFF) option(STATIC_CAPSTONE "statically link libcapstone into the shared library" OFF) diff --git a/src/arch/x86_64/disasm_wrapper.c b/src/arch/x86_64/disasm_wrapper.c index d399c74..ba2e077 100644 --- a/src/arch/x86_64/disasm_wrapper.c +++ b/src/arch/x86_64/disasm_wrapper.c @@ -229,4 +229,4 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, result.is_set = true; return result; -} \ No newline at end of file +} diff --git a/src/arch/x86_64/patcher.c b/src/arch/x86_64/patcher.c index ab9c465..0ee0db2 100644 --- a/src/arch/x86_64/patcher.c +++ b/src/arch/x86_64/patcher.c @@ -764,4 +764,4 @@ activate_patches(struct intercept_desc *desc) mprotect_no_intercept(first_page, size, PROT_READ | PROT_EXEC, "mprotect PROT_READ | PROT_EXEC"); -} \ No newline at end of file +} From 9b0ae571302c124e35fa886f912fed2f8b997cda Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 6 Feb 2025 11:18:49 +0100 Subject: [PATCH 040/143] Removed unused flag --- src/arch/riscv/disasm_wrapper.c | 3 +-- src/disasm_wrapper.h | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/arch/riscv/disasm_wrapper.c b/src/arch/riscv/disasm_wrapper.c index c3ca551..014252d 100644 --- a/src/arch/riscv/disasm_wrapper.c +++ b/src/arch/riscv/disasm_wrapper.c @@ -72,7 +72,7 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, #endif switch (context->insn->id) { - /* PC-relative jumps */ + /* PC-relative jumps */ case RISCV_INS_BEQ: case RISCV_INS_BGE: case RISCV_INS_BGEU: @@ -101,7 +101,6 @@ intercept_disasm_next_instruction(struct intercept_disasm_context *context, default: result.is_jump = false; result.has_ip_relative_opr = false; -// result.uses_ra = false; cs_riscv_op *op; result.uses_t6 = false; for (uint8_t op_i = 0; !result.uses_t6 && diff --git a/src/disasm_wrapper.h b/src/disasm_wrapper.h index 61dca3a..d9ee84a 100644 --- a/src/disasm_wrapper.h +++ b/src/disasm_wrapper.h @@ -67,9 +67,6 @@ struct intercept_disasm_result { /* as of now this only refers to endbr64 */ bool is_endbr; - /* Flag marking if ra is one of the operands of the instruction */ - bool uses_ra; - /* Flag marking if t6 is one of the operands of the instruction*/ bool uses_t6; From f220d8ed087a8c9a4a11c55f91ef0b7c77ee88cf Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 6 Feb 2025 11:46:06 +0100 Subject: [PATCH 041/143] Disabling perl style check again --- CMakeLists.txt | 2 +- test/intercept_sys_open.c | 35 ------------ ...pt_sys_open_2.c => intercept_sys_openat.c} | 11 +--- test/intercept_sys_read_2.c | 49 ----------------- test/intercept_sys_write_2.c | 53 ------------------- 5 files changed, 2 insertions(+), 148 deletions(-) delete mode 100644 test/intercept_sys_open.c rename test/{intercept_sys_open_2.c => intercept_sys_openat.c} (63%) delete mode 100644 test/intercept_sys_read_2.c delete mode 100644 test/intercept_sys_write_2.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 31ce7ff..a6f17c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ if(",${CMAKE_SOURCE_DIR}," STREQUAL ",${CMAKE_BINARY_DIR},") endif() option(PERFORM_STYLE_CHECKS - "check coding style, license headers (requires perl)" ON) + "check coding style, license headers (requires perl)" OFF) option(BUILD_TESTS "build and enable tests" OFF) option(BUILD_EXAMPLES "build examples" OFF) option(TREAT_WARNINGS_AS_ERRORS diff --git a/test/intercept_sys_open.c b/test/intercept_sys_open.c deleted file mode 100644 index 9c062d0..0000000 --- a/test/intercept_sys_open.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "libsyscall_intercept_hook_point.h" -#include -#include -#include -#include -#include -#include - - -static int hook(long syscall_number, - long arg0, long arg1, - long arg2, long arg3, - long arg4, long arg5, - long *result) -{ - if (syscall_number == SYS_openat) { - write(1,"Proof of openat interception\n",29); - } - return 1; -} - -static __attribute__((constructor)) void init(void) -{ - intercept_hook_point = hook; -} - -//int main() { -// int fd = openat(AT_FDCWD,"non_existing_original_file.txt", O_RDONLY); -// if (fd >= 0) { -// write(1, "Success: File opened\n", 21); -// } else { -// write(1, "Specified file doesn't exist - Test is ok if previous line is:\n" -// "\"Proof of openat interception\"\n", 25); -// } -//} diff --git a/test/intercept_sys_open_2.c b/test/intercept_sys_openat.c similarity index 63% rename from test/intercept_sys_open_2.c rename to test/intercept_sys_openat.c index f55f987..392401b 100644 --- a/test/intercept_sys_open_2.c +++ b/test/intercept_sys_openat.c @@ -14,7 +14,7 @@ static int hook(long syscall_number, long *result) { if (syscall_number == SYS_openat) { - write(1,"Proof of openat interception\n",29); + write(1,"Proof of openat interception\n",29); } return 1; } @@ -23,12 +23,3 @@ static __attribute__((constructor)) void init(void) { intercept_hook_point = hook; } - -int main() { - int fd = openat(AT_FDCWD,"non_existing_original_file.txt", O_RDONLY); - if (fd >= 0) { - write(1, "Success: File opened\n", 21); - } else { - write(1, "Failure: File not opened\n", 25); - } -} diff --git a/test/intercept_sys_read_2.c b/test/intercept_sys_read_2.c deleted file mode 100644 index 5889044..0000000 --- a/test/intercept_sys_read_2.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "libsyscall_intercept_hook_point.h" -#include -#include -#include -#include -#include - - -static int hook(long syscall_number, - long arg0, long arg1, - long arg2, long arg3, - long arg4, long arg5, - long *result) -{ - (void)arg3; - (void)arg4; - (void)arg5; - (void)result; - - if (syscall_number == SYS_read) { - char *buf = (char *)arg1; - size_t len = (size_t)arg2; - const char interc[] = "intercepted_read\n"; - const char *src = interc; - - if (len > sizeof(interc)) { - *result = 0; - while (*src != '\0') { - *buf++ = *src++; - *result += 1; - } - *buf = '\0'; - *result += 1; - } - return 0; - } - return 1; -} - -static __attribute__((constructor)) void init(void) -{ - intercept_hook_point = hook; -} - -int main() { - char buf[128]; - read(0, buf, sizeof(buf)); - write(1, buf, strlen(buf)); // Should print "intercepted_read" -} \ No newline at end of file diff --git a/test/intercept_sys_write_2.c b/test/intercept_sys_write_2.c deleted file mode 100644 index e544d5f..0000000 --- a/test/intercept_sys_write_2.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "libsyscall_intercept_hook_point.h" -#include -#include -#include -#include -#include - -static int -hook(long syscall_number, - long arg0, long arg1, - long arg2, long arg3, - long arg4, long arg5, - long *result) -{ - (void)arg0; - (void)arg2; - (void)arg3; - (void)arg4; - (void)arg5; - (void)result; - - if (syscall_number == SYS_write) { - const char interc[] = "intercepted_"; - const char *src = interc; - - /* write(fd, buf, len) */ - size_t len = (size_t)arg2; - char *buf = (char *)arg1; - -#ifdef EXPECT_SPURIOUS_SYSCALLS - if (strcmp(buf, "original_syscall") != 0) - return 1; -#endif - - if (len > sizeof(interc)) { - while (*src != '\0') - *buf++ = *src++; - } - } - - return 1; -} - -static __attribute__((constructor)) void -init(void) -{ - intercept_hook_point = hook; -} - -int main() { - char buf[128] = "original_syscall\n"; - write(1, buf, strlen(buf)); -} From db3308f5ae8e1fcde68c54bf77384853f8f5a73a Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 6 Feb 2025 11:47:21 +0100 Subject: [PATCH 042/143] Commented lines cleanup --- src/disasm_wrapper.h | 2 +- src/intercept.c | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/disasm_wrapper.h b/src/disasm_wrapper.h index d9ee84a..ffe64dc 100644 --- a/src/disasm_wrapper.h +++ b/src/disasm_wrapper.h @@ -67,7 +67,7 @@ struct intercept_disasm_result { /* as of now this only refers to endbr64 */ bool is_endbr; - /* Flag marking if t6 is one of the operands of the instruction*/ + /* Flag marking if t6 is one of the operands of the instruction */ bool uses_t6; /* diff --git a/src/intercept.c b/src/intercept.c index 1ae8c59..18e6337 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -661,8 +661,6 @@ intercept_routine(struct context *context) get_syscall_in_context(context, &desc); - // debug_dump("ra: %lx", context->ra); - if (handle_magic_syscalls(&desc, &result) == 0) return (struct wrapper_ret){FIRST_RET_REG = result, SECOND_RET_REG = 1 }; @@ -718,7 +716,6 @@ intercept_routine(struct context *context) } intercept_log_syscall(patch, &desc, KNOWN, result); - // debug_dump("intercepted ecall -> returning to asm_wrapper - result: %ld\n",result); return (struct wrapper_ret){ FIRST_RET_REG = result, SECOND_RET_REG = 1 }; } From eb98da3726d01a078f9490a904a4ba8c74d49155 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 6 Feb 2025 11:56:26 +0100 Subject: [PATCH 043/143] Removed unused patcher.c from arch-independent directory --- src/patcher.c | 753 -------------------------------------------------- 1 file changed, 753 deletions(-) delete mode 100644 src/patcher.c diff --git a/src/patcher.c b/src/patcher.c deleted file mode 100644 index ac9d89c..0000000 --- a/src/patcher.c +++ /dev/null @@ -1,753 +0,0 @@ -/* - * Copyright 2016-2020, Intel Corporation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * patcher.c -- patching a library - * - * Jumping from the subject library: - * - * /--------------------------\ - * | subject.so | - * | | - * | jmp to_trampoline_table | patched by activate_patches() - * /->| | | - * | \___|______________________/ - * | | - * | /---|--------------------------\ - * | | movabs %r11, wrapper_address | jmp generated by activate_patches() - * | | jmp *%r11 | This allows subject.so and - * | | | | libsyscall_intercept.so to be farther - * | \___|__________________________/ than 2 gigabytes from each other - * | | - * | /---|-----------------------------\ - * | | | libsyscall_intercept.so | - * | | | | - * | | /-|--------------------------\ | - * | | | | static unsigned char | | - * | | | | asm_wrapper_space[] | | - * | | | | in BSS | | wrapper routine - * | | | | | | generated into asm_wrapper_space - * | | | | | | by create_wrapper() - * | | |wrapper routine | | - * | | |calls C hook function ----------> intercept_routine in intercept.c - * | | |movabs %r11, return_address | | - * | | |jmp *%r11 | | - * | | \_|__________________________/ | - * | \___|_____________________________/ - * | | - * \______/ - * - */ - -#include "intercept.h" -#include "intercept_util.h" -#include "intercept_log.h" - -#include -#include -#include -#include -#include - -#include -#include - -#define COMPAT_HWCAP_ISA_C (1 << ('C' - 'A')) - -/* The size of a trampoline jump, 64-bit address loading process into a register - * (which requires 14 instructions to encode directly in machine code) + JALR. - * These are preceded and succeeded by storing and restoring of tmp registers - * used for the creation of the absolute jump. We can't clobber them since two - * instructions that were placed before the original ecall still must be - * executed. - */ -// enum { TRAMPOLINE_SIZE = 23 * 4 }; - -static void create_wrapper(struct patch_desc *patch, unsigned char **dst); -static void create_load_uint64t_into_t0(uint8_t *code, uint64_t value); -static void create_load_uint64t_into_t6(uint8_t *code, uint64_t value); - -/* - * create_absolute_jump(from, to) - * - */ -static unsigned char * -create_absolute_jump(unsigned char *from, void *to) -{ - uint32_t *instructions = (uint32_t *)from; - instructions[0] = 0xfe010113; // addi sp, sp, -32 - instructions[1] = 0x00613023; // sd t1, 0(sp) - instructions[2] = 0x00713423; // sd t2, 8(sp) - instructions[3] = 0x01c13823; // sd t3, 16(sp) - instructions[9] = 0x7ffff337; // lui t1, 0x7ffff - instructions[10] = 0x7ff06393; // ori t2, zero, 0x7ff - instructions[11] = 0x00139393; // slli t2, t2, 1 - instructions[12] = 0x0013e393; // ori t2, t2, 1 - instructions[13] = 0x00736333; // or t1, t1, t2 - instructions[14] = 0x00131313; // slli t1, t1, 1 - instructions[15] = 0x00136313; // ori t1, t1, 1 - instructions[16] = 0x006e7e33; // and t3, t3, t1 - instructions[17] = 0x01cfefb3; // or t6, t6, t3 - instructions[18] = 0x00013303; // ld t1, 0(sp) - instructions[19] = 0x00813383; // ld t2, 8(sp) - instructions[20] = 0x01013e03; // ld t3, 16(sp) - instructions[21] = 0x02010113; // addi sp, sp, 32 - instructions[22] = 0x000f8067; // jalr zero, t6, 0 - create_load_uint64t_into_t6((uint8_t *)(instructions + 4),(uint64_t)to); // writes 5 instructions starting from instructions[4] - return (unsigned char *)(instructions + 23); -} - -/* - * create_jump(opcode, from, to) - * Create a 5 byte jmp/call instruction jumping to address to, by overwriting - * code starting at address from. - */ -void -create_jump(unsigned char opcode, unsigned char *from, void *to) -{ - /* - * The operand is the difference between the - * instruction pointer pointing to the instruction - * just after the call, and the to address. - * Thus RIP seen by the call instruction is from + 5 - */ - ptrdiff_t delta = ((unsigned char *)to) - (from + JUMP_INS_SIZE); - - if (delta > ((ptrdiff_t)INT32_MAX) || delta < ((ptrdiff_t)INT32_MIN)) - xabort("create_jump distance check"); - - int32_t delta32 = (int32_t)delta; - unsigned char *d = (unsigned char *)&delta32; - - from[0] = opcode; - from[1] = d[0]; - from[2] = d[1]; - from[3] = d[2]; - from[4] = d[3]; -} - -/* - * check_trampoline_usage - - * Make sure the trampoline table allocated at the beginning of patching has - * enough space for all trampolines. This just aborts the process if the - * allocate space does not seem to be enough, but it can be fairly easy - * to implement more allocation here if such need would arise. - */ -static void -check_trampoline_usage(const struct intercept_desc *desc) -{ - if (!desc->uses_trampoline_table) - return; - - /* - * We might actually not have enough space for creating - * more trampolines. - */ - - size_t used = (size_t)(desc->next_trampoline - desc->trampoline_table); - - if (used + TRAMPOLINE_SIZE >= desc->trampoline_table_size) - xabort("trampoline space not enough"); -} - -/* - * is_copiable_before_syscall - * checks if an instruction found before a syscall instruction - * can be copied (and thus overwritten). - */ -static bool -is_copiable_before_syscall(struct intercept_disasm_result ins) -{ - if (!ins.is_set) - return false; - - return !(ins.has_ip_relative_opr || - ins.is_call || - ins.is_rel_jump || - ins.is_jump || - ins.is_ret || - ins.is_endbr || - ins.is_syscall || - ins.uses_t6); -} - -/* - * is_copiable_after_syscall - * checks if an instruction found after a syscall instruction - * can be copied (and thus overwritten). - * - * Notice: we allow the copy of ret instructions. - */ -static bool -is_copiable_after_syscall(struct intercept_disasm_result ins) -{ - if (!ins.is_set) - return false; - - return !(ins.has_ip_relative_opr || - ins.is_call || - ins.is_rel_jump || - ins.is_jump || - ins.is_endbr || - ins.is_syscall || - ins.uses_t6); -} - - -/* - * check_surrounding_instructions - * Sets up the following members in a patch_desc, based on - * instruction being relocatable or not: - * uses_prev_ins ; uses_prev_ins_2 ; uses_next_ins - */ -static void -check_surrounding_instructions(struct intercept_desc *desc, - struct patch_desc *patch) -{ - patch->uses_prev_ins = (is_copiable_before_syscall(patch->preceding_ins) && - !has_jump(desc, patch->syscall_addr)); - - if (patch->uses_prev_ins) { - patch->uses_prev_ins_2 = (patch->uses_prev_ins && - is_copiable_before_syscall(patch->preceding_ins_2) && - !has_jump(desc, patch->syscall_addr - patch->preceding_ins.length)); - } else { - patch->uses_prev_ins_2 = false; - } - - patch->uses_next_ins = (is_copiable_after_syscall(patch->following_ins) && - !has_jump(desc, patch->syscall_addr + SYSCALL_INS_SIZE)); -} - -/* - * create_patch_wrappers - create the custom assembly wrappers - * around each syscall to be intercepted. Well, actually, the - * function create_wrapper does that, so perhaps this function - * deserves a better name. - * What this function actually does, is figure out how to create - * a jump instruction in libc ( which bytes to overwrite ). - * If it successfully finds suitable bytes for hotpatching, - * then it determines the exact bytes to overwrite, and the exact - * address for jumping back to libc. - * - * This is all based on the information collected by the routine - * find_syscalls, which does the disassembling, finding jump destinations, - * finding padding bytes, etc... - */ -void -create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) -{ - short min_treshold = JUMP_INS_SIZE; - bool c_isa_supported = getauxval(AT_HWCAP) & COMPAT_HWCAP_ISA_C; - for (unsigned patch_i = 0; patch_i < desc->count; ++patch_i) { - struct patch_desc *patch = desc->items + patch_i; - debug_dump("patching %s:0x%lx - patch_number: %u\n", desc->path, - patch->syscall_addr - desc->base_addr, patch_i); - - /* - * No padding space is available, so check the - * instructions surrounding the syscall instruction. - * If they can be relocated, then they can be - * overwritten. Of course some instructions depend - * on the value of the RIP register, these can not - * be relocated. - */ - - check_surrounding_instructions(desc, patch); - - /* - * Count the number of overwritable bytes - * in the variable length. - * Sum up the bytes that can be overwritten. - * The 4 bytes of the ecall instruction can - * be overwritten definitely, so length starts - * as SYSCALL_INS_SIZE ( 4 bytes ). - */ - unsigned length = SYSCALL_INS_SIZE; - - patch->needs_compressed_ins = false; - patch->padding_is_needed = false; - patch->dst_jmp_patch = patch->syscall_addr; - - /* - * If the preceding instruction is relocatable, - * add its length. Also, the instruction right - * before that. - */ - if (patch->uses_prev_ins) { - length += patch->preceding_ins.length; - patch->dst_jmp_patch -= - patch->preceding_ins.length; - - if (patch->uses_prev_ins_2 && (length < JUMP_INS_SIZE)) { - length += patch->preceding_ins_2.length; - patch->dst_jmp_patch -= - patch->preceding_ins_2.length; - } else { - /* - * If it could be used but is not necessary we need - * to set the flag to false so that it's not relocated - */ - patch->uses_prev_ins_2 = false; - } - } - - /* - * If the following instruction is relocatable, - * add its length. This also affects the return address. - * Normally, the library would return to libc after - * handling the syscall by jumping to instruction - * right after the syscall. But if that instruction - * is overwritten, the returning jump must jump to - * the instruction after it. - */ - if (patch->uses_next_ins && (length < JUMP_INS_SIZE)) { - length += patch->following_ins.length; - - /* - * Address of the syscall instruction - * plus 4 bytes - * plus the length of the following instruction - * - * adds up to: - * - * the address of the second instruction after - * the syscall. - */ - patch->return_address = patch->syscall_addr + - SYSCALL_INS_SIZE + - patch->following_ins.length; - } else { - /* - * If it could be used but is not necessary we need - * to set the flag to false so that it's not relocated - */ - patch->uses_next_ins = false; - patch->return_address = patch->syscall_addr + SYSCALL_INS_SIZE; - } - - if (length > JUMP_INS_SIZE) { - patch->padding_is_needed = true; - // patch->return_address -= (length - JUMP_INS_SIZE); - } - - /* - * Check if compressed instructions module is supported by the CPU. - * If yes, 6 bytes are enough to place an auipc+c.jalr sequence. - * If the length of the patch is exactly 6 bytes, then we assert - * the flag marking the need of said sequence. - * - * If length is less than minimum needed bytes (value depending on - * ISA C module being supported or not), give up. - * - * TO DO: creating an environment variable marking if all ECALLs - * must be patchable for success or if we could just skip the - * unpatchable ones. - */ - if (c_isa_supported) { - if (length == 6) { - patch->needs_compressed_ins = true; - } - min_treshold = 6; - } - if (length < min_treshold) { - char buffer[0x1000]; - - int l = snprintf(buffer, sizeof(buffer), - "unintercepted syscall at: %s 0x%lx\n", - desc->path, - patch->syscall_offset); - - intercept_log(buffer, (size_t)l); - debug_dump("unintercepted syscall at: %s 0x%lx\n", - desc->path, - patch->syscall_offset); - xabort("not enough space for patching" - " around syscal"); - } - - mark_jump(desc, patch->return_address); - - create_wrapper(patch, dst); - } -} - -/* - * Referencing symbols defined in intercept_template.s - */ -extern unsigned char intercept_asm_wrapper_tmpl[]; -extern unsigned char intercept_asm_wrapper_tmpl_end; -extern unsigned char intercept_asm_wrapper_patch_desc_addr; -extern unsigned char intercept_asm_wrapper_wrapper_level1_addr; -extern unsigned char intercept_wrapper; - -size_t asm_wrapper_tmpl_size; -static ptrdiff_t o_patch_desc_addr; -static ptrdiff_t o_wrapper_level1_addr; - -bool intercept_routine_must_save_ymm = false; // temporarily hardcoded - -/* - * init_patcher - * Some variables need to be initialized before patching. - * This routine must be called once before patching any library. - */ -void -init_patcher(void) -{ - unsigned char *begin = &intercept_asm_wrapper_tmpl[0]; - - assert(&intercept_asm_wrapper_tmpl_end > begin); - assert(&intercept_asm_wrapper_patch_desc_addr > begin); - assert(&intercept_asm_wrapper_wrapper_level1_addr > begin); - assert(&intercept_asm_wrapper_patch_desc_addr < - &intercept_asm_wrapper_tmpl_end); - assert(&intercept_asm_wrapper_wrapper_level1_addr < - &intercept_asm_wrapper_tmpl_end); - - asm_wrapper_tmpl_size = - (size_t)(&intercept_asm_wrapper_tmpl_end - begin); - o_patch_desc_addr = &intercept_asm_wrapper_patch_desc_addr - begin; - o_wrapper_level1_addr = - &intercept_asm_wrapper_wrapper_level1_addr - begin; -} - - -/* - * create_ret_from_template - * Write a RET instruction (encoded as JALR) to return to patch->return_address. - * This is possible as long patch->return_address is saved to ra in the first - * place when jumping to trampoline when intercepting the system call. This is - * not explicitly written at the end of intercept_template.S since the fourth - * overwritten instruction has to be relocated before RET. - */ -static unsigned char * -create_ret_from_template(unsigned char *code) -{ - *((uint32_t *)code) = 0x00008067; // jalr zero, ra, 0 - return code + 4; -} - -/* - * create_load_uint64t_into_t0 - * Generates the first 5 instructions (LUI,ADDI,SLLI,LUI,ADDI) of a convoluted - * 14 instructions sequence that assign a 64 bit constant to a register. - * See intercept_template.S for the following 9 at - * intercept_asm_wrapper_patch_desc_addr (an equal sequence is placed at - * intercept_asm_wrapper_wrapper_level1_addr as well). - */ -static void -create_load_uint64t_into_t0(uint8_t *code, uint64_t value) -{ - - uint32_t *instructions = (uint32_t *)code; - uint32_t upper_32 = (value & 0xffffffff00000000) >> 32; - uint32_t lower_32 = (uint32_t)value; - - uint32_t lui_imm_field = upper_32 & 0xfffff000; - uint32_t addi_imm_field = 0; - if (upper_32 % 4096 != 0) { - addi_imm_field = upper_32 - lui_imm_field; - if (addi_imm_field > 2047) { - lui_imm_field += 4096; - addi_imm_field = -(4096 - addi_imm_field); - } - } - - instructions[0] = 0x000002b7 | lui_imm_field; // lui t0, 0x..... - instructions[1] = 0x00028293 | (addi_imm_field << 20); // addi t0, t0, 0x... - instructions[2] = 0x02029293; // slli t0, t0, 32 - - lui_imm_field = lower_32 & 0xfffff000; - addi_imm_field = 0; - if (lower_32 % 4096 != 0) { - addi_imm_field = lower_32 - lui_imm_field; - if (addi_imm_field > 2047) { - lui_imm_field += 4096; - addi_imm_field = -(4096 - addi_imm_field); - } - } - - instructions[3] = 0x00000e37 | lui_imm_field; // lui t3, 0x..... - instructions[4] = 0x000e0e13 | (addi_imm_field << 20); // addi t3, t3, 0x... -} - -static void -create_load_uint64t_into_t6(uint8_t *code, uint64_t value) -{ - - uint32_t *instructions = (uint32_t *)code; - uint32_t upper_32 = (value & 0xffffffff00000000) >> 32; - uint32_t lower_32 = (uint32_t)value; - - uint32_t lui_imm_field = upper_32 & 0xfffff000; - uint32_t addi_imm_field = 0; - if (upper_32 % 4096 != 0) { - addi_imm_field = upper_32 - lui_imm_field; - if (addi_imm_field > 2047) { - lui_imm_field += 4096; - addi_imm_field = -(4096 - addi_imm_field); - } - } - - instructions[0] = 0x00000fb7 | lui_imm_field; // lui t6, 0x..... - instructions[1] = 0x000f8f93 | (addi_imm_field << 20); // addi t6, t6, 0x... - instructions[2] = 0x020f9f93; // slli t6, t6, 32 - - lui_imm_field = lower_32 & 0xfffff000; - addi_imm_field = 0; - if (lower_32 % 4096 != 0) { - addi_imm_field = lower_32 - lui_imm_field; - if (addi_imm_field > 2047) { - lui_imm_field += 4096; - addi_imm_field = -(4096 - addi_imm_field); - } - } - - instructions[3] = 0x00000e37 | lui_imm_field; // lui t3, 0x..... - instructions[4] = 0x000e0e13 | (addi_imm_field << 20); // addi t3, t3, 0x... -} - -/* - * relocate_instruction - * Places an instruction equivalent to `ins` to the memory location at `dst`. - * Only handles instructions that can be copied verbatim, and some LEA - * instructions. - */ -static unsigned char * -relocate_instruction(unsigned char *dst, - const struct intercept_disasm_result *ins) -{ - memcpy(dst, ins->address, ins->length); - return dst + ins->length; -} - -/* - * create_wrapper - * Generates an assembly wrapper. Copies the template written in - * intercept_template.s, and generates the instructions specific - * to a particular syscall into the new copy. - * After this wrapper is created, a syscall can be replaced with a - * jump to this wrapper, and wrapper is going to call dest_routine - * (actually only after a call to mprotect_asm_wrappers). - */ -static void -create_wrapper(struct patch_desc *patch, unsigned char **dst) -{ - /* Create a new copy of the template */ - patch->asm_wrapper = *dst; - - /* Copy the previous instruction(s) */ - if (patch->uses_prev_ins) { - if (patch->uses_prev_ins_2) { - *dst = relocate_instruction(*dst, &patch->preceding_ins_2); - } - *dst = relocate_instruction(*dst, &patch->preceding_ins); - } - - memcpy(*dst, intercept_asm_wrapper_tmpl, asm_wrapper_tmpl_size); - create_load_uint64t_into_t0(*dst + o_patch_desc_addr, (uintptr_t)patch); // why the uintptr_t cast? What if the address is not representable on 32 bit? - create_load_uint64t_into_t0(*dst + o_wrapper_level1_addr, - (uintptr_t)&intercept_wrapper); - *dst += asm_wrapper_tmpl_size; - - /* Copy the following instruction */ - if (patch->uses_next_ins) - *dst = relocate_instruction(*dst, &patch->following_ins); - - *dst = create_absolute_jump(*dst, patch->return_address); - // *dst = create_ret_from_template(*dst); -} - -/* - * create_j(from, to) - * Create a 4 byte JAL instruction jumping to address to, by overwriting - * code starting at address from, if trampoline displacement is within + or - - * 1 MiB. Otherwise, create a 2 instructions sequence (LUI + JALR) which allows - * to reach trampoline if its displacement is within -2 GiB or JALR_MAX_OFFSET, - * which is (+2 GiB - 2050 Bytes). - */ -void -create_j(unsigned char *from, void *to) -{ - /* - * The operand is the difference between the - * instruction pointer pointing to the instruction - * just after the call, and the to address. - */ - ptrdiff_t delta = ((unsigned char *)to) - from; - uint32_t *instructions = (uint32_t *)from; - debug_dump("%p: ecall -> jalr %ld\t# %p\n", from, delta, to); - - const ptrdiff_t JALR_MAX_OFFSET = 2147481598; // ((2^31-1)-4095)+(2^11-1) = 0x7ffff000 + 0x7ff - const ptrdiff_t JALR_MIN_OFFSET = -2147483648; // (-2^31) = -0x80000000 - - if ((delta & 0x1) != 0) { - - xabort("create_j misaligned instruction fetch exception"); - - } - if (delta <= JALR_MAX_OFFSET && delta >= JALR_MIN_OFFSET) { - - uint32_t auipc = 0x00000f97; // auipc t6, 0x..... - uint32_t jalr = 0x000f8067; // jalr zero, t6, 0x... - uint32_t jalr_imm_field = 0; - uint32_t auipc_imm_field = (uint32_t)delta & 0xfffff000; // offset[31:12] - - /* - * if the offset is not a multiple of 4096 the 12 least significant bits - * of its value must be set by adding the correct immediate value contained - * in jalr imm field to the rs1 value which is set by auipc instruction - * preceding jalr - */ - if ((uint32_t)delta % 4096 != 0) { - jalr_imm_field = (uint32_t)delta - auipc_imm_field; - if (jalr_imm_field > 2046) { - auipc_imm_field += 4096; - jalr_imm_field = -(4096 - jalr_imm_field); - } - } - auipc |= auipc_imm_field; - jalr |= (jalr_imm_field << 20); - instructions[0] = auipc; // auipc t6, 0x..... - instructions[1] = jalr; // jalr zero, t6, 0x... - } else { - xabort("create_j distance check"); - } -} - -void -create_c_j(unsigned char *from, void *to) { - ptrdiff_t delta = ((unsigned char *)to) - from; - debug_dump("%p: ecall -> c.jalr %ld\t# %p\n", from, delta, to); - const ptrdiff_t AUIPC_MAX_OFFSET = 2147479552; - const ptrdiff_t AUIPC_MIN_OFFSET = -2147483648; - if ((delta & 0xfff) != 0) { - xabort("create_c_j misaligned instruction fetch exception"); - } - if (delta >= AUIPC_MIN_OFFSET && delta <= AUIPC_MAX_OFFSET) { - uint32_t auipc = 0x00000f97; // auipc t6, 0x..... - uint16_t c_jr = 0x8f82; // c.jr t6 - uint32_t auipc_imm_field = (uint32_t)delta & 0xfffff000; // offset[31:12] - auipc |= auipc_imm_field; - *(uint32_t *)from = auipc; - *(uint16_t *)(from + 4) = c_jr; - } else { - xabort("create_c_j distance check"); - } - -} - -/* - * activate_patches() - * Loop over all the patches, and overwrite each syscall. - */ -void -activate_patches(struct intercept_desc *desc) -{ - unsigned char *first_page; - size_t size; - - if (desc->count == 0) - return; - - first_page = round_down_address(desc->text_start); - size = (size_t)(desc->text_end - first_page); - - mprotect_no_intercept(first_page, size, - PROT_READ | PROT_WRITE | PROT_EXEC, - "mprotect PROT_READ | PROT_WRITE | PROT_EXEC"); - - for (unsigned i = 0; i < desc->count; ++i) { - const struct patch_desc *patch = desc->items + i; - debug_dump("\nactivating patch at dst_jmp_patch: 0x%lx - patch->return_address: 0x%lx - patch_n:%u\n" - "patch_absolute_return_address: %p\n", - patch->dst_jmp_patch-desc->base_addr,patch->return_address-desc->base_addr,i,patch->return_address); - - if (patch->dst_jmp_patch < desc->text_start || - patch->dst_jmp_patch > desc->text_end) - xabort("dst_jmp_patch outside text"); - - /* - * The dst_jmp_patch pointer contains the address where - * the actual jump instruction escaping the patched text - * segment should be written. - * This is either at the place of the original syscall - * instruction, or at some usable padding space close to - * it (an overwritable NOP instruction). - */ - - if (desc->uses_trampoline_table) { - /* - * First jump to the trampoline table, which - * should be in a 2 gigabyte range. From there, - * jump to the asm_wrapper. - */ - check_trampoline_usage(desc); - if (!patch->needs_compressed_ins) { - - /* jump - escape the text segment */ - create_j(patch->dst_jmp_patch, desc->next_trampoline); - - /* - * if patch is 10 bytes long, fill the last two - * with c.ebreak instruction. Template will jump back to the - * return address so c.ebreak will never be executed as long - * as the patching correctly the return jump from template. - */ - if (patch->padding_is_needed) { - *(uint16_t *)(patch->return_address-2) = 0x8002; // c.ebreak - } - - /* jump - escape the 2 GB range of the text segment */ - desc->next_trampoline = create_absolute_jump( - desc->next_trampoline, patch->asm_wrapper); - } else { - const int rem = (desc->next_trampoline - patch->dst_jmp_patch) % 4096; - if (rem) { - desc->next_trampoline += 4096 - rem; - } - create_c_j(patch->dst_jmp_patch, desc->next_trampoline); - - desc->next_trampoline = create_absolute_jump( - desc->next_trampoline, patch->asm_wrapper); - } - } else { - create_j(patch->dst_jmp_patch, patch->asm_wrapper); - } - - } - - mprotect_no_intercept(first_page, size, - PROT_READ | PROT_EXEC, - "mprotect PROT_READ | PROT_EXEC"); -} From 70f43e6fe82d827d93a6d9c52320e1cabbd4fa58 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 6 Feb 2025 18:10:23 +0100 Subject: [PATCH 044/143] Started writing arch-specific READMEs --- README.md | 83 ++++++++++++++++++++-------- src/arch/riscv/asm_wrapper.md | 19 +++++++ src/{ => arch/x86_64}/asm_wrapper.md | 8 +-- 3 files changed, 83 insertions(+), 27 deletions(-) create mode 100644 src/arch/riscv/asm_wrapper.md rename src/{ => arch/x86_64}/asm_wrapper.md (96%) diff --git a/README.md b/README.md index a813942..4847a3c 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,18 @@ # syscall_intercept -[![Build Status](https://travis-ci.org/pmem/syscall_intercept.svg)](https://travis-ci.org/pmem/syscall_intercept) -[![Coverage Status](https://codecov.io/github/pmem/syscall_intercept/coverage.svg)](https://codecov.io/gh/pmem/syscall_intercept) -[![Coverity Scan Build Status](https://scan.coverity.com/projects/12890/badge.svg)](https://scan.coverity.com/projects/syscall_intercept) +[//]: # ([![Build Status](https://travis-ci.org/pmem/syscall_intercept.svg)](https://travis-ci.org/pmem/syscall_intercept)) -This repository is a port to risc-V of the [syscall_intercept library](https://github.com/pmem/syscall_intercept). -Userspace syscall intercepting library. +[//]: # ([![Coverage Status](https://codecov.io/github/pmem/syscall_intercept/coverage.svg)](https://codecov.io/gh/pmem/syscall_intercept)) + +[//]: # ([![Coverity Scan Build Status](https://scan.coverity.com/projects/12890/badge.svg)](https://scan.coverity.com/projects/syscall_intercept)) + +This repository contains a multi-architecture porting of [syscall_intercept](https://github.com/pmem/syscall_intercept) working on both x86_64 and RISC-V # Dependencies # ## Runtime dependencies ## - * libcapstone -- the disassembly engine used under the hood + * libcapstone -- the disassembly engine used under the hood (RISC-V support requires version 5.0 or higher) ## Build dependencies ## @@ -53,10 +54,13 @@ There is an install target. For now, all it does, is cp. make install ``` -Coming soon: -```sh -make test -``` +[//]: # (Coming soon:) + +[//]: # (```sh) + +[//]: # (make test) + +[//]: # (```) # Synopsis # @@ -92,7 +96,7 @@ to signal to the intercepting library that the specific system call was ignored by the user and the original syscall should be executed. A zero return value signals that the user takes over the system call. In this case, the result of the system call -(the value stored in the RAX register after the system call) +(the value stored in the x86_64 `%rax` or RISC-V `$a0` register after the system call) can be set via the *result pointer. In order to use the library, the intercepting code is expected to be loaded using the LD_PRELOAD feature provided by the system loader. @@ -182,7 +186,7 @@ ls: reading directory '.': Operation not supported In order to handle syscalls in user space, the library relies on the following assumptions: -- Each syscall made by the applicaton is issued via libc +- Each syscall made by the application is issued via libc - No other facility attempts to hotpatch libc in the same process - The libc implementation is already loaded in the processes memory space when the intercepting library is being initialized @@ -193,27 +197,29 @@ for the methods listed in this section ##### Disassembly: ##### The library disassembles the text segment of the libc loaded into the memory space of the process it is initialized in. It -locates all syscall instructions, and replaces each of them -with a jump to a unique address. Since the syscall instruction -of the x86_64 ISA occupies only two bytes, the method involves +locates all `syscall` or `ecall` instructions, and replaces each of them +with a jump to a unique address. Since x86_64 ISA `syscall` instruction +occupies only two bytes and the RV64G ISA `ecall` instruction occupies only four, the method involves locating other bytes close to the syscall suitable for overwriting. -The destination of the jump (unique for each syscall) is a +The destination of the jump (unique for each `syscall` or `ecall`) is a small routine, which accomplishes the following tasks: 1. Optionally executes any instruction that originally -preceded the syscall instruction, and was overwritten to +preceded the system call instruction, and was overwritten to make space for the jump instruction 2. Saves the current state of all registers to the stack 3. Translates the arguments (in the registers) from -the Linux x86_64 syscall calling convention to the C ABI's -calling convention used on x86_64 +the Linux kernel-level ABI calling conventions of the targeted architecture to +the C user-space functions calling convention 4. Calls a function written in C (which in turn calls the callback supplied by the library user) 5. Loads the values from the stack back into the registers 6. Jumps back to libc, to the instruction following the overwritten part -##### In action: ##### +### In action: ### + +#### x86_64 #### *Simple hotpatching:* Replace a mov and a syscall instruction with a jmp instruction @@ -270,18 +276,49 @@ Before: After: ``` +#### RISC-V #### + +``` +Before: After: +00000000000aa1b8 <__open>: 00000000000aa1b8 <__open>: +aa1b8: c.addi16sp sp,-112 aa1b8: c.addi16sp sp,-112 +... ... +aa1fa: addi a7,zero,56 aa1fa: addi a7,zero,56 +aa1fe: addi a0,zero,-100 aa1fe: auipc t6, {trampoline[31:12], 12'b0} \ +aa202: c.mv a2,s0 /-aa202: jalr zero, t6, trampoline[11:0] | patch +aa204: ecall | aa206: c.ebreak _______________________________/ +aa208: c.lui a5,0xfffff | aa208: c.lui a5,0xfffff <------\ +aa20a: bltu a5,a0,aa262 <__open+0xaa> | aa20a: bltu a5,a0,aa262 <__open+0xaa> \ +... | ... | + | 00000000abcdef02 | + | ... | + \-# jump to | + /-# asm_wrapper_space | + | ... | + | 0000000008000000 | + | ... | + \-8000100: addi a0,zero,-100 | + 8000104: c.mv a2,s0 | + 8000106: # rest of interception code | + ... / + 8000200: # jump back to original .so __________/ +``` + # Limitations: # * Only Linux is supported -* Only x86\_64 is supported +* Only x86\_64 and RISC-V are supported * Only tested with glibc, although perhaps it works with some other libc implementations as well -* There are known issues with the following syscalls: +* RISC-V version assumes `$t6` is not used as base pointer or as source +register without being reinitialized after an `ecall` and before the ending of +a function (tested with glibc 2.35, 2.37 and 2.39) +* There are known issues with the following system calls: * clone * rt_sigreturn # Debugging: # Besides logging, the most important factor during debugging is to make -sure the syscalls in the debugger are not intercepted. To achieve this, use +sure the system calls in the debugger are not intercepted. To achieve this, use the INTERCEPT_HOOK_CMDLINE_FILTER variable described above. ``` diff --git a/src/arch/riscv/asm_wrapper.md b/src/arch/riscv/asm_wrapper.md new file mode 100644 index 0000000..50cbdfc --- /dev/null +++ b/src/arch/riscv/asm_wrapper.md @@ -0,0 +1,19 @@ +# RISC-V porting problems and solutions # + +### Nop-trampoline heuristic + +As in the x86_64 version of the library, the patching process aims at +overwriting the `ecall` instruction with a PC-relative jump reaching the +trampoline table allocated within the ยฑ2GiB range, where an absolute jump will +transfer the execution to the interposition code anywhere in the 64-bit address +space. We surely dispose of the 4 byte occupied by the `ecall` instruction, +which would be enough for a `jal` instruction, which is capable of performing +just a PC-relative jump in the ยฑ1MiB range, which is insufficient. Therefore, at +least eight adjacent bytes and a support register are required in order to +invoke a 32-bit relative jump with the `auipc` and `jalr` instructions. While +the original version would try to found an at least 7-bytes long `nop`, the +RISC-V version would require at least 10 bytes of consecutive `nop` or `c.nop` +which are just highly unlikely to find. For example, an objdump of the glibc +v2.39 RISC-V binary shows only 155 `nop` and `c.nop` instructions in the entire +library, while the same command executed on the x86_64 reports more than 16k +occurrences. diff --git a/src/asm_wrapper.md b/src/arch/x86_64/asm_wrapper.md similarity index 96% rename from src/asm_wrapper.md rename to src/arch/x86_64/asm_wrapper.md index 89d6a1f..3ab1c7c 100644 --- a/src/asm_wrapper.md +++ b/src/arch/x86_64/asm_wrapper.md @@ -24,7 +24,7 @@ this purpose. Different instances are generated from this template to different locations in memory, all of which are able to jump back to the right address in the intercepted code. These instance are also equipped with an another information specific to a syscall: a pointer to the -[struct patch_desc](intercept.h#L92) instance associated with the +[struct patch_desc](../../intercept.h#L92) instance associated with the particular patched syscall. An illustration of this with two syscalls in a section of intercepted code: @@ -128,7 +128,7 @@ jumping back to the intercepted code, once everything is done. Following a clone syscall, the execution of a program might continue with a different stack pointer (e.g. after creating a new thread). This poses a problem -when such a syscall is executed in the [intercept_routine](intercept.c#L650), +when such a syscall is executed in the [intercept_routine](../../intercept.c#L650), which is a C function. This function would attempt to log the result of the syscall, then proceed to return to the calling side, which involves restoring the saved registers. But the saved registers would be restored from a location @@ -143,7 +143,7 @@ site. At this point, no stack is used (all registers are already restored), so the syscall's modification of the stack pointer is not relevant. The process is as follows: - 1) The C intercept_routine [indicates](intercept.c#L646) this + 1) The C intercept_routine [indicates](../../intercept.c#L646) this special case to the asm wrappers, by returning 2 in the rdx register. The register RDX is used because the C ABI allows return two values (a struct) in RAX and RDX. Normally RAX is used as the return value of @@ -170,7 +170,7 @@ jumping to back to the beginning of the wrapper code in this is case that the value of RAX is not a syscall number, but the result of a clone syscall. Of course the hooking code would be able to figure this out on its own, by just examining the value of RAX, so it is indicated by -calling a different C function: [intercept_routine_post_clone](intercept.c#L670). +calling a different C function: [intercept_routine_post_clone](../../intercept.c#L670). Which function to call is controlled by another value passed in RCX, as seen in the branch in [intercept_wrapper.s](intercept_wrapper.s#L165). From b8e98771f6f693d11bf5764b2092394ee06a17c8 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 7 Feb 2025 14:49:18 +0100 Subject: [PATCH 045/143] Updated READMEs and CMakeLists.txt builds test and examples just if arch is x64 --- CMakeLists.txt | 11 +++- src/arch/riscv/asm_wrapper.md | 113 +++++++++++++++++++++++++++++++-- src/arch/x86_64/asm_wrapper.md | 2 +- 3 files changed, 117 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a6f17c2..c36f57b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,8 +42,13 @@ endif() option(PERFORM_STYLE_CHECKS "check coding style, license headers (requires perl)" OFF) -option(BUILD_TESTS "build and enable tests" OFF) -option(BUILD_EXAMPLES "build examples" OFF) +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86(_64)?)$") + option(BUILD_TESTS "build and enable tests" ON) + option(BUILD_EXAMPLES "build examples" ON) +elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv(32|64))$") + option(BUILD_TESTS "build and enable tests" OFF) + option(BUILD_EXAMPLES "build examples" OFF) +endif() option(TREAT_WARNINGS_AS_ERRORS "make the build fail on any warnings during compilation, or linking" ON) option(EXPECT_SPURIOUS_SYSCALLS @@ -74,7 +79,6 @@ set(SOURCES_C src/intercept_desc.c src/intercept_log.c src/intercept_util.c -# src/patcher.c src/magic_syscalls.c src/syscall_formats.c) @@ -100,6 +104,7 @@ elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv(32|64))$") ) endif() +# set the following directories according with your installation of capstone include_directories(include "/usr/local/include/capstone") link_directories("/usr/local/lib") diff --git a/src/arch/riscv/asm_wrapper.md b/src/arch/riscv/asm_wrapper.md index 50cbdfc..07e521c 100644 --- a/src/arch/riscv/asm_wrapper.md +++ b/src/arch/riscv/asm_wrapper.md @@ -1,6 +1,6 @@ # RISC-V porting problems and solutions # -### Nop-trampoline heuristic +### Nop-trampoline heuristic ### As in the x86_64 version of the library, the patching process aims at overwriting the `ecall` instruction with a PC-relative jump reaching the @@ -13,7 +13,110 @@ least eight adjacent bytes and a support register are required in order to invoke a 32-bit relative jump with the `auipc` and `jalr` instructions. While the original version would try to found an at least 7-bytes long `nop`, the RISC-V version would require at least 10 bytes of consecutive `nop` or `c.nop` -which are just highly unlikely to find. For example, an objdump of the glibc -v2.39 RISC-V binary shows only 155 `nop` and `c.nop` instructions in the entire -library, while the same command executed on the x86_64 reports more than 16k -occurrences. +which are just highly unlikely to find (2 more bytes would be needed for a +`c.j` avoiding the nop trampoline on a sequential execution). For example, an +objdump of the glibc v2.39 RISC-V binary shows only 155 `nop` and `c.nop` +instructions in the entire library, while the same command executed on the +x86_64 reports more than 16k occurrences. + +### Support register ### + +As said above, the `auipc` and `jalr` sequence needs one support register +because the `auipc` writes the higher 20-bit of the destination address into a +register while the `jalr` adds a 12-bit signed offset to the value saved in +that register and perform an absolute jump to the obtained result address. +`jalr` is able of writing the return address into `$ra` but `ecall` is not +concerned by user-space calling conventions. For that reason saving the return +address in `$ra` with `jalr` would cause disruptive behaviour in leaf procedure. +The following function is an example from glibc v2.35 binary: + +```asm +00000000000a9f1a : + a9f1a: addi a7,zero,44 + a9f1e: ecall + a9f22: c.lui a5,0xfffff + a9f24: bltu a5,a0,a9f2c + a9f28: c.addiw a0,0 + a9f2a: c.jr ra + a9f2c: auipc a5,0x7c + a9f30: ld a5,1732(a5) # 1265f0 <_GLOBAL_OFFSET_TABLE_+0x60> + a9f34: subw a4,zero,a0 + a9f38: c.li a0,-1 + a9f3a: c.add a5,tp + a9f3c: c.sw a4,0(a5) + a9f3e: c.jr ra +``` +As showed in the function, `$ra` is used as source register in both occurrences +of `c.jr` without being restored from stack. Patching the ecall with a `jalr` +writing to `$ra` would at least cause an infinite loop when returning from +`fstatfs`. Solving this problem would require 8 additional bytes adjacent to +the patch: 4 compressed instructions would be able to (i) decrement the stack +pointer (ii) store `$ra` on the stack (iii) loading it back from the stack and +(iv) restoring the stack pointer. Our first porting attempt tried to find 16 +over-writable bytes, resulting in failing the patching of the majority of +occurrences of `ecall` since such an amount of suitable bytes is very unlikely +to be found. + +For these reasons, `$t6` was empirically chosen as the destination register for +`auipc` and as the source register for `jalr`. By not saving its value on the +stack we chose to clobber it, deliberately not respecting calling conventions. +However, this choice never caused any problems with the tested glibc versions. +That said, nothing prevents us from developing a more careful approach by +determining a suitable register to be "sacrificed" for this purpose by parsing +the `ecall` following instructions until the end of the function. Still, this +solution does not set us free from the assumption that at least a register is +suitable to be clobbered. + +### Building an absolute jump ### + +Each trampoline and each jump returning to the original shared object after the +interception template require an instructions sequence in hand-coded machine +language. This means we can't use any comfort provided by assembly programming, +such as pseudo-instructions or labels. Similarly to `auipc`+`jalr`, we can +write a 32-bit constant into a register with the `lui`+`addi` sequence, which +handles the most significant 20 bit with the first instruction and the least +significant 12 with the latter. Difficulties originate from 32-bit addresses +being impossible to just be split into a 20-bit upper immediate for auipc and a +12-bit lower offset for jalr, as both instructions accept signed immediate +values: the `auipc` instruction stores a multiple of 4096 into its destination +register, and `jalr` sums an immediate offset in the range [โˆ’2048, 2046]. To +solve this inconsistency, each destination address whose remainder, divided by +4096, is 2048 or more will result in auipc encoding the next higher multiple of +4096 so that jalr can compute the correct destination using a negative offset. +A 64-bit constant is even more complex since it relies on building the two +halves of the constant while making sure the lower half is not sign extended. +This requires using a mask whose construction must deals with sign extension +itself. With this caution, building the 64-bit constant is in the end possible +by just logical ORing the upper half and the lower half. +The following lines constitute a typical machine language trampoline expressed +wrote as a sequence of assembly instructions: +```asm +addi sp, sp, -32 +sd t1, 0(sp) +sd t2, 8(sp) +sd t3, 16(sp) +lui t6, 0x12345 +addi t6, t6, 0x678 +slli t6, t6, 32 +lui t3, 0x9abcd +addi t3, t3, 0xef0 +lui t1, 0x7ffff +ori t2, zero, 0x7ff +slli t2, t2, 1 +ori t2, t2, 1 +or t1, t1, t2 +slli t1, t1, 1 +ori t1, t1, 1 +and t3, t3, t1 +or t6, t6, t3 +ld t1, 0(sp) +ld t2, 8(sp) +ld t3, 16(sp) +addi sp, sp, 32 +jalr zero, t6, 0 +``` +`$t6` keeps being used as the source register for the jump destination since +it's already clobbered, while `$t1`, `$t2` and `$t3`are preserved. +The same 64-bit constant building sequence is appended to each interception +template to be able to return to the patched shared object without needing +`$ra`. \ No newline at end of file diff --git a/src/arch/x86_64/asm_wrapper.md b/src/arch/x86_64/asm_wrapper.md index 3ab1c7c..6cfd593 100644 --- a/src/arch/x86_64/asm_wrapper.md +++ b/src/arch/x86_64/asm_wrapper.md @@ -23,7 +23,7 @@ jumps. The code in [intercept_template.s](intercept_template.s) serves this purpose. Different instances are generated from this template to different locations in memory, all of which are able to jump back to the right address in the intercepted code. These instance are also equipped with -an another information specific to a syscall: a pointer to the +another information specific to a syscall: a pointer to the [struct patch_desc](../../intercept.h#L92) instance associated with the particular patched syscall. From 9314b6415e979260db20d952c39a0e05f6a0ffbf Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 7 Feb 2025 15:02:11 +0100 Subject: [PATCH 046/143] Restored original x64 test --- test/mock_trampoline_table.S | 100 ++++++++++++++++++----------------- test/pattern1.in.S | 15 +++--- test/pattern1.out.S | 19 ++++--- 3 files changed, 71 insertions(+), 63 deletions(-) diff --git a/test/mock_trampoline_table.S b/test/mock_trampoline_table.S index 4215a47..098ae0e 100644 --- a/test/mock_trampoline_table.S +++ b/test/mock_trampoline_table.S @@ -45,62 +45,64 @@ # trampoline table has the same format, each mock entry has the same size as # as such a trampoline jump would have. Since these patched syscalls are # never executed in these low level tests, these jumps don't need to be -# real functioning jumps, thus their destination is ".space 92, 0" in all +# real functioning jumps, thus their destination is ".space 8, 0" in all # cases -- the only thing that matters, is to have these at predictable # addresses. +.intel_syntax noprefix + .global trampoline_table; .global trampoline_table_end; .data trampoline_table: -dst0: - .space 92, 0 -dst1: - .space 92, 0 -dst2: - .space 92, 0 -dst3: - .space 92, 0 -dst4: - .space 92, 0 -dst5: - .space 92, 0 -dst6: - .space 92, 0 -dst7: - .space 92, 0 -dst8: - .space 92, 0 -dst9: - .space 92, 0 -dst10: - .space 92, 0 -dst11: - .space 92, 0 -dst12: - .space 92, 0 -dst13: - .space 92, 0 -dst14: - .space 92, 0 -dst15: - .space 92, 0 -dst16: - .space 92, 0 -dst17: - .space 92, 0 -dst18: - .space 92, 0 -dst19: - .space 92, 0 -dst20: - .space 92, 0 -dst21: - .space 92, 0 -dst22: - .space 92, 0 -dst23: - .space 92, 0 +dst0: jmp [rip] + .space 8, 0 +dst1: jmp [rip] + .space 8, 0 +dst2: jmp [rip] + .space 8, 0 +dst3: jmp [rip] + .space 8, 0 +dst4: jmp [rip] + .space 8, 0 +dst5: jmp [rip] + .space 8, 0 +dst6: jmp [rip] + .space 8, 0 +dst7: jmp [rip] + .space 8, 0 +dst8: jmp [rip] + .space 8, 0 +dst9: jmp [rip] + .space 8, 0 +dst10: jmp [rip] + .space 8, 0 +dst11: jmp [rip] + .space 8, 0 +dst12: jmp [rip] + .space 8, 0 +dst13: jmp [rip] + .space 8, 0 +dst14: jmp [rip] + .space 8, 0 +dst15: jmp [rip] + .space 8, 0 +dst16: jmp [rip] + .space 8, 0 +dst17: jmp [rip] + .space 8, 0 +dst18: jmp [rip] + .space 8, 0 +dst19: jmp [rip] + .space 8, 0 +dst20: jmp [rip] + .space 8, 0 +dst21: jmp [rip] + .space 8, 0 +dst22: jmp [rip] + .space 8, 0 +dst23: jmp [rip] + .space 8, 0 trampoline_table_end: \ No newline at end of file diff --git a/test/pattern1.in.S b/test/pattern1.in.S index fd00ebc..79c50ef 100644 --- a/test/pattern1.in.S +++ b/test/pattern1.in.S @@ -33,18 +33,17 @@ # A simple test with a single syscall instruction. # +.intel_syntax noprefix + .global text_start; .global text_end; -.include "mock_trampoline_table.S" +#include "mock_trampoline_table.S" .text text_start: - addi a7, zero, 1 - addi a7, a7, zero - c.mv t2, t1 - c.mv t0, t1 - ecall - c.mv t3, a0 -text_end: + mov rax, 1 + syscall + cmp rax, -1 +text_end: \ No newline at end of file diff --git a/test/pattern1.out.S b/test/pattern1.out.S index 30b2ea7..b1cb913 100644 --- a/test/pattern1.out.S +++ b/test/pattern1.out.S @@ -31,16 +31,23 @@ # see pattern1.in.S +.intel_syntax noprefix + .global text_start; .global text_end; -.include "mock_trampoline_table.S" +#include "mock_trampoline_table.S" .text text_start: - addi a7, zero, 1 - addi a7, a7, zero - jal dst0 - c.mv t3, a0 -text_end: + jmp dst0 + int3 + int3 + int3 + int3 + int3 + int3 + int3 + int3 +text_end: \ No newline at end of file From 71b38aa755ed2e926d9dba494ea4a92d154d5d62 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 12 Feb 2025 13:15:59 +0100 Subject: [PATCH 047/143] Updated READMEs --- README.md | 11 ++++++++++- src/arch/riscv/asm_wrapper.md | 22 +++++++++++----------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 4847a3c..91a2fe2 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,9 @@ This repository contains a multi-architecture porting of [syscall_intercept](htt ## Runtime dependencies ## - * libcapstone -- the disassembly engine used under the hood (RISC-V support requires version 5.0 or higher) + * libcapstone -- the disassembly engine used under the hood + (RISC-V support requires version **5.0** or higher, while apt installs version 4.0.2 by default, as february 2025). + Compiling capstone by hand will require setting [CMakeLists.txt](CMakeLists.txt#L109) accordingly ## Build dependencies ## @@ -329,3 +331,10 @@ INTERCEPT_HOOK_CMDLINE_FILTER=ls \ With this filtering, the intercepting library is not activated in the gdb process itself. + +# RISC-V porting # + +Ottavio Monticelli (Maintainer) \ +Marco Edoardo Santimaria (Maintainer) \ +Marco Aldinucci (Maintainer) \ +Iacopo Colonnelli (Maintainer) \ No newline at end of file diff --git a/src/arch/riscv/asm_wrapper.md b/src/arch/riscv/asm_wrapper.md index 07e521c..254c1cf 100644 --- a/src/arch/riscv/asm_wrapper.md +++ b/src/arch/riscv/asm_wrapper.md @@ -27,7 +27,7 @@ register while the `jalr` adds a 12-bit signed offset to the value saved in that register and perform an absolute jump to the obtained result address. `jalr` is able of writing the return address into `$ra` but `ecall` is not concerned by user-space calling conventions. For that reason saving the return -address in `$ra` with `jalr` would cause disruptive behaviour in leaf procedure. +address in `$ra` with `jalr` would cause disruptive behaviour in leaf procedures. The following function is an example from glibc v2.35 binary: ```asm @@ -77,29 +77,29 @@ write a 32-bit constant into a register with the `lui`+`addi` sequence, which handles the most significant 20 bit with the first instruction and the least significant 12 with the latter. Difficulties originate from 32-bit addresses being impossible to just be split into a 20-bit upper immediate for auipc and a -12-bit lower offset for jalr, as both instructions accept signed immediate +12-bit lower offset for `jalr`, as both instructions accept signed immediate values: the `auipc` instruction stores a multiple of 4096 into its destination register, and `jalr` sums an immediate offset in the range [โˆ’2048, 2046]. To solve this inconsistency, each destination address whose remainder, divided by 4096, is 2048 or more will result in auipc encoding the next higher multiple of -4096 so that jalr can compute the correct destination using a negative offset. +4096 so that `jalr` can compute the correct destination using a negative offset. A 64-bit constant is even more complex since it relies on building the two halves of the constant while making sure the lower half is not sign extended. This requires using a mask whose construction must deals with sign extension itself. With this caution, building the 64-bit constant is in the end possible by just logical ORing the upper half and the lower half. -The following lines constitute a typical machine language trampoline expressed +The following lines constitute a typical machine language trampoline wrote as a sequence of assembly instructions: ```asm addi sp, sp, -32 sd t1, 0(sp) sd t2, 8(sp) sd t3, 16(sp) -lui t6, 0x12345 -addi t6, t6, 0x678 +lui t6, 0x12345 #placeholder value +addi t6, t6, 0x678 #placeholder value slli t6, t6, 32 -lui t3, 0x9abcd -addi t3, t3, 0xef0 +lui t3, 0x90abcd #placeholder value +addi t3, t3, 0xdef #placeholder value lui t1, 0x7ffff ori t2, zero, 0x7ff slli t2, t2, 1 @@ -117,6 +117,6 @@ jalr zero, t6, 0 ``` `$t6` keeps being used as the source register for the jump destination since it's already clobbered, while `$t1`, `$t2` and `$t3`are preserved. -The same 64-bit constant building sequence is appended to each interception -template to be able to return to the patched shared object without needing -`$ra`. \ No newline at end of file +The same 64-bit constant building sequence is appended to each occurrence of the +interception template to be able to return to the patched shared object without +using `$ra`. \ No newline at end of file From 1f3f0355ea73135c31de3e1e79d8c4070e96e280 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 12 Feb 2025 13:16:33 +0100 Subject: [PATCH 048/143] Corrected copyright headers --- CMakeLists.txt | 3 +- LICENSE | 3 +- include/libsyscall_intercept_hook_point.h | 2 +- src/arch/riscv/disasm_wrapper.c | 3 +- src/arch/riscv/intercept_template.S | 3 +- src/arch/riscv/intercept_wrapper.S | 3 +- src/arch/riscv/patcher.c | 3 +- src/arch/riscv/util.S | 3 +- src/arch/x86_64/disasm_wrapper.c | 2 +- src/arch/x86_64/intercept_template.S | 2 +- src/arch/x86_64/intercept_wrapper.S | 2 +- src/arch/x86_64/patcher.c | 2 +- src/arch/x86_64/util.S | 2 +- src/capstone_wrapper.h | 2 +- src/cmdline_filter.c | 2 +- src/cpp_compile_mock.c | 2 +- src/cpp_compile_test.cc | 2 +- src/disasm_wrapper.c | 3 +- src/disasm_wrapper.h | 3 +- src/intercept.c | 3 +- src/intercept.h | 3 +- src/intercept_desc.c | 3 +- src/intercept_log.c | 3 +- src/intercept_log.h | 2 +- src/intercept_util.c | 2 +- src/intercept_util.h | 2 +- src/magic_syscalls.c | 2 +- src/magic_syscalls.h | 2 +- src/syscall_formats.c | 4 +-- src/syscall_formats.h | 2 +- test/fcntl64_test.c | 32 +++++++++++++++++++++ test/intercept_sys_openat.c | 33 ++++++++++++++++++++++ test/intercept_sys_read.c | 32 +++++++++++++++++++++ test/openat_test.c | 32 +++++++++++++++++++++ test/read_test.c | 32 +++++++++++++++++++++ test/write_test | Bin 0 -> 16064 bytes test/write_test.c | 32 +++++++++++++++++++++ 37 files changed, 237 insertions(+), 31 deletions(-) create mode 100755 test/write_test diff --git a/CMakeLists.txt b/CMakeLists.txt index c36f57b..36a9c13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,6 @@ # -# Copyright 2017-2020, Intel Corporation +# Copyright 2025, University of Turin +# Copyright 2017-2024, Intel Corporation # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions diff --git a/LICENSE b/LICENSE index 18badb1..d284069 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,5 @@ -Copyright 2016-2017, Intel Corporation +Copyright 2025, University of Turin +Copyright 2016-2024, Intel Corporation Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/include/libsyscall_intercept_hook_point.h b/include/libsyscall_intercept_hook_point.h index 2fe7d57..399eadd 100644 --- a/include/libsyscall_intercept_hook_point.h +++ b/include/libsyscall_intercept_hook_point.h @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017, Intel Corporation + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/arch/riscv/disasm_wrapper.c b/src/arch/riscv/disasm_wrapper.c index 014252d..4ab8f6f 100644 --- a/src/arch/riscv/disasm_wrapper.c +++ b/src/arch/riscv/disasm_wrapper.c @@ -1,5 +1,6 @@ /* - * Copyright 2016-2020, Intel Corporation + * Copyright 2025, University of Turin + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/arch/riscv/intercept_template.S b/src/arch/riscv/intercept_template.S index 73e95e3..3d7d76b 100644 --- a/src/arch/riscv/intercept_template.S +++ b/src/arch/riscv/intercept_template.S @@ -1,5 +1,6 @@ /* - * Copyright 2016-2017, Intel Corporation + * Copyright 2025, University of Turin + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/arch/riscv/intercept_wrapper.S b/src/arch/riscv/intercept_wrapper.S index 3064ad2..46c4bf7 100644 --- a/src/arch/riscv/intercept_wrapper.S +++ b/src/arch/riscv/intercept_wrapper.S @@ -1,5 +1,6 @@ /* - * Copyright 2016-2017, Intel Corporation + * Copyright 2025, University of Turin + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/arch/riscv/patcher.c b/src/arch/riscv/patcher.c index 7630dfa..aa7bf3a 100644 --- a/src/arch/riscv/patcher.c +++ b/src/arch/riscv/patcher.c @@ -1,5 +1,6 @@ /* - * Copyright 2016-2020, Intel Corporation + * Copyright 2025, University of Turin + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/arch/riscv/util.S b/src/arch/riscv/util.S index c4a84f4..2478c03 100644 --- a/src/arch/riscv/util.S +++ b/src/arch/riscv/util.S @@ -1,5 +1,6 @@ /* - * Copyright 2016-2027, Intel Corporation + * Copyright 2025, University of Turin + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/arch/x86_64/disasm_wrapper.c b/src/arch/x86_64/disasm_wrapper.c index ba2e077..f0a38f9 100644 --- a/src/arch/x86_64/disasm_wrapper.c +++ b/src/arch/x86_64/disasm_wrapper.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020, Intel Corporation + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/arch/x86_64/intercept_template.S b/src/arch/x86_64/intercept_template.S index 70f60d8..b5f2229 100644 --- a/src/arch/x86_64/intercept_template.S +++ b/src/arch/x86_64/intercept_template.S @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017, Intel Corporation + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/arch/x86_64/intercept_wrapper.S b/src/arch/x86_64/intercept_wrapper.S index 7291a17..0d4a27d 100644 --- a/src/arch/x86_64/intercept_wrapper.S +++ b/src/arch/x86_64/intercept_wrapper.S @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017, Intel Corporation + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/arch/x86_64/patcher.c b/src/arch/x86_64/patcher.c index 0ee0db2..270c583 100644 --- a/src/arch/x86_64/patcher.c +++ b/src/arch/x86_64/patcher.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020, Intel Corporation + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/arch/x86_64/util.S b/src/arch/x86_64/util.S index 88e48ce..70ac3ea 100644 --- a/src/arch/x86_64/util.S +++ b/src/arch/x86_64/util.S @@ -1,5 +1,5 @@ /* - * Copyright 2016-2027, Intel Corporation + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/capstone_wrapper.h b/src/capstone_wrapper.h index 7b90ddf..ec84622 100644 --- a/src/capstone_wrapper.h +++ b/src/capstone_wrapper.h @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017, Intel Corporation + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/cmdline_filter.c b/src/cmdline_filter.c index 6196d0b..65650c9 100644 --- a/src/cmdline_filter.c +++ b/src/cmdline_filter.c @@ -1,5 +1,5 @@ /* - * Copyright 2017, Intel Corporation + * Copyright 2017-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/cpp_compile_mock.c b/src/cpp_compile_mock.c index bc6acbc..1cd912a 100644 --- a/src/cpp_compile_mock.c +++ b/src/cpp_compile_mock.c @@ -1,5 +1,5 @@ /* - * Copyright 2017, Intel Corporation + * Copyright 2017-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/cpp_compile_test.cc b/src/cpp_compile_test.cc index c18c1ed..8703b94 100644 --- a/src/cpp_compile_test.cc +++ b/src/cpp_compile_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2017, Intel Corporation + * Copyright 2017-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/disasm_wrapper.c b/src/disasm_wrapper.c index f8cc53c..bb639ae 100644 --- a/src/disasm_wrapper.c +++ b/src/disasm_wrapper.c @@ -1,5 +1,6 @@ /* - * Copyright 2016-2020, Intel Corporation + * Copyright 2025, University of Turin + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/disasm_wrapper.h b/src/disasm_wrapper.h index ffe64dc..0c51bd4 100644 --- a/src/disasm_wrapper.h +++ b/src/disasm_wrapper.h @@ -1,5 +1,6 @@ /* - * Copyright 2016-2020, Intel Corporation + * Copyright 2025, University of Turin + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/intercept.c b/src/intercept.c index 18e6337..c990a12 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -1,5 +1,6 @@ /* - * Copyright 2016-2017, Intel Corporation + * Copyright 2025, University of Turin + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/intercept.h b/src/intercept.h index 8e1d669..f744ec9 100644 --- a/src/intercept.h +++ b/src/intercept.h @@ -1,5 +1,6 @@ /* - * Copyright 2016-2020, Intel Corporation + * Copyright 2025, University of Turin + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/intercept_desc.c b/src/intercept_desc.c index 2ba35ed..b0dcf31 100644 --- a/src/intercept_desc.c +++ b/src/intercept_desc.c @@ -1,5 +1,6 @@ /* - * Copyright 2016-2017, Intel Corporation + * Copyright 2025, University of Turin + * Copyright 2016-2014, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/intercept_log.c b/src/intercept_log.c index 37dcebe..3c295da 100644 --- a/src/intercept_log.c +++ b/src/intercept_log.c @@ -1,5 +1,6 @@ /* - * Copyright 2016-2017, Intel Corporation + * Copyright 2025, University of Turin + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/intercept_log.h b/src/intercept_log.h index 9f50079..59064dd 100644 --- a/src/intercept_log.h +++ b/src/intercept_log.h @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017, Intel Corporation + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/intercept_util.c b/src/intercept_util.c index f650631..badb241 100644 --- a/src/intercept_util.c +++ b/src/intercept_util.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017, Intel Corporation + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/intercept_util.h b/src/intercept_util.h index 2dadbe4..17c087f 100644 --- a/src/intercept_util.h +++ b/src/intercept_util.h @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017, Intel Corporation + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/magic_syscalls.c b/src/magic_syscalls.c index 2308f11..cb92f17 100644 --- a/src/magic_syscalls.c +++ b/src/magic_syscalls.c @@ -1,5 +1,5 @@ /* - * Copyright 2017, Intel Corporation + * Copyright 2017-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/magic_syscalls.h b/src/magic_syscalls.h index cca64f6..f841041 100644 --- a/src/magic_syscalls.h +++ b/src/magic_syscalls.h @@ -1,5 +1,5 @@ /* - * Copyright 2017, Intel Corporation + * Copyright 2017-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/syscall_formats.c b/src/syscall_formats.c index 492e557..c99735e 100644 --- a/src/syscall_formats.c +++ b/src/syscall_formats.c @@ -1,6 +1,6 @@ - /* - * Copyright 2017, Intel Corporation + * Copyright 2025, University of Turin + * Copyright 2017-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/syscall_formats.h b/src/syscall_formats.h index 76fefd4..526f489 100644 --- a/src/syscall_formats.h +++ b/src/syscall_formats.h @@ -1,5 +1,5 @@ /* - * Copyright 2017, Intel Corporation + * Copyright 2017-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/test/fcntl64_test.c b/test/fcntl64_test.c index 0bbee6f..83cc0d8 100644 --- a/test/fcntl64_test.c +++ b/test/fcntl64_test.c @@ -1,3 +1,35 @@ +/* + * Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include "libsyscall_intercept_hook_point.h" #include #include diff --git a/test/intercept_sys_openat.c b/test/intercept_sys_openat.c index 392401b..8ac3b8f 100644 --- a/test/intercept_sys_openat.c +++ b/test/intercept_sys_openat.c @@ -1,3 +1,36 @@ +/* + * Copyright 2025, University of Turin + * Copyright 2017-2024, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include "libsyscall_intercept_hook_point.h" #include #include diff --git a/test/intercept_sys_read.c b/test/intercept_sys_read.c index c1a18e7..d72b6f8 100644 --- a/test/intercept_sys_read.c +++ b/test/intercept_sys_read.c @@ -1,3 +1,35 @@ +/* + * Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include "libsyscall_intercept_hook_point.h" #include #include diff --git a/test/openat_test.c b/test/openat_test.c index 1816d34..772d014 100644 --- a/test/openat_test.c +++ b/test/openat_test.c @@ -1,3 +1,35 @@ +/* + * Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include #include #include diff --git a/test/read_test.c b/test/read_test.c index 0239dde..2ff883e 100644 --- a/test/read_test.c +++ b/test/read_test.c @@ -1,3 +1,35 @@ +/* + * Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include #include diff --git a/test/write_test b/test/write_test new file mode 100755 index 0000000000000000000000000000000000000000..fedec41fbabd6f05bd521eedeb4cb2303cd378be GIT binary patch literal 16064 zcmeHOYitzP6~4O|Fb!Z6Ok*I$t29(ekq6rt7t%T`*lWhAc@&JAO0>h+JNB;Fhr2sl zY=lxrgeES~(jTS$kxKNT2C4mFRgprgN-bkq zlUk+b5nV%9T#AEuJ*o?UwcY5G5eu$uZ$; zgTyn4Ei9r04C+#%3u3pHDImAOY4=Sx`R}y1Q*<>kuNoD^c1gWOF8+D~&dfZs=(4Xg7*^qs?oW`xT>$=hW8idlXeO z#hipuMaQ*``naq?%Gtkr*>gL-dd1$`@QL16{`krBuU%N+q}Yf1%^LRM#Pwl{u+4eC zckH9%@hs&u$9T>8RhDtKw44eatWvn2xL6hb3F4~xGgpo0epTb2Cq713Fr6eK79`1D zL)Rl!cx72d*B;z&4W{;6Lv}i&if$p}5dJiSHfK4Il5Hf73o*&p)lW?c?X862iMa z9&K~+l<@3}XNLL9KAxWkq^myO`y59>h+zc62!s&`BM?R)j6fKHFarNl1pZRD>Tl-Z zH*3wKbAP*5Df7sb8!cZo5C5$8yjM?o{g;U@uRcb9>zd+<{Zm|W>-BQEJaodddEt2L z*Y|B+Fy1;>vCFH!Lh7Nqrf%iw%d2|=_LBj-V}{-Or{0NcpED<3HxIvYduM;5b*lA> zdA#%I)Jl2TQgVHJ$f#?2j!YWB@y?CJn8)X~F>Ji+E~BBnW9XqRDBq}S8fU-rg5JC@aoarm)+Y1p-8p9DqIvC}+dvgukP2$cH}p85=kbqsaH&0LvN%LsU>c_mQ z5_emt%rp5ydYE5j%%51rvErbe$(R#IMo4H*e0`MRQeylA?0+fo0s$k}!}v|XQ-Y@j zCk4+4P6=KXyefEI@P^>DhsUM$OVb-@fab(G6U@a|c|uGtAzD{`bkE(Sxu(Gzk2`m| zkqWNR^x`3VbFVVnxZ*H{5eOp?Mj(tp7=bVXVFbbmgb@fM5Jn)3!2cow5&nH@<(!YV zQ04r)%EPzIsV&g~GJ?j13$NIf=T_!(I z$i9@Acj=lUp8JZ#ZE-)(QhRrpOf0VdQnYK)yy!Ibh>0+T5eOp?Mj(tp7=bVXVFbbm zgb@fM5JuqtD+1Wxhy8rms~4AHEW~i+rHM8Zdg+jC#^imUoUm_jr8d32q?}zLHuewl zdle_VLjCn#InVZ_Y}UgbyvZ77u@_aT>r&1?MRJ{jmjoO@MolB==YTP(Pm07q5V~2!|(59JwA%7N6}A|-grl)KKg~#vk`ZC z-Sq5zQvR;k7>88x`D> zj*@4#J=4~1w6s4i^n2IHajH>w%0Vx_4-qOkCV`5H!&1U({(PUJv`hACU|g(YUdjGe zGQG5p{xXl}L}=AZnF!7D`nYCrA9+y<%JT&NZOT;JpS^?v5`&Wu z4|zO&dc=JsWt)kwR?jBl>(%l~oT2Jr|L78h&m-`Cv(#hF!XK3SgZ+7)_!uhn;Ys3` zM3*bfZxnr(c^-j?P%CyjAV^U(X>78SiB{+L%#ofrQJnV;VO zrl{~T@!X%F|8IzoLF~h~h=0UqBfB8V@uW}vz;mH?4;I{3BTqZj?SZuA+QW*7qFWjo zG6vQC-Rzc|wFY@Vdyzbod22Y6AFwl4(#;o&mR%ZEgZb=8#&Mmb(Nf)mch;vZyHK#l zEGOp{#?(;3&N^1Il+BKj#AjLL>CSNVHsf2aQ*^0UmesRs^R|SQ*xqf?Ui$9OY~Q@C zw~J^x1YspiDK)!yDQj!rjxC$}tQ|c)yA%CZ|K=@y2~q^N{>QPm|9y7xd%dVQ^Y(ws zN!qThys^p2f|=!k(+8D8Ixb+bR38Z-W9In)D_P82DLa?svje?5$Sax7S*4#GA*YND}&~BmZmG7qyH3n9Yv2QeOKrdJkN%8loWfu$TNPJE?&DpKij!2_T_~2 zinf&Mpp0K1Jio>NclRfJ&Vl3aMZX^3%fJ{M1%vue6aNmaeb9fb4}oYOXGMbjw@J@y zL+G)7te~{ZedIVpk9Ay{I9^IXkM(E;sm!0a4uASQ8N9ZG9_u+EzT?n;_yM0GJ+BpE zW4#EBOJl+Q3$2b*hGPmn)~~=RaYXyU@qa_~Tf`6RVW8>LbIgMJZxhEcLH(8Q6Zu}j zdxBKs^%Z%>7wPirW1<7b*~ypibp?Eh%KZ9$QUHV>s(=lg4CqIs0N4VdAauYV2lS_; z0QfuZoG(EK>Q&14`;YYv5bt5|4?aH^M2~rKrr*eOS4%};$ z;r>IvA*M@!Kh$RBFXj)3o0M5h7v6jDeu?vzL4VjlUKiE*^jL>aHWNt+e%iWkgZ~E= z@Z3fFSRdp3EY8XD^T!D~+{Ygf$K!_{@1LjFvbR!CYpDE%9ypK0e!Yr|Yl}v-g9@O7 zy^zGrp?$0i>qQ^*=eGQb*X_)Sd!-2aH5Eo@p!Xy0z27x16`qieeTWKqj-o&K{N?vK h^xdz&$}eJ+>H?LcU0teQ->T{VuwHwt2nYhE`X{X*U`qf1 literal 0 HcmV?d00001 diff --git a/test/write_test.c b/test/write_test.c index 1ee552c..dffe448 100644 --- a/test/write_test.c +++ b/test/write_test.c @@ -1,3 +1,35 @@ +/* + * Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include #include From f9cee3f92b16199ff739ea1b4750210ad8182d9b Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 12 Feb 2025 13:30:11 +0100 Subject: [PATCH 049/143] Removed executable in test --- test/write_test | Bin 16064 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 test/write_test diff --git a/test/write_test b/test/write_test deleted file mode 100755 index fedec41fbabd6f05bd521eedeb4cb2303cd378be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16064 zcmeHOYitzP6~4O|Fb!Z6Ok*I$t29(ekq6rt7t%T`*lWhAc@&JAO0>h+JNB;Fhr2sl zY=lxrgeES~(jTS$kxKNT2C4mFRgprgN-bkq zlUk+b5nV%9T#AEuJ*o?UwcY5G5eu$uZ$; zgTyn4Ei9r04C+#%3u3pHDImAOY4=Sx`R}y1Q*<>kuNoD^c1gWOF8+D~&dfZs=(4Xg7*^qs?oW`xT>$=hW8idlXeO z#hipuMaQ*``naq?%Gtkr*>gL-dd1$`@QL16{`krBuU%N+q}Yf1%^LRM#Pwl{u+4eC zckH9%@hs&u$9T>8RhDtKw44eatWvn2xL6hb3F4~xGgpo0epTb2Cq713Fr6eK79`1D zL)Rl!cx72d*B;z&4W{;6Lv}i&if$p}5dJiSHfK4Il5Hf73o*&p)lW?c?X862iMa z9&K~+l<@3}XNLL9KAxWkq^myO`y59>h+zc62!s&`BM?R)j6fKHFarNl1pZRD>Tl-Z zH*3wKbAP*5Df7sb8!cZo5C5$8yjM?o{g;U@uRcb9>zd+<{Zm|W>-BQEJaodddEt2L z*Y|B+Fy1;>vCFH!Lh7Nqrf%iw%d2|=_LBj-V}{-Or{0NcpED<3HxIvYduM;5b*lA> zdA#%I)Jl2TQgVHJ$f#?2j!YWB@y?CJn8)X~F>Ji+E~BBnW9XqRDBq}S8fU-rg5JC@aoarm)+Y1p-8p9DqIvC}+dvgukP2$cH}p85=kbqsaH&0LvN%LsU>c_mQ z5_emt%rp5ydYE5j%%51rvErbe$(R#IMo4H*e0`MRQeylA?0+fo0s$k}!}v|XQ-Y@j zCk4+4P6=KXyefEI@P^>DhsUM$OVb-@fab(G6U@a|c|uGtAzD{`bkE(Sxu(Gzk2`m| zkqWNR^x`3VbFVVnxZ*H{5eOp?Mj(tp7=bVXVFbbmgb@fM5Jn)3!2cow5&nH@<(!YV zQ04r)%EPzIsV&g~GJ?j13$NIf=T_!(I z$i9@Acj=lUp8JZ#ZE-)(QhRrpOf0VdQnYK)yy!Ibh>0+T5eOp?Mj(tp7=bVXVFbbm zgb@fM5JuqtD+1Wxhy8rms~4AHEW~i+rHM8Zdg+jC#^imUoUm_jr8d32q?}zLHuewl zdle_VLjCn#InVZ_Y}UgbyvZ77u@_aT>r&1?MRJ{jmjoO@MolB==YTP(Pm07q5V~2!|(59JwA%7N6}A|-grl)KKg~#vk`ZC z-Sq5zQvR;k7>88x`D> zj*@4#J=4~1w6s4i^n2IHajH>w%0Vx_4-qOkCV`5H!&1U({(PUJv`hACU|g(YUdjGe zGQG5p{xXl}L}=AZnF!7D`nYCrA9+y<%JT&NZOT;JpS^?v5`&Wu z4|zO&dc=JsWt)kwR?jBl>(%l~oT2Jr|L78h&m-`Cv(#hF!XK3SgZ+7)_!uhn;Ys3` zM3*bfZxnr(c^-j?P%CyjAV^U(X>78SiB{+L%#ofrQJnV;VO zrl{~T@!X%F|8IzoLF~h~h=0UqBfB8V@uW}vz;mH?4;I{3BTqZj?SZuA+QW*7qFWjo zG6vQC-Rzc|wFY@Vdyzbod22Y6AFwl4(#;o&mR%ZEgZb=8#&Mmb(Nf)mch;vZyHK#l zEGOp{#?(;3&N^1Il+BKj#AjLL>CSNVHsf2aQ*^0UmesRs^R|SQ*xqf?Ui$9OY~Q@C zw~J^x1YspiDK)!yDQj!rjxC$}tQ|c)yA%CZ|K=@y2~q^N{>QPm|9y7xd%dVQ^Y(ws zN!qThys^p2f|=!k(+8D8Ixb+bR38Z-W9In)D_P82DLa?svje?5$Sax7S*4#GA*YND}&~BmZmG7qyH3n9Yv2QeOKrdJkN%8loWfu$TNPJE?&DpKij!2_T_~2 zinf&Mpp0K1Jio>NclRfJ&Vl3aMZX^3%fJ{M1%vue6aNmaeb9fb4}oYOXGMbjw@J@y zL+G)7te~{ZedIVpk9Ay{I9^IXkM(E;sm!0a4uASQ8N9ZG9_u+EzT?n;_yM0GJ+BpE zW4#EBOJl+Q3$2b*hGPmn)~~=RaYXyU@qa_~Tf`6RVW8>LbIgMJZxhEcLH(8Q6Zu}j zdxBKs^%Z%>7wPirW1<7b*~ypibp?Eh%KZ9$QUHV>s(=lg4CqIs0N4VdAauYV2lS_; z0QfuZoG(EK>Q&14`;YYv5bt5|4?aH^M2~rKrr*eOS4%};$ z;r>IvA*M@!Kh$RBFXj)3o0M5h7v6jDeu?vzL4VjlUKiE*^jL>aHWNt+e%iWkgZ~E= z@Z3fFSRdp3EY8XD^T!D~+{Ygf$K!_{@1LjFvbR!CYpDE%9ypK0e!Yr|Yl}v-g9@O7 zy^zGrp?$0i>qQ^*=eGQb*X_)Sd!-2aH5Eo@p!Xy0z27x16`qieeTWKqj-o&K{N?vK h^xdz&$}eJ+>H?LcU0teQ->T{VuwHwt2nYhE`X{X*U`qf1 From 384830ada9dc62bb7eb1e31e2c439be2552f09a6 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 12 Feb 2025 14:57:06 +0100 Subject: [PATCH 050/143] Updated REAME.md --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 91a2fe2..789de39 100644 --- a/README.md +++ b/README.md @@ -314,9 +314,6 @@ with some other libc implementations as well * RISC-V version assumes `$t6` is not used as base pointer or as source register without being reinitialized after an `ecall` and before the ending of a function (tested with glibc 2.35, 2.37 and 2.39) -* There are known issues with the following system calls: - * clone - * rt_sigreturn # Debugging: # Besides logging, the most important factor during debugging is to make From 4a9755944c2939aab7c6cf7fb3fdac88b1ae6d65 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 14 Feb 2025 14:15:57 +0100 Subject: [PATCH 051/143] Restored vfork handling in intercept_routine --- include/libsyscall_intercept_hook_point.h | 2 +- src/capstone_wrapper.h | 2 +- src/cmdline_filter.c | 2 +- src/cpp_compile_mock.c | 2 +- src/cpp_compile_test.cc | 2 +- src/intercept.c | 5 ++++- src/intercept_log.h | 2 +- src/intercept_util.c | 2 +- src/intercept_util.h | 2 +- src/magic_syscalls.c | 2 +- src/magic_syscalls.h | 2 +- src/syscall_formats.h | 2 +- test/mock_trampoline_table.S | 2 +- test/pattern1.in.S | 2 +- test/pattern1.out.S | 2 +- 15 files changed, 18 insertions(+), 15 deletions(-) diff --git a/include/libsyscall_intercept_hook_point.h b/include/libsyscall_intercept_hook_point.h index 399eadd..2fe7d57 100644 --- a/include/libsyscall_intercept_hook_point.h +++ b/include/libsyscall_intercept_hook_point.h @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024, Intel Corporation + * Copyright 2016-2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/capstone_wrapper.h b/src/capstone_wrapper.h index ec84622..7b90ddf 100644 --- a/src/capstone_wrapper.h +++ b/src/capstone_wrapper.h @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024, Intel Corporation + * Copyright 2016-2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/cmdline_filter.c b/src/cmdline_filter.c index 65650c9..6196d0b 100644 --- a/src/cmdline_filter.c +++ b/src/cmdline_filter.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024, Intel Corporation + * Copyright 2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/cpp_compile_mock.c b/src/cpp_compile_mock.c index 1cd912a..bc6acbc 100644 --- a/src/cpp_compile_mock.c +++ b/src/cpp_compile_mock.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024, Intel Corporation + * Copyright 2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/cpp_compile_test.cc b/src/cpp_compile_test.cc index 8703b94..c18c1ed 100644 --- a/src/cpp_compile_test.cc +++ b/src/cpp_compile_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024, Intel Corporation + * Copyright 2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/intercept.c b/src/intercept.c index c990a12..c03ff6f 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -676,8 +676,11 @@ intercept_routine(struct context *context) desc.args[4], desc.args[5], &result); - +#if defined(__x86_64__) || defined(_M_X64) + if (desc.nr == SYS_vfork || desc.nr == SYS_rt_sigreturn) { +#elif defined(__riscv) if (desc.nr == SYS_rt_sigreturn) { +#endif /* can't handle these syscalls the normal way */ return (struct wrapper_ret){FIRST_RET_REG = SYSCALL_NR, SECOND_RET_REG = 0 }; } diff --git a/src/intercept_log.h b/src/intercept_log.h index 59064dd..9f50079 100644 --- a/src/intercept_log.h +++ b/src/intercept_log.h @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024, Intel Corporation + * Copyright 2016-2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/intercept_util.c b/src/intercept_util.c index badb241..f650631 100644 --- a/src/intercept_util.c +++ b/src/intercept_util.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024, Intel Corporation + * Copyright 2016-2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/intercept_util.h b/src/intercept_util.h index 17c087f..2dadbe4 100644 --- a/src/intercept_util.h +++ b/src/intercept_util.h @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024, Intel Corporation + * Copyright 2016-2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/magic_syscalls.c b/src/magic_syscalls.c index cb92f17..2308f11 100644 --- a/src/magic_syscalls.c +++ b/src/magic_syscalls.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024, Intel Corporation + * Copyright 2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/magic_syscalls.h b/src/magic_syscalls.h index f841041..cca64f6 100644 --- a/src/magic_syscalls.h +++ b/src/magic_syscalls.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024, Intel Corporation + * Copyright 2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/syscall_formats.h b/src/syscall_formats.h index 526f489..76fefd4 100644 --- a/src/syscall_formats.h +++ b/src/syscall_formats.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024, Intel Corporation + * Copyright 2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/test/mock_trampoline_table.S b/test/mock_trampoline_table.S index 098ae0e..c97bcee 100644 --- a/test/mock_trampoline_table.S +++ b/test/mock_trampoline_table.S @@ -105,4 +105,4 @@ dst22: jmp [rip] .space 8, 0 dst23: jmp [rip] .space 8, 0 -trampoline_table_end: \ No newline at end of file +trampoline_table_end: diff --git a/test/pattern1.in.S b/test/pattern1.in.S index 79c50ef..561c89f 100644 --- a/test/pattern1.in.S +++ b/test/pattern1.in.S @@ -46,4 +46,4 @@ text_start: mov rax, 1 syscall cmp rax, -1 -text_end: \ No newline at end of file +text_end: diff --git a/test/pattern1.out.S b/test/pattern1.out.S index b1cb913..333175a 100644 --- a/test/pattern1.out.S +++ b/test/pattern1.out.S @@ -50,4 +50,4 @@ text_start: int3 int3 int3 -text_end: \ No newline at end of file +text_end: From d3a00ba4cde551063ddf42b108d24de0a621ed20 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 21 Feb 2025 13:57:28 +0100 Subject: [PATCH 052/143] Corrected copyright notes --- src/arch/riscv/intercept_template.S | 3 ++- src/arch/x86_64/disasm_wrapper.c | 1 + src/arch/x86_64/intercept_template.S | 2 +- src/arch/x86_64/intercept_wrapper.S | 2 +- src/arch/x86_64/util.S | 2 +- src/intercept_desc.c | 2 +- 6 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/arch/riscv/intercept_template.S b/src/arch/riscv/intercept_template.S index 3d7d76b..536398b 100644 --- a/src/arch/riscv/intercept_template.S +++ b/src/arch/riscv/intercept_template.S @@ -165,9 +165,10 @@ l5: intercept_asm_wrapper_tmpl_end: /* + * following_ins + * * This template must be appended here with a * jump back to the intercepted code, whic is written by * create_absolute_jump(*dst, patch->return_address) in patcher.c * - * following_ins */ diff --git a/src/arch/x86_64/disasm_wrapper.c b/src/arch/x86_64/disasm_wrapper.c index f0a38f9..af84942 100644 --- a/src/arch/x86_64/disasm_wrapper.c +++ b/src/arch/x86_64/disasm_wrapper.c @@ -1,4 +1,5 @@ /* + * Copyright 2025, University of Turin * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without diff --git a/src/arch/x86_64/intercept_template.S b/src/arch/x86_64/intercept_template.S index b5f2229..70f60d8 100644 --- a/src/arch/x86_64/intercept_template.S +++ b/src/arch/x86_64/intercept_template.S @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024, Intel Corporation + * Copyright 2016-2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/arch/x86_64/intercept_wrapper.S b/src/arch/x86_64/intercept_wrapper.S index 0d4a27d..7291a17 100644 --- a/src/arch/x86_64/intercept_wrapper.S +++ b/src/arch/x86_64/intercept_wrapper.S @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024, Intel Corporation + * Copyright 2016-2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/arch/x86_64/util.S b/src/arch/x86_64/util.S index 70ac3ea..4b375c8 100644 --- a/src/arch/x86_64/util.S +++ b/src/arch/x86_64/util.S @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024, Intel Corporation + * Copyright 2016-2017, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/intercept_desc.c b/src/intercept_desc.c index b0dcf31..f88aed8 100644 --- a/src/intercept_desc.c +++ b/src/intercept_desc.c @@ -1,6 +1,6 @@ /* * Copyright 2025, University of Turin - * Copyright 2016-2014, Intel Corporation + * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions From 0ff4b72c1718b0710cd2b69ab85adc05bc66ae44 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 21 Feb 2025 14:09:53 +0100 Subject: [PATCH 053/143] Cleaned up commented lines, placed TRAMPOLINE_SIZE definition here back --- src/arch/riscv/patcher.c | 13 ++++++------- src/arch/x86_64/patcher.c | 3 ++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/arch/riscv/patcher.c b/src/arch/riscv/patcher.c index aa7bf3a..d1643f5 100644 --- a/src/arch/riscv/patcher.c +++ b/src/arch/riscv/patcher.c @@ -85,6 +85,9 @@ #define COMPAT_HWCAP_ISA_C (1 << ('C' - 'A')) #define COMPAT_HWCAP_ISA_V (1 << ('V' - 'A')) +/* The size of a trampoline jump, see src/arch/riscv/asm_wrapper.md */ +enum { TRAMPOLINE_SIZE = 4 * 23 }; + static void create_wrapper(struct patch_desc *patch, unsigned char **dst); static void create_load_uint64t_into_t0(uint8_t *code, uint64_t value); static void create_load_uint64t_into_t6(uint8_t *code, uint64_t value); @@ -120,7 +123,8 @@ create_absolute_jump(unsigned char *from, void *to) instructions[20] = 0x01013e03; // ld t3, 16(sp) instructions[21] = 0x02010113; // addi sp, sp, 32 instructions[22] = 0x000f8067; // jalr zero, t6, 0 - create_load_uint64t_into_t6((uint8_t *)(instructions + 4),(uint64_t)to); // writes 5 instructions starting from instructions[4] + // next call writes five 4-byte instructions starting from instructions[4] + create_load_uint64t_into_t6((uint8_t *)(instructions + 4),(uint64_t)to); return (unsigned char *)(instructions + 23); } @@ -160,11 +164,8 @@ is_copiable_before_syscall(struct intercept_disasm_result ins) return false; return !(ins.has_ip_relative_opr || -// ins.is_call || ins.is_rel_jump || ins.is_jump || -// ins.is_ret || -// ins.is_endbr || ins.is_syscall || ins.uses_t6); } @@ -183,10 +184,8 @@ is_copiable_after_syscall(struct intercept_disasm_result ins) return false; return !(ins.has_ip_relative_opr || -// ins.is_call || ins.is_rel_jump || ins.is_jump || -// ins.is_endbr || ins.is_syscall || ins.uses_t6); } @@ -528,7 +527,7 @@ create_wrapper(struct patch_desc *patch, unsigned char **dst) } memcpy(*dst, intercept_asm_wrapper_tmpl, asm_wrapper_tmpl_size); - create_load_uint64t_into_t0(*dst + o_patch_desc_addr, (uintptr_t)patch); // why the uintptr_t cast? What if the address is not representable on 32 bit? + create_load_uint64t_into_t0(*dst + o_patch_desc_addr, (uintptr_t)patch); create_load_uint64t_into_t0(*dst + o_wrapper_level1_addr, (uintptr_t)&intercept_wrapper); *dst += asm_wrapper_tmpl_size; diff --git a/src/arch/x86_64/patcher.c b/src/arch/x86_64/patcher.c index 270c583..f77743b 100644 --- a/src/arch/x86_64/patcher.c +++ b/src/arch/x86_64/patcher.c @@ -1,4 +1,5 @@ /* + * Copyright 2025, University of Turin * Copyright 2016-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without @@ -81,7 +82,7 @@ #include /* The size of a trampoline jump, jmp instruction + pointer */ -//enum { TRAMPOLINE_SIZE = 6 + 8 }; +enum { TRAMPOLINE_SIZE = 6 + 8 }; static void create_wrapper(struct patch_desc *patch, unsigned char **dst); From 519c6fbf9d1bf65f5c3e70204933a17fd1260752 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 21 Feb 2025 14:11:13 +0100 Subject: [PATCH 054/143] Smarter definition of macros and boolean flags depending on the target architecture --- src/disasm_wrapper.h | 16 +++++++++++----- src/intercept.h | 42 ++++++++++++++---------------------------- 2 files changed, 25 insertions(+), 33 deletions(-) diff --git a/src/disasm_wrapper.h b/src/disasm_wrapper.h index 0c51bd4..636e909 100644 --- a/src/disasm_wrapper.h +++ b/src/disasm_wrapper.h @@ -65,12 +65,13 @@ struct intercept_disasm_result { */ bool has_ip_relative_opr; + bool is_jump; + +#if defined(__x86_64__) || defined(_M_X64) + /* as of now this only refers to endbr64 */ bool is_endbr; - /* Flag marking if t6 is one of the operands of the instruction */ - bool uses_t6; - /* * Flag marking lea instructions setting a 64 bit register to a * RIP relative address. They can be relocated -- but by simple memcpy. @@ -86,8 +87,6 @@ struct intercept_disasm_result { /* call instruction */ bool is_call; - bool is_jump; - /* * The flag is_rel_jump marks any instruction that jumps, to * a relative address encoded in its operand. @@ -112,6 +111,13 @@ struct intercept_disasm_result { int32_t rip_disp; const unsigned char *rip_ref_addr; +#elif defined(__riscv) + + /* Flag marking if t6 is one of the operands of the instruction */ + bool uses_t6; + +#endif + #ifndef NDEBUG const char *mnemonic; #endif diff --git a/src/intercept.h b/src/intercept.h index f744ec9..4fc8724 100644 --- a/src/intercept.h +++ b/src/intercept.h @@ -220,18 +220,7 @@ void mprotect_asm_wrappers(void); void activate_patches(struct intercept_desc *desc); #if defined(__x86_64__) || defined(_M_X64) - #define SYSCALL_INS_SIZE 2 - #define JUMP_INS_SIZE 5 - #define TRAMPOLINE_SIZE 14 /* jmp instruction + pointer */ - #define SYSCALL_NR context->rax - #define FIRST_ARG_REG context->rdi - #define SECOND_ARG_REG context->rsi - #define THIRD_ARG_REG context->rdx - #define FOURTH_ARG_REG context->r10 - #define FIFTH_ARG_REG context->r8 - #define SIXTH_ARG_REG context->r9 - #define FIRST_RET_REG .rax - #define SECOND_RET_REG .rdx + #define PARAM_BY_ARCH(opt1, opt2) opt1 #define CALL_OPCODE 0xe8 #define JMP_OPCODE 0xe9 #define SHORT_JMP_OPCODE 0xeb @@ -239,26 +228,23 @@ void activate_patches(struct intercept_desc *desc); #define NOP_OPCODE 0x90 #define INT3_OPCODE 0xCC #elif defined(__riscv) - #define SYSCALL_INS_SIZE 4 - /* - * 8 bytes are needed to be able to perform - * a PC-relative jump with a 32-bit offset - */ - #define JUMP_INS_SIZE 8 - #define TRAMPOLINE_SIZE 92 /* see create_absolute_jump() in arch/riscv/patcher.c */ - #define SYSCALL_NR context->a[7] - #define FIRST_ARG_REG context->a[0] - #define SECOND_ARG_REG context->a[1] - #define THIRD_ARG_REG context->a[2] - #define FOURTH_ARG_REG context->a[3] - #define FIFTH_ARG_REG context->a[4] - #define SIXTH_ARG_REG context->a[5] - #define FIRST_RET_REG .a[0] - #define SECOND_RET_REG .a[1] + #define PARAM_BY_ARCH(opt1, opt2) opt2 #else #error "Unsupported ISA" #endif +#define SYSCALL_INS_SIZE PARAM_BY_ARCH(2, 4) +#define JUMP_INS_SIZE PARAM_BY_ARCH(5,8) +#define SYSCALL_NR PARAM_BY_ARCH(context->rax,context->a[7]) +#define FIRST_ARG_REG PARAM_BY_ARCH(context->rdi,context->a[0]) +#define SECOND_ARG_REG PARAM_BY_ARCH(context->rsi,context->a[1]) +#define THIRD_ARG_REG PARAM_BY_ARCH(context->rdx,context->a[2]) +#define FOURTH_ARG_REG PARAM_BY_ARCH(context->r10,context->a[3]) +#define FIFTH_ARG_REG PARAM_BY_ARCH(context->r8,context->a[4]) +#define SIXTH_ARG_REG PARAM_BY_ARCH(context->r9,context->a[5]) +#define FIRST_RET_REG PARAM_BY_ARCH(.rax,.a[0]) +#define SECOND_RET_REG PARAM_BY_ARCH(.rdx,.a[1]) + bool is_overwritable_nop(const struct intercept_disasm_result *ins); void create_jump(unsigned char opcode, unsigned char *from, void *to); From 6007fe6337fb4fdb2fa96ccca5c19bb00b610a74 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 21 Feb 2025 14:17:27 +0100 Subject: [PATCH 055/143] Refined arch-dependant definition --- src/intercept_desc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/intercept_desc.c b/src/intercept_desc.c index f88aed8..2551dbb 100644 --- a/src/intercept_desc.c +++ b/src/intercept_desc.c @@ -419,6 +419,8 @@ add_new_patch(struct intercept_desc *desc) return &(desc->items[desc->count++]); } + +#if defined(__x86_64__) || defined(_M_X64) /* * is_overwritable_nop * Check if an instruction just disassembled is a NOP that can be @@ -447,6 +449,7 @@ is_overwritable_nop(const struct intercept_disasm_result *ins) { return ins->is_nop && ins->length >= 2 + 5; } +#endif /* * crawl_text From 2ec36ea76eb689b3cb28a433b02784b1da2f8849 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 21 Feb 2025 14:20:02 +0100 Subject: [PATCH 056/143] Refined arch-dependant definition --- src/arch/riscv/patcher.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/arch/riscv/patcher.c b/src/arch/riscv/patcher.c index d1643f5..e0f6242 100644 --- a/src/arch/riscv/patcher.c +++ b/src/arch/riscv/patcher.c @@ -164,7 +164,6 @@ is_copiable_before_syscall(struct intercept_disasm_result ins) return false; return !(ins.has_ip_relative_opr || - ins.is_rel_jump || ins.is_jump || ins.is_syscall || ins.uses_t6); @@ -184,7 +183,6 @@ is_copiable_after_syscall(struct intercept_disasm_result ins) return false; return !(ins.has_ip_relative_opr || - ins.is_rel_jump || ins.is_jump || ins.is_syscall || ins.uses_t6); From cce5d5364aa7f0e325e436a20fc514396f812ed3 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 21 Feb 2025 14:34:03 +0100 Subject: [PATCH 057/143] Cleaned up unnecessary inclusions and fixed copyright notes --- test/example.c | 35 ++++++++++++++++++++++- test/fcntl64_test.c | 25 ----------------- test/intercept_sys_fcntl64.c | 54 ++++++++++++++++++++++++++++++++++++ test/intercept_sys_openat.c | 5 ---- test/intercept_sys_read.c | 3 -- test/openat_test.c | 5 ++-- test/read_test.c | 2 +- test/write_test.c | 2 +- 8 files changed, 93 insertions(+), 38 deletions(-) create mode 100644 test/intercept_sys_fcntl64.c diff --git a/test/example.c b/test/example.c index bf9e2b3..30d2a0c 100644 --- a/test/example.c +++ b/test/example.c @@ -1,3 +1,36 @@ +/* + * Copyright 2025, University of Turin + * Copyright 2017-2024, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include "libsyscall_intercept_hook_point.h" #include #include @@ -35,4 +68,4 @@ init(void) { // Set up the callback function intercept_hook_point = hook; -} \ No newline at end of file +} diff --git a/test/fcntl64_test.c b/test/fcntl64_test.c index 83cc0d8..d0ad920 100644 --- a/test/fcntl64_test.c +++ b/test/fcntl64_test.c @@ -30,33 +30,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "libsyscall_intercept_hook_point.h" -#include -#include -#include -#include -#include #include -static int -hook(long syscall_number, - long arg0, long arg1, - long arg2, long arg3, - long arg4, long arg5, - long *result) -{ - if (syscall_number == SYS_fcntl) { - write(1,"Proof of fcntl64 interception\n",30); - } - return 1; -} - -static __attribute__((constructor)) void -init(void) -{ - intercept_hook_point = hook; -} - int main() { int fd = openat(AT_FDCWD, "intercepting_original_file.txt", O_RDONLY); int fd_dup = fcntl(fd, F_DUPFD, 0); diff --git a/test/intercept_sys_fcntl64.c b/test/intercept_sys_fcntl64.c new file mode 100644 index 0000000..5d3893e --- /dev/null +++ b/test/intercept_sys_fcntl64.c @@ -0,0 +1,54 @@ +/* + * Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libsyscall_intercept_hook_point.h" +#include +#include + +static int +hook(long syscall_number, + long arg0, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long *result) +{ + if (syscall_number == SYS_fcntl) { + write(1,"Proof of fcntl64 interception\n",30); + } + return 1; +} + +static __attribute__((constructor)) void +init(void) +{ + intercept_hook_point = hook; +} \ No newline at end of file diff --git a/test/intercept_sys_openat.c b/test/intercept_sys_openat.c index 8ac3b8f..e6a9b40 100644 --- a/test/intercept_sys_openat.c +++ b/test/intercept_sys_openat.c @@ -1,6 +1,5 @@ /* * Copyright 2025, University of Turin - * Copyright 2017-2024, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,12 +31,8 @@ */ #include "libsyscall_intercept_hook_point.h" -#include #include -#include #include -#include -#include static int hook(long syscall_number, diff --git a/test/intercept_sys_read.c b/test/intercept_sys_read.c index d72b6f8..79e6ac3 100644 --- a/test/intercept_sys_read.c +++ b/test/intercept_sys_read.c @@ -33,9 +33,6 @@ #include "libsyscall_intercept_hook_point.h" #include #include -#include -#include -#include static int hook(long syscall_number, diff --git a/test/openat_test.c b/test/openat_test.c index 772d014..28c3ea2 100644 --- a/test/openat_test.c +++ b/test/openat_test.c @@ -36,8 +36,9 @@ int main() { int fd = openat(AT_FDCWD,"non_existing_original_file.txt", O_RDONLY); - char buf[128] = "Specified file doesn't exist - Test is ok if previous line is:\n" - "\"Proof of openat interception\"\n"; + char buf[128] = "Specified file doesn't exist - " + "Test is ok if next line is printed before this one as well:\n" + "Proof of openat interception\n"; if (fd >= 0) { write(1, "Success: File opened\n", 21); } else { diff --git a/test/read_test.c b/test/read_test.c index 2ff883e..1ebc88a 100644 --- a/test/read_test.c +++ b/test/read_test.c @@ -37,4 +37,4 @@ int main() { char buf[128]; read(0, buf, sizeof(buf)); write(1, buf, strlen(buf)); // Should print "intercepted_read" -} \ No newline at end of file +} diff --git a/test/write_test.c b/test/write_test.c index dffe448..da28b01 100644 --- a/test/write_test.c +++ b/test/write_test.c @@ -36,4 +36,4 @@ int main() { char buf[128] = "original_syscall\n"; write(1, buf, strlen(buf)); -} \ No newline at end of file +} From a1da7244146676cad456b5097da2e572d5ad14b5 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 21 Feb 2025 14:45:44 +0100 Subject: [PATCH 058/143] Updated team roles --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 789de39..8248722 100644 --- a/README.md +++ b/README.md @@ -333,5 +333,5 @@ process itself. Ottavio Monticelli (Maintainer) \ Marco Edoardo Santimaria (Maintainer) \ -Marco Aldinucci (Maintainer) \ -Iacopo Colonnelli (Maintainer) \ No newline at end of file +Marco Aldinucci (Maintainer and Principal Investigator) \ +Iacopo Colonnelli (Maintainer and Principal Investigator) \ No newline at end of file From e1186a1654c02608c08dd66cceb2ec053e5f312c Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sat, 22 Feb 2025 14:18:08 +0100 Subject: [PATCH 059/143] SARGS definition are now dependant on SYS_* macro definition instead of architecture --- src/intercept_desc.c | 10 ++--- src/intercept_log.c | 6 +-- src/syscall_formats.c | 96 ++++++++++++++++++++++++++++--------------- 3 files changed, 72 insertions(+), 40 deletions(-) diff --git a/src/intercept_desc.c b/src/intercept_desc.c index 2551dbb..43c9513 100644 --- a/src/intercept_desc.c +++ b/src/intercept_desc.c @@ -62,12 +62,12 @@ static int open_orig_file(const struct intercept_desc *desc) { int fd; -#if defined(__x86_64__) || defined(_M_X64) +#if defined(SYS_open) fd = syscall_no_intercept(SYS_open, desc->path, O_RDONLY); -#elif defined(__riscv) +#elif defined(SYS_openat) fd = syscall_no_intercept(SYS_openat, AT_FDCWD, desc->path, O_RDONLY); #else - #error "Unsupported ISA" + #error "No open syscalls defined" #endif xabort_on_syserror(fd, __func__); @@ -580,10 +580,10 @@ get_min_address(void) min_address = 0x10000; /* best guess */ -#if defined(__x86_64__) || defined(_M_X64) +#if defined(SYS_open) int fd = syscall_no_intercept(SYS_open, "/proc/sys/vm/mmap_min_addr", O_RDONLY); -#elif defined(__riscv) +#elif defined(SYS_openat) int fd = syscall_no_intercept(SYS_openat, AT_FDCWD, "/proc/sys/vm/mmap_min_addr", O_RDONLY); #else diff --git a/src/intercept_log.c b/src/intercept_log.c index 3c295da..8b26b66 100644 --- a/src/intercept_log.c +++ b/src/intercept_log.c @@ -831,12 +831,12 @@ intercept_setup_log(const char *path, const char *trunc) intercept_log_close(); /* in case a log was already open */ -#if defined(__x86_64__) || defined(_M_X64) +#if defined(SYS_open) log_fd = (int)syscall_no_intercept(SYS_open, full_path, flags, 0700); -#elif defined(__riscv) +#elif defined(SYS_openat) log_fd = (int)syscall_no_intercept(SYS_openat, AT_FDCWD, full_path, flags, 0700); #else -#error "Unsupported ISA" + #error "No open syscalls defined" #endif xabort_on_syserror(log_fd, "opening log"); } diff --git a/src/syscall_formats.c b/src/syscall_formats.c index c99735e..d397f4d 100644 --- a/src/syscall_formats.c +++ b/src/syscall_formats.c @@ -44,16 +44,18 @@ static const struct syscall_format formats[] = { SARGS(read, rdec, arg_fd, arg_buf_out, arg_dec), SARGS(write, rdec, arg_fd, arg_buf_in, arg_dec), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_open SARGS(open, rdec, arg_cstr, arg_open_flags), #endif SARGS(close, rdec, arg_fd), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_stat SARGS(stat, rdec, arg_cstr, arg_pointer), #endif SARGS(fstat, rdec, arg_fd, arg_pointer), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_lstat SARGS(lstat, rdec, arg_cstr, arg_pointer), +#endif +#ifdef SYS_poll SARGS(poll, rdec, arg_pointer, arg_, arg_), #endif SARGS(lseek, rdec, arg_fd, arg_dec, arg_seek_whence), @@ -69,9 +71,13 @@ static const struct syscall_format formats[] = { SARGS(pwrite64, rdec, arg_fd, arg_buf_in, arg_dec, arg_dec), SARGS(readv, rdec, arg_fd, arg_pointer, arg_dec), SARGS(writev, rdec, arg_fd, arg_pointer, arg_dec), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_access SARGS(access, rdec, arg_cstr, arg_access_mode), +#endif +#ifdef SYS_pipe SARGS(pipe, rdec, arg_2fds), +#endif +#ifdef SYS_select SARGS(select, rdec, arg_dec32, arg_pointer, arg_pointer, arg_pointer, arg_pointer), #endif SARGS(sched_yield, rdec, arg_none), @@ -83,13 +89,15 @@ static const struct syscall_format formats[] = { SARGS(shmat, rhex, arg_, arg_, arg_), SARGS(shmctl, rdec, arg_, arg_, arg_), SARGS(dup, rdec, arg_fd), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_dup2 SARGS(dup2, rdec, arg_fd, arg_fd), +#endif +#ifdef SYS_pause SARGS(pause, rdec, arg_none), #endif SARGS(nanosleep, rdec, arg_, arg_), SARGS(getitimer, rdec, arg_, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_alarm SARGS(alarm, rdec, arg_), #endif SARGS(setitimer, rdec, arg_, arg_, arg_), @@ -111,8 +119,10 @@ static const struct syscall_format formats[] = { SARGS(setsockopt, rdec, arg_fd, arg_, arg_, arg_, arg_), SARGS(getsockopt, rdec, arg_fd, arg_, arg_, arg_, arg_), SARGS(clone, rdec, arg_clone_flags, arg_pointer, arg_pointer, arg_pointer, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_fork SARGS(fork, rdec, arg_none), +#endif +#ifdef SYS_vfork SARGS(vfork, rdec, arg_none), #endif SARGS(execve, rdec, arg_, arg_, arg_), @@ -134,29 +144,45 @@ static const struct syscall_format formats[] = { SARGS(fdatasync, rdec, arg_fd), SARGS(truncate, rdec, arg_cstr, arg_), SARGS(ftruncate, rdec, arg_fd, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_getdents SARGS(getdents, rdec, arg_fd, arg_, arg_), #endif SARGS(getcwd, rdec, arg_, arg_), SARGS(chdir, rdec, arg_cstr), SARGS(fchdir, rdec, arg_fd), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_rename SARGS(rename, rdec, arg_cstr, arg_cstr), +#endif +#ifdef SYS_mkdir SARGS(mkdir, rdec, arg_cstr, arg_oct_mode), +#endif +#ifdef SYS_rmdir SARGS(rmdir, rdec, arg_cstr), +#endif +#ifdef SYS_creat SARGS(creat, rdec, arg_cstr, arg_oct_mode), +#endif +#ifdef SYS_link SARGS(link, rdec, arg_cstr, arg_cstr), +#endif +#ifdef SYS_unlink SARGS(unlink, rdec, arg_cstr), +#endif +#ifdef SYS_symlink SARGS(symlink, rdec, arg_cstr, arg_cstr), +#endif +#ifdef SYS_readlink SARGS(readlink, rdec, arg_cstr, arg_buf_out, arg_dec), +#endif +#ifdef SYS_chmod SARGS(chmod, rdec, arg_cstr, arg_oct_mode), #endif SARGS(fchmod, rdec, arg_fd, arg_oct_mode), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_chown SARGS(chown, rdec, arg_cstr, arg_, arg_), #endif SARGS(fchown, rdec, arg_fd, arg_, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_lchown SARGS(lchown, rdec, arg_cstr, arg_, arg_), #endif SARGS(umask, rmode, arg_oct_mode), @@ -174,7 +200,7 @@ static const struct syscall_format formats[] = { SARGS(geteuid, rdec, arg_none), SARGS(getegid, rdec, arg_none), SARGS(setpgid, rdec, arg_none), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_getpgrp SARGS(getpgrp, rdec, arg_none), #endif SARGS(setsid, rdec, arg_none), @@ -197,18 +223,22 @@ static const struct syscall_format formats[] = { SARGS(rt_sigqueueinfo, rdec, arg_, arg_, arg_), SARGS(rt_sigsuspend, rdec, arg_, arg_), SARGS(sigaltstack, rdec, arg_, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_utime SARGS(utime, rdec, arg_cstr, arg_), +#endif +#ifdef SYS_mknod SARGS(mknod, rdec, arg_cstr, arg_, arg_), +#endif +#ifdef SYS_uselib SARGS(uselib, rdec, arg_cstr), #endif SARGS(personality, rdec, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_ustat SARGS(ustat, rdec, arg_, arg_), #endif SARGS(statfs, rdec, arg_cstr, arg_), SARGS(fstatfs, rdec, arg_fd, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_sysfs SARGS(sysfs, rdec, arg_, arg_, arg_), #endif SARGS(getpriority, rdec, arg_, arg_), @@ -225,15 +255,15 @@ static const struct syscall_format formats[] = { SARGS(mlockall, rdec, arg_), SARGS(munlockall, rdec, arg_none), SARGS(vhangup, rdec, arg_none), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_modify_ldt SARGS(modify_ldt, rdec, arg_, arg_, arg_), #endif SARGS(pivot_root, rdec, arg_cstr, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS__sysctl SARGS(_sysctl, rdec, arg_), #endif SARGS(prctl, rdec, arg_, arg_, arg_, arg_, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_arch_prctl SARGS(arch_prctl, rdec, arg_, arg_, arg_), #endif SARGS(adjtimex, rdec, arg_), @@ -249,8 +279,10 @@ static const struct syscall_format formats[] = { SARGS(reboot, rdec, arg_, arg_, arg_, arg_), SARGS(sethostname, rdec, arg_, arg_), SARGS(setdomainname, rdec, arg_, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_iopl SARGS(iopl, rdec, arg_), +#endif +#ifdef SYS_ioperm SARGS(ioperm, rdec, arg_, arg_, arg_), #endif SARGS(gettid, rdec, arg_none), @@ -268,13 +300,13 @@ static const struct syscall_format formats[] = { SARGS(lremovexattr, rdec, arg_cstr, arg_cstr), SARGS(fremovexattr, rdec, arg_fd, arg_cstr), SARGS(tkill, rdec, arg_, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_time SARGS(time, rdec, arg_), #endif SARGS(futex, rdec, arg_, arg_, arg_, arg_, arg_, arg_), SARGS(sched_setaffinity, rdec, arg_, arg_, arg_), SARGS(sched_getaffinity, rdec, arg_, arg_, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_set_thread_area SARGS(set_thread_area, rdec, arg_), #endif SARGS(io_setup, rdec, arg_, arg_), @@ -282,11 +314,11 @@ static const struct syscall_format formats[] = { SARGS(io_getevents, rdec, arg_, arg_, arg_, arg_, arg_), SARGS(io_submit, rdec, arg_, arg_, arg_), SARGS(io_cancel, rdec, arg_, arg_, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_get_thread_area SARGS(get_thread_area, rdec, arg_), #endif SARGS(lookup_dcookie, rdec, arg_, arg_, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_epoll_create SARGS(epoll_create, rdec, arg_), #endif SARGS(getdents64, rdec, arg_fd, arg_, arg_), @@ -303,12 +335,12 @@ static const struct syscall_format formats[] = { SARGS(clock_getres, rdec, arg_, arg_), SARGS(clock_nanosleep, rdec, arg_, arg_, arg_, arg_), SARGS(exit_group, rnoreturn, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_epoll_wait SARGS(epoll_wait, rdec, arg_fd, arg_, arg_, arg_), #endif SARGS(epoll_ctl, rdec, arg_fd, arg_, arg_fd, arg_), SARGS(tgkill, rdec, arg_, arg_, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_utimes SARGS(utimes, rdec, arg_cstr, arg_), #endif SARGS(mbind, rdec, arg_, arg_, arg_, arg_, arg_), @@ -327,7 +359,7 @@ static const struct syscall_format formats[] = { SARGS(keyctl, rdec, arg_, arg_, arg_, arg_, arg_), SARGS(ioprio_set, rdec, arg_, arg_, arg_), SARGS(ioprio_get, rdec, arg_, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_inotify_init SARGS(inotify_init, rdec, arg_none), #endif SARGS(inotify_add_watch, rdec, arg_fd, arg_cstr, arg_), @@ -337,12 +369,12 @@ static const struct syscall_format formats[] = { SARGS(mkdirat, rdec, arg_atfd, arg_cstr, arg_oct_mode), SARGS(mknodat, rdec, arg_atfd, arg_cstr, arg_oct_mode, arg_), SARGS(fchownat, rdec, arg_atfd, arg_cstr, arg_, arg_, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_futimesat SARGS(futimesat, rdec, arg_atfd, arg_cstr, arg_), #endif SARGS(newfstatat, rdec, arg_atfd, arg_cstr, arg_, arg_), SARGS(unlinkat, rdec, arg_atfd, arg_cstr, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_renameat SARGS(renameat, rdec, arg_atfd, arg_cstr, arg_atfd, arg_cstr), #endif SARGS(linkat, rdec, arg_atfd, arg_cstr, arg_atfd, arg_cstr, arg_), @@ -362,11 +394,11 @@ static const struct syscall_format formats[] = { SARGS(move_pages, rdec, arg_, arg_, arg_, arg_, arg_, arg_), SARGS(utimensat, rdec, arg_atfd, arg_cstr, arg_, arg_), SARGS(epoll_pwait, rdec, arg_fd, arg_, arg_, arg_, arg_, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_signalfd SARGS(signalfd, rdec, arg_fd, arg_, arg_), #endif SARGS(timerfd_create, rdec, arg_, arg_), -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_eventfd SARGS(eventfd, rdec, arg_), #endif SARGS(fallocate, rdec, arg_fd, arg_, arg_, arg_), @@ -538,7 +570,7 @@ static const struct syscall_format formats[] = { #undef SARGS -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_open static struct syscall_format open_with_o_creat = {.name = "open", rdec, {arg_cstr, arg_open_flags, arg_oct_mode}}; #endif @@ -594,7 +626,7 @@ get_syscall_format(const struct syscall_desc *desc) if (formats[desc->nr].name == NULL) return &unkown; -#if defined(__x86_64__) || defined(_M_X64) +#ifdef SYS_open if (desc->nr == SYS_open && oflags_refer_mode_arg((int)desc->args[1])) return &open_with_o_creat; #endif From 367e7dfbb658596f0012f2fe43b497264024a8bf Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Mon, 24 Feb 2025 19:35:22 +0100 Subject: [PATCH 060/143] Added simple brk test --- test/brk_test.c | 48 +++++++++++++++++++++++++++++++++++ test/intercept_sys_brk.c | 54 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 test/brk_test.c create mode 100644 test/intercept_sys_brk.c diff --git a/test/brk_test.c b/test/brk_test.c new file mode 100644 index 0000000..3544e31 --- /dev/null +++ b/test/brk_test.c @@ -0,0 +1,48 @@ +/* + * Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +int main() { + void *old_brk = sbrk(0); // Get current program break + printf("Old brk: %p\n", old_brk); + + // Increase the program break + void *new_brk = old_brk + 4096; // Allocate one page + if (brk(new_brk) != 0) { + perror("brk failed"); + return 1; + } + printf("New brk: %p\n", new_brk); +} diff --git a/test/intercept_sys_brk.c b/test/intercept_sys_brk.c new file mode 100644 index 0000000..94f0cb4 --- /dev/null +++ b/test/intercept_sys_brk.c @@ -0,0 +1,54 @@ +/* + * Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libsyscall_intercept_hook_point.h" + +#include +#include + + +static int hook(long syscall_number, + long arg0, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long *result) +{ + if (syscall_number == SYS_brk) { + write(1,"Proof of brk interception\n",26); + } + return 1; +} + +static __attribute__((constructor)) void init(void) +{ + intercept_hook_point = hook; +} From 1319a0f2155deb333fe08c8e813c7851ab40f063 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 25 Feb 2025 11:10:01 +0100 Subject: [PATCH 061/143] Added statx test --- test/intercept_sys_statx.c | 54 ++++++++++++++++++++++++++++++++++++++ test/statx_test.c | 54 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 test/intercept_sys_statx.c create mode 100644 test/statx_test.c diff --git a/test/intercept_sys_statx.c b/test/intercept_sys_statx.c new file mode 100644 index 0000000..2468641 --- /dev/null +++ b/test/intercept_sys_statx.c @@ -0,0 +1,54 @@ +/* + * Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libsyscall_intercept_hook_point.h" + +#include +#include + + +static int hook(long syscall_number, + long arg0, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long *result) +{ + if (syscall_number == SYS_statx) { + write(1,"Proof of statx interception\n",28); + } + return 1; +} + +static __attribute__((constructor)) void init(void) +{ + intercept_hook_point = hook; +} diff --git a/test/statx_test.c b/test/statx_test.c new file mode 100644 index 0000000..c9332f9 --- /dev/null +++ b/test/statx_test.c @@ -0,0 +1,54 @@ +/* + * Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +int main() { + struct statx stx; + int ret = syscall(SYS_statx, AT_FDCWD, "testfile.txt", 0, STATX_ALL, &stx); + + if (ret == -1) { + perror("statx failed"); + return 1; + } + + printf("statx succeeded: inode = %llu, size = %llu bytes\n", + (unsigned long long)stx.stx_ino, + (unsigned long long)stx.stx_size); + + return 0; +} From 64eac8960a4ff4195cd89c53be9d207f278cfacf Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 26 Feb 2025 15:30:06 +0100 Subject: [PATCH 062/143] Made write and openat tests assertive --- test/intercept_sys_openat.c | 15 +++++++++++++-- test/openat_test.c | 25 ++++++++++++++++--------- test/write_test.c | 27 +++++++++++++++++++++++++-- 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/test/intercept_sys_openat.c b/test/intercept_sys_openat.c index e6a9b40..acd1f60 100644 --- a/test/intercept_sys_openat.c +++ b/test/intercept_sys_openat.c @@ -32,7 +32,9 @@ #include "libsyscall_intercept_hook_point.h" #include -#include +#include +#include +#include static int hook(long syscall_number, @@ -41,8 +43,17 @@ static int hook(long syscall_number, long arg4, long arg5, long *result) { + if (syscall_number == SYS_openat) { - write(1,"Proof of openat interception\n",29); + const char non_existing[] = "non_existing.txt"; + const char *tmp = non_existing; + if (strcmp((char *)arg1, tmp) == 0) { + const char testfile[] = "testfile.txt"; + long flags = O_RDWR; + *result = syscall_no_intercept(SYS_openat,arg0,(uintptr_t)testfile, + flags,arg3,arg4,arg5); + return 0; + } } return 1; } diff --git a/test/openat_test.c b/test/openat_test.c index 28c3ea2..c4c903a 100644 --- a/test/openat_test.c +++ b/test/openat_test.c @@ -30,18 +30,25 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * execution of this test must be preloaded with the corresponding interception + * library, i.e. from the syscall_intercept/test directory + * LD_LIBRARY_PATH=.:../build LD_PRELOAD=intercept_sys_openat.so ./openat_test + */ + #include #include #include +#include int main() { - int fd = openat(AT_FDCWD,"non_existing_original_file.txt", O_RDONLY); - char buf[128] = "Specified file doesn't exist - " - "Test is ok if next line is printed before this one as well:\n" - "Proof of openat interception\n"; - if (fd >= 0) { - write(1, "Success: File opened\n", 21); - } else { - write(1, buf, strlen(buf)); - } + int create_fd = openat(AT_FDCWD, "testfile.txt", O_CREAT | O_TRUNC | O_RDONLY); + int test_fd = openat(AT_FDCWD, "non_existing.txt", O_RDONLY); + char buf[128] = "impossible write rerouted on testfile.txt"; + write(test_fd, buf, strlen(buf)); + char test_buf[128]; + read(create_fd, test_buf, strlen(buf)); + assert(strcmp(test_buf, buf) == 0); + write(1,"OPENAT TEST - OK\n",17); + return 0; } \ No newline at end of file diff --git a/test/write_test.c b/test/write_test.c index da28b01..f407892 100644 --- a/test/write_test.c +++ b/test/write_test.c @@ -30,10 +30,33 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * execution of this test must be preloaded with the corresponding interception + * library, i.e. from the syscall_intercept/test directory + * LD_LIBRARY_PATH=.:../build LD_PRELOAD=intercept_sys_write.so ./write_test + */ + #include #include +#include +#include +#include +#include int main() { - char buf[128] = "original_syscall\n"; - write(1, buf, strlen(buf)); + int test_fd = openat(AT_FDCWD, "testfile.txt", O_RDWR | O_CREAT | O_TRUNC); + if (test_fd == -1) { + printf("intercepted_openat error nr: %d\n", errno); + return 1; + } + char buf[128] = "original_syscall\n"; + write(test_fd, buf, strlen(buf)); + lseek(test_fd, 0, SEEK_SET); + char test_buf[128]; + int n = read(test_fd, test_buf, strlen(buf)); + test_buf[n] = '\0'; + assert(strcmp(test_buf, "intercepted_call\n") == 0); + char test_ok[128] = "placeholder_TEST - OK\n"; + write(1,test_ok,strlen(test_ok)); + return 0; } From 97670a873e2ab7aadf914b73901a9cdcb729f1ca Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 26 Feb 2025 15:38:48 +0100 Subject: [PATCH 063/143] Corrected openat_test --- test/openat_test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/openat_test.c b/test/openat_test.c index c4c903a..f34d889 100644 --- a/test/openat_test.c +++ b/test/openat_test.c @@ -47,7 +47,8 @@ int main() { char buf[128] = "impossible write rerouted on testfile.txt"; write(test_fd, buf, strlen(buf)); char test_buf[128]; - read(create_fd, test_buf, strlen(buf)); + int n = read(create_fd, test_buf, strlen(buf)); + test_buf[n] = '\0'; assert(strcmp(test_buf, buf) == 0); write(1,"OPENAT TEST - OK\n",17); return 0; From a795f91a2e7d0161af808542d6cd27faa69b509f Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 28 Feb 2025 14:09:46 +0100 Subject: [PATCH 064/143] Fixed clone() handling --- src/arch/riscv/intercept_template.S | 132 ++++++++++++++++++---------- src/arch/x86_64/asm_wrapper.md | 2 +- src/intercept.c | 6 +- src/intercept.h | 1 + 4 files changed, 91 insertions(+), 50 deletions(-) diff --git a/src/arch/riscv/intercept_template.S b/src/arch/riscv/intercept_template.S index 536398b..91fcb5e 100644 --- a/src/arch/riscv/intercept_template.S +++ b/src/arch/riscv/intercept_template.S @@ -47,32 +47,49 @@ * preceding_ins */ intercept_asm_wrapper_tmpl: - addi sp, sp, -8 - sd t5, 0(sp) + addi sp, sp, -72 + addi t6, sp, 72 # sp+72 is the sp value before interception + sd t6, 0(sp) + sd ra, 16(sp) + sd t0, 24(sp) + sd t1, 32(sp) + sd t2, 40(sp) + sd t3, 48(sp) + sd t4, 56(sp) + sd t5, 64(sp) li t5, 0 # choose intercept_routine -l0: - bnez t5, l3 - mv t6, sp # remember original sp - j l4 -l3: - ld t6, 0(sp) # we cloned, so save actual original sp -l4: - addi sp, sp, -64 # allocate stack for some locals - sd t6, 0(sp) # original sp on stack - sd ra, 16(sp) # patch->return_address on stack - sd s0, 24(sp) # follows conventions by saving s0 on stack since we use it - sd t0, 32(sp) - sd t1, 40(sp) - sd t2, 48(sp) - sd t3, 56(sp) - bnez t5, intercept_asm_wrapper_patch_desc_addr - li s0, 0 # s0 as flag: 1 if we are going for post_clone, 0 otherwise + beqz t5, intercept_asm_wrapper_patch_desc_addr +post_clone: + addi sp, sp, -72 + addi t6, sp, 72 # sp+72 is the sp value before interception + sd t6, 0(sp) + sd ra, 16(sp) + sd t0, 24(sp) + sd t1, 32(sp) + sd t2, 40(sp) + sd t3, 48(sp) + sd t4, 56(sp) + sd t5, 64(sp) + li t5, 1 # choose intercept_routine_post_clone +# j l4 +# l3: +# l4: + # addi sp, sp, -64 # allocate stack for some locals + # sd t6, 0(sp) # original sp on stack + # sd ra, 16(sp) # patch->return_address on stack + # sd s0, 24(sp) # follows conventions by saving s0 on stack since we use it + # sd t0, 32(sp) + # sd t1, 40(sp) + # sd t2, 48(sp) + # sd t3, 56(sp) + # bnez t5, intercept_asm_wrapper_patch_desc_addr + # li s0, 0 # s0 as flag: 1 if we are going for post_clone, 0 otherwise intercept_asm_wrapper_patch_desc_addr: /* load patch_desc address in t0 */ /* - * the 5 following instructions are placeholders for the correct ones which are - * overwritten in machine language by create_load_uint64t_into_t0() + * the 5 following instructions are placeholders for the correct ones which + * are overwritten in machine language by create_load_uint64t_into_t0() * * lui t0, 0x00000 * addi t0, t0, 0x000 @@ -124,6 +141,19 @@ intercept_asm_wrapper_wrapper_level1_addr: /* calling intercept_wrapper */ jalr ra, t0, 0 + /* + * restoring registers used before the intercept_wrapper function could + * save them on the stack + */ + ld ra, 16(sp) + ld t0, 24(sp) + ld t1, 32(sp) + ld t2, 40(sp) + ld t3, 48(sp) + ld t4, 56(sp) + ld t5, 64(sp) + addi sp, sp, 72 + /* * The intercept_wrapper function did restore all registers to their * original state, except for a0, sp and t6. @@ -133,35 +163,45 @@ intercept_asm_wrapper_wrapper_level1_addr: * If t6 is 1, a0 contains the return value of the hooked syscall. * If t6 is 2, a clone syscall is executed here. */ - beqz t6, l2 + beqz t6, execute_unhandled_ecall + addi sp, sp, -8 + sd t0, 0(sp) li t0, 1 - beq t6, t0, restore_sp + beq t6, t0, handled_ecall li t0, 2 - beq t6, t0, l1 - - li a7, 94 /* exit_group if t6 contains an invalid value, */ - ecall /* namely different from 0, 1 or 2 */ -l1: - mv a7, a0 + beq t6, t0, execute_clone + ebreak # if t6 holds invalid value +# li a7, 94 /* exit_group if t6 contains an invalid value, */ +# ecall /* namely different from 0, 1 or 2 */ +execute_clone: + ld t0, 0(sp) + addi sp, sp, 8 ecall - li t5, 1 /* choose intercept_routine_post_clone */ - li s0, 1 /* flag to signal we cloned, restoring sp will require adding 128 */ - j l0 -l2: - mv a7, a0 + j post_clone + +# mv a7, a0 +# ecall +# li t5, 1 /* choose intercept_routine_post_clone */ +# li s0, 1 /* flag to signal we cloned, restoring sp will require adding 128 */ +# j l0 + # beqz s0, l5 + # addi sp, sp, 64 +# l5: +# ld ra, 16(sp) +# ld s0, 24(sp) +# ld t0, 32(sp) +# ld t1, 40(sp) +# ld t2, 48(sp) +# ld t3, 56(sp) +# ld t5, 64(sp) # t5 was saved at what currently can be accessed with 64(sp) +# addi sp, sp, 72 +execute_unhandled_ecall: + # mv a7, a0 # a7 should still contain the original value which is syscall_nr ecall -restore_sp: - beqz s0, l5 - addi sp, sp, 64 -l5: - ld ra, 16(sp) - ld s0, 24(sp) - ld t0, 32(sp) - ld t1, 40(sp) - ld t2, 48(sp) - ld t3, 56(sp) - ld t5, 64(sp) # t5 was saved at what currently can be accessed with 64(sp) - addi sp, sp, 72 + j intercept_asm_wrapper_tmpl_end +handled_ecall: + ld t0, 0(sp) + addi sp, sp, 8 intercept_asm_wrapper_tmpl_end: /* diff --git a/src/arch/x86_64/asm_wrapper.md b/src/arch/x86_64/asm_wrapper.md index 6cfd593..72faffa 100644 --- a/src/arch/x86_64/asm_wrapper.md +++ b/src/arch/x86_64/asm_wrapper.md @@ -133,7 +133,7 @@ which is a C function. This function would attempt to log the result of the sysc then proceed to return to the calling side, which involves restoring the saved registers. But the saved registers would be restored from a location relative to the stack pointer. The result would be reading unspecified values -form the new stack location, and very likely a page fault. +from the new stack location, and very likely a page fault. To avoid this problem, this sort of clone syscall is not executed in the C function. Instead, the C function returns without executing the syscall, and of course without logging its result. It asks the assembly wrapper code to diff --git a/src/intercept.c b/src/intercept.c index c03ff6f..5c82157 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -731,13 +731,13 @@ intercept_routine(struct context *context) struct wrapper_ret intercept_routine_post_clone(struct context *context) { - if (SYSCALL_NR == 0) { + if (THREAD_PID == 0) { if (intercept_hook_point_clone_child != NULL) intercept_hook_point_clone_child(); } else { if (intercept_hook_point_clone_parent != NULL) - intercept_hook_point_clone_parent(SYSCALL_NR); + intercept_hook_point_clone_parent(THREAD_PID); } - return (struct wrapper_ret){FIRST_RET_REG = SYSCALL_NR, SECOND_RET_REG = 1 }; + return (struct wrapper_ret){FIRST_RET_REG = THREAD_PID, SECOND_RET_REG = 1 }; } diff --git a/src/intercept.h b/src/intercept.h index 4fc8724..d06f889 100644 --- a/src/intercept.h +++ b/src/intercept.h @@ -236,6 +236,7 @@ void activate_patches(struct intercept_desc *desc); #define SYSCALL_INS_SIZE PARAM_BY_ARCH(2, 4) #define JUMP_INS_SIZE PARAM_BY_ARCH(5,8) #define SYSCALL_NR PARAM_BY_ARCH(context->rax,context->a[7]) +#define THREAD_PID PARAM_BY_ARCH(context->rax,context->a[0]) #define FIRST_ARG_REG PARAM_BY_ARCH(context->rdi,context->a[0]) #define SECOND_ARG_REG PARAM_BY_ARCH(context->rsi,context->a[1]) #define THIRD_ARG_REG PARAM_BY_ARCH(context->rdx,context->a[2]) From 311633cea004d239d666c867bca44ec79e0ed204 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 28 Feb 2025 14:11:56 +0100 Subject: [PATCH 065/143] Added clone test --- test/clone_test.c | 63 ++++++++++++++++++++++++++++++++++++++ test/intercept_sys_clone.c | 38 +++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 test/clone_test.c create mode 100644 test/intercept_sys_clone.c diff --git a/test/clone_test.c b/test/clone_test.c new file mode 100644 index 0000000..191fe89 --- /dev/null +++ b/test/clone_test.c @@ -0,0 +1,63 @@ +/* + * Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +int child_func(void *arg) { + printf("Child process callback function: PID = %d\n", getpid()); + return 0; +} + +int main() { + char child_stack[8192]; // Stack for the child process + + printf("Parent process: PID = %d\n", getpid()); + + pid_t pid = clone(child_func, child_stack + sizeof(child_stack), + CLONE_VM | SIGCHLD, NULL); + + if (pid == -1) { + perror("clone failed"); + return 1; + } + + printf("clone() returned PID: %d\n", pid); + wait(NULL); + return 0; +} + + diff --git a/test/intercept_sys_clone.c b/test/intercept_sys_clone.c new file mode 100644 index 0000000..121a2bd --- /dev/null +++ b/test/intercept_sys_clone.c @@ -0,0 +1,38 @@ +#define _GNU_SOURCE +#include "libsyscall_intercept_hook_point.h" +#include +#include +#include +#include +#include // For CLONE_* flags +#include + +static int hook(long syscall_number, + long arg0, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long *result) +{ + if (syscall_number == SYS_clone) { + printf("[HOOK] clone intercepted! flags: 0x%lx\n", arg0); + } + return 1; +} + +static void hook_clone_parent(long child_pid) +{ + printf("Executing parent hook: %d - Its child pid should be %lu\n",getpid(),child_pid); +} + +static void hook_clone_child(void) +{ + printf("Executing child hook: %d\n", getpid()); +} + +static __attribute__((constructor)) void +init(void) +{ + intercept_hook_point = hook; + intercept_hook_point_clone_child = hook_clone_child; + intercept_hook_point_clone_parent = hook_clone_parent; +} From 4c732358d4f23ef0bfab4b6f887d21317948b468 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 28 Feb 2025 14:18:40 +0100 Subject: [PATCH 066/143] Comment, formatting --- test/intercept_sys_openat.c | 5 +++++ test/statx_test.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/test/intercept_sys_openat.c b/test/intercept_sys_openat.c index acd1f60..e0e9ba1 100644 --- a/test/intercept_sys_openat.c +++ b/test/intercept_sys_openat.c @@ -30,6 +30,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * see openat_test.c for details about this test library, which must be compiled with + * gcc -o intercept_sys_openat.so intercept_sys_write.c -I../include -L../build -lsyscall_intercept -fpic -shared + */ + #include "libsyscall_intercept_hook_point.h" #include #include diff --git a/test/statx_test.c b/test/statx_test.c index c9332f9..a372d3f 100644 --- a/test/statx_test.c +++ b/test/statx_test.c @@ -38,7 +38,7 @@ #include int main() { - struct statx stx; + struct statx stx; int ret = syscall(SYS_statx, AT_FDCWD, "testfile.txt", 0, STATX_ALL, &stx); if (ret == -1) { From 9100592df59c7372fca20d63eb0d0f4f3b438b6f Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 28 Feb 2025 14:20:45 +0100 Subject: [PATCH 067/143] modified .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 01cee36..35c17bf 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ build/ .idea/ cmake-build-debug/ test/*.so +test/testfile.txt From 163a11b2c166f47f7dc9bbcd23f706ceaba6a5c5 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 5 Mar 2025 00:29:36 +0100 Subject: [PATCH 068/143] Created a temporary folder for RISC-V testing --- .gitignore | 4 ++- test/{ => riscv/src}/clone_test.c | 0 test/{brk_test.c => riscv/src/fcntl_test.c} | 23 ++++++------- test/{ => riscv/src}/intercept_sys_clone.c | 0 .../src/intercept_sys_fcntl.c} | 12 ++++--- .../src/intercept_sys_mkdir.c} | 5 ++- test/{ => riscv/src}/intercept_sys_openat.c | 0 test/{ => riscv/src}/intercept_sys_read.c | 0 test/{ => riscv/src}/intercept_sys_statx.c | 0 .../src/mkdir_test.c} | 33 +++++++++++++++++-- test/{ => riscv/src}/openat_test.c | 0 test/{ => riscv/src}/read_test.c | 0 test/{ => riscv/src}/statx_test.c | 0 test/{ => riscv/src}/write_test.c | 0 14 files changed, 58 insertions(+), 19 deletions(-) rename test/{ => riscv/src}/clone_test.c (100%) rename test/{brk_test.c => riscv/src/fcntl_test.c} (76%) rename test/{ => riscv/src}/intercept_sys_clone.c (100%) rename test/{intercept_sys_fcntl64.c => riscv/src/intercept_sys_fcntl.c} (86%) rename test/{intercept_sys_brk.c => riscv/src/intercept_sys_mkdir.c} (91%) rename test/{ => riscv/src}/intercept_sys_openat.c (100%) rename test/{ => riscv/src}/intercept_sys_read.c (100%) rename test/{ => riscv/src}/intercept_sys_statx.c (100%) rename test/{fcntl64_test.c => riscv/src/mkdir_test.c} (63%) rename test/{ => riscv/src}/openat_test.c (100%) rename test/{ => riscv/src}/read_test.c (100%) rename test/{ => riscv/src}/statx_test.c (100%) rename test/{ => riscv/src}/write_test.c (100%) diff --git a/.gitignore b/.gitignore index 35c17bf..983a332 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,6 @@ build/ .idea/ cmake-build-debug/ test/*.so -test/testfile.txt +test/riscv/bin/ +test/riscv/build/ +test/riscv/*.txt diff --git a/test/clone_test.c b/test/riscv/src/clone_test.c similarity index 100% rename from test/clone_test.c rename to test/riscv/src/clone_test.c diff --git a/test/brk_test.c b/test/riscv/src/fcntl_test.c similarity index 76% rename from test/brk_test.c rename to test/riscv/src/fcntl_test.c index 3544e31..d0766a4 100644 --- a/test/brk_test.c +++ b/test/riscv/src/fcntl_test.c @@ -30,19 +30,20 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include -#include +#include int main() { - void *old_brk = sbrk(0); // Get current program break - printf("Old brk: %p\n", old_brk); - - // Increase the program break - void *new_brk = old_brk + 4096; // Allocate one page - if (brk(new_brk) != 0) { - perror("brk failed"); - return 1; - } - printf("New brk: %p\n", new_brk); + int fd = openat(AT_FDCWD, "../testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + int fd2 = openat(AT_FDCWD, "../testfile2.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + int fd2_dup = fcntl(fd2, F_DUPFD, 0); + char buf[128] = "writing to fd2_dup\n"; + write(fd2_dup, buf, strlen(buf)); + char dst_buf[128]; + int n = read(fd, dst_buf, sizeof(buf)); + dst_buf[n] = '\0'; + assert(strcmp(buf, dst_buf) == 0); + write(1, "FCNTL TEST - OK\n",16); } diff --git a/test/intercept_sys_clone.c b/test/riscv/src/intercept_sys_clone.c similarity index 100% rename from test/intercept_sys_clone.c rename to test/riscv/src/intercept_sys_clone.c diff --git a/test/intercept_sys_fcntl64.c b/test/riscv/src/intercept_sys_fcntl.c similarity index 86% rename from test/intercept_sys_fcntl64.c rename to test/riscv/src/intercept_sys_fcntl.c index 5d3893e..e3c999d 100644 --- a/test/intercept_sys_fcntl64.c +++ b/test/riscv/src/intercept_sys_fcntl.c @@ -33,6 +33,7 @@ #include "libsyscall_intercept_hook_point.h" #include #include +#include static int hook(long syscall_number, @@ -41,10 +42,13 @@ hook(long syscall_number, long arg4, long arg5, long *result) { - if (syscall_number == SYS_fcntl) { - write(1,"Proof of fcntl64 interception\n",30); - } - return 1; + if (syscall_number == SYS_fcntl) { + int fd = openat(AT_FDCWD, "../testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + int ret = syscall_no_intercept(syscall_number, fd, arg1, arg2, arg3, arg4, arg5); + *result = ret; + return 0; + } + return 1; } static __attribute__((constructor)) void diff --git a/test/intercept_sys_brk.c b/test/riscv/src/intercept_sys_mkdir.c similarity index 91% rename from test/intercept_sys_brk.c rename to test/riscv/src/intercept_sys_mkdir.c index 94f0cb4..bfcfeb2 100644 --- a/test/intercept_sys_brk.c +++ b/test/riscv/src/intercept_sys_mkdir.c @@ -34,6 +34,7 @@ #include #include +#include static int hook(long syscall_number, @@ -43,7 +44,9 @@ static int hook(long syscall_number, long *result) { if (syscall_number == SYS_brk) { - write(1,"Proof of brk interception\n",26); + *result = syscall_no_intercept(syscall_number, 0, arg1, arg2, arg3, arg4, arg5, result); + return 0; +// printf("Brk arg0 %p\n", (void *)arg0); } return 1; } diff --git a/test/intercept_sys_openat.c b/test/riscv/src/intercept_sys_openat.c similarity index 100% rename from test/intercept_sys_openat.c rename to test/riscv/src/intercept_sys_openat.c diff --git a/test/intercept_sys_read.c b/test/riscv/src/intercept_sys_read.c similarity index 100% rename from test/intercept_sys_read.c rename to test/riscv/src/intercept_sys_read.c diff --git a/test/intercept_sys_statx.c b/test/riscv/src/intercept_sys_statx.c similarity index 100% rename from test/intercept_sys_statx.c rename to test/riscv/src/intercept_sys_statx.c diff --git a/test/fcntl64_test.c b/test/riscv/src/mkdir_test.c similarity index 63% rename from test/fcntl64_test.c rename to test/riscv/src/mkdir_test.c index d0ad920..2dfd6a1 100644 --- a/test/fcntl64_test.c +++ b/test/riscv/src/mkdir_test.c @@ -30,9 +30,38 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * The following test assumes 4096 bytes as the smallest page size. It + * therefore makes sense on those architectures compliant with that + * assumption, as both amd64 and riscv64 are. Following that assumption, + * a brk(0) would result in an increase of the program break by 4096 bytes + */ + +#include +#include +#include #include +#include +#include +#include int main() { - int fd = openat(AT_FDCWD, "intercepting_original_file.txt", O_RDONLY); - int fd_dup = fcntl(fd, F_DUPFD, 0); + void *old_brk = sbrk(0); // Get current program break + int fd = openat(AT_FDCWD, "../testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + printf("Old brk: %p\n", old_brk); + + void *new_brk = old_brk + 8192; // Allocate two pages + dprintf(fd, "%p\n", new_brk); + + if (brk(new_brk) != 0) { + perror("brk failed"); + return 1; + } + char buf[128]; + lseek(fd, 0, SEEK_SET); + int n = read(fd, &buf, sizeof(buf)); + buf[n] = '\0'; + n = atoi(buf); +// assert(); + printf("New brk: %p\n", sbrk(0)); } diff --git a/test/openat_test.c b/test/riscv/src/openat_test.c similarity index 100% rename from test/openat_test.c rename to test/riscv/src/openat_test.c diff --git a/test/read_test.c b/test/riscv/src/read_test.c similarity index 100% rename from test/read_test.c rename to test/riscv/src/read_test.c diff --git a/test/statx_test.c b/test/riscv/src/statx_test.c similarity index 100% rename from test/statx_test.c rename to test/riscv/src/statx_test.c diff --git a/test/write_test.c b/test/riscv/src/write_test.c similarity index 100% rename from test/write_test.c rename to test/riscv/src/write_test.c From 5f55f0c28e3ea1f11d88f9b8d772b42c8756e40b Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 5 Mar 2025 00:32:16 +0100 Subject: [PATCH 069/143] Added Makefile --- test/riscv/Makefile | 66 ++++++++++++++++++++++ test/riscv/src/intercept_sys_write.c | 83 ++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 test/riscv/Makefile create mode 100644 test/riscv/src/intercept_sys_write.c diff --git a/test/riscv/Makefile b/test/riscv/Makefile new file mode 100644 index 0000000..1ae9b13 --- /dev/null +++ b/test/riscv/Makefile @@ -0,0 +1,66 @@ +CC = gcc +CFLAGS += -I../../include +CFLAGS += -L../../build +CFLAGS += -lsyscall_intercept +CFLAGS += -fpic -shared + +BIN_DIR = bin +BUILD_DIR = build +SRC_DIR = src + +LD_LIBRARY_PATH = ./build:../../build +LD_PRELOAD = ./build + +TESTS = clone \ + fcntl \ + mkdir \ + openat \ + read \ + statx \ + write + + +EXECUTABLES = $(BIN_DIR)/mkdir_test \ + $(BIN_DIR)/clone_test \ + $(BIN_DIR)/fcntl_test \ + $(BIN_DIR)/openat_test \ + $(BIN_DIR)/read_test \ + $(BIN_DIR)/statx_test \ + $(BIN_DIR)/write_test + +INTERCEPT_LIBS = $(BUILD_DIR)/intercept_sys_mkdir.so \ + $(BUILD_DIR)/intercept_sys_clone.so \ + $(BUILD_DIR)/intercept_sys_fcntl.so \ + $(BUILD_DIR)/intercept_sys_openat.so \ + $(BUILD_DIR)/intercept_sys_read.so \ + $(BUILD_DIR)/intercept_sys_statx.so \ + $(BUILD_DIR)/intercept_sys_write.so + +all: $(BIN_DIR) $(BUILD_DIR) $(EXECUTABLES) $(INTERCEPT_LIBS) + +$(BUILD_DIR)/%.so: $(SRC_DIR)/%.c + $(CC) -o $@ $< $(CFLAGS) + +$(BIN_DIR)/%: $(SRC_DIR)/%.c + $(CC) $< -o $@ + +test: $(TESTS) + +$(TESTS): + @echo "Running test: $@" + @LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) LD_PRELOAD=$(LD_PRELOAD)/intercept_sys_$@.so $(BIN_DIR)/$@_test \ + && echo "Test $@ - \033[32mPASSED\033[0m" \ + || echo "Test $@ - \033[31mFAILED\033[0m" + @echo + +clean: + rm -f $(BIN_DIR)/* + rm -f $(BUILD_DIR)/* + rm -f *.txt + rm -rf wrongdir/ + +$(BIN_DIR): + mkdir -p $(BIN_DIR) + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) diff --git a/test/riscv/src/intercept_sys_write.c b/test/riscv/src/intercept_sys_write.c new file mode 100644 index 0000000..103d0a6 --- /dev/null +++ b/test/riscv/src/intercept_sys_write.c @@ -0,0 +1,83 @@ +/* + * Copyright 2017, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libsyscall_intercept_hook_point.h" + +#include +#include +#include + +static int +hook(long syscall_number, + long arg0, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long *result) +{ + (void) arg0; + (void) arg2; + (void) arg3; + (void) arg4; + (void) arg5; + (void) result; + + if (syscall_number == SYS_write) { + const char test[] = "WRITE TEST - OK\n"; + const char *tmp = test; + if (strcmp((char *)arg1, tmp) == 0) return 1; + + const char interc[] = "intercepted_"; + const char *src = interc; + + /* write(fd, buf, len) */ + size_t len = (size_t)arg2; + char *buf = (char *)arg1; + +#ifdef EXPECT_SPURIOUS_SYSCALLS + if (strcmp(buf, "original_syscall") != 0) + return 1; +#endif + + if (len > sizeof(interc)) { + while (*src != '\0') + *buf++ = *src++; + } + } + + return 1; +} + +static __attribute__((constructor)) void +init(void) +{ + intercept_hook_point = hook; +} From e747d2d5c8633ab9455925845f1e131ea7c7dbcb Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 5 Mar 2025 00:35:43 +0100 Subject: [PATCH 070/143] All tests are updated --- test/riscv/src/clone_test.c | 25 ++++++++++++--- test/riscv/src/intercept_sys_clone.c | 45 ++++++++++++++++++++++----- test/riscv/src/intercept_sys_mkdir.c | 15 ++++++--- test/riscv/src/intercept_sys_openat.c | 10 +++--- test/riscv/src/intercept_sys_read.c | 22 +++++-------- test/riscv/src/intercept_sys_statx.c | 9 +++++- test/riscv/src/mkdir_test.c | 25 +++++---------- test/riscv/src/openat_test.c | 6 ++-- test/riscv/src/read_test.c | 10 ++++-- test/riscv/src/statx_test.c | 18 ++++++----- test/riscv/src/write_test.c | 6 ++-- 11 files changed, 120 insertions(+), 71 deletions(-) diff --git a/test/riscv/src/clone_test.c b/test/riscv/src/clone_test.c index 191fe89..4aa3b94 100644 --- a/test/riscv/src/clone_test.c +++ b/test/riscv/src/clone_test.c @@ -36,27 +36,42 @@ #include #include #include +#include +#include +#include +#include int child_func(void *arg) { - printf("Child process callback function: PID = %d\n", getpid()); + int fd = openat(AT_FDCWD, "../testfile.txt", O_RDONLY); + char buf[128]; + int n = read(fd, buf, strlen(buf)); + buf[n] = '\0'; + n = atoi(buf); + assert(n == getpid()); return 0; } int main() { - char child_stack[8192]; // Stack for the child process + int fd = openat(AT_FDCWD, "../testfile.txt", O_CREAT | O_TRUNC | O_RDWR, 0666); + int fd2 = openat(AT_FDCWD, "../testfile2.txt", O_CREAT | O_TRUNC | O_RDWR, 0666); - printf("Parent process: PID = %d\n", getpid()); + char child_stack[8192]; pid_t pid = clone(child_func, child_stack + sizeof(child_stack), CLONE_VM | SIGCHLD, NULL); if (pid == -1) { - perror("clone failed"); + perror("Clone failed"); return 1; } - printf("clone() returned PID: %d\n", pid); wait(NULL); + char buf[128]; + int n = read(fd2, buf, sizeof(buf)); + buf[n] = '\0'; + n = atoi(buf); + assert(n == getpid()); + write(1, "CLONE TEST - OK\n", 16); return 0; } diff --git a/test/riscv/src/intercept_sys_clone.c b/test/riscv/src/intercept_sys_clone.c index 121a2bd..b56675e 100644 --- a/test/riscv/src/intercept_sys_clone.c +++ b/test/riscv/src/intercept_sys_clone.c @@ -1,11 +1,40 @@ -#define _GNU_SOURCE +/* + * Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include "libsyscall_intercept_hook_point.h" #include #include #include -#include -#include // For CLONE_* flags -#include +#include static int hook(long syscall_number, long arg0, long arg1, @@ -14,19 +43,21 @@ static int hook(long syscall_number, long *result) { if (syscall_number == SYS_clone) { - printf("[HOOK] clone intercepted! flags: 0x%lx\n", arg0); + printf("Clone intercepted - Flags: 0x%lx - PID: %d\n", arg0, getpid()); } return 1; } static void hook_clone_parent(long child_pid) { - printf("Executing parent hook: %d - Its child pid should be %lu\n",getpid(),child_pid); + int fd = openat(AT_FDCWD, "../testfile2.txt", O_WRONLY); + dprintf(fd, "%d\n", getpid()); } static void hook_clone_child(void) { - printf("Executing child hook: %d\n", getpid()); + int fd = openat(AT_FDCWD, "../testfile.txt", O_WRONLY); + dprintf(fd, "%d\n", getpid()); } static __attribute__((constructor)) void diff --git a/test/riscv/src/intercept_sys_mkdir.c b/test/riscv/src/intercept_sys_mkdir.c index bfcfeb2..f97f08f 100644 --- a/test/riscv/src/intercept_sys_mkdir.c +++ b/test/riscv/src/intercept_sys_mkdir.c @@ -35,6 +35,8 @@ #include #include #include +#include +#include static int hook(long syscall_number, @@ -43,10 +45,15 @@ static int hook(long syscall_number, long arg4, long arg5, long *result) { - if (syscall_number == SYS_brk) { - *result = syscall_no_intercept(syscall_number, 0, arg1, arg2, arg3, arg4, arg5, result); - return 0; -// printf("Brk arg0 %p\n", (void *)arg0); + if (syscall_number == SYS_mkdir) { + char buf[128] = "../wrongdir/"; + char *tmp = buf; + if (strcmp((char *)arg0, tmp) == 0) { + const char testdir[] = "../testdir/"; + syscall_no_intercept(syscall_number, (uintptr_t)testdir, arg1, arg2, + arg3, arg4, arg5); + return 0; + } } return 1; } diff --git a/test/riscv/src/intercept_sys_openat.c b/test/riscv/src/intercept_sys_openat.c index e0e9ba1..516f936 100644 --- a/test/riscv/src/intercept_sys_openat.c +++ b/test/riscv/src/intercept_sys_openat.c @@ -50,13 +50,13 @@ static int hook(long syscall_number, { if (syscall_number == SYS_openat) { - const char non_existing[] = "non_existing.txt"; + const char non_existing[] = "../non_existing.txt"; const char *tmp = non_existing; if (strcmp((char *)arg1, tmp) == 0) { - const char testfile[] = "testfile.txt"; - long flags = O_RDWR; - *result = syscall_no_intercept(SYS_openat,arg0,(uintptr_t)testfile, - flags,arg3,arg4,arg5); + const char testfile[] = "../testfile.txt"; + long flags = O_WRONLY; + *result = syscall_no_intercept(SYS_openat, arg0, (uintptr_t)testfile, + flags, arg3, arg4, arg5); return 0; } } diff --git a/test/riscv/src/intercept_sys_read.c b/test/riscv/src/intercept_sys_read.c index 79e6ac3..a584a7d 100644 --- a/test/riscv/src/intercept_sys_read.c +++ b/test/riscv/src/intercept_sys_read.c @@ -33,6 +33,9 @@ #include "libsyscall_intercept_hook_point.h" #include #include +#include +#include +#include static int hook(long syscall_number, @@ -47,21 +50,10 @@ static int hook(long syscall_number, (void)result; if (syscall_number == SYS_read) { - char *buf = (char *)arg1; - size_t len = (size_t)arg2; - const char interc[] = "intercepted_read\n"; - const char *src = interc; - - if (len > sizeof(interc)) { - *result = 0; - while (*src != '\0') { - *buf++ = *src++; - *result += 1; - } - *buf = '\0'; - *result += 1; - } - return 0; + int fd = openat(AT_FDCWD, "../testfile.txt", O_WRONLY); + char buf[128] = "write from read hook\n"; + write(fd, buf, strlen(buf)); + lseek(fd, 0, SEEK_SET); } return 1; } diff --git a/test/riscv/src/intercept_sys_statx.c b/test/riscv/src/intercept_sys_statx.c index 2468641..4274b7e 100644 --- a/test/riscv/src/intercept_sys_statx.c +++ b/test/riscv/src/intercept_sys_statx.c @@ -34,6 +34,7 @@ #include #include +#include static int hook(long syscall_number, @@ -43,7 +44,13 @@ static int hook(long syscall_number, long *result) { if (syscall_number == SYS_statx) { - write(1,"Proof of statx interception\n",28); + const char file2[] = "../testfile2.txt"; + const char *tmp = file2; + if (strcmp((char *)arg1, tmp) == 0) { + const char testfile[] = "../testfile.txt"; + syscall_no_intercept(syscall_number, arg0, testfile, arg2, arg3, arg4, arg5, result); + return 0; + } } return 1; } diff --git a/test/riscv/src/mkdir_test.c b/test/riscv/src/mkdir_test.c index 2dfd6a1..2c12880 100644 --- a/test/riscv/src/mkdir_test.c +++ b/test/riscv/src/mkdir_test.c @@ -44,24 +44,13 @@ #include #include #include +#include int main() { - void *old_brk = sbrk(0); // Get current program break - int fd = openat(AT_FDCWD, "../testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); - printf("Old brk: %p\n", old_brk); - - void *new_brk = old_brk + 8192; // Allocate two pages - dprintf(fd, "%p\n", new_brk); - - if (brk(new_brk) != 0) { - perror("brk failed"); - return 1; - } - char buf[128]; - lseek(fd, 0, SEEK_SET); - int n = read(fd, &buf, sizeof(buf)); - buf[n] = '\0'; - n = atoi(buf); -// assert(); - printf("New brk: %p\n", sbrk(0)); + mkdir("../wrongdir/", 0777); + int fd = openat(AT_FDCWD, "../testdir/testdirfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + assert(fd != -1); + system("rm -rf ../testdir/"); + write(1, "MKDIR TEST - OK\n", 16); + return 0; } diff --git a/test/riscv/src/openat_test.c b/test/riscv/src/openat_test.c index f34d889..ec6d861 100644 --- a/test/riscv/src/openat_test.c +++ b/test/riscv/src/openat_test.c @@ -42,14 +42,14 @@ #include int main() { - int create_fd = openat(AT_FDCWD, "testfile.txt", O_CREAT | O_TRUNC | O_RDONLY); - int test_fd = openat(AT_FDCWD, "non_existing.txt", O_RDONLY); + int create_fd = openat(AT_FDCWD, "../testfile.txt", O_CREAT | O_TRUNC | O_RDONLY, 0666); + int test_fd = openat(AT_FDCWD, "../non_existing.txt", O_RDONLY); char buf[128] = "impossible write rerouted on testfile.txt"; write(test_fd, buf, strlen(buf)); char test_buf[128]; int n = read(create_fd, test_buf, strlen(buf)); test_buf[n] = '\0'; assert(strcmp(test_buf, buf) == 0); - write(1,"OPENAT TEST - OK\n",17); + write(1, "OPENAT TEST - OK\n", 17); return 0; } \ No newline at end of file diff --git a/test/riscv/src/read_test.c b/test/riscv/src/read_test.c index 1ebc88a..2dc6cc1 100644 --- a/test/riscv/src/read_test.c +++ b/test/riscv/src/read_test.c @@ -32,9 +32,15 @@ #include #include +#include +#include int main() { + int fd = openat(AT_FDCWD, "../testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); char buf[128]; - read(0, buf, sizeof(buf)); - write(1, buf, strlen(buf)); // Should print "intercepted_read" + char expected_string[] = "write from read hook\n"; + int n = read(fd, buf, strlen(expected_string)); + buf[n] = '\0'; + assert(strcmp(buf,expected_string) == 0); + write(1, "READ TEST - OK\n",15); } diff --git a/test/riscv/src/statx_test.c b/test/riscv/src/statx_test.c index a372d3f..1e8b59d 100644 --- a/test/riscv/src/statx_test.c +++ b/test/riscv/src/statx_test.c @@ -30,25 +30,27 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define _GNU_SOURCE #include #include #include #include +#include #include #include +#include int main() { + int fd = openat(AT_FDCWD, "../testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); struct statx stx; - int ret = syscall(SYS_statx, AT_FDCWD, "testfile.txt", 0, STATX_ALL, &stx); + statx(AT_FDCWD, "../testfile.txt", 0, STATX_BASIC_STATS | STATX_BTIME, &stx); - if (ret == -1) { - perror("statx failed"); - return 1; - } + int fd2 = openat(AT_FDCWD, "../testfile2.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + struct statx stx2; + statx(AT_FDCWD, "../testfile2.txt", 0, STATX_BASIC_STATS | STATX_BTIME, &stx2); - printf("statx succeeded: inode = %llu, size = %llu bytes\n", - (unsigned long long)stx.stx_ino, - (unsigned long long)stx.stx_size); + assert(stx.stx_ino == stx2.stx_ino); + write(1, "STATX TEST - OK\n", 16); return 0; } diff --git a/test/riscv/src/write_test.c b/test/riscv/src/write_test.c index f407892..dd8c90f 100644 --- a/test/riscv/src/write_test.c +++ b/test/riscv/src/write_test.c @@ -44,7 +44,7 @@ #include int main() { - int test_fd = openat(AT_FDCWD, "testfile.txt", O_RDWR | O_CREAT | O_TRUNC); + int test_fd = openat(AT_FDCWD, "../testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); if (test_fd == -1) { printf("intercepted_openat error nr: %d\n", errno); return 1; @@ -56,7 +56,7 @@ int main() { int n = read(test_fd, test_buf, strlen(buf)); test_buf[n] = '\0'; assert(strcmp(test_buf, "intercepted_call\n") == 0); - char test_ok[128] = "placeholder_TEST - OK\n"; - write(1,test_ok,strlen(test_ok)); + char test_ok[128] = "WRITE TEST - OK\n"; + write(1, test_ok, strlen(test_ok)); return 0; } From 66eddc8033011f2423b3d683242053a9a4139fc0 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 5 Mar 2025 00:44:59 +0100 Subject: [PATCH 071/143] Reformatting --- test/riscv/src/intercept_sys_clone.c | 4 ++-- test/riscv/src/write_test.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/riscv/src/intercept_sys_clone.c b/test/riscv/src/intercept_sys_clone.c index b56675e..0291af9 100644 --- a/test/riscv/src/intercept_sys_clone.c +++ b/test/riscv/src/intercept_sys_clone.c @@ -57,13 +57,13 @@ static void hook_clone_parent(long child_pid) static void hook_clone_child(void) { int fd = openat(AT_FDCWD, "../testfile.txt", O_WRONLY); - dprintf(fd, "%d\n", getpid()); + dprintf(fd, "%d\n", getpid()); } static __attribute__((constructor)) void init(void) { intercept_hook_point = hook; - intercept_hook_point_clone_child = hook_clone_child; + intercept_hook_point_clone_child = hook_clone_child; intercept_hook_point_clone_parent = hook_clone_parent; } diff --git a/test/riscv/src/write_test.c b/test/riscv/src/write_test.c index dd8c90f..f013c30 100644 --- a/test/riscv/src/write_test.c +++ b/test/riscv/src/write_test.c @@ -44,15 +44,15 @@ #include int main() { - int test_fd = openat(AT_FDCWD, "../testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); - if (test_fd == -1) { - printf("intercepted_openat error nr: %d\n", errno); - return 1; - } - char buf[128] = "original_syscall\n"; - write(test_fd, buf, strlen(buf)); + int test_fd = openat(AT_FDCWD, "../testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + if (test_fd == -1) { + printf("intercepted_openat error nr: %d\n", errno); + return 1; + } + char buf[128] = "original_syscall\n"; + write(test_fd, buf, strlen(buf)); lseek(test_fd, 0, SEEK_SET); - char test_buf[128]; + char test_buf[128]; int n = read(test_fd, test_buf, strlen(buf)); test_buf[n] = '\0'; assert(strcmp(test_buf, "intercepted_call\n") == 0); From 58500df0179b533dd22e242467ea0143caa9ee5b Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 5 Mar 2025 00:48:26 +0100 Subject: [PATCH 072/143] Switched to mkdirat since mkdir is not defined on RISC-V --- test/riscv/Makefile | 6 +++--- .../src/{intercept_sys_mkdir.c => intercept_sys_mkdirat.c} | 6 +++--- test/riscv/src/{mkdir_test.c => mkdirat_test.c} | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) rename test/riscv/src/{intercept_sys_mkdir.c => intercept_sys_mkdirat.c} (93%) rename test/riscv/src/{mkdir_test.c => mkdirat_test.c} (96%) diff --git a/test/riscv/Makefile b/test/riscv/Makefile index 1ae9b13..bb935ee 100644 --- a/test/riscv/Makefile +++ b/test/riscv/Makefile @@ -13,14 +13,14 @@ LD_PRELOAD = ./build TESTS = clone \ fcntl \ - mkdir \ + mkdirat \ openat \ read \ statx \ write -EXECUTABLES = $(BIN_DIR)/mkdir_test \ +EXECUTABLES = $(BIN_DIR)/mkdirat_test \ $(BIN_DIR)/clone_test \ $(BIN_DIR)/fcntl_test \ $(BIN_DIR)/openat_test \ @@ -28,7 +28,7 @@ EXECUTABLES = $(BIN_DIR)/mkdir_test \ $(BIN_DIR)/statx_test \ $(BIN_DIR)/write_test -INTERCEPT_LIBS = $(BUILD_DIR)/intercept_sys_mkdir.so \ +INTERCEPT_LIBS = $(BUILD_DIR)/intercept_sys_mkdirat.so \ $(BUILD_DIR)/intercept_sys_clone.so \ $(BUILD_DIR)/intercept_sys_fcntl.so \ $(BUILD_DIR)/intercept_sys_openat.so \ diff --git a/test/riscv/src/intercept_sys_mkdir.c b/test/riscv/src/intercept_sys_mkdirat.c similarity index 93% rename from test/riscv/src/intercept_sys_mkdir.c rename to test/riscv/src/intercept_sys_mkdirat.c index f97f08f..a4e48cc 100644 --- a/test/riscv/src/intercept_sys_mkdir.c +++ b/test/riscv/src/intercept_sys_mkdirat.c @@ -45,12 +45,12 @@ static int hook(long syscall_number, long arg4, long arg5, long *result) { - if (syscall_number == SYS_mkdir) { + if (syscall_number == SYS_mkdirat) { char buf[128] = "../wrongdir/"; char *tmp = buf; - if (strcmp((char *)arg0, tmp) == 0) { + if (strcmp((char *)arg1, tmp) == 0) { const char testdir[] = "../testdir/"; - syscall_no_intercept(syscall_number, (uintptr_t)testdir, arg1, arg2, + syscall_no_intercept(syscall_number, arg0, (uintptr_t)testdir, arg2, arg3, arg4, arg5); return 0; } diff --git a/test/riscv/src/mkdir_test.c b/test/riscv/src/mkdirat_test.c similarity index 96% rename from test/riscv/src/mkdir_test.c rename to test/riscv/src/mkdirat_test.c index 2c12880..417fad2 100644 --- a/test/riscv/src/mkdir_test.c +++ b/test/riscv/src/mkdirat_test.c @@ -47,10 +47,10 @@ #include int main() { - mkdir("../wrongdir/", 0777); + mkdirat(AT_FDCWD,"../wrongdir/", 0777); int fd = openat(AT_FDCWD, "../testdir/testdirfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); assert(fd != -1); system("rm -rf ../testdir/"); - write(1, "MKDIR TEST - OK\n", 16); + write(1, "MKDIRAT TEST - OK\n", 16); return 0; } From 64423d9d699773bf16ef09bf1dc2a52d5d797ca1 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 5 Mar 2025 00:58:54 +0100 Subject: [PATCH 073/143] Reinforced clone test --- test/riscv/src/clone_test.c | 8 +++++++- test/riscv/src/mkdirat_test.c | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/test/riscv/src/clone_test.c b/test/riscv/src/clone_test.c index 4aa3b94..5bd7295 100644 --- a/test/riscv/src/clone_test.c +++ b/test/riscv/src/clone_test.c @@ -65,7 +65,13 @@ int main() { return 1; } - wait(NULL); + int status; + wait(&status); + if (WIFSIGNALED(status) && WTERMSIG(status) == SIGABRT) { + fprintf(stderr, "Child assertion failed\n"); + return 1; + } + char buf[128]; int n = read(fd2, buf, sizeof(buf)); buf[n] = '\0'; diff --git a/test/riscv/src/mkdirat_test.c b/test/riscv/src/mkdirat_test.c index 417fad2..a62e9f4 100644 --- a/test/riscv/src/mkdirat_test.c +++ b/test/riscv/src/mkdirat_test.c @@ -51,6 +51,6 @@ int main() { int fd = openat(AT_FDCWD, "../testdir/testdirfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); assert(fd != -1); system("rm -rf ../testdir/"); - write(1, "MKDIRAT TEST - OK\n", 16); + write(1, "MKDIRAT TEST - OK\n", 18); return 0; } From 7249ac2f3e3aebbed37e195c15a85e75ac5f8694 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 5 Mar 2025 01:13:16 +0100 Subject: [PATCH 074/143] Corrected relative paths --- test/riscv/src/clone_test.c | 6 +++--- test/riscv/src/fcntl_test.c | 4 ++-- test/riscv/src/intercept_sys_clone.c | 4 ++-- test/riscv/src/intercept_sys_fcntl.c | 2 +- test/riscv/src/intercept_sys_mkdirat.c | 4 ++-- test/riscv/src/intercept_sys_openat.c | 4 ++-- test/riscv/src/intercept_sys_read.c | 2 +- test/riscv/src/intercept_sys_statx.c | 4 ++-- test/riscv/src/mkdirat_test.c | 6 +++--- test/riscv/src/openat_test.c | 4 ++-- test/riscv/src/read_test.c | 2 +- test/riscv/src/statx_test.c | 8 ++++---- test/riscv/src/write_test.c | 2 +- 13 files changed, 26 insertions(+), 26 deletions(-) diff --git a/test/riscv/src/clone_test.c b/test/riscv/src/clone_test.c index 5bd7295..9490685 100644 --- a/test/riscv/src/clone_test.c +++ b/test/riscv/src/clone_test.c @@ -42,7 +42,7 @@ #include int child_func(void *arg) { - int fd = openat(AT_FDCWD, "../testfile.txt", O_RDONLY); + int fd = openat(AT_FDCWD, "testfile.txt", O_RDONLY); char buf[128]; int n = read(fd, buf, strlen(buf)); buf[n] = '\0'; @@ -52,8 +52,8 @@ int child_func(void *arg) { } int main() { - int fd = openat(AT_FDCWD, "../testfile.txt", O_CREAT | O_TRUNC | O_RDWR, 0666); - int fd2 = openat(AT_FDCWD, "../testfile2.txt", O_CREAT | O_TRUNC | O_RDWR, 0666); + int fd = openat(AT_FDCWD, "testfile.txt", O_CREAT | O_TRUNC | O_RDWR, 0666); + int fd2 = openat(AT_FDCWD, "testfile2.txt", O_CREAT | O_TRUNC | O_RDWR, 0666); char child_stack[8192]; diff --git a/test/riscv/src/fcntl_test.c b/test/riscv/src/fcntl_test.c index d0766a4..3c54cf2 100644 --- a/test/riscv/src/fcntl_test.c +++ b/test/riscv/src/fcntl_test.c @@ -36,8 +36,8 @@ #include int main() { - int fd = openat(AT_FDCWD, "../testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); - int fd2 = openat(AT_FDCWD, "../testfile2.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + int fd = openat(AT_FDCWD, "testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + int fd2 = openat(AT_FDCWD, "testfile2.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); int fd2_dup = fcntl(fd2, F_DUPFD, 0); char buf[128] = "writing to fd2_dup\n"; write(fd2_dup, buf, strlen(buf)); diff --git a/test/riscv/src/intercept_sys_clone.c b/test/riscv/src/intercept_sys_clone.c index 0291af9..543d21f 100644 --- a/test/riscv/src/intercept_sys_clone.c +++ b/test/riscv/src/intercept_sys_clone.c @@ -50,13 +50,13 @@ static int hook(long syscall_number, static void hook_clone_parent(long child_pid) { - int fd = openat(AT_FDCWD, "../testfile2.txt", O_WRONLY); + int fd = openat(AT_FDCWD, "testfile2.txt", O_WRONLY); dprintf(fd, "%d\n", getpid()); } static void hook_clone_child(void) { - int fd = openat(AT_FDCWD, "../testfile.txt", O_WRONLY); + int fd = openat(AT_FDCWD, "testfile.txt", O_WRONLY); dprintf(fd, "%d\n", getpid()); } diff --git a/test/riscv/src/intercept_sys_fcntl.c b/test/riscv/src/intercept_sys_fcntl.c index e3c999d..2470a74 100644 --- a/test/riscv/src/intercept_sys_fcntl.c +++ b/test/riscv/src/intercept_sys_fcntl.c @@ -43,7 +43,7 @@ hook(long syscall_number, long *result) { if (syscall_number == SYS_fcntl) { - int fd = openat(AT_FDCWD, "../testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + int fd = openat(AT_FDCWD, "testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); int ret = syscall_no_intercept(syscall_number, fd, arg1, arg2, arg3, arg4, arg5); *result = ret; return 0; diff --git a/test/riscv/src/intercept_sys_mkdirat.c b/test/riscv/src/intercept_sys_mkdirat.c index a4e48cc..41d311d 100644 --- a/test/riscv/src/intercept_sys_mkdirat.c +++ b/test/riscv/src/intercept_sys_mkdirat.c @@ -46,10 +46,10 @@ static int hook(long syscall_number, long *result) { if (syscall_number == SYS_mkdirat) { - char buf[128] = "../wrongdir/"; + char buf[128] = "wrongdir/"; char *tmp = buf; if (strcmp((char *)arg1, tmp) == 0) { - const char testdir[] = "../testdir/"; + const char testdir[] = "testdir/"; syscall_no_intercept(syscall_number, arg0, (uintptr_t)testdir, arg2, arg3, arg4, arg5); return 0; diff --git a/test/riscv/src/intercept_sys_openat.c b/test/riscv/src/intercept_sys_openat.c index 516f936..7c38553 100644 --- a/test/riscv/src/intercept_sys_openat.c +++ b/test/riscv/src/intercept_sys_openat.c @@ -50,10 +50,10 @@ static int hook(long syscall_number, { if (syscall_number == SYS_openat) { - const char non_existing[] = "../non_existing.txt"; + const char non_existing[] = "non_existing.txt"; const char *tmp = non_existing; if (strcmp((char *)arg1, tmp) == 0) { - const char testfile[] = "../testfile.txt"; + const char testfile[] = "testfile.txt"; long flags = O_WRONLY; *result = syscall_no_intercept(SYS_openat, arg0, (uintptr_t)testfile, flags, arg3, arg4, arg5); diff --git a/test/riscv/src/intercept_sys_read.c b/test/riscv/src/intercept_sys_read.c index a584a7d..f9a2482 100644 --- a/test/riscv/src/intercept_sys_read.c +++ b/test/riscv/src/intercept_sys_read.c @@ -50,7 +50,7 @@ static int hook(long syscall_number, (void)result; if (syscall_number == SYS_read) { - int fd = openat(AT_FDCWD, "../testfile.txt", O_WRONLY); + int fd = openat(AT_FDCWD, "testfile.txt", O_WRONLY); char buf[128] = "write from read hook\n"; write(fd, buf, strlen(buf)); lseek(fd, 0, SEEK_SET); diff --git a/test/riscv/src/intercept_sys_statx.c b/test/riscv/src/intercept_sys_statx.c index 4274b7e..6c7112c 100644 --- a/test/riscv/src/intercept_sys_statx.c +++ b/test/riscv/src/intercept_sys_statx.c @@ -44,10 +44,10 @@ static int hook(long syscall_number, long *result) { if (syscall_number == SYS_statx) { - const char file2[] = "../testfile2.txt"; + const char file2[] = "testfile2.txt"; const char *tmp = file2; if (strcmp((char *)arg1, tmp) == 0) { - const char testfile[] = "../testfile.txt"; + const char testfile[] = "testfile.txt"; syscall_no_intercept(syscall_number, arg0, testfile, arg2, arg3, arg4, arg5, result); return 0; } diff --git a/test/riscv/src/mkdirat_test.c b/test/riscv/src/mkdirat_test.c index a62e9f4..5700a1f 100644 --- a/test/riscv/src/mkdirat_test.c +++ b/test/riscv/src/mkdirat_test.c @@ -47,10 +47,10 @@ #include int main() { - mkdirat(AT_FDCWD,"../wrongdir/", 0777); - int fd = openat(AT_FDCWD, "../testdir/testdirfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + mkdirat(AT_FDCWD,"wrongdir/", 0777); + int fd = openat(AT_FDCWD, "testdir/testdirfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); assert(fd != -1); - system("rm -rf ../testdir/"); + system("rm -rf testdir/"); write(1, "MKDIRAT TEST - OK\n", 18); return 0; } diff --git a/test/riscv/src/openat_test.c b/test/riscv/src/openat_test.c index ec6d861..d663fd1 100644 --- a/test/riscv/src/openat_test.c +++ b/test/riscv/src/openat_test.c @@ -42,8 +42,8 @@ #include int main() { - int create_fd = openat(AT_FDCWD, "../testfile.txt", O_CREAT | O_TRUNC | O_RDONLY, 0666); - int test_fd = openat(AT_FDCWD, "../non_existing.txt", O_RDONLY); + int create_fd = openat(AT_FDCWD, "testfile.txt", O_CREAT | O_TRUNC | O_RDONLY, 0666); + int test_fd = openat(AT_FDCWD, "non_existing.txt", O_RDONLY); char buf[128] = "impossible write rerouted on testfile.txt"; write(test_fd, buf, strlen(buf)); char test_buf[128]; diff --git a/test/riscv/src/read_test.c b/test/riscv/src/read_test.c index 2dc6cc1..d396e13 100644 --- a/test/riscv/src/read_test.c +++ b/test/riscv/src/read_test.c @@ -36,7 +36,7 @@ #include int main() { - int fd = openat(AT_FDCWD, "../testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + int fd = openat(AT_FDCWD, "testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); char buf[128]; char expected_string[] = "write from read hook\n"; int n = read(fd, buf, strlen(expected_string)); diff --git a/test/riscv/src/statx_test.c b/test/riscv/src/statx_test.c index 1e8b59d..3e2c922 100644 --- a/test/riscv/src/statx_test.c +++ b/test/riscv/src/statx_test.c @@ -41,13 +41,13 @@ #include int main() { - int fd = openat(AT_FDCWD, "../testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + int fd = openat(AT_FDCWD, "testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); struct statx stx; - statx(AT_FDCWD, "../testfile.txt", 0, STATX_BASIC_STATS | STATX_BTIME, &stx); + statx(AT_FDCWD, "testfile.txt", 0, STATX_BASIC_STATS | STATX_BTIME, &stx); - int fd2 = openat(AT_FDCWD, "../testfile2.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + int fd2 = openat(AT_FDCWD, "testfile2.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); struct statx stx2; - statx(AT_FDCWD, "../testfile2.txt", 0, STATX_BASIC_STATS | STATX_BTIME, &stx2); + statx(AT_FDCWD, "testfile2.txt", 0, STATX_BASIC_STATS | STATX_BTIME, &stx2); assert(stx.stx_ino == stx2.stx_ino); write(1, "STATX TEST - OK\n", 16); diff --git a/test/riscv/src/write_test.c b/test/riscv/src/write_test.c index f013c30..4aa7615 100644 --- a/test/riscv/src/write_test.c +++ b/test/riscv/src/write_test.c @@ -44,7 +44,7 @@ #include int main() { - int test_fd = openat(AT_FDCWD, "../testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + int test_fd = openat(AT_FDCWD, "testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); if (test_fd == -1) { printf("intercepted_openat error nr: %d\n", errno); return 1; From f411c565410b671a457e0b84e6bde08efcc42144 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 5 Mar 2025 11:30:38 +0100 Subject: [PATCH 075/143] Corrected clone test --- test/riscv/src/clone_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/riscv/src/clone_test.c b/test/riscv/src/clone_test.c index 9490685..7c42189 100644 --- a/test/riscv/src/clone_test.c +++ b/test/riscv/src/clone_test.c @@ -44,7 +44,7 @@ int child_func(void *arg) { int fd = openat(AT_FDCWD, "testfile.txt", O_RDONLY); char buf[128]; - int n = read(fd, buf, strlen(buf)); + int n = read(fd, buf, sizeof(buf)); buf[n] = '\0'; n = atoi(buf); assert(n == getpid()); From aca84154c3fe8b349d90e2b241578f2a8ec59ab5 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 6 Mar 2025 11:42:33 +0100 Subject: [PATCH 076/143] Updated READMEs --- README.md | 19 ++++++++++++------- test/riscv/README.md | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 test/riscv/README.md diff --git a/README.md b/README.md index 8248722..2e6feb5 100644 --- a/README.md +++ b/README.md @@ -56,13 +56,17 @@ There is an install target. For now, all it does, is cp. make install ``` -[//]: # (Coming soon:) - -[//]: # (```sh) - -[//]: # (make test) +Testing on **x86_64**: +```shell +make test +``` -[//]: # (```) +Testing on **RISC-V**:\ +Go to `syscall_intercept/test/riscv/`, then +```shell +make +make test +``` # Synopsis # @@ -313,7 +317,8 @@ aa20a: bltu a5,a0,aa262 <__open+0xaa> | aa20a: bltu a5,a0,aa262 <__ope with some other libc implementations as well * RISC-V version assumes `$t6` is not used as base pointer or as source register without being reinitialized after an `ecall` and before the ending of -a function (tested with glibc 2.35, 2.37 and 2.39) +a function - tested with glibc 2.35, 2.37 and 2.39 +* **Clone** handling on **RISC-V** is work in progress # Debugging: # Besides logging, the most important factor during debugging is to make diff --git a/test/riscv/README.md b/test/riscv/README.md new file mode 100644 index 0000000..7cad175 --- /dev/null +++ b/test/riscv/README.md @@ -0,0 +1,35 @@ +# Testing on RISC-V # + +The tests inside `./src` must be considered as couples containing an executable +and an initialization library, named as follows: +- `_test.c` +- `intercept_sys_.c` + +They can be compiled with +```shell +make +``` +and executed with +```shell +make test +``` +Alternatively, it is possible to execute a specific test with the following +command, where syscall-name must be replaced with one of the entries in +the TESTS variable in the Makefile +``` +make +``` + +## How these test work ## + +These tests basically assert a condition which can't possibly be true unless +the hook function is executed as expected thanks to a correct interception of +the tested system call. As an example, the `write` test writes a string to a +file, then reads the written string from that file and in the end asserts that +the two strings are perfectly equal. By looking at the content of +[write_test.c](src/write_test.c) it is obvious how the assertion could never be +true since the written string and the expected string are different. The hook +function which will be executed before forwarding the system call to the kernel +will make sure to modify the string that is going to be written to the file so +that the actual written string and the expected string match. +All the tests implement the described pattern. \ No newline at end of file From 66554ab5adb0c21aaaa0c225a1350c8cac4633d9 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 6 Mar 2025 11:47:22 +0100 Subject: [PATCH 077/143] Solved relative inclusions --- CMakeLists.txt | 1 + src/arch/riscv/disasm_wrapper.c | 4 +- src/arch/riscv/intercept_template.S | 82 +++++++++++------------------ src/arch/riscv/patcher.c | 22 ++++---- src/arch/x86_64/disasm_wrapper.c | 4 +- src/arch/x86_64/patcher.c | 10 ++-- 6 files changed, 50 insertions(+), 73 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 36a9c13..b6b701d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,6 +107,7 @@ endif() # set the following directories according with your installation of capstone include_directories(include "/usr/local/include/capstone") +include_directories(${PROJECT_SOURCE_DIR}/src) link_directories("/usr/local/lib") set(CMAKE_POSITION_INDEPENDENT_CODE ON) diff --git a/src/arch/riscv/disasm_wrapper.c b/src/arch/riscv/disasm_wrapper.c index 4ab8f6f..518c915 100644 --- a/src/arch/riscv/disasm_wrapper.c +++ b/src/arch/riscv/disasm_wrapper.c @@ -33,9 +33,9 @@ #include #include -#include "../../disasm_wrapper.h" +#include -#include "../../capstone_wrapper.h" +#include struct intercept_disasm_context { csh handle; diff --git a/src/arch/riscv/intercept_template.S b/src/arch/riscv/intercept_template.S index 91fcb5e..951ea2a 100644 --- a/src/arch/riscv/intercept_template.S +++ b/src/arch/riscv/intercept_template.S @@ -49,7 +49,7 @@ intercept_asm_wrapper_tmpl: addi sp, sp, -72 addi t6, sp, 72 # sp+72 is the sp value before interception - sd t6, 0(sp) + sd t6, 0(sp) # original sp on stack sd ra, 16(sp) sd t0, 24(sp) sd t1, 32(sp) @@ -57,6 +57,10 @@ intercept_asm_wrapper_tmpl: sd t3, 48(sp) sd t4, 56(sp) sd t5, 64(sp) + /* + * t5 content will be evaluated in intercept_wrapper to determine which + * interception routine must be called. 1 for post_clone, 0 otherwise + */ li t5, 0 # choose intercept_routine beqz t5, intercept_asm_wrapper_patch_desc_addr post_clone: @@ -71,25 +75,12 @@ post_clone: sd t4, 56(sp) sd t5, 64(sp) li t5, 1 # choose intercept_routine_post_clone -# j l4 -# l3: -# l4: - # addi sp, sp, -64 # allocate stack for some locals - # sd t6, 0(sp) # original sp on stack - # sd ra, 16(sp) # patch->return_address on stack - # sd s0, 24(sp) # follows conventions by saving s0 on stack since we use it - # sd t0, 32(sp) - # sd t1, 40(sp) - # sd t2, 48(sp) - # sd t3, 56(sp) - # bnez t5, intercept_asm_wrapper_patch_desc_addr - # li s0, 0 # s0 as flag: 1 if we are going for post_clone, 0 otherwise intercept_asm_wrapper_patch_desc_addr: /* load patch_desc address in t0 */ /* - * the 5 following instructions are placeholders for the correct ones which - * are overwritten in machine language by create_load_uint64t_into_t0() + * the 5 following instructions are an indication for the actual ones which + * are written in binary by create_load_uint64t_into_t0() in patcher.c:528 * * lui t0, 0x00000 * addi t0, t0, 0x000 @@ -99,7 +90,7 @@ intercept_asm_wrapper_patch_desc_addr: */ .space 20, 0 - /* the 9 following instructions load the 64-bit address in t0 */ + /* the 9 following instructions compose the 64-bit address in t0 */ lui t1, 0x7ffff ori t2, zero, 0x7ff slli t2, t2, 1 @@ -115,8 +106,8 @@ intercept_asm_wrapper_wrapper_level1_addr: /* load intercept_wrapper address in t0 */ /* - * the 5 following instructions are placeholders for the correct ones which are - * written in machine language in create_load_uint64t_into_t0() in patcher.c + * the 5 following instructions are an indication for the actual ones which + * are written in binary by create_load_uint64t_into_t0() in patcher.c:529 * * lui t0, 0x00000 * ori t0, t0, 0x000 @@ -127,7 +118,7 @@ intercept_asm_wrapper_wrapper_level1_addr: */ .space 20, 0 - /* the 9 following instructions load the 64-bit address in t0 */ + /* the 9 following instructions compose the 64-bit address in t0 */ lui t1, 0x7ffff ori t2, zero, 0x7ff slli t2, t2, 1 @@ -156,7 +147,8 @@ intercept_asm_wrapper_wrapper_level1_addr: /* * The intercept_wrapper function did restore all registers to their - * original state, except for a0, sp and t6. + * original state, except for a0, sp, t5 and t6. sp and t5 have just been + * restored up here (lines 145-146). * * If t6 is zero, a0 contains a syscall number, and that syscall * is executed here. @@ -164,44 +156,30 @@ intercept_asm_wrapper_wrapper_level1_addr: * If t6 is 2, a clone syscall is executed here. */ beqz t6, execute_unhandled_ecall - addi sp, sp, -8 - sd t0, 0(sp) - li t0, 1 - beq t6, t0, handled_ecall - li t0, 2 - beq t6, t0, execute_clone - ebreak # if t6 holds invalid value -# li a7, 94 /* exit_group if t6 contains an invalid value, */ -# ecall /* namely different from 0, 1 or 2 */ + srli t6, t6, 1 + beqz t6, handled_ecall + srli t6, t6, 1 + beqz t6, execute_clone + #addi sp, sp, -8 + #sd t0, 0(sp) + #li t0, 1 + #beq t6, t0, handled_ecall + #li t0, 2 + #beq t6, t0, execute_clone + ebreak # if t6 holds invalid value, i. e. different from 0, 1 or 2 + execute_clone: - ld t0, 0(sp) - addi sp, sp, 8 + #ld t0, 0(sp) + #addi sp, sp, 8 ecall j post_clone -# mv a7, a0 -# ecall -# li t5, 1 /* choose intercept_routine_post_clone */ -# li s0, 1 /* flag to signal we cloned, restoring sp will require adding 128 */ -# j l0 - # beqz s0, l5 - # addi sp, sp, 64 -# l5: -# ld ra, 16(sp) -# ld s0, 24(sp) -# ld t0, 32(sp) -# ld t1, 40(sp) -# ld t2, 48(sp) -# ld t3, 56(sp) -# ld t5, 64(sp) # t5 was saved at what currently can be accessed with 64(sp) -# addi sp, sp, 72 execute_unhandled_ecall: - # mv a7, a0 # a7 should still contain the original value which is syscall_nr ecall j intercept_asm_wrapper_tmpl_end handled_ecall: - ld t0, 0(sp) - addi sp, sp, 8 + #ld t0, 0(sp) + #addi sp, sp, 8 intercept_asm_wrapper_tmpl_end: /* @@ -209,6 +187,6 @@ intercept_asm_wrapper_tmpl_end: * * This template must be appended here with a * jump back to the intercepted code, whic is written by - * create_absolute_jump(*dst, patch->return_address) in patcher.c + * create_absolute_jump(*dst, patch->return_address) in patcher.c:537 * */ diff --git a/src/arch/riscv/patcher.c b/src/arch/riscv/patcher.c index e0f6242..d78e42e 100644 --- a/src/arch/riscv/patcher.c +++ b/src/arch/riscv/patcher.c @@ -69,9 +69,9 @@ * */ -#include "../../intercept.h" -#include "../../intercept_util.h" -#include "../../intercept_log.h" +#include +#include +#include #include #include @@ -123,7 +123,7 @@ create_absolute_jump(unsigned char *from, void *to) instructions[20] = 0x01013e03; // ld t3, 16(sp) instructions[21] = 0x02010113; // addi sp, sp, 32 instructions[22] = 0x000f8067; // jalr zero, t6, 0 - // next call writes five 4-byte instructions starting from instructions[4] + // next call writes five 4-byte instructions starting from instructions[4] create_load_uint64t_into_t6((uint8_t *)(instructions + 4),(uint64_t)to); return (unsigned char *)(instructions + 23); } @@ -243,7 +243,7 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) * Check the instructions surrounding the syscall instruction. * If they can be relocated, then they can be overwritten. * Of course some instructions depend on the value of the - * PC register, these can not be relocated. + * PC register, these can not be relocated. */ check_surrounding_instructions(desc, patch); @@ -319,11 +319,11 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) patch->return_address = patch->syscall_addr + SYSCALL_INS_SIZE; } - /* The following happens when we found 6 suitable bytes for - * rewriting and a 4-byte instruction is found after those, + /* The following happens when we found 6 suitable bytes for + * rewriting and a 4-byte instruction is found after those, * resulting in patch size being 10 bytes but just 8 are used so * padding with a c.ebreak will be reasonable - */ + */ if (length > JUMP_INS_SIZE) { patch->padding_is_needed = true; } @@ -347,16 +347,16 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) char buffer[0x1000]; int l = snprintf(buffer, sizeof(buffer), - "unintercepted syscall at: %s 0x%lx\n", + "unintercepted ecall at: %s 0x%lx\n", desc->path, patch->syscall_offset); intercept_log(buffer, (size_t)l); - debug_dump("unintercepted syscall at: %s 0x%lx\n", + debug_dump("unintercepted ecall at: %s 0x%lx\n", desc->path, patch->syscall_offset); xabort("not enough space for patching" - " around syscal"); + " around ecall"); } mark_jump(desc, patch->return_address); diff --git a/src/arch/x86_64/disasm_wrapper.c b/src/arch/x86_64/disasm_wrapper.c index af84942..ad202fe 100644 --- a/src/arch/x86_64/disasm_wrapper.c +++ b/src/arch/x86_64/disasm_wrapper.c @@ -33,9 +33,9 @@ #include #include -#include "../../disasm_wrapper.h" +#include -#include "../../capstone_wrapper.h" +#include struct intercept_disasm_context { csh handle; diff --git a/src/arch/x86_64/patcher.c b/src/arch/x86_64/patcher.c index f77743b..b05566c 100644 --- a/src/arch/x86_64/patcher.c +++ b/src/arch/x86_64/patcher.c @@ -69,16 +69,14 @@ * */ -#include "../../intercept.h" -#include "../../intercept_util.h" -#include "../../intercept_log.h" +#include +#include +#include #include #include -#include #include #include - #include /* The size of a trampoline jump, jmp instruction + pointer */ @@ -482,7 +480,7 @@ create_patch_wrappers(struct intercept_desc *desc, unsigned char **dst) intercept_log(buffer, (size_t)l); xabort("not enough space for patching" - " around syscal"); + " around syscall"); } } From 5e5434b8e88669a2c1874b35637b0bbaf3ce6a01 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 6 Mar 2025 12:14:16 +0100 Subject: [PATCH 078/143] Comments cleanup --- src/arch/riscv/intercept_template.S | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/arch/riscv/intercept_template.S b/src/arch/riscv/intercept_template.S index 951ea2a..11ce98a 100644 --- a/src/arch/riscv/intercept_template.S +++ b/src/arch/riscv/intercept_template.S @@ -160,17 +160,9 @@ intercept_asm_wrapper_wrapper_level1_addr: beqz t6, handled_ecall srli t6, t6, 1 beqz t6, execute_clone - #addi sp, sp, -8 - #sd t0, 0(sp) - #li t0, 1 - #beq t6, t0, handled_ecall - #li t0, 2 - #beq t6, t0, execute_clone ebreak # if t6 holds invalid value, i. e. different from 0, 1 or 2 execute_clone: - #ld t0, 0(sp) - #addi sp, sp, 8 ecall j post_clone @@ -178,8 +170,6 @@ execute_unhandled_ecall: ecall j intercept_asm_wrapper_tmpl_end handled_ecall: - #ld t0, 0(sp) - #addi sp, sp, 8 intercept_asm_wrapper_tmpl_end: /* From fe441574742d261cea200616f2aafcff2c50b69f Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 6 Mar 2025 12:33:31 +0100 Subject: [PATCH 079/143] Ditched clone test as clone handling is WIP --- test/riscv/Makefile | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/test/riscv/Makefile b/test/riscv/Makefile index bb935ee..76ad85b 100644 --- a/test/riscv/Makefile +++ b/test/riscv/Makefile @@ -11,30 +11,26 @@ SRC_DIR = src LD_LIBRARY_PATH = ./build:../../build LD_PRELOAD = ./build -TESTS = clone \ - fcntl \ - mkdirat \ - openat \ - read \ - statx \ - write - - -EXECUTABLES = $(BIN_DIR)/mkdirat_test \ - $(BIN_DIR)/clone_test \ - $(BIN_DIR)/fcntl_test \ - $(BIN_DIR)/openat_test \ - $(BIN_DIR)/read_test \ - $(BIN_DIR)/statx_test \ - $(BIN_DIR)/write_test - -INTERCEPT_LIBS = $(BUILD_DIR)/intercept_sys_mkdirat.so \ - $(BUILD_DIR)/intercept_sys_clone.so \ - $(BUILD_DIR)/intercept_sys_fcntl.so \ - $(BUILD_DIR)/intercept_sys_openat.so \ - $(BUILD_DIR)/intercept_sys_read.so \ - $(BUILD_DIR)/intercept_sys_statx.so \ - $(BUILD_DIR)/intercept_sys_write.so +TESTS += fcntl +TESTS += mkdirat +TESTS += openat +TESTS += read +TESTS += statx +TESTS += write + +EXECUTABLES += $(BIN_DIR)/mkdirat_test +EXECUTABLES += $(BIN_DIR)/fcntl_test +EXECUTABLES += $(BIN_DIR)/openat_test +EXECUTABLES += $(BIN_DIR)/read_test +EXECUTABLES += $(BIN_DIR)/statx_test +EXECUTABLES += $(BIN_DIR)/write_test + +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_mkdirat.so +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_fcntl.so +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_openat.so +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_read.so +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_statx.so +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_write.so all: $(BIN_DIR) $(BUILD_DIR) $(EXECUTABLES) $(INTERCEPT_LIBS) From 3ef8a802784b7133da973fa40264904dfff158e6 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 6 Mar 2025 18:02:22 +0100 Subject: [PATCH 080/143] Corrected one instruction --- src/arch/riscv/intercept_template.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arch/riscv/intercept_template.S b/src/arch/riscv/intercept_template.S index 11ce98a..5ab555f 100644 --- a/src/arch/riscv/intercept_template.S +++ b/src/arch/riscv/intercept_template.S @@ -50,7 +50,7 @@ intercept_asm_wrapper_tmpl: addi sp, sp, -72 addi t6, sp, 72 # sp+72 is the sp value before interception sd t6, 0(sp) # original sp on stack - sd ra, 16(sp) + sd ra, 16(sp) # libc won't need to restore ra after just an ecall sd t0, 24(sp) sd t1, 32(sp) sd t2, 40(sp) @@ -62,7 +62,7 @@ intercept_asm_wrapper_tmpl: * interception routine must be called. 1 for post_clone, 0 otherwise */ li t5, 0 # choose intercept_routine - beqz t5, intercept_asm_wrapper_patch_desc_addr + j intercept_asm_wrapper_patch_desc_addr post_clone: addi sp, sp, -72 addi t6, sp, 72 # sp+72 is the sp value before interception From 74b04712219a5723faf0665e6ddec1c0722c6d5b Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 24 Apr 2025 17:10:51 +0200 Subject: [PATCH 081/143] Updated test/riscv/Makefile --- test/riscv/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/riscv/Makefile b/test/riscv/Makefile index 76ad85b..fa58402 100644 --- a/test/riscv/Makefile +++ b/test/riscv/Makefile @@ -17,6 +17,7 @@ TESTS += openat TESTS += read TESTS += statx TESTS += write +TESTS += clone EXECUTABLES += $(BIN_DIR)/mkdirat_test EXECUTABLES += $(BIN_DIR)/fcntl_test @@ -24,6 +25,7 @@ EXECUTABLES += $(BIN_DIR)/openat_test EXECUTABLES += $(BIN_DIR)/read_test EXECUTABLES += $(BIN_DIR)/statx_test EXECUTABLES += $(BIN_DIR)/write_test +EXECUTABLES += $(BIN_DIR)/clone_test INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_mkdirat.so INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_fcntl.so @@ -31,6 +33,7 @@ INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_openat.so INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_read.so INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_statx.so INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_write.so +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_clone.so all: $(BIN_DIR) $(BUILD_DIR) $(EXECUTABLES) $(INTERCEPT_LIBS) @@ -54,6 +57,7 @@ clean: rm -f $(BUILD_DIR)/* rm -f *.txt rm -rf wrongdir/ + rm -rf testdir/ $(BIN_DIR): mkdir -p $(BIN_DIR) From d569ae88c3e0d4b76f00e1184cf64538449659eb Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 2 May 2025 13:31:14 +0200 Subject: [PATCH 082/143] Clone handling with NULL arg1 --- src/intercept.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intercept.c b/src/intercept.c index 5c82157..aa19504 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -698,7 +698,7 @@ intercept_routine(struct context *context) * the clone_child_intercept_routine instead, executing * it on the new child threads stack, then returns to libc. */ - if (desc.nr == SYS_clone && desc.args[1] != 0) { + if (desc.nr == SYS_clone /*&& desc.args[1] != 0*/) { return (struct wrapper_ret){ FIRST_RET_REG = SYSCALL_NR, SECOND_RET_REG = 2 }; } From 890c794c9a7a3de25e188d999259b0fa8f514177 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 8 May 2025 11:56:52 +0200 Subject: [PATCH 083/143] Fixed unhandled ecall case context restoring --- src/arch/riscv/intercept_wrapper.S | 9 ++++++++- src/intercept_log.c | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/arch/riscv/intercept_wrapper.S b/src/arch/riscv/intercept_wrapper.S index 46c4bf7..1751046 100644 --- a/src/arch/riscv/intercept_wrapper.S +++ b/src/arch/riscv/intercept_wrapper.S @@ -136,7 +136,14 @@ l1: ld t3, 32(sp) ld t4, 40(sp) - /* no point in restoring in context values at 48(sp), 56(sp) and 64(sp) */ + /* + * No point in restoring in context values at 48(sp) and 56(sp), while a0 + * must be restored only if system call has not been handled yet + */ + li a1, 1 + beq t6, a1, handled_ecall + ld a0, 64(sp) +handled_ecall: ld a1, 72(sp) ld a2, 80(sp) ld a3, 88(sp) diff --git a/src/intercept_log.c b/src/intercept_log.c index 8b26b66..f6fc96c 100644 --- a/src/intercept_log.c +++ b/src/intercept_log.c @@ -46,6 +46,7 @@ #include #include #include +#include #include /* @@ -274,6 +275,7 @@ static const struct flag_desc clone_flags[] = { FLAG_ENTRY(CLONE_UNTRACED), FLAG_ENTRY(CLONE_VFORK), FLAG_ENTRY(CLONE_VM), + FLAG_ENTRY(SIGCHLD), { .flag = 0, } }; From 95232d29919d27da151d03a9183080bc5d25c4f7 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 8 May 2025 12:47:28 +0200 Subject: [PATCH 084/143] Refined clone_test --- test/riscv/src/clone_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/riscv/src/clone_test.c b/test/riscv/src/clone_test.c index 7c42189..176c201 100644 --- a/test/riscv/src/clone_test.c +++ b/test/riscv/src/clone_test.c @@ -58,7 +58,7 @@ int main() { char child_stack[8192]; pid_t pid = clone(child_func, child_stack + sizeof(child_stack), - CLONE_VM | SIGCHLD, NULL); + SIGCHLD, NULL); if (pid == -1) { perror("Clone failed"); From ebfaac8163f03b9304a0e6ffebeaee46b8c85ab2 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Mon, 12 May 2025 18:04:03 +0200 Subject: [PATCH 085/143] Added fork test --- test/riscv/Makefile | 3 ++ test/riscv/src/fork_test.c | 71 +++++++++++++++++++++++++++++ test/riscv/src/intercept_sys_fork.c | 69 ++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 test/riscv/src/fork_test.c create mode 100644 test/riscv/src/intercept_sys_fork.c diff --git a/test/riscv/Makefile b/test/riscv/Makefile index fa58402..f17f13b 100644 --- a/test/riscv/Makefile +++ b/test/riscv/Makefile @@ -18,6 +18,7 @@ TESTS += read TESTS += statx TESTS += write TESTS += clone +TESTS += fork EXECUTABLES += $(BIN_DIR)/mkdirat_test EXECUTABLES += $(BIN_DIR)/fcntl_test @@ -26,6 +27,7 @@ EXECUTABLES += $(BIN_DIR)/read_test EXECUTABLES += $(BIN_DIR)/statx_test EXECUTABLES += $(BIN_DIR)/write_test EXECUTABLES += $(BIN_DIR)/clone_test +EXECUTABLES += $(BIN_DIR)/fork_test INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_mkdirat.so INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_fcntl.so @@ -34,6 +36,7 @@ INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_read.so INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_statx.so INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_write.so INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_clone.so +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_fork.so all: $(BIN_DIR) $(BUILD_DIR) $(EXECUTABLES) $(INTERCEPT_LIBS) diff --git a/test/riscv/src/fork_test.c b/test/riscv/src/fork_test.c new file mode 100644 index 0000000..bb966b4 --- /dev/null +++ b/test/riscv/src/fork_test.c @@ -0,0 +1,71 @@ +/* + * Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +int main() { + + int fd = openat(AT_FDCWD, "testfile.txt", O_CREAT | O_TRUNC | O_RDWR, 0666); + int fd2 = openat(AT_FDCWD, "testfile2.txt", O_CREAT | O_TRUNC | O_RDWR, 0666); + + pid_t pid = fork(); + int n, n2; + char buf[128]; + char buf2[128]; + + switch(pid) { + case -1: + perror("fork failed\n"); + break; + case 0: + n = read(fd, buf, sizeof(buf)); + buf[n] = '\0'; + n = atoi(buf); + assert(n == getpid()); + exit(EXIT_SUCCESS); + break; + default: + n2 = read(fd2, buf2, sizeof(buf2)); + buf2[n2] = '\0'; + n2 = atoi(buf2); + assert(n2 == getpid()); + siginfo_t info; + waitid(P_PID,pid,&info,0); + break; + } + return 0; +} diff --git a/test/riscv/src/intercept_sys_fork.c b/test/riscv/src/intercept_sys_fork.c new file mode 100644 index 0000000..0cf2d41 --- /dev/null +++ b/test/riscv/src/intercept_sys_fork.c @@ -0,0 +1,69 @@ +/* +* Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libsyscall_intercept_hook_point.h" +#include +#include +#include +#include + +static int hook(long syscall_number, + long arg0, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long *result) +{ + if (syscall_number == SYS_clone) { + printf("Fork intercepted - Flags: 0x%lx - PID: %d\n", arg0, getpid()); + } + return 1; +} + +static void hook_clone_parent(long child_pid) +{ + int fd = openat(AT_FDCWD, "testfile2.txt", O_WRONLY); + dprintf(fd, "%d\n", getpid()); +} + +static void hook_clone_child(void) +{ + int fd = openat(AT_FDCWD, "testfile.txt", O_WRONLY); + dprintf(fd, "%d\n", getpid()); +} + +static __attribute__((constructor)) void +init(void) +{ + intercept_hook_point = hook; + intercept_hook_point_clone_child = hook_clone_child; + intercept_hook_point_clone_parent = hook_clone_parent; +} From 13be19c81c18ed950ede365ce0ffa143c31acbe5 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 21 May 2025 10:33:34 +0000 Subject: [PATCH 086/143] Capstone 5.0.6 is now automatically fetched and compiled --- CMakeLists.txt | 31 ++++++++++++++++++++++++++----- capstone/CMakeLists.txt | 14 ++++++++++++++ test/riscv/src/fork_test.c | 11 ++++++++--- 3 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 capstone/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index b6b701d..d48fc5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,28 @@ option(EXPECT_SPURIOUS_SYSCALLS "account for some unexpected syscalls in tests - enable while using sanitizers, gcov" OFF) option(STATIC_CAPSTONE "statically link libcapstone into the shared library" OFF) +##################################### +# External projects +##################################### +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/capstone) + +set(CAPSTONE_INCLUDE_FOLDER "${CMAKE_CURRENT_BINARY_DIR}/capstone/_deps/capstone-src/include/capstone") +set(CAPSTONE_LIB_FOLDER "${CMAKE_CURRENT_BINARY_DIR}/capstone/_deps/capstone-build") + +execute_process( + COMMAND ${CMAKE_COMMAND} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DBUILD_SHARED_LIBS=ON + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_INSTALL_PREFIX:PATH= + "${CMAKE_CURRENT_SOURCE_DIR}/capstone" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/capstone" +) + +execute_process(COMMAND make + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/capstone" +) + find_program(CTAGS ctags) if(CTAGS) option(AUTO_RUN_CTAGS "create tags file every on every rebuild" ON) @@ -68,7 +90,7 @@ set(SYSCALL_INTERCEPT_VERSION_PATCH 0) set(SYSCALL_INTERCEPT_VERSION ${SYSCALL_INTERCEPT_VERSION_MAJOR}.${SYSCALL_INTERCEPT_VERSION_MINOR}.${SYSCALL_INTERCEPT_VERSION_PATCH}) -include(cmake/find_capstone.cmake) + include(GNUInstallDirs) include(cmake/toolchain_features.cmake) include(CheckLanguage) @@ -105,10 +127,9 @@ elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv(32|64))$") ) endif() -# set the following directories according with your installation of capstone -include_directories(include "/usr/local/include/capstone") -include_directories(${PROJECT_SOURCE_DIR}/src) -link_directories("/usr/local/lib") + +include_directories(include ${PROJECT_SOURCE_DIR}/src ${CAPSTONE_INCLUDE_FOLDER}) +link_directories(${CAPSTONE_LIB_FOLDER}) set(CMAKE_POSITION_INDEPENDENT_CODE ON) diff --git a/capstone/CMakeLists.txt b/capstone/CMakeLists.txt new file mode 100644 index 0000000..d6da7d5 --- /dev/null +++ b/capstone/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.3) +project(capstone) +include(FetchContent) + +##################################### +# Import external project from git +##################################### +FetchContent_Declare(capstone + GIT_REPOSITORY https://github.com/capstone-engine/capstone.git + GIT_TAG accf4df62f1fba6f92cae692985d27063552601c +) + +FetchContent_MakeAvailable(capstone) + diff --git a/test/riscv/src/fork_test.c b/test/riscv/src/fork_test.c index bb966b4..3a00c71 100644 --- a/test/riscv/src/fork_test.c +++ b/test/riscv/src/fork_test.c @@ -63,9 +63,14 @@ int main() { buf2[n2] = '\0'; n2 = atoi(buf2); assert(n2 == getpid()); - siginfo_t info; - waitid(P_PID,pid,&info,0); - break; + int status; + wait(&status); + if (WIFSIGNALED(status) && WTERMSIG(status) == SIGABRT) { + fprintf(stderr, "Child assertion failed\n"); + return 1; + } + + break; } return 0; } From 3e8695cdf62d17af041eaee987bb26fcee2691ff Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 21 May 2025 12:41:55 +0200 Subject: [PATCH 087/143] fix: linking x64 tests and capstone --- test/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5452223..20364b6 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -44,6 +44,7 @@ set(CMAKE_ASM_CREATE_SHARED_LIBRARY ${CMAKE_C_CREATE_SHARED_LIBRARY}) add_executable(asm_pattern asm_pattern.c $ $) +target_link_libraries(asm_pattern PUBLIC ${CAPSTONE_LIB_FOLDER}/libcapstone.so) target_link_libraries(asm_pattern PRIVATE ${CMAKE_DL_LIBS} ${capstone_LDFLAGS}) @@ -141,6 +142,7 @@ add_test(NAME "fork_logging" add_library(hook_test_preload_o OBJECT hook_test_preload.c) add_executable(hook_test hook_test.c) +target_link_libraries(hook_test PUBLIC ${CAPSTONE_LIB_FOLDER}/libcapstone.so) add_library(hook_test_preload_with_shared SHARED $) From bf3a719d03f1e2f45d2198ce7573c2735a888f21 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 24 Jun 2025 12:24:13 +0200 Subject: [PATCH 088/143] update: cmake minimum required version is now 3.10 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d48fc5f..1f2cb23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -cmake_minimum_required(VERSION 3.3) +cmake_minimum_required(VERSION 3.10) project(syscall_intercept C ASM) set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) From 623aa8415b2ff0b9b81bd08f791850723edea18c Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria <39337626+marcoSanti@users.noreply.github.com> Date: Tue, 24 Jun 2025 14:40:48 +0200 Subject: [PATCH 089/143] Bump capstone project came_minimum_required --- capstone/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/capstone/CMakeLists.txt b/capstone/CMakeLists.txt index d6da7d5..5b6ad33 100644 --- a/capstone/CMakeLists.txt +++ b/capstone/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.3) +cmake_minimum_required(VERSION 3.10) project(capstone) include(FetchContent) From 30be91cf3c85b9808831c8bd7ddafd1b39d9c93a Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 2 Jul 2025 19:34:14 +0200 Subject: [PATCH 090/143] update: post_clone for stack space sharing clone is called from normal C routine --- src/intercept.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/intercept.c b/src/intercept.c index aa19504..2977a01 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -621,6 +621,18 @@ get_syscall_in_context(struct context *context, struct syscall_desc *sys) sys->args[5] = SIXTH_ARG_REG; } +void +intercept_routine_post_clone_c(long a0) +{ + if (a0 == 0) { + if (intercept_hook_point_clone_child != NULL) + intercept_hook_point_clone_child(); + } else { + if (intercept_hook_point_clone_parent != NULL) + intercept_hook_point_clone_parent(a0); + } +} + /* * intercept_routine(...) * This is the function called from the asm wrappers, @@ -698,7 +710,7 @@ intercept_routine(struct context *context) * the clone_child_intercept_routine instead, executing * it on the new child threads stack, then returns to libc. */ - if (desc.nr == SYS_clone /*&& desc.args[1] != 0*/) { + if (desc.nr == SYS_clone && desc.args[1] != 0) { return (struct wrapper_ret){ FIRST_RET_REG = SYSCALL_NR, SECOND_RET_REG = 2 }; } @@ -719,6 +731,10 @@ intercept_routine(struct context *context) desc.args[5]); } + if (desc.nr == SYS_clone) { + intercept_routine_post_clone_c(result); + } + intercept_log_syscall(patch, &desc, KNOWN, result); return (struct wrapper_ret){ FIRST_RET_REG = result, SECOND_RET_REG = 1 }; } From c2dee0f427336e533c71c2983cdd09a1bcc95ec2 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 4 Jul 2025 12:15:03 +0200 Subject: [PATCH 091/143] update: capstone compilation, clone full support --- README.md | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 2e6feb5..a7eebde 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # syscall_intercept +
[//]: # ([![Build Status](https://travis-ci.org/pmem/syscall_intercept.svg)](https://travis-ci.org/pmem/syscall_intercept)) @@ -6,15 +7,20 @@ [//]: # ([![Coverity Scan Build Status](https://scan.coverity.com/projects/12890/badge.svg)](https://scan.coverity.com/projects/syscall_intercept)) -This repository contains a multi-architecture porting of [syscall_intercept](https://github.com/pmem/syscall_intercept) working on both x86_64 and RISC-V +This repository contains a multi-architecture porting of [syscall_intercept](https://github.com/pmem/syscall_intercept) working on both **x86_64** and **RISC-V**. +Full-featured support for **aarch64** (ARM64) is **work in progress**. +[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) # Dependencies # +
## Runtime dependencies ## * libcapstone -- the disassembly engine used under the hood (RISC-V support requires version **5.0** or higher, while apt installs version 4.0.2 by default, as february 2025). - Compiling capstone by hand will require setting [CMakeLists.txt](CMakeLists.txt#L109) accordingly + Since a manual installation of capstone could not be automatically detected while compiling syscall_intercept, we made + sure that libcapstone 5.0.6 is **automatically compiled** from source during the syscall_intercept cmake execution. + In other words, you don't need to care about having and installing capstone at all on your system. ## Build dependencies ## @@ -61,14 +67,16 @@ Testing on **x86_64**: make test ``` -Testing on **RISC-V**:\ -Go to `syscall_intercept/test/riscv/`, then +Testing on **RISC-V**: ```shell +# From the project root directory +cd test/riscv/ make make test ``` # Synopsis # +
```c #include @@ -187,6 +195,7 @@ ls: reading directory '.': Operation not supported ``` # Under the hood: # +
##### Assumptions: ##### In order to handle syscalls in user space, the library relies @@ -311,16 +320,20 @@ aa20a: bltu a5,a0,aa262 <__open+0xaa> | aa20a: bltu a5,a0,aa262 <__ope ``` # Limitations: # +
+ * Only Linux is supported * Only x86\_64 and RISC-V are supported * Only tested with glibc, although perhaps it works with some other libc implementations as well * RISC-V version assumes `$t6` is not used as base pointer or as source register without being reinitialized after an `ecall` and before the ending of -a function - tested with glibc 2.35, 2.37 and 2.39 -* **Clone** handling on **RISC-V** is work in progress +a function. While this assumption involves heuristics, this choice was tested +on different glibc version, i.e. 2.35, 2.37 and 2.39, and on different kernel +implementations manifesting a consistent and working behaviour. # Debugging: # +
Besides logging, the most important factor during debugging is to make sure the system calls in the debugger are not intercepted. To achieve this, use the INTERCEPT_HOOK_CMDLINE_FILTER variable described above. @@ -335,8 +348,9 @@ With this filtering, the intercepting library is not activated in the gdb process itself. # RISC-V porting # +
-Ottavio Monticelli (Maintainer) \ +Ottavio Monticelli (Maintainer) \ Marco Edoardo Santimaria (Maintainer) \ Marco Aldinucci (Maintainer and Principal Investigator) \ Iacopo Colonnelli (Maintainer and Principal Investigator) \ No newline at end of file From 91b673d1ab6b95d9f5ada51c095bd196649c9dd5 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 4 Jul 2025 12:22:22 +0200 Subject: [PATCH 092/143] chore: syntax correction --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a7eebde..5d03bc4 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # syscall_intercept -
+ [//]: # ([![Build Status](https://travis-ci.org/pmem/syscall_intercept.svg)](https://travis-ci.org/pmem/syscall_intercept)) @@ -12,7 +12,7 @@ Full-featured support for **aarch64** (ARM64) is **work in progress**. [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) # Dependencies # -
+ ## Runtime dependencies ## @@ -76,7 +76,7 @@ make test ``` # Synopsis # -
+ ```c #include @@ -195,7 +195,7 @@ ls: reading directory '.': Operation not supported ``` # Under the hood: # -
+ ##### Assumptions: ##### In order to handle syscalls in user space, the library relies @@ -320,7 +320,7 @@ aa20a: bltu a5,a0,aa262 <__open+0xaa> | aa20a: bltu a5,a0,aa262 <__ope ``` # Limitations: # -
+ * Only Linux is supported * Only x86\_64 and RISC-V are supported @@ -333,7 +333,7 @@ on different glibc version, i.e. 2.35, 2.37 and 2.39, and on different kernel implementations manifesting a consistent and working behaviour. # Debugging: # -
+ Besides logging, the most important factor during debugging is to make sure the system calls in the debugger are not intercepted. To achieve this, use the INTERCEPT_HOOK_CMDLINE_FILTER variable described above. @@ -348,7 +348,7 @@ With this filtering, the intercepting library is not activated in the gdb process itself. # RISC-V porting # -
+ Ottavio Monticelli (Maintainer) \ Marco Edoardo Santimaria (Maintainer) \ From e0fdaac5e975ba4c88dbcbbacd72f3afd1f1d39f Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 4 Jul 2025 16:25:05 +0200 Subject: [PATCH 093/143] calling same post_clone routine both from C routine and ASM wrapper --- src/intercept.c | 69 +++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/src/intercept.c b/src/intercept.c index 2977a01..7621a6d 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -76,6 +76,8 @@ void (*intercept_hook_point_clone_parent)(long) bool debug_dumps_on; +// void intercept_routine_post_clone_c(long pid); + void debug_dump(const char *fmt, ...) { @@ -621,16 +623,23 @@ get_syscall_in_context(struct context *context, struct syscall_desc *sys) sys->args[5] = SIXTH_ARG_REG; } -void -intercept_routine_post_clone_c(long a0) +/* + * intercept_routine_post_clone + * The routine called by an assembly wrapper when a clone syscall returns zero, + * and a new stack pointer is used in the child thread. + */ +struct wrapper_ret +intercept_routine_post_clone(struct context *context) { - if (a0 == 0) { + if (THREAD_PID == 0) { if (intercept_hook_point_clone_child != NULL) intercept_hook_point_clone_child(); } else { if (intercept_hook_point_clone_parent != NULL) - intercept_hook_point_clone_parent(a0); + intercept_hook_point_clone_parent(THREAD_PID); } + + return (struct wrapper_ret){FIRST_RET_REG = THREAD_PID, SECOND_RET_REG = 1 }; } /* @@ -729,31 +738,41 @@ intercept_routine(struct context *context) desc.args[3], desc.args[4], desc.args[5]); - } - if (desc.nr == SYS_clone) { - intercept_routine_post_clone_c(result); + /* + * Here clone calls with arg[1] == 0 are granted the execution + * of their post_clone hook functions + */ + if (desc.nr == SYS_clone) { + THREAD_PID = result; + intercept_routine_post_clone(context); + } +#ifdef SYS_clone3 + else if (desc.nr == SYS_clone3) { + THREAD_PID = result; + intercept_routine_post_clone(context); + } +#endif } intercept_log_syscall(patch, &desc, KNOWN, result); return (struct wrapper_ret){ FIRST_RET_REG = result, SECOND_RET_REG = 1 }; } -/* - * intercept_routine_post_clone - * The routine called by an assembly wrapper when a clone syscall returns zero, - * and a new stack pointer is used in the child thread. - */ -struct wrapper_ret -intercept_routine_post_clone(struct context *context) -{ - if (THREAD_PID == 0) { - if (intercept_hook_point_clone_child != NULL) - intercept_hook_point_clone_child(); - } else { - if (intercept_hook_point_clone_parent != NULL) - intercept_hook_point_clone_parent(THREAD_PID); - } - - return (struct wrapper_ret){FIRST_RET_REG = THREAD_PID, SECOND_RET_REG = 1 }; -} +// /* +// * intercept_routine_post_clone_c +// * The routine called by the C coded intercept_routine when a clone syscall is +// * intercepted but stack space is shared (arg[1] == 0) after the kernel +// * execution of the clone +// */ +// void +// intercept_routine_post_clone_c(long pid) +// { +// if (pid == 0) { +// if (intercept_hook_point_clone_child != NULL) +// intercept_hook_point_clone_child(); +// } else { +// if (intercept_hook_point_clone_parent != NULL) +// intercept_hook_point_clone_parent(pid); +// } +// } From 61004feb6f90c693f1c8cbaecb719c21c3aacce4 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Mon, 7 Jul 2025 15:28:48 +0200 Subject: [PATCH 094/143] code cleanup --- src/intercept.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/intercept.c b/src/intercept.c index 7621a6d..6e56d53 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -76,8 +76,6 @@ void (*intercept_hook_point_clone_parent)(long) bool debug_dumps_on; -// void intercept_routine_post_clone_c(long pid); - void debug_dump(const char *fmt, ...) { @@ -758,21 +756,3 @@ intercept_routine(struct context *context) intercept_log_syscall(patch, &desc, KNOWN, result); return (struct wrapper_ret){ FIRST_RET_REG = result, SECOND_RET_REG = 1 }; } - -// /* -// * intercept_routine_post_clone_c -// * The routine called by the C coded intercept_routine when a clone syscall is -// * intercepted but stack space is shared (arg[1] == 0) after the kernel -// * execution of the clone -// */ -// void -// intercept_routine_post_clone_c(long pid) -// { -// if (pid == 0) { -// if (intercept_hook_point_clone_child != NULL) -// intercept_hook_point_clone_child(); -// } else { -// if (intercept_hook_point_clone_parent != NULL) -// intercept_hook_point_clone_parent(pid); -// } -// } From 91d9d523d949ef613d5e2c96441dac17db9edc6b Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 8 Jul 2025 21:06:57 +0200 Subject: [PATCH 095/143] solving minor issues with pmem tests --- src/syscall_formats.c | 2 +- test/CMakeLists.txt | 4 ++-- test/libcintercept0.log.match | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/syscall_formats.c b/src/syscall_formats.c index d397f4d..f9bb52b 100644 --- a/src/syscall_formats.c +++ b/src/syscall_formats.c @@ -385,7 +385,7 @@ static const struct syscall_format formats[] = { SARGS(pselect6, rdec, arg_, arg_, arg_, arg_, arg_, arg_), SARGS(ppoll, rdec, arg_, arg_, arg_, arg_, arg_), SARGS(unshare, rdec, arg_), - SARGS(set_robust_list, rdec, arg_, arg_), + SARGS(set_robust_list, rdec, arg_, arg_dec), SARGS(get_robust_list, rdec, arg_, arg_, arg_), SARGS(splice, rdec, arg_fd, arg_, arg_fd, arg_, arg_, arg_), SARGS(tee, rdec, arg_fd, arg_fd, arg_, arg_), diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 20364b6..7c2e0d8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -159,7 +159,7 @@ add_test(NAME "hook_with_shared" add_library(hook_test_preload_with_static SHARED $) -target_link_libraries(hook_test_preload_with_static PRIVATE syscall_intercept_static) +target_link_libraries(hook_test_preload_with_static PRIVATE syscall_intercept_static ${CAPSTONE_LIB_FOLDER}/libcapstone.so) add_test(NAME "hook_with_static" COMMAND ${CMAKE_COMMAND} -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} @@ -339,7 +339,7 @@ add_test(NAME "syscall_format_logging" COMMAND ${CMAKE_COMMAND} -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -DTEST_PROG=$ - -DLIB_FILE= + -DLIB_FILE=$ -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/syscall_format.log.match -DTEST_NAME=syscall_format_logging ${CHECK_LOG_COMMON_ARGS}) diff --git a/test/libcintercept0.log.match b/test/libcintercept0.log.match index 1191f10..b9b89e7 100644 --- a/test/libcintercept0.log.match +++ b/test/libcintercept0.log.match @@ -1,9 +1,9 @@ -$(S) $(XX) -- clone(CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | 0x11, (null), (null), $(XX), $(XX)) = ? -$(OPT)$(S) $(XX) -- clone(CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | 0x11, (null), (null), $(XX), $(XX)) = 0 -$(S) $(XX) -- clone(CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | 0x11, (null), (null), $(XX), $(XX)) = $(N) -$(OPT)$(S) $(XX) -- clone(CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | 0x11, (null), (null), $(XX), $(XX)) = 0 +$(S) $(XX) -- clone(CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD, (null), (null), $(XX), $(XX)) = ? +$(OPT)$(S) $(XX) -- clone(CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD, (null), (null), $(XX), $(XX)) = 0 +$(S) $(XX) -- clone(CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD, (null), (null), $(XX), $(XX)) = $(N) +$(OPT)$(S) $(XX) -- clone(CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD, (null), (null), $(XX), $(XX)) = 0 $(S) $(XX) -- wait4($(N), 0x0, 0x0, 0x0) = ? -$(OPT)$(S) $(XX) -- clone(CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | 0x11, (null), (null), $(XX), $(XX)) = 0 +$(OPT)$(S) $(XX) -- clone(CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD, (null), (null), $(XX), $(XX)) = 0 $(OPT)$(S) $(XX) -- set_robust_list($(XX), $(N)) = ? $(OPT)$(S) $(XX) -- set_robust_list($(XX), $(N)) = $(N) $(S) $(XX) -- wait4($(N), 0x0, 0x0, 0x0) = $(N) From aac467f28f02244a661dc33ce88c0f65fe9203c0 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 10 Jul 2025 15:21:20 +0200 Subject: [PATCH 096/143] updated original pmem x64 tests to work with newer glibc versions --- test/CMakeLists.txt | 2 +- test/libcintercept0.log.match | 8 +-- test/libcintercept0_child.log.match | 8 +-- test/syscall_format.c | 16 ++--- test/syscall_format.log.match | 92 ++++++++++++++--------------- 5 files changed, 61 insertions(+), 65 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7c2e0d8..724321f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -339,7 +339,7 @@ add_test(NAME "syscall_format_logging" COMMAND ${CMAKE_COMMAND} -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -DTEST_PROG=$ - -DLIB_FILE=$ + -DLIB_FILE= -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/syscall_format.log.match -DTEST_NAME=syscall_format_logging ${CHECK_LOG_COMMON_ARGS}) diff --git a/test/libcintercept0.log.match b/test/libcintercept0.log.match index b9b89e7..68dd704 100644 --- a/test/libcintercept0.log.match +++ b/test/libcintercept0.log.match @@ -11,16 +11,16 @@ $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = $(N) $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = $(N) -$(S) $(XX) -- fstat($(N), $(XX)) = ? -$(S) $(XX) -- fstat($(N), $(XX)) = 0 +$(S) $(XX) -- newfstatat($(N), $(S), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat($(N), $(S), $(XX), $(XX)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(S) $(XX) -- read($(N), $(XX), $(N)) = ? $(S) $(XX) -- read($(N), "/*\n * Copyright 2016-2017, Intel Corporation\n *\n * Redistribution and use in source and binary forms, with or without\n...", $(N)) = $(N) -$(S) $(XX) -- fstat(1, $(XX)) = ? -$(S) $(XX) -- fstat(1, $(XX)) = 0 +$(S) $(XX) -- newfstatat(1, $(S), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(1, $(S), $(XX), $(XX)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? diff --git a/test/libcintercept0_child.log.match b/test/libcintercept0_child.log.match index bcd3f60..b2aa92b 100644 --- a/test/libcintercept0_child.log.match +++ b/test/libcintercept0_child.log.match @@ -2,16 +2,16 @@ $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = $(N) $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = $(N) -$(S) $(XX) -- fstat($(N), $(XX)) = ? -$(S) $(XX) -- fstat($(N), $(XX)) = 0 +$(S) $(XX) -- newfstatat($(N), $(S), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat($(N), $(S), $(XX), $(XX)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(S) $(XX) -- read($(N), $(XX), $(N)) = ? $(S) $(XX) -- read($(N), "/*\n * Copyright 2016-2017, Intel Corporation\n *\n * Redistribution and use in source and binary forms, with or without\n...", $(N)) = $(N) -$(S) $(XX) -- fstat(1, $(XX)) = ? -$(S) $(XX) -- fstat(1, $(XX)) = 0 +$(S) $(XX) -- newfstatat($(N), $(S), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat($(N), $(S), $(XX), $(XX)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? diff --git a/test/syscall_format.c b/test/syscall_format.c index 8d33be3..fbad1fb 100644 --- a/test/syscall_format.c +++ b/test/syscall_format.c @@ -240,7 +240,9 @@ main(int argc, char **argv) void *p0 = (void *)0x123000; void *p1 = (void *)0x234000; void *p2 = (void *)0x456000; - void *p3 = (void *)0x567000; + struct timeval tv = {.tv_sec = 123, .tv_usec = 456}; + struct utimbuf utb = {.actime = 1234567890, .modtime = 1234567890}; + struct timeval tv_arr[2] = {tv, tv}; socklen_t sl[2] = {1, 1}; @@ -307,8 +309,6 @@ main(int argc, char **argv) stat(NULL, &statbuf); stat("/", &statbuf); fstat(0, NULL); - fstat(-1, NULL); - fstat(AT_FDCWD, &statbuf); fstat(2, &statbuf); lstat(NULL, NULL); lstat("/", NULL); @@ -388,7 +388,7 @@ main(int argc, char **argv) pipe(fd2); pipe2(fd2, 0); - select(2, p0, p1, p2, p3); + select(2, p0, p1, p2, &tv); syscall(SYS_pselect6, 2, p0, p1, p0, p1, p0); sched_yield(); @@ -396,7 +396,7 @@ main(int argc, char **argv) /* shared memory */ shmget(3, 4, 5); shmat(3, p0, 5); - shmctl(3, 5, p0); + shmctl(3, SHM_INFO, p0); shmdt(p0); dup(4); @@ -576,9 +576,9 @@ main(int argc, char **argv) syscall(SYS_rt_sigsuspend, p0, 3); syscall(SYS_sigaltstack, p0, p1); - utime(input[0], p0); - utimes(input[0], p0); - futimesat(4, input[0], p0); + utime(input[0], &utb); + utimes(input[0], tv_arr); + futimesat(4, input[0], tv_arr); mknod(input[0], 1, 2); mknodat(1, input[0], 1, 2); diff --git a/test/syscall_format.log.match b/test/syscall_format.log.match index 8c89d45..c581482 100644 --- a/test/syscall_format.log.match +++ b/test/syscall_format.log.match @@ -66,30 +66,26 @@ $(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_ $(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_TMPFILE, 0333) = 22 $(S) $(XX) -- close(9) = ? $(S) $(XX) -- close(9) = 22 -$(S) $(XX) -- stat((null), (null)) = ? -$(S) $(XX) -- stat((null), (null)) = 22 -$(S) $(XX) -- stat("/", (null)) = ? -$(S) $(XX) -- stat("/", (null)) = 22 -$(S) $(XX) -- stat((null), $(XX)) = ? -$(S) $(XX) -- stat((null), $(XX)) = 22 -$(S) $(XX) -- stat("/", $(XX)) = ? -$(S) $(XX) -- stat("/", $(XX)) = 22 -$(S) $(XX) -- fstat(0, (null)) = ? -$(S) $(XX) -- fstat(0, (null)) = 22 -$(S) $(XX) -- fstat(-1, (null)) = ? -$(S) $(XX) -- fstat(-1, (null)) = 22 -$(S) $(XX) -- fstat(-100, $(XX)) = ? -$(S) $(XX) -- fstat(-100, $(XX)) = 22 -$(S) $(XX) -- fstat(2, $(XX)) = ? -$(S) $(XX) -- fstat(2, $(XX)) = 22 -$(S) $(XX) -- lstat((null), (null)) = ? -$(S) $(XX) -- lstat((null), (null)) = 22 -$(S) $(XX) -- lstat("/", (null)) = ? -$(S) $(XX) -- lstat("/", (null)) = 22 -$(S) $(XX) -- lstat((null), $(XX)) = ? -$(S) $(XX) -- lstat((null), $(XX)) = 22 -$(S) $(XX) -- lstat("/", $(XX)) = ? -$(S) $(XX) -- lstat("/", $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(0, $(S), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(0, $(S), $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(2, $(S), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(2, $(S), $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x0, 0x0) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x0, 0x0) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, (null), 0x0, 0x0) = ? @@ -194,20 +190,20 @@ $(S) $(XX) -- access("", R_OK | W_OK) = ? $(S) $(XX) -- access("", R_OK | W_OK) = 22 $(S) $(XX) -- access("input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = ? $(S) $(XX) -- access("input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = 22 -$(S) $(XX) -- faccessat(AT_FDCWD, (null), 00) = ? -$(S) $(XX) -- faccessat(AT_FDCWD, (null), 00) = 22 -$(S) $(XX) -- faccessat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01) = ? -$(S) $(XX) -- faccessat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01) = 22 -$(S) $(XX) -- faccessat(AT_FDCWD, "", 06) = ? -$(S) $(XX) -- faccessat(AT_FDCWD, "", 06) = 22 -$(S) $(XX) -- faccessat(9, "input_data\x01\x02\x03\n\r\t", 07) = ? -$(S) $(XX) -- faccessat(9, "input_data\x01\x02\x03\n\r\t", 07) = 22 -$(S) $(XX) -- pipe($(XX)) = ? -$(S) $(XX) -- pipe([123, 234]) = 22 +$(S) $(XX) -- faccessat2(AT_FDCWD, (null), 00, $(XX)) = ? +$(S) $(XX) -- faccessat2(AT_FDCWD, (null), 00, $(XX)) = 22 +$(S) $(XX) -- faccessat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, $(XX)) = ? +$(S) $(XX) -- faccessat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, $(XX)) = 22 +$(S) $(XX) -- faccessat2(AT_FDCWD, "", 06, $(XX)) = ? +$(S) $(XX) -- faccessat2(AT_FDCWD, "", 06, $(XX)) = 22 +$(S) $(XX) -- faccessat2(9, "input_data\x01\x02\x03\n\r\t", 07, $(XX)) = ? +$(S) $(XX) -- faccessat2(9, "input_data\x01\x02\x03\n\r\t", 07, $(XX)) = 22 +$(S) $(XX) -- pipe2($(XX), $(N)) = ? +$(S) $(XX) -- pipe2([123, 234], $(N)) = 22 $(S) $(XX) -- pipe2($(XX), 0) = ? $(S) $(XX) -- pipe2([123, 234], 0) = 22 -$(S) $(XX) -- select(2, 0x0000000000123000, 0x0000000000234000, 0x0000000000456000, 0x0000000000567000) = ? -$(S) $(XX) -- select(2, 0x0000000000123000, 0x0000000000234000, 0x0000000000456000, 0x0000000000567000) = 22 +$(S) $(XX) -- pselect6(0x2, 0x123000, 0x234000, 0x456000, $(XX), $(XX)) = ? +$(S) $(XX) -- pselect6(0x2, 0x123000, 0x234000, 0x456000, $(XX), $(XX)) = 22 $(S) $(XX) -- pselect6(0x2, 0x123000, 0x234000, 0x123000, 0x234000, 0x123000) = ? $(S) $(XX) -- pselect6(0x2, 0x123000, 0x234000, 0x123000, 0x234000, 0x123000) = 22 $(S) $(XX) -- sched_yield() = ? @@ -216,8 +212,8 @@ $(S) $(XX) -- shmget(0x3, 0x4, 0x5) = ? $(S) $(XX) -- shmget(0x3, 0x4, 0x5) = 22 $(S) $(XX) -- shmat(0x3, 0x123000, 0x5) = ? $(S) $(XX) -- shmat(0x3, 0x123000, 0x5) = 0x16 -$(S) $(XX) -- shmctl(0x3, 0x5, 0x123000) = ? -$(S) $(XX) -- shmctl(0x3, 0x5, 0x123000) = 22 +$(S) $(XX) -- shmctl(0x3, 0xe, 0x123000) = ? +$(S) $(XX) -- shmctl(0x3, 0xe, 0x123000) = 22 $(S) $(XX) -- shmdt(0x123000) = ? $(S) $(XX) -- shmdt(0x123000) = 22 $(S) $(XX) -- dup(4) = ? @@ -490,14 +486,14 @@ $(S) $(XX) -- rt_sigsuspend(0x123000, 0x3) = ? $(S) $(XX) -- rt_sigsuspend(0x123000, 0x3) = 22 $(S) $(XX) -- sigaltstack(0x123000, 0x234000) = ? $(S) $(XX) -- sigaltstack(0x123000, 0x234000) = 22 -$(S) $(XX) -- utime("input_data\x01\x02\x03\n\r\t", 0x123000) = ? -$(S) $(XX) -- utime("input_data\x01\x02\x03\n\r\t", 0x123000) = 22 -$(S) $(XX) -- utimes("input_data\x01\x02\x03\n\r\t", 0x123000) = ? -$(S) $(XX) -- utimes("input_data\x01\x02\x03\n\r\t", 0x123000) = 22 -$(S) $(XX) -- futimesat(4, "input_data\x01\x02\x03\n\r\t", 0x123000) = ? -$(S) $(XX) -- futimesat(4, "input_data\x01\x02\x03\n\r\t", 0x123000) = 22 -$(S) $(XX) -- mknod("input_data\x01\x02\x03\n\r\t", 0x1, 0x2) = ? -$(S) $(XX) -- mknod("input_data\x01\x02\x03\n\r\t", 0x1, 0x2) = 22 +$(S) $(XX) -- utimensat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = ? +$(S) $(XX) -- utimensat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = 22 +$(S) $(XX) -- utimensat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = ? +$(S) $(XX) -- utimensat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = 22 +$(S) $(XX) -- utimensat(4, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = ? +$(S) $(XX) -- utimensat(4, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = 22 +$(S) $(XX) -- mknodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = ? +$(S) $(XX) -- mknodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = 22 $(S) $(XX) -- mknodat(1, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = ? $(S) $(XX) -- mknodat(1, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = 22 $(S) $(XX) -- mknodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = ? @@ -724,8 +720,8 @@ $(S) $(XX) -- migrate_pages(0x1, 0x2, 0x123000, 0x234000) = ? $(S) $(XX) -- migrate_pages(0x1, 0x2, 0x123000, 0x234000) = 22 $(S) $(XX) -- unshare(0x20400) = ? $(S) $(XX) -- unshare(0x20400) = 22 -$(S) $(XX) -- set_robust_list(0x123000, 0x21) = ? -$(S) $(XX) -- set_robust_list(0x123000, 0x21) = 22 +$(S) $(XX) -- set_robust_list(0x123000, 33) = ? +$(S) $(XX) -- set_robust_list(0x123000, 33) = 22 $(S) $(XX) -- get_robust_list(0x2c, 0x123000, 0x234000) = ? $(S) $(XX) -- get_robust_list(0x2c, 0x123000, 0x234000) = 22 $(S) $(XX) -- splice(2, 0x123000, 3, 0x234000, 0x7b, 0x1) = ? From f63d4c31e1ee3c41333b0d26f3830c27eef95f1d Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 10 Jul 2025 15:26:02 +0200 Subject: [PATCH 097/143] updated CI pipeline to run on Ubuntu 22 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index fd75dab..8c25272 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,7 +15,7 @@ jobs: # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. # You can convert this to a matrix build if you need cross-platform coverage. # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - runs-on: [ubuntu-20.04] + runs-on: [ubuntu-22.04] steps: - uses: actions/checkout@v3 From 0436c23706d70971b14c92e9c9bc7c209593578f Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 11 Jul 2025 13:11:02 +0200 Subject: [PATCH 098/143] fine-tuned fstat logging --- src/syscall_formats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/syscall_formats.c b/src/syscall_formats.c index f9bb52b..f1be30c 100644 --- a/src/syscall_formats.c +++ b/src/syscall_formats.c @@ -51,7 +51,7 @@ static const struct syscall_format formats[] = { #ifdef SYS_stat SARGS(stat, rdec, arg_cstr, arg_pointer), #endif - SARGS(fstat, rdec, arg_fd, arg_pointer), + SARGS(fstat, rdec, arg_atfd, arg_pointer), #ifdef SYS_lstat SARGS(lstat, rdec, arg_cstr, arg_pointer), #endif From 218287c43fbd5401617d33d86f947fa284010a28 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 11 Jul 2025 18:31:45 +0200 Subject: [PATCH 099/143] tailored tests to work on different glibc versions --- test/libcintercept0.log.match | 8 ++++---- test/libcintercept0_child.log.match | 8 ++++---- test/syscall_format.c | 8 ++++++++ test/syscall_format.log.match | 12 ++++++++---- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/test/libcintercept0.log.match b/test/libcintercept0.log.match index 68dd704..546c085 100644 --- a/test/libcintercept0.log.match +++ b/test/libcintercept0.log.match @@ -11,16 +11,16 @@ $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = $(N) $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = $(N) -$(S) $(XX) -- newfstatat($(N), $(S), $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat($(N), $(S), $(XX), $(XX)) = 0 +$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(S) $(XX) -- read($(N), $(XX), $(N)) = ? $(S) $(XX) -- read($(N), "/*\n * Copyright 2016-2017, Intel Corporation\n *\n * Redistribution and use in source and binary forms, with or without\n...", $(N)) = $(N) -$(S) $(XX) -- newfstatat(1, $(S), $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(1, $(S), $(XX), $(XX)) = 0 +$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? diff --git a/test/libcintercept0_child.log.match b/test/libcintercept0_child.log.match index b2aa92b..4f8478c 100644 --- a/test/libcintercept0_child.log.match +++ b/test/libcintercept0_child.log.match @@ -2,16 +2,16 @@ $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = $(N) $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = $(N) -$(S) $(XX) -- newfstatat($(N), $(S), $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat($(N), $(S), $(XX), $(XX)) = 0 +$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(S) $(XX) -- read($(N), $(XX), $(N)) = ? $(S) $(XX) -- read($(N), "/*\n * Copyright 2016-2017, Intel Corporation\n *\n * Redistribution and use in source and binary forms, with or without\n...", $(N)) = $(N) -$(S) $(XX) -- newfstatat($(N), $(S), $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat($(N), $(S), $(XX), $(XX)) = 0 +$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? diff --git a/test/syscall_format.c b/test/syscall_format.c index fbad1fb..cb5040b 100644 --- a/test/syscall_format.c +++ b/test/syscall_format.c @@ -309,6 +309,14 @@ main(int argc, char **argv) stat(NULL, &statbuf); stat("/", &statbuf); fstat(0, NULL); + /* + * fstat implementation from some glibc versions doesn't invoke kernel if + * fd is negative so the related expected entries in + * syscall_format_logging.match (79-82) of the next two calls are marked + * with optional token $(OPT) + */ + fstat(-1, NULL); + fstat(AT_FDCWD, &statbuf); fstat(2, &statbuf); lstat(NULL, NULL); lstat("/", NULL); diff --git a/test/syscall_format.log.match b/test/syscall_format.log.match index c581482..709c7fd 100644 --- a/test/syscall_format.log.match +++ b/test/syscall_format.log.match @@ -74,10 +74,14 @@ $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(0, $(S), $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(0, $(S), $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(2, $(S), $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(2, $(S), $(XX), $(XX)) = 22 +$(S) $(XX) -- $(*)fstat$(*)(0, $(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)(0, $(*)) = 22 +$(OPT)$(S) $(XX) -- $(*)fstat$(*)(-1, $(*)) = ? +$(OPT)$(S) $(XX) -- $(*)fstat$(*)(-1, $(*)) = 22 +$(OPT)$(S) $(XX) -- $(*)fstat$(*)(AT_FDCWD, $(*)) = ? +$(OPT)$(S) $(XX) -- $(*)fstat$(*)(AT_FDCWD, $(*)) = 22 +$(S) $(XX) -- $(*)fstat$(*)(2, $(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)(2, $(*)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? From 4495eae5af8fb5f82c58f28f8e0a0655ba929cc9 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sat, 12 Jul 2025 16:37:22 +0200 Subject: [PATCH 100/143] rearranged riscv tests in dedicated directory --- .gitignore | 6 +++--- {test/riscv => riscv_test}/Makefile | 6 +++--- {test/riscv => riscv_test}/README.md | 0 {test/riscv => riscv_test}/src/clone_test.c | 0 {test/riscv => riscv_test}/src/fcntl_test.c | 0 {test/riscv => riscv_test}/src/fork_test.c | 0 {test/riscv => riscv_test}/src/intercept_sys_clone.c | 0 {test/riscv => riscv_test}/src/intercept_sys_fcntl.c | 0 {test/riscv => riscv_test}/src/intercept_sys_fork.c | 0 {test/riscv => riscv_test}/src/intercept_sys_mkdirat.c | 0 {test/riscv => riscv_test}/src/intercept_sys_openat.c | 0 {test/riscv => riscv_test}/src/intercept_sys_read.c | 0 {test/riscv => riscv_test}/src/intercept_sys_statx.c | 0 {test/riscv => riscv_test}/src/intercept_sys_write.c | 0 {test/riscv => riscv_test}/src/mkdirat_test.c | 0 {test/riscv => riscv_test}/src/openat_test.c | 0 {test/riscv => riscv_test}/src/read_test.c | 0 {test/riscv => riscv_test}/src/statx_test.c | 0 {test/riscv => riscv_test}/src/write_test.c | 0 19 files changed, 6 insertions(+), 6 deletions(-) rename {test/riscv => riscv_test}/Makefile (94%) rename {test/riscv => riscv_test}/README.md (100%) rename {test/riscv => riscv_test}/src/clone_test.c (100%) rename {test/riscv => riscv_test}/src/fcntl_test.c (100%) rename {test/riscv => riscv_test}/src/fork_test.c (100%) rename {test/riscv => riscv_test}/src/intercept_sys_clone.c (100%) rename {test/riscv => riscv_test}/src/intercept_sys_fcntl.c (100%) rename {test/riscv => riscv_test}/src/intercept_sys_fork.c (100%) rename {test/riscv => riscv_test}/src/intercept_sys_mkdirat.c (100%) rename {test/riscv => riscv_test}/src/intercept_sys_openat.c (100%) rename {test/riscv => riscv_test}/src/intercept_sys_read.c (100%) rename {test/riscv => riscv_test}/src/intercept_sys_statx.c (100%) rename {test/riscv => riscv_test}/src/intercept_sys_write.c (100%) rename {test/riscv => riscv_test}/src/mkdirat_test.c (100%) rename {test/riscv => riscv_test}/src/openat_test.c (100%) rename {test/riscv => riscv_test}/src/read_test.c (100%) rename {test/riscv => riscv_test}/src/statx_test.c (100%) rename {test/riscv => riscv_test}/src/write_test.c (100%) diff --git a/.gitignore b/.gitignore index 983a332..617e59e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,6 @@ build/ .idea/ cmake-build-debug/ test/*.so -test/riscv/bin/ -test/riscv/build/ -test/riscv/*.txt +riscv_test/bin/ +riscv_test/build/ +riscv_test/*.txt diff --git a/test/riscv/Makefile b/riscv_test/Makefile similarity index 94% rename from test/riscv/Makefile rename to riscv_test/Makefile index f17f13b..42c1767 100644 --- a/test/riscv/Makefile +++ b/riscv_test/Makefile @@ -1,6 +1,6 @@ CC = gcc -CFLAGS += -I../../include -CFLAGS += -L../../build +CFLAGS += -I../include +CFLAGS += -L../build CFLAGS += -lsyscall_intercept CFLAGS += -fpic -shared @@ -8,7 +8,7 @@ BIN_DIR = bin BUILD_DIR = build SRC_DIR = src -LD_LIBRARY_PATH = ./build:../../build +LD_LIBRARY_PATH = ./build:../build LD_PRELOAD = ./build TESTS += fcntl diff --git a/test/riscv/README.md b/riscv_test/README.md similarity index 100% rename from test/riscv/README.md rename to riscv_test/README.md diff --git a/test/riscv/src/clone_test.c b/riscv_test/src/clone_test.c similarity index 100% rename from test/riscv/src/clone_test.c rename to riscv_test/src/clone_test.c diff --git a/test/riscv/src/fcntl_test.c b/riscv_test/src/fcntl_test.c similarity index 100% rename from test/riscv/src/fcntl_test.c rename to riscv_test/src/fcntl_test.c diff --git a/test/riscv/src/fork_test.c b/riscv_test/src/fork_test.c similarity index 100% rename from test/riscv/src/fork_test.c rename to riscv_test/src/fork_test.c diff --git a/test/riscv/src/intercept_sys_clone.c b/riscv_test/src/intercept_sys_clone.c similarity index 100% rename from test/riscv/src/intercept_sys_clone.c rename to riscv_test/src/intercept_sys_clone.c diff --git a/test/riscv/src/intercept_sys_fcntl.c b/riscv_test/src/intercept_sys_fcntl.c similarity index 100% rename from test/riscv/src/intercept_sys_fcntl.c rename to riscv_test/src/intercept_sys_fcntl.c diff --git a/test/riscv/src/intercept_sys_fork.c b/riscv_test/src/intercept_sys_fork.c similarity index 100% rename from test/riscv/src/intercept_sys_fork.c rename to riscv_test/src/intercept_sys_fork.c diff --git a/test/riscv/src/intercept_sys_mkdirat.c b/riscv_test/src/intercept_sys_mkdirat.c similarity index 100% rename from test/riscv/src/intercept_sys_mkdirat.c rename to riscv_test/src/intercept_sys_mkdirat.c diff --git a/test/riscv/src/intercept_sys_openat.c b/riscv_test/src/intercept_sys_openat.c similarity index 100% rename from test/riscv/src/intercept_sys_openat.c rename to riscv_test/src/intercept_sys_openat.c diff --git a/test/riscv/src/intercept_sys_read.c b/riscv_test/src/intercept_sys_read.c similarity index 100% rename from test/riscv/src/intercept_sys_read.c rename to riscv_test/src/intercept_sys_read.c diff --git a/test/riscv/src/intercept_sys_statx.c b/riscv_test/src/intercept_sys_statx.c similarity index 100% rename from test/riscv/src/intercept_sys_statx.c rename to riscv_test/src/intercept_sys_statx.c diff --git a/test/riscv/src/intercept_sys_write.c b/riscv_test/src/intercept_sys_write.c similarity index 100% rename from test/riscv/src/intercept_sys_write.c rename to riscv_test/src/intercept_sys_write.c diff --git a/test/riscv/src/mkdirat_test.c b/riscv_test/src/mkdirat_test.c similarity index 100% rename from test/riscv/src/mkdirat_test.c rename to riscv_test/src/mkdirat_test.c diff --git a/test/riscv/src/openat_test.c b/riscv_test/src/openat_test.c similarity index 100% rename from test/riscv/src/openat_test.c rename to riscv_test/src/openat_test.c diff --git a/test/riscv/src/read_test.c b/riscv_test/src/read_test.c similarity index 100% rename from test/riscv/src/read_test.c rename to riscv_test/src/read_test.c diff --git a/test/riscv/src/statx_test.c b/riscv_test/src/statx_test.c similarity index 100% rename from test/riscv/src/statx_test.c rename to riscv_test/src/statx_test.c diff --git a/test/riscv/src/write_test.c b/riscv_test/src/write_test.c similarity index 100% rename from test/riscv/src/write_test.c rename to riscv_test/src/write_test.c From 339e8226fa5ed5c6383e83bf360ac620bb468b00 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sat, 12 Jul 2025 16:39:23 +0200 Subject: [PATCH 101/143] updated riscv test directory --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5d03bc4..a4971e4 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ make test Testing on **RISC-V**: ```shell # From the project root directory -cd test/riscv/ +cd riscv_test/ make make test ``` From 474475684e0f550e6a017f84632eb7c7526afccf Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sat, 12 Jul 2025 16:41:30 +0200 Subject: [PATCH 102/143] test list order is now consistent --- riscv_test/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv_test/Makefile b/riscv_test/Makefile index 42c1767..fa1b7c9 100644 --- a/riscv_test/Makefile +++ b/riscv_test/Makefile @@ -11,8 +11,8 @@ SRC_DIR = src LD_LIBRARY_PATH = ./build:../build LD_PRELOAD = ./build -TESTS += fcntl TESTS += mkdirat +TESTS += fcntl TESTS += openat TESTS += read TESTS += statx From d1bfc3d80ed3f9ff7f65b745cc1e1bd55bf7d9b9 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sat, 12 Jul 2025 17:00:02 +0200 Subject: [PATCH 103/143] refined trampoline allocation --- src/arch/riscv/patcher.c | 4 ++-- src/intercept.h | 2 ++ src/intercept_desc.c | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/arch/riscv/patcher.c b/src/arch/riscv/patcher.c index d78e42e..f3c4a90 100644 --- a/src/arch/riscv/patcher.c +++ b/src/arch/riscv/patcher.c @@ -555,8 +555,8 @@ create_j(unsigned char *from, void *to) uint32_t *instructions = (uint32_t *)from; debug_dump("%p: ecall -> jalr %ld\t# %p\n", from, delta, to); - const ptrdiff_t JALR_MAX_OFFSET = 2147481598; // ((2^31-1)-4095)+(2^11-1) = 0x7ffff000 + 0x7ff - const ptrdiff_t JALR_MIN_OFFSET = -2147483648; // (-2^31) = -0x80000000 + const ptrdiff_t JALR_MAX_OFFSET = ABS_MAX_POS_OFFSET; // ((2^31-1)-4095)+(2^11-2) = 0x7ffff000 + 0x7fe + const ptrdiff_t JALR_MIN_OFFSET = -(ABS_MAX_NEG_OFFSET); // (-2^31) = -0x80000000 - 0x800 if ((delta & 0x1) != 0) { diff --git a/src/intercept.h b/src/intercept.h index d06f889..f07e48f 100644 --- a/src/intercept.h +++ b/src/intercept.h @@ -245,6 +245,8 @@ void activate_patches(struct intercept_desc *desc); #define SIXTH_ARG_REG PARAM_BY_ARCH(context->r9,context->a[5]) #define FIRST_RET_REG PARAM_BY_ARCH(.rax,.a[0]) #define SECOND_RET_REG PARAM_BY_ARCH(.rdx,.a[1]) +#define ABS_MAX_NEG_OFFSET PARAM_BY_ARCH(INT32_MAX,((long)INT32_MAX+0x800)) +#define ABS_MAX_POS_OFFSET PARAM_BY_ARCH(INT32_MAX,INT32_MAX-0x801) bool is_overwritable_nop(const struct intercept_disasm_result *ins); diff --git a/src/intercept_desc.c b/src/intercept_desc.c index 43c9513..bfc9516 100644 --- a/src/intercept_desc.c +++ b/src/intercept_desc.c @@ -631,7 +631,7 @@ allocate_trampoline_table(struct intercept_desc *desc) unsigned char *guess; /* Where we would like to allocate the table */ size_t size; - if ((uintptr_t)desc->text_end < INT32_MAX) { + if ((uintptr_t)desc->text_end < ABS_MAX_NEG_OFFSET) { /* start from the bottom of memory */ guess = (void *)0; } else { @@ -641,7 +641,7 @@ allocate_trampoline_table(struct intercept_desc *desc) * Round up to a memory page boundary, as this address must be * mappable. */ - guess = desc->text_end - INT32_MAX; + guess = desc->text_end - ABS_MAX_NEG_OFFSET; guess = (unsigned char *)(((uintptr_t)guess) & ~((uintptr_t)(0xfff))) + 0x1000; } @@ -679,7 +679,7 @@ allocate_trampoline_table(struct intercept_desc *desc) */ guess = end; - if (guess + size >= desc->text_start + INT32_MAX) { + if (guess + size >= desc->text_start + ABS_MAX_POS_OFFSET) { /* Too far away */ xabort("unable to find place for trampoline table"); } From bfae1e37967555f43b1dc323418c12fe978357f7 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli <102027096+SilenceDesigner@users.noreply.github.com> Date: Tue, 15 Jul 2025 12:04:35 +0200 Subject: [PATCH 104/143] Update README.md Co-authored-by: Iacopo Colonnelli --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fa25a43..142abab 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [//]: # ([![Coverity Scan Build Status](https://scan.coverity.com/projects/12890/badge.svg)](https://scan.coverity.com/projects/syscall_intercept)) This repository contains a multi-architecture porting of [syscall_intercept](https://github.com/pmem/syscall_intercept) working on both **x86_64** and **RISC-V**. -Full-featured support for **aarch64** (ARM64) is **work in progress**. +Full-featured support for **aarch64** (ARM64) is in progress. [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) # Dependencies # From e94f6c80086e7709f74a6e493668e90a9309fc9e Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli <102027096+SilenceDesigner@users.noreply.github.com> Date: Tue, 15 Jul 2025 12:05:00 +0200 Subject: [PATCH 105/143] Update README.md Co-authored-by: Iacopo Colonnelli --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 142abab..b9f33f0 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,7 @@ Full-featured support for **aarch64** (ARM64) is in progress. * libcapstone -- the disassembly engine used under the hood (RISC-V support requires version **5.0** or higher, while apt installs version 4.0.2 by default, as february 2025). - Since a manual installation of capstone could not be automatically detected while compiling syscall_intercept, we made - sure that libcapstone 5.0.6 is **automatically compiled** from source during the syscall_intercept cmake execution. - In other words, you don't need to care about having and installing capstone at all on your system. + Since a manual installation of Capstone could not be automatically detected while compiling syscall_intercept, we ensured that libcapstone v5.0.6 is **automatically compiled** from source during the syscall_intercept cmake execution. ## Build dependencies ## From 66d954f1c472d4d1c13bc71aa30cea5571b33c3a Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 15 Jul 2025 12:09:10 +0200 Subject: [PATCH 106/143] Specified referenced capstone version --- capstone/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/capstone/CMakeLists.txt b/capstone/CMakeLists.txt index 5b6ad33..4e208f6 100644 --- a/capstone/CMakeLists.txt +++ b/capstone/CMakeLists.txt @@ -7,6 +7,7 @@ include(FetchContent) ##################################### FetchContent_Declare(capstone GIT_REPOSITORY https://github.com/capstone-engine/capstone.git + # the following git tag refers to capstone version 5.0.6 GIT_TAG accf4df62f1fba6f92cae692985d27063552601c ) From d5d5bd6a5323093e131f2567f7a9f6a50320ca6f Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 15 Jul 2025 17:33:32 +0200 Subject: [PATCH 107/143] rearranged arch-specific tests --- test/CMakeLists.txt | 299 +++++++++--------- test/arch/x86_64/CMakeLists.txt | 184 +++++++++++ test/{ => arch/x86_64}/asm_pattern.c | 0 test/arch/x86_64/check.cmake | 62 ++++ .../x86_64}/executable_with_syscall.S | 0 .../{ => arch/x86_64}/mock_trampoline_table.S | 0 test/{ => arch/x86_64}/nosyscall.in.S | 0 test/{ => arch/x86_64}/nosyscall.out.S | 0 test/{ => arch/x86_64}/pattern1.in.S | 0 test/{ => arch/x86_64}/pattern1.out.S | 0 test/{ => arch/x86_64}/pattern2.in.S | 0 test/{ => arch/x86_64}/pattern2.out.S | 0 test/{ => arch/x86_64}/pattern3.in.S | 0 test/{ => arch/x86_64}/pattern3.out.S | 0 test/{ => arch/x86_64}/pattern4.in.S | 0 test/{ => arch/x86_64}/pattern4.out.S | 0 .../x86_64}/pattern_double_syscall.in.S | 0 .../x86_64}/pattern_double_syscall.out.S | 0 test/{ => arch/x86_64}/pattern_endbr64.in.S | 0 test/{ => arch/x86_64}/pattern_endbr64.out.S | 0 test/{ => arch/x86_64}/pattern_jmps.in.S | 0 test/{ => arch/x86_64}/pattern_jmps.out.S | 0 .../x86_64}/pattern_lea_rip_r12.in.S | 0 .../x86_64}/pattern_lea_rip_r12.out.S | 0 .../x86_64}/pattern_lea_rip_rdi.in.S | 0 .../x86_64}/pattern_lea_rip_rdi.out.S | 0 test/{ => arch/x86_64}/pattern_loop.in.S | 0 test/{ => arch/x86_64}/pattern_loop.out.S | 0 test/{ => arch/x86_64}/pattern_loop2.in.S | 0 test/{ => arch/x86_64}/pattern_loop2.out.S | 0 .../x86_64}/pattern_nop_padding0.in.S | 0 .../x86_64}/pattern_nop_padding0.out.S | 0 .../x86_64}/pattern_nop_padding1.in.S | 0 .../x86_64}/pattern_nop_padding1.out.S | 0 .../x86_64}/pattern_nop_padding2.in.S | 0 .../x86_64}/pattern_nop_padding2.out.S | 0 .../x86_64}/pattern_nop_padding3.in.S | 0 .../x86_64}/pattern_nop_padding3.out.S | 0 .../x86_64}/pattern_nop_padding4.in.S | 0 .../x86_64}/pattern_nop_padding4.out.S | 0 .../x86_64}/pattern_nop_padding5.in.S | 0 .../x86_64}/pattern_nop_padding5.out.S | 0 .../x86_64}/pattern_nop_padding6.in.S | 0 .../x86_64}/pattern_nop_padding6.out.S | 0 .../x86_64}/pattern_nop_padding7.in.S | 0 .../x86_64}/pattern_nop_padding7.out.S | 0 .../x86_64}/pattern_nop_padding8.in.S | 0 .../x86_64}/pattern_nop_padding8.out.S | 0 .../x86_64}/pattern_nop_padding9.in.S | 0 .../x86_64}/pattern_nop_padding9.out.S | 0 test/{ => arch/x86_64}/pattern_rets.in.S | 0 test/{ => arch/x86_64}/pattern_rets.out.S | 0 .../x86_64}/pattern_symbol_boundary0.in.S | 0 .../x86_64}/pattern_symbol_boundary0.out.S | 0 .../x86_64}/pattern_symbol_boundary1.in.S | 0 .../x86_64}/pattern_symbol_boundary1.out.S | 0 .../x86_64}/pattern_symbol_boundary2.in.S | 0 .../x86_64}/pattern_symbol_boundary2.out.S | 0 .../x86_64}/pattern_symbol_boundary3.in.S | 0 .../x86_64}/pattern_symbol_boundary3.out.S | 0 60 files changed, 397 insertions(+), 148 deletions(-) create mode 100644 test/arch/x86_64/CMakeLists.txt rename test/{ => arch/x86_64}/asm_pattern.c (100%) create mode 100644 test/arch/x86_64/check.cmake rename test/{ => arch/x86_64}/executable_with_syscall.S (100%) rename test/{ => arch/x86_64}/mock_trampoline_table.S (100%) rename test/{ => arch/x86_64}/nosyscall.in.S (100%) rename test/{ => arch/x86_64}/nosyscall.out.S (100%) rename test/{ => arch/x86_64}/pattern1.in.S (100%) rename test/{ => arch/x86_64}/pattern1.out.S (100%) rename test/{ => arch/x86_64}/pattern2.in.S (100%) rename test/{ => arch/x86_64}/pattern2.out.S (100%) rename test/{ => arch/x86_64}/pattern3.in.S (100%) rename test/{ => arch/x86_64}/pattern3.out.S (100%) rename test/{ => arch/x86_64}/pattern4.in.S (100%) rename test/{ => arch/x86_64}/pattern4.out.S (100%) rename test/{ => arch/x86_64}/pattern_double_syscall.in.S (100%) rename test/{ => arch/x86_64}/pattern_double_syscall.out.S (100%) rename test/{ => arch/x86_64}/pattern_endbr64.in.S (100%) rename test/{ => arch/x86_64}/pattern_endbr64.out.S (100%) rename test/{ => arch/x86_64}/pattern_jmps.in.S (100%) rename test/{ => arch/x86_64}/pattern_jmps.out.S (100%) rename test/{ => arch/x86_64}/pattern_lea_rip_r12.in.S (100%) rename test/{ => arch/x86_64}/pattern_lea_rip_r12.out.S (100%) rename test/{ => arch/x86_64}/pattern_lea_rip_rdi.in.S (100%) rename test/{ => arch/x86_64}/pattern_lea_rip_rdi.out.S (100%) rename test/{ => arch/x86_64}/pattern_loop.in.S (100%) rename test/{ => arch/x86_64}/pattern_loop.out.S (100%) rename test/{ => arch/x86_64}/pattern_loop2.in.S (100%) rename test/{ => arch/x86_64}/pattern_loop2.out.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding0.in.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding0.out.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding1.in.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding1.out.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding2.in.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding2.out.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding3.in.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding3.out.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding4.in.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding4.out.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding5.in.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding5.out.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding6.in.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding6.out.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding7.in.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding7.out.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding8.in.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding8.out.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding9.in.S (100%) rename test/{ => arch/x86_64}/pattern_nop_padding9.out.S (100%) rename test/{ => arch/x86_64}/pattern_rets.in.S (100%) rename test/{ => arch/x86_64}/pattern_rets.out.S (100%) rename test/{ => arch/x86_64}/pattern_symbol_boundary0.in.S (100%) rename test/{ => arch/x86_64}/pattern_symbol_boundary0.out.S (100%) rename test/{ => arch/x86_64}/pattern_symbol_boundary1.in.S (100%) rename test/{ => arch/x86_64}/pattern_symbol_boundary1.out.S (100%) rename test/{ => arch/x86_64}/pattern_symbol_boundary2.in.S (100%) rename test/{ => arch/x86_64}/pattern_symbol_boundary2.out.S (100%) rename test/{ => arch/x86_64}/pattern_symbol_boundary3.in.S (100%) rename test/{ => arch/x86_64}/pattern_symbol_boundary3.out.S (100%) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 724321f..b391951 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -39,88 +39,91 @@ find_package(Threads) include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/test) -set(CMAKE_ASM_CREATE_SHARED_LIBRARY ${CMAKE_C_CREATE_SHARED_LIBRARY}) - -add_executable(asm_pattern asm_pattern.c - $ - $) -target_link_libraries(asm_pattern PUBLIC ${CAPSTONE_LIB_FOLDER}/libcapstone.so) - -target_link_libraries(asm_pattern - PRIVATE ${CMAKE_DL_LIBS} ${capstone_LDFLAGS}) - -set(asm_patterns - nosyscall - pattern1 - pattern2 - pattern3 - pattern4 - pattern_loop - pattern_loop2 - pattern_symbol_boundary0 - pattern_symbol_boundary1 - pattern_symbol_boundary2 - pattern_symbol_boundary3 - pattern_nop_padding0 - pattern_nop_padding1 - pattern_nop_padding2 - pattern_nop_padding3 - pattern_nop_padding4 - pattern_nop_padding5 - pattern_nop_padding6 - pattern_nop_padding7 - pattern_nop_padding8 - pattern_nop_padding9 - pattern_lea_rip_rdi - pattern_lea_rip_r12) - -try_compile(ASSEMBLER_SUPPORTS_ENDBR64 ${CMAKE_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/pattern_endbr64.in.S - CMAKE_FLAGS "-DCMAKE_ASM_LINK_EXECUTABLE='echo skip linking'") -if(ASSEMBLER_SUPPORTS_ENDBR64) - list(APPEND asm_patterns pattern_endbr64) +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86(_64)?)$") + add_subdirectory(arch/x86_64) +# set(CMAKE_ASM_CREATE_SHARED_LIBRARY ${CMAKE_C_CREATE_SHARED_LIBRARY}) +# +# add_executable(asm_pattern asm_pattern.c +# $ +# $) +# target_link_libraries(asm_pattern PUBLIC ${CAPSTONE_LIB_FOLDER}/libcapstone.so) +# +# target_link_libraries(asm_pattern +# PRIVATE ${CMAKE_DL_LIBS} ${capstone_LDFLAGS}) +# +# set(asm_patterns +# nosyscall +# pattern1 +# pattern2 +# pattern3 +# pattern4 +# pattern_loop +# pattern_loop2 +# pattern_symbol_boundary0 +# pattern_symbol_boundary1 +# pattern_symbol_boundary2 +# pattern_symbol_boundary3 +# pattern_nop_padding0 +# pattern_nop_padding1 +# pattern_nop_padding2 +# pattern_nop_padding3 +# pattern_nop_padding4 +# pattern_nop_padding5 +# pattern_nop_padding6 +# pattern_nop_padding7 +# pattern_nop_padding8 +# pattern_nop_padding9 +# pattern_lea_rip_rdi +# pattern_lea_rip_r12) +# +# try_compile(ASSEMBLER_SUPPORTS_ENDBR64 ${CMAKE_BINARY_DIR} +# ${CMAKE_CURRENT_SOURCE_DIR}/pattern_endbr64.in.S +# CMAKE_FLAGS "-DCMAKE_ASM_LINK_EXECUTABLE='echo skip linking'") +# if(ASSEMBLER_SUPPORTS_ENDBR64) +# list(APPEND asm_patterns pattern_endbr64) +# endif() +# +# set(asm_patterns_failing +# pattern_double_syscall +# pattern_rets +# pattern_jmps) +# +# macro(add_asm_test test_name failing) +# add_library(${test_name}.in SHARED ${test_name}.in.S) +# add_library(${test_name}.out SHARED ${test_name}.out.S) +# if(LINKER_HAS_NOSTDLIB) +# set_target_properties(${test_name}.in +# PROPERTIES LINK_FLAGS "-nostdlib") +# set_target_properties(${test_name}.out +# PROPERTIES LINK_FLAGS "-nostdlib") +# endif() +# if(HAS_NOUNUSEDARG) +# target_compile_options(${test_name}.in BEFORE +# PRIVATE "-Wno-unused-command-line-argument") +# target_compile_options(${test_name}.out BEFORE +# PRIVATE "-Wno-unused-command-line-argument") +# +# endif() +# add_test(NAME "asm_pattern_${test_name}" +# COMMAND $ +# $ +# $) +# if(${failing}) +# set_tests_properties("asm_pattern_${test_name}" +# PROPERTIES WILL_FAIL ON +# PASS_REGULAR_EXPRESSION "Invalid patch") +# endif() +# endmacro() +# +# foreach(name ${asm_patterns}) +# add_asm_test(${name} FALSE) +# endforeach() +# +# foreach(name ${asm_patterns_failing}) +# add_asm_test(${name} TRUE) +# endforeach() endif() -set(asm_patterns_failing - pattern_double_syscall - pattern_rets - pattern_jmps) - -macro(add_asm_test test_name failing) - add_library(${test_name}.in SHARED ${test_name}.in.S) - add_library(${test_name}.out SHARED ${test_name}.out.S) - if(LINKER_HAS_NOSTDLIB) - set_target_properties(${test_name}.in - PROPERTIES LINK_FLAGS "-nostdlib") - set_target_properties(${test_name}.out - PROPERTIES LINK_FLAGS "-nostdlib") - endif() - if(HAS_NOUNUSEDARG) - target_compile_options(${test_name}.in BEFORE - PRIVATE "-Wno-unused-command-line-argument") - target_compile_options(${test_name}.out BEFORE - PRIVATE "-Wno-unused-command-line-argument") - - endif() - add_test(NAME "asm_pattern_${test_name}" - COMMAND $ - $ - $) - if(${failing}) - set_tests_properties("asm_pattern_${test_name}" - PROPERTIES WILL_FAIL ON - PASS_REGULAR_EXPRESSION "Invalid patch") - endif() -endmacro() - -foreach(name ${asm_patterns}) - add_asm_test(${name} FALSE) -endforeach() - -foreach(name ${asm_patterns_failing}) - add_asm_test(${name} TRUE) -endforeach() - set(CHECK_LOG_COMMON_ARGS -DMATCH_SCRIPT=${PROJECT_SOURCE_DIR}/utils/match.pl -DEXPECT_SPURIOUS_SYSCALLS=${EXPECT_SPURIOUS_SYSCALLS} @@ -251,74 +254,74 @@ set_tests_properties("clone_thread" add_library(intercept_sys_write SHARED intercept_sys_write.c) target_link_libraries(intercept_sys_write PRIVATE syscall_intercept_shared) -add_executable(executable_with_syscall_pie executable_with_syscall.S) -if(HAS_NOUNUSEDARG) - target_compile_options(executable_with_syscall_pie BEFORE - PRIVATE "-Wno-unused-command-line-argument") -endif() -set_target_properties(executable_with_syscall_pie - PROPERTIES POSITION_INDEPENDENT_CODE True) -if(HAS_ARG_PIE) - target_compile_options(executable_with_syscall_pie PRIVATE "-pie") - target_link_libraries(executable_with_syscall_pie PRIVATE "-pie") -endif() - -add_executable(executable_with_syscall_no_pie executable_with_syscall.S) -if(HAS_NOUNUSEDARG) - target_compile_options(executable_with_syscall_no_pie BEFORE - PRIVATE "-Wno-unused-command-line-argument") -endif() -set_target_properties(executable_with_syscall_no_pie - PROPERTIES POSITION_INDEPENDENT_CODE False) -if(HAS_ARG_NOPIE) - target_compile_options(executable_with_syscall_no_pie PRIVATE "-nopie") - target_link_libraries(executable_with_syscall_no_pie PRIVATE "-nopie") -elseif(HAS_ARG_NO_PIE) - target_compile_options(executable_with_syscall_no_pie PRIVATE "-no-pie") - target_link_libraries(executable_with_syscall_no_pie PRIVATE "-no-pie") -endif() - -add_test(NAME "prog_pie_intercept_libc_only" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DTEST_PROG=$ - -DLIB_FILE=$ - -DTEST_PROG_ARGS=original_syscall - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -set_tests_properties("prog_pie_intercept_libc_only" - PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") - -add_test(NAME "prog_no_pie_intercept_libc_only" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DTEST_PROG=$ - -DLIB_FILE=$ - -DTEST_PROG_ARGS=original_syscall - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -set_tests_properties("prog_no_pie_intercept_libc_only" - PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") - -add_test(NAME "prog_pie_intercept_all" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DINTERCEPT_ALL=1 - -DTEST_PROG=$ - -DLIB_FILE=$ - -DTEST_PROG_ARGS=original_syscall - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -set_tests_properties("prog_pie_intercept_all" - PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") - -add_test(NAME "prog_no_pie_intercept_all" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DINTERCEPT_ALL=1 - -DTEST_PROG=$ - -DLIB_FILE=$ - -DTEST_PROG_ARGS=original_syscall - -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -set_tests_properties("prog_no_pie_intercept_all" - PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") +#add_executable(executable_with_syscall_pie executable_with_syscall.S) +#if(HAS_NOUNUSEDARG) +# target_compile_options(executable_with_syscall_pie BEFORE +# PRIVATE "-Wno-unused-command-line-argument") +#endif() +#set_target_properties(executable_with_syscall_pie +# PROPERTIES POSITION_INDEPENDENT_CODE True) +#if(HAS_ARG_PIE) +# target_compile_options(executable_with_syscall_pie PRIVATE "-pie") +# target_link_libraries(executable_with_syscall_pie PRIVATE "-pie") +#endif() +# +#add_executable(executable_with_syscall_no_pie executable_with_syscall.S) +#if(HAS_NOUNUSEDARG) +# target_compile_options(executable_with_syscall_no_pie BEFORE +# PRIVATE "-Wno-unused-command-line-argument") +#endif() +#set_target_properties(executable_with_syscall_no_pie +# PROPERTIES POSITION_INDEPENDENT_CODE False) +#if(HAS_ARG_NOPIE) +# target_compile_options(executable_with_syscall_no_pie PRIVATE "-nopie") +# target_link_libraries(executable_with_syscall_no_pie PRIVATE "-nopie") +#elseif(HAS_ARG_NO_PIE) +# target_compile_options(executable_with_syscall_no_pie PRIVATE "-no-pie") +# target_link_libraries(executable_with_syscall_no_pie PRIVATE "-no-pie") +#endif() +# +#add_test(NAME "prog_pie_intercept_libc_only" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DTEST_PROG=$ +# -DLIB_FILE=$ +# -DTEST_PROG_ARGS=original_syscall +# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +#set_tests_properties("prog_pie_intercept_libc_only" +# PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") +# +#add_test(NAME "prog_no_pie_intercept_libc_only" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DTEST_PROG=$ +# -DLIB_FILE=$ +# -DTEST_PROG_ARGS=original_syscall +# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +#set_tests_properties("prog_no_pie_intercept_libc_only" +# PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") +# +#add_test(NAME "prog_pie_intercept_all" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DINTERCEPT_ALL=1 +# -DTEST_PROG=$ +# -DLIB_FILE=$ +# -DTEST_PROG_ARGS=original_syscall +# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +#set_tests_properties("prog_pie_intercept_all" +# PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") +# +#add_test(NAME "prog_no_pie_intercept_all" +# COMMAND ${CMAKE_COMMAND} +# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} +# -DINTERCEPT_ALL=1 +# -DTEST_PROG=$ +# -DLIB_FILE=$ +# -DTEST_PROG_ARGS=original_syscall +# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +#set_tests_properties("prog_no_pie_intercept_all" +# PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") add_executable(vfork_logging vfork_logging.c) add_test(NAME "vfork_logging" diff --git a/test/arch/x86_64/CMakeLists.txt b/test/arch/x86_64/CMakeLists.txt new file mode 100644 index 0000000..d6bdd2a --- /dev/null +++ b/test/arch/x86_64/CMakeLists.txt @@ -0,0 +1,184 @@ +# +# Copyright 2017-2020, Intel Corporation +# Copyright 2025, University of Turin +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# See: https://cmake.org/Wiki/CMake/Testing_With_CTest + +set(CMAKE_ASM_CREATE_SHARED_LIBRARY ${CMAKE_C_CREATE_SHARED_LIBRARY}) + +add_executable(asm_pattern asm_pattern.c + $ + $) +target_link_libraries(asm_pattern PUBLIC ${CAPSTONE_LIB_FOLDER}/libcapstone.so) + +target_link_libraries(asm_pattern + PRIVATE ${CMAKE_DL_LIBS} ${capstone_LDFLAGS}) + +set(asm_patterns + nosyscall + pattern1 + pattern2 + pattern3 + pattern4 + pattern_loop + pattern_loop2 + pattern_symbol_boundary0 + pattern_symbol_boundary1 + pattern_symbol_boundary2 + pattern_symbol_boundary3 + pattern_nop_padding0 + pattern_nop_padding1 + pattern_nop_padding2 + pattern_nop_padding3 + pattern_nop_padding4 + pattern_nop_padding5 + pattern_nop_padding6 + pattern_nop_padding7 + pattern_nop_padding8 + pattern_nop_padding9 + pattern_lea_rip_rdi + pattern_lea_rip_r12) + +try_compile(ASSEMBLER_SUPPORTS_ENDBR64 ${CMAKE_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/pattern_endbr64.in.S + CMAKE_FLAGS "-DCMAKE_ASM_LINK_EXECUTABLE='echo skip linking'") +if(ASSEMBLER_SUPPORTS_ENDBR64) + list(APPEND asm_patterns pattern_endbr64) +endif() + +set(asm_patterns_failing + pattern_double_syscall + pattern_rets + pattern_jmps) + +macro(add_asm_test test_name failing) + add_library(${test_name}.in SHARED ${test_name}.in.S) + add_library(${test_name}.out SHARED ${test_name}.out.S) + if(LINKER_HAS_NOSTDLIB) + set_target_properties(${test_name}.in + PROPERTIES LINK_FLAGS "-nostdlib") + set_target_properties(${test_name}.out + PROPERTIES LINK_FLAGS "-nostdlib") + endif() + if(HAS_NOUNUSEDARG) + target_compile_options(${test_name}.in BEFORE + PRIVATE "-Wno-unused-command-line-argument") + target_compile_options(${test_name}.out BEFORE + PRIVATE "-Wno-unused-command-line-argument") + + endif() + add_test(NAME "asm_pattern_${test_name}" + COMMAND $ + $ + $) + if(${failing}) + set_tests_properties("asm_pattern_${test_name}" + PROPERTIES WILL_FAIL ON + PASS_REGULAR_EXPRESSION "Invalid patch") + endif() +endmacro() + +foreach(name ${asm_patterns}) + add_asm_test(${name} FALSE) +endforeach() + +foreach(name ${asm_patterns_failing}) + add_asm_test(${name} TRUE) +endforeach() + +add_executable(executable_with_syscall_pie executable_with_syscall.S) +if(HAS_NOUNUSEDARG) + target_compile_options(executable_with_syscall_pie BEFORE + PRIVATE "-Wno-unused-command-line-argument") +endif() +set_target_properties(executable_with_syscall_pie + PROPERTIES POSITION_INDEPENDENT_CODE True) +if(HAS_ARG_PIE) + target_compile_options(executable_with_syscall_pie PRIVATE "-pie") + target_link_libraries(executable_with_syscall_pie PRIVATE "-pie") +endif() + +add_executable(executable_with_syscall_no_pie executable_with_syscall.S) +if(HAS_NOUNUSEDARG) + target_compile_options(executable_with_syscall_no_pie BEFORE + PRIVATE "-Wno-unused-command-line-argument") +endif() +set_target_properties(executable_with_syscall_no_pie + PROPERTIES POSITION_INDEPENDENT_CODE False) +if(HAS_ARG_NOPIE) + target_compile_options(executable_with_syscall_no_pie PRIVATE "-nopie") + target_link_libraries(executable_with_syscall_no_pie PRIVATE "-nopie") +elseif(HAS_ARG_NO_PIE) + target_compile_options(executable_with_syscall_no_pie PRIVATE "-no-pie") + target_link_libraries(executable_with_syscall_no_pie PRIVATE "-no-pie") +endif() + +add_test(NAME "prog_pie_intercept_libc_only" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DTEST_PROG=$ + -DLIB_FILE=$ + -DTEST_PROG_ARGS=original_syscall + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +set_tests_properties("prog_pie_intercept_libc_only" + PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") + +add_test(NAME "prog_no_pie_intercept_libc_only" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DTEST_PROG=$ + -DLIB_FILE=$ + -DTEST_PROG_ARGS=original_syscall + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +set_tests_properties("prog_no_pie_intercept_libc_only" + PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") + +add_test(NAME "prog_pie_intercept_all" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DINTERCEPT_ALL=1 + -DTEST_PROG=$ + -DLIB_FILE=$ + -DTEST_PROG_ARGS=original_syscall + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +set_tests_properties("prog_pie_intercept_all" + PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") + +add_test(NAME "prog_no_pie_intercept_all" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DINTERCEPT_ALL=1 + -DTEST_PROG=$ + -DLIB_FILE=$ + -DTEST_PROG_ARGS=original_syscall + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) +set_tests_properties("prog_no_pie_intercept_all" + PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") \ No newline at end of file diff --git a/test/asm_pattern.c b/test/arch/x86_64/asm_pattern.c similarity index 100% rename from test/asm_pattern.c rename to test/arch/x86_64/asm_pattern.c diff --git a/test/arch/x86_64/check.cmake b/test/arch/x86_64/check.cmake new file mode 100644 index 0000000..31823f3 --- /dev/null +++ b/test/arch/x86_64/check.cmake @@ -0,0 +1,62 @@ +# +# Copyright 2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +if(FILTER_PLUS_ONECHAR) + string(SUBSTRING "${FILTER_PLUS_ONECHAR}" 1 -1 FILTER) +endif() + +if(FILTER) + set(ENV{INTERCEPT_HOOK_CMDLINE_FILTER} ${FILTER}) + message("FILTER: ${FILTER}") +endif() + +if(LIB_FILE) +if(TEST_EXTRA_PRELOAD) + set(ENV{LD_PRELOAD} ${TEST_EXTRA_PRELOAD}:${LIB_FILE}) +else() + set(ENV{LD_PRELOAD} ${LIB_FILE}) +endif() +endif() + +if(INTERCEPT_ALL) + set(ENV{INTERCEPT_ALL_OBJS} 1) +else() + unset(ENV{INTERCEPT_ALL_OBJS}) +endif() + +execute_process(COMMAND ${TEST_PROG} ${TEST_PROG_ARGS} RESULT_VARIABLE HAD_ERROR) + +unset(ENV{LD_PRELOAD}) + +if(HAD_ERROR) + message(FATAL_ERROR "Error: ${HAD_ERROR}") +endif() diff --git a/test/executable_with_syscall.S b/test/arch/x86_64/executable_with_syscall.S similarity index 100% rename from test/executable_with_syscall.S rename to test/arch/x86_64/executable_with_syscall.S diff --git a/test/mock_trampoline_table.S b/test/arch/x86_64/mock_trampoline_table.S similarity index 100% rename from test/mock_trampoline_table.S rename to test/arch/x86_64/mock_trampoline_table.S diff --git a/test/nosyscall.in.S b/test/arch/x86_64/nosyscall.in.S similarity index 100% rename from test/nosyscall.in.S rename to test/arch/x86_64/nosyscall.in.S diff --git a/test/nosyscall.out.S b/test/arch/x86_64/nosyscall.out.S similarity index 100% rename from test/nosyscall.out.S rename to test/arch/x86_64/nosyscall.out.S diff --git a/test/pattern1.in.S b/test/arch/x86_64/pattern1.in.S similarity index 100% rename from test/pattern1.in.S rename to test/arch/x86_64/pattern1.in.S diff --git a/test/pattern1.out.S b/test/arch/x86_64/pattern1.out.S similarity index 100% rename from test/pattern1.out.S rename to test/arch/x86_64/pattern1.out.S diff --git a/test/pattern2.in.S b/test/arch/x86_64/pattern2.in.S similarity index 100% rename from test/pattern2.in.S rename to test/arch/x86_64/pattern2.in.S diff --git a/test/pattern2.out.S b/test/arch/x86_64/pattern2.out.S similarity index 100% rename from test/pattern2.out.S rename to test/arch/x86_64/pattern2.out.S diff --git a/test/pattern3.in.S b/test/arch/x86_64/pattern3.in.S similarity index 100% rename from test/pattern3.in.S rename to test/arch/x86_64/pattern3.in.S diff --git a/test/pattern3.out.S b/test/arch/x86_64/pattern3.out.S similarity index 100% rename from test/pattern3.out.S rename to test/arch/x86_64/pattern3.out.S diff --git a/test/pattern4.in.S b/test/arch/x86_64/pattern4.in.S similarity index 100% rename from test/pattern4.in.S rename to test/arch/x86_64/pattern4.in.S diff --git a/test/pattern4.out.S b/test/arch/x86_64/pattern4.out.S similarity index 100% rename from test/pattern4.out.S rename to test/arch/x86_64/pattern4.out.S diff --git a/test/pattern_double_syscall.in.S b/test/arch/x86_64/pattern_double_syscall.in.S similarity index 100% rename from test/pattern_double_syscall.in.S rename to test/arch/x86_64/pattern_double_syscall.in.S diff --git a/test/pattern_double_syscall.out.S b/test/arch/x86_64/pattern_double_syscall.out.S similarity index 100% rename from test/pattern_double_syscall.out.S rename to test/arch/x86_64/pattern_double_syscall.out.S diff --git a/test/pattern_endbr64.in.S b/test/arch/x86_64/pattern_endbr64.in.S similarity index 100% rename from test/pattern_endbr64.in.S rename to test/arch/x86_64/pattern_endbr64.in.S diff --git a/test/pattern_endbr64.out.S b/test/arch/x86_64/pattern_endbr64.out.S similarity index 100% rename from test/pattern_endbr64.out.S rename to test/arch/x86_64/pattern_endbr64.out.S diff --git a/test/pattern_jmps.in.S b/test/arch/x86_64/pattern_jmps.in.S similarity index 100% rename from test/pattern_jmps.in.S rename to test/arch/x86_64/pattern_jmps.in.S diff --git a/test/pattern_jmps.out.S b/test/arch/x86_64/pattern_jmps.out.S similarity index 100% rename from test/pattern_jmps.out.S rename to test/arch/x86_64/pattern_jmps.out.S diff --git a/test/pattern_lea_rip_r12.in.S b/test/arch/x86_64/pattern_lea_rip_r12.in.S similarity index 100% rename from test/pattern_lea_rip_r12.in.S rename to test/arch/x86_64/pattern_lea_rip_r12.in.S diff --git a/test/pattern_lea_rip_r12.out.S b/test/arch/x86_64/pattern_lea_rip_r12.out.S similarity index 100% rename from test/pattern_lea_rip_r12.out.S rename to test/arch/x86_64/pattern_lea_rip_r12.out.S diff --git a/test/pattern_lea_rip_rdi.in.S b/test/arch/x86_64/pattern_lea_rip_rdi.in.S similarity index 100% rename from test/pattern_lea_rip_rdi.in.S rename to test/arch/x86_64/pattern_lea_rip_rdi.in.S diff --git a/test/pattern_lea_rip_rdi.out.S b/test/arch/x86_64/pattern_lea_rip_rdi.out.S similarity index 100% rename from test/pattern_lea_rip_rdi.out.S rename to test/arch/x86_64/pattern_lea_rip_rdi.out.S diff --git a/test/pattern_loop.in.S b/test/arch/x86_64/pattern_loop.in.S similarity index 100% rename from test/pattern_loop.in.S rename to test/arch/x86_64/pattern_loop.in.S diff --git a/test/pattern_loop.out.S b/test/arch/x86_64/pattern_loop.out.S similarity index 100% rename from test/pattern_loop.out.S rename to test/arch/x86_64/pattern_loop.out.S diff --git a/test/pattern_loop2.in.S b/test/arch/x86_64/pattern_loop2.in.S similarity index 100% rename from test/pattern_loop2.in.S rename to test/arch/x86_64/pattern_loop2.in.S diff --git a/test/pattern_loop2.out.S b/test/arch/x86_64/pattern_loop2.out.S similarity index 100% rename from test/pattern_loop2.out.S rename to test/arch/x86_64/pattern_loop2.out.S diff --git a/test/pattern_nop_padding0.in.S b/test/arch/x86_64/pattern_nop_padding0.in.S similarity index 100% rename from test/pattern_nop_padding0.in.S rename to test/arch/x86_64/pattern_nop_padding0.in.S diff --git a/test/pattern_nop_padding0.out.S b/test/arch/x86_64/pattern_nop_padding0.out.S similarity index 100% rename from test/pattern_nop_padding0.out.S rename to test/arch/x86_64/pattern_nop_padding0.out.S diff --git a/test/pattern_nop_padding1.in.S b/test/arch/x86_64/pattern_nop_padding1.in.S similarity index 100% rename from test/pattern_nop_padding1.in.S rename to test/arch/x86_64/pattern_nop_padding1.in.S diff --git a/test/pattern_nop_padding1.out.S b/test/arch/x86_64/pattern_nop_padding1.out.S similarity index 100% rename from test/pattern_nop_padding1.out.S rename to test/arch/x86_64/pattern_nop_padding1.out.S diff --git a/test/pattern_nop_padding2.in.S b/test/arch/x86_64/pattern_nop_padding2.in.S similarity index 100% rename from test/pattern_nop_padding2.in.S rename to test/arch/x86_64/pattern_nop_padding2.in.S diff --git a/test/pattern_nop_padding2.out.S b/test/arch/x86_64/pattern_nop_padding2.out.S similarity index 100% rename from test/pattern_nop_padding2.out.S rename to test/arch/x86_64/pattern_nop_padding2.out.S diff --git a/test/pattern_nop_padding3.in.S b/test/arch/x86_64/pattern_nop_padding3.in.S similarity index 100% rename from test/pattern_nop_padding3.in.S rename to test/arch/x86_64/pattern_nop_padding3.in.S diff --git a/test/pattern_nop_padding3.out.S b/test/arch/x86_64/pattern_nop_padding3.out.S similarity index 100% rename from test/pattern_nop_padding3.out.S rename to test/arch/x86_64/pattern_nop_padding3.out.S diff --git a/test/pattern_nop_padding4.in.S b/test/arch/x86_64/pattern_nop_padding4.in.S similarity index 100% rename from test/pattern_nop_padding4.in.S rename to test/arch/x86_64/pattern_nop_padding4.in.S diff --git a/test/pattern_nop_padding4.out.S b/test/arch/x86_64/pattern_nop_padding4.out.S similarity index 100% rename from test/pattern_nop_padding4.out.S rename to test/arch/x86_64/pattern_nop_padding4.out.S diff --git a/test/pattern_nop_padding5.in.S b/test/arch/x86_64/pattern_nop_padding5.in.S similarity index 100% rename from test/pattern_nop_padding5.in.S rename to test/arch/x86_64/pattern_nop_padding5.in.S diff --git a/test/pattern_nop_padding5.out.S b/test/arch/x86_64/pattern_nop_padding5.out.S similarity index 100% rename from test/pattern_nop_padding5.out.S rename to test/arch/x86_64/pattern_nop_padding5.out.S diff --git a/test/pattern_nop_padding6.in.S b/test/arch/x86_64/pattern_nop_padding6.in.S similarity index 100% rename from test/pattern_nop_padding6.in.S rename to test/arch/x86_64/pattern_nop_padding6.in.S diff --git a/test/pattern_nop_padding6.out.S b/test/arch/x86_64/pattern_nop_padding6.out.S similarity index 100% rename from test/pattern_nop_padding6.out.S rename to test/arch/x86_64/pattern_nop_padding6.out.S diff --git a/test/pattern_nop_padding7.in.S b/test/arch/x86_64/pattern_nop_padding7.in.S similarity index 100% rename from test/pattern_nop_padding7.in.S rename to test/arch/x86_64/pattern_nop_padding7.in.S diff --git a/test/pattern_nop_padding7.out.S b/test/arch/x86_64/pattern_nop_padding7.out.S similarity index 100% rename from test/pattern_nop_padding7.out.S rename to test/arch/x86_64/pattern_nop_padding7.out.S diff --git a/test/pattern_nop_padding8.in.S b/test/arch/x86_64/pattern_nop_padding8.in.S similarity index 100% rename from test/pattern_nop_padding8.in.S rename to test/arch/x86_64/pattern_nop_padding8.in.S diff --git a/test/pattern_nop_padding8.out.S b/test/arch/x86_64/pattern_nop_padding8.out.S similarity index 100% rename from test/pattern_nop_padding8.out.S rename to test/arch/x86_64/pattern_nop_padding8.out.S diff --git a/test/pattern_nop_padding9.in.S b/test/arch/x86_64/pattern_nop_padding9.in.S similarity index 100% rename from test/pattern_nop_padding9.in.S rename to test/arch/x86_64/pattern_nop_padding9.in.S diff --git a/test/pattern_nop_padding9.out.S b/test/arch/x86_64/pattern_nop_padding9.out.S similarity index 100% rename from test/pattern_nop_padding9.out.S rename to test/arch/x86_64/pattern_nop_padding9.out.S diff --git a/test/pattern_rets.in.S b/test/arch/x86_64/pattern_rets.in.S similarity index 100% rename from test/pattern_rets.in.S rename to test/arch/x86_64/pattern_rets.in.S diff --git a/test/pattern_rets.out.S b/test/arch/x86_64/pattern_rets.out.S similarity index 100% rename from test/pattern_rets.out.S rename to test/arch/x86_64/pattern_rets.out.S diff --git a/test/pattern_symbol_boundary0.in.S b/test/arch/x86_64/pattern_symbol_boundary0.in.S similarity index 100% rename from test/pattern_symbol_boundary0.in.S rename to test/arch/x86_64/pattern_symbol_boundary0.in.S diff --git a/test/pattern_symbol_boundary0.out.S b/test/arch/x86_64/pattern_symbol_boundary0.out.S similarity index 100% rename from test/pattern_symbol_boundary0.out.S rename to test/arch/x86_64/pattern_symbol_boundary0.out.S diff --git a/test/pattern_symbol_boundary1.in.S b/test/arch/x86_64/pattern_symbol_boundary1.in.S similarity index 100% rename from test/pattern_symbol_boundary1.in.S rename to test/arch/x86_64/pattern_symbol_boundary1.in.S diff --git a/test/pattern_symbol_boundary1.out.S b/test/arch/x86_64/pattern_symbol_boundary1.out.S similarity index 100% rename from test/pattern_symbol_boundary1.out.S rename to test/arch/x86_64/pattern_symbol_boundary1.out.S diff --git a/test/pattern_symbol_boundary2.in.S b/test/arch/x86_64/pattern_symbol_boundary2.in.S similarity index 100% rename from test/pattern_symbol_boundary2.in.S rename to test/arch/x86_64/pattern_symbol_boundary2.in.S diff --git a/test/pattern_symbol_boundary2.out.S b/test/arch/x86_64/pattern_symbol_boundary2.out.S similarity index 100% rename from test/pattern_symbol_boundary2.out.S rename to test/arch/x86_64/pattern_symbol_boundary2.out.S diff --git a/test/pattern_symbol_boundary3.in.S b/test/arch/x86_64/pattern_symbol_boundary3.in.S similarity index 100% rename from test/pattern_symbol_boundary3.in.S rename to test/arch/x86_64/pattern_symbol_boundary3.in.S diff --git a/test/pattern_symbol_boundary3.out.S b/test/arch/x86_64/pattern_symbol_boundary3.out.S similarity index 100% rename from test/pattern_symbol_boundary3.out.S rename to test/arch/x86_64/pattern_symbol_boundary3.out.S From 96d012b5bd08773b7c544e3229a5aadecfb6dc0b Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 15 Jul 2025 17:48:20 +0200 Subject: [PATCH 108/143] Now building tests on both x86_64 and riscv --- CMakeLists.txt | 3 +- test/CMakeLists.txt | 150 -------------------------------------------- 2 files changed, 1 insertion(+), 152 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f2cb23..09c8b8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,11 +43,10 @@ endif() option(PERFORM_STYLE_CHECKS "check coding style, license headers (requires perl)" OFF) +option(BUILD_TESTS "build and enable tests" ON) if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86(_64)?)$") - option(BUILD_TESTS "build and enable tests" ON) option(BUILD_EXAMPLES "build examples" ON) elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv(32|64))$") - option(BUILD_TESTS "build and enable tests" OFF) option(BUILD_EXAMPLES "build examples" OFF) endif() option(TREAT_WARNINGS_AS_ERRORS diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b391951..dd66c24 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -41,87 +41,6 @@ include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/test) if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86(_64)?)$") add_subdirectory(arch/x86_64) -# set(CMAKE_ASM_CREATE_SHARED_LIBRARY ${CMAKE_C_CREATE_SHARED_LIBRARY}) -# -# add_executable(asm_pattern asm_pattern.c -# $ -# $) -# target_link_libraries(asm_pattern PUBLIC ${CAPSTONE_LIB_FOLDER}/libcapstone.so) -# -# target_link_libraries(asm_pattern -# PRIVATE ${CMAKE_DL_LIBS} ${capstone_LDFLAGS}) -# -# set(asm_patterns -# nosyscall -# pattern1 -# pattern2 -# pattern3 -# pattern4 -# pattern_loop -# pattern_loop2 -# pattern_symbol_boundary0 -# pattern_symbol_boundary1 -# pattern_symbol_boundary2 -# pattern_symbol_boundary3 -# pattern_nop_padding0 -# pattern_nop_padding1 -# pattern_nop_padding2 -# pattern_nop_padding3 -# pattern_nop_padding4 -# pattern_nop_padding5 -# pattern_nop_padding6 -# pattern_nop_padding7 -# pattern_nop_padding8 -# pattern_nop_padding9 -# pattern_lea_rip_rdi -# pattern_lea_rip_r12) -# -# try_compile(ASSEMBLER_SUPPORTS_ENDBR64 ${CMAKE_BINARY_DIR} -# ${CMAKE_CURRENT_SOURCE_DIR}/pattern_endbr64.in.S -# CMAKE_FLAGS "-DCMAKE_ASM_LINK_EXECUTABLE='echo skip linking'") -# if(ASSEMBLER_SUPPORTS_ENDBR64) -# list(APPEND asm_patterns pattern_endbr64) -# endif() -# -# set(asm_patterns_failing -# pattern_double_syscall -# pattern_rets -# pattern_jmps) -# -# macro(add_asm_test test_name failing) -# add_library(${test_name}.in SHARED ${test_name}.in.S) -# add_library(${test_name}.out SHARED ${test_name}.out.S) -# if(LINKER_HAS_NOSTDLIB) -# set_target_properties(${test_name}.in -# PROPERTIES LINK_FLAGS "-nostdlib") -# set_target_properties(${test_name}.out -# PROPERTIES LINK_FLAGS "-nostdlib") -# endif() -# if(HAS_NOUNUSEDARG) -# target_compile_options(${test_name}.in BEFORE -# PRIVATE "-Wno-unused-command-line-argument") -# target_compile_options(${test_name}.out BEFORE -# PRIVATE "-Wno-unused-command-line-argument") -# -# endif() -# add_test(NAME "asm_pattern_${test_name}" -# COMMAND $ -# $ -# $) -# if(${failing}) -# set_tests_properties("asm_pattern_${test_name}" -# PROPERTIES WILL_FAIL ON -# PASS_REGULAR_EXPRESSION "Invalid patch") -# endif() -# endmacro() -# -# foreach(name ${asm_patterns}) -# add_asm_test(${name} FALSE) -# endforeach() -# -# foreach(name ${asm_patterns_failing}) -# add_asm_test(${name} TRUE) -# endforeach() endif() set(CHECK_LOG_COMMON_ARGS @@ -254,75 +173,6 @@ set_tests_properties("clone_thread" add_library(intercept_sys_write SHARED intercept_sys_write.c) target_link_libraries(intercept_sys_write PRIVATE syscall_intercept_shared) -#add_executable(executable_with_syscall_pie executable_with_syscall.S) -#if(HAS_NOUNUSEDARG) -# target_compile_options(executable_with_syscall_pie BEFORE -# PRIVATE "-Wno-unused-command-line-argument") -#endif() -#set_target_properties(executable_with_syscall_pie -# PROPERTIES POSITION_INDEPENDENT_CODE True) -#if(HAS_ARG_PIE) -# target_compile_options(executable_with_syscall_pie PRIVATE "-pie") -# target_link_libraries(executable_with_syscall_pie PRIVATE "-pie") -#endif() -# -#add_executable(executable_with_syscall_no_pie executable_with_syscall.S) -#if(HAS_NOUNUSEDARG) -# target_compile_options(executable_with_syscall_no_pie BEFORE -# PRIVATE "-Wno-unused-command-line-argument") -#endif() -#set_target_properties(executable_with_syscall_no_pie -# PROPERTIES POSITION_INDEPENDENT_CODE False) -#if(HAS_ARG_NOPIE) -# target_compile_options(executable_with_syscall_no_pie PRIVATE "-nopie") -# target_link_libraries(executable_with_syscall_no_pie PRIVATE "-nopie") -#elseif(HAS_ARG_NO_PIE) -# target_compile_options(executable_with_syscall_no_pie PRIVATE "-no-pie") -# target_link_libraries(executable_with_syscall_no_pie PRIVATE "-no-pie") -#endif() -# -#add_test(NAME "prog_pie_intercept_libc_only" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DTEST_PROG=$ -# -DLIB_FILE=$ -# -DTEST_PROG_ARGS=original_syscall -# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -#set_tests_properties("prog_pie_intercept_libc_only" -# PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") -# -#add_test(NAME "prog_no_pie_intercept_libc_only" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DTEST_PROG=$ -# -DLIB_FILE=$ -# -DTEST_PROG_ARGS=original_syscall -# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -#set_tests_properties("prog_no_pie_intercept_libc_only" -# PROPERTIES PASS_REGULAR_EXPRESSION "original_syscall") -# -#add_test(NAME "prog_pie_intercept_all" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DINTERCEPT_ALL=1 -# -DTEST_PROG=$ -# -DLIB_FILE=$ -# -DTEST_PROG_ARGS=original_syscall -# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -#set_tests_properties("prog_pie_intercept_all" -# PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") -# -#add_test(NAME "prog_no_pie_intercept_all" -# COMMAND ${CMAKE_COMMAND} -# -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -# -DINTERCEPT_ALL=1 -# -DTEST_PROG=$ -# -DLIB_FILE=$ -# -DTEST_PROG_ARGS=original_syscall -# -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) -#set_tests_properties("prog_no_pie_intercept_all" -# PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") - add_executable(vfork_logging vfork_logging.c) add_test(NAME "vfork_logging" COMMAND ${CMAKE_COMMAND} From 3dd50f0b2d252fc13eb66688e41f23faa4e117dc Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 15 Jul 2025 18:05:02 +0200 Subject: [PATCH 109/143] optional inclusion of arch_prctl --- test/syscall_format.c | 8 ++++++-- test/syscall_format.log.match | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/test/syscall_format.c b/test/syscall_format.c index cb5040b..2145b7f 100644 --- a/test/syscall_format.c +++ b/test/syscall_format.c @@ -60,7 +60,6 @@ #undef _FORTIFY_SOURCE #endif -#include #include #include #include @@ -117,6 +116,10 @@ #include #include +#ifdef SYS_arch_prctl + #include +#endif + #include "libsyscall_intercept_hook_point.h" #include "magic_syscalls.h" @@ -619,8 +622,9 @@ main(int argc, char **argv) syscall(SYS__sysctl, p0); prctl(PR_CAPBSET_DROP, 1, 2, 3, 4); +#ifdef SYS_arch_prctl syscall(SYS_arch_prctl, ARCH_SET_FS, p0); - +#endif adjtimex(p0); chroot(input[0]); diff --git a/test/syscall_format.log.match b/test/syscall_format.log.match index 709c7fd..65c1063 100644 --- a/test/syscall_format.log.match +++ b/test/syscall_format.log.match @@ -540,8 +540,8 @@ $(S) $(XX) -- _sysctl(0x123000) = ? $(S) $(XX) -- _sysctl(0x123000) = 22 $(S) $(XX) -- prctl(0x18, 0x1, 0x2, 0x3, 0x4) = ? $(S) $(XX) -- prctl(0x18, 0x1, 0x2, 0x3, 0x4) = 22 -$(S) $(XX) -- arch_prctl(0x1002, 0x123000, $(XX)) = ? -$(S) $(XX) -- arch_prctl(0x1002, 0x123000, $(XX)) = 22 +$(OPT)$(S) $(XX) -- arch_prctl(0x1002, 0x123000, $(XX)) = ? +$(OPT)$(S) $(XX) -- arch_prctl(0x1002, 0x123000, $(XX)) = 22 $(S) $(XX) -- clock_adjtime(0x0, 0x123000) = ? $(S) $(XX) -- clock_adjtime(0x0, 0x123000) = 22 $(S) $(XX) -- chroot("input_data\x01\x02\x03\n\r\t") = ? From dbe5686a4fbd6b48af7a0d90effb0247e6681b48 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 15 Jul 2025 18:10:38 +0200 Subject: [PATCH 110/143] optional inclusion of sys/io.h --- test/syscall_format.c | 9 +++++++-- test/syscall_format.log.match | 8 ++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/test/syscall_format.c b/test/syscall_format.c index 2145b7f..18c0a76 100644 --- a/test/syscall_format.c +++ b/test/syscall_format.c @@ -83,7 +83,6 @@ #include #include #include -#include #include #include #include @@ -119,6 +118,9 @@ #ifdef SYS_arch_prctl #include #endif +#ifdef SYS_iopl || SYS_ioperm + #include +#endif #include "libsyscall_intercept_hook_point.h" #include "magic_syscalls.h" @@ -642,9 +644,12 @@ main(int argc, char **argv) sethostname(input[0], len0); setdomainname(input[0], len0); - +#ifdef SYS_iopl iopl(1); +#endif +#ifdef SYS_ioperm ioperm(3, 4, 1); +#endif syscall(SYS_init_module, p0, 16, p1); syscall(SYS_finit_module, 3, p0, 0); diff --git a/test/syscall_format.log.match b/test/syscall_format.log.match index 65c1063..a92d684 100644 --- a/test/syscall_format.log.match +++ b/test/syscall_format.log.match @@ -566,10 +566,10 @@ $(S) $(XX) -- sethostname($(XX), 0x10) = ? $(S) $(XX) -- sethostname($(XX), 0x10) = 22 $(S) $(XX) -- setdomainname($(XX), 0x10) = ? $(S) $(XX) -- setdomainname($(XX), 0x10) = 22 -$(S) $(XX) -- iopl(0x1) = ? -$(S) $(XX) -- iopl(0x1) = 22 -$(S) $(XX) -- ioperm(0x3, 0x4, 0x1) = ? -$(S) $(XX) -- ioperm(0x3, 0x4, 0x1) = 22 +$(OPT)$(S) $(XX) -- iopl(0x1) = ? +$(OPT)$(S) $(XX) -- iopl(0x1) = 22 +$(OPT)$(S) $(XX) -- ioperm(0x3, 0x4, 0x1) = ? +$(OPT)$(S) $(XX) -- ioperm(0x3, 0x4, 0x1) = 22 $(S) $(XX) -- syscall(175, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? $(S) $(XX) -- syscall(175, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 $(S) $(XX) -- finit_module(3, 0x123000, 0x0) = ? From 97506866c381e56ee0950da624563d07a230f10a Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 15 Jul 2025 18:32:38 +0200 Subject: [PATCH 111/143] optional inclusion of system calls not defined on RISCV --- test/syscall_format.c | 30 ++++++++++++- test/syscall_format.log.match | 84 +++++++++++++++++------------------ 2 files changed, 71 insertions(+), 43 deletions(-) diff --git a/test/syscall_format.c b/test/syscall_format.c index 18c0a76..7a4112d 100644 --- a/test/syscall_format.c +++ b/test/syscall_format.c @@ -118,7 +118,7 @@ #ifdef SYS_arch_prctl #include #endif -#ifdef SYS_iopl || SYS_ioperm +#if defined(SYS_iopl) || defined(SYS_ioperm) #include #endif @@ -287,6 +287,7 @@ main(int argc, char **argv) pwritev(1, NULL, 4, 0x1000); /* open, close */ +#ifdef SYS_open syscall(SYS_open, input[0], O_CREAT | O_RDWR | O_SYNC, 0321); syscall(SYS_open, input[0], 0, 0321); syscall(SYS_open, NULL, all_o_flags, 0777); @@ -294,6 +295,7 @@ main(int argc, char **argv) syscall(SYS_open, input[1], O_RDWR | O_NONBLOCK, 0111); syscall(SYS_open, input[1], 0); syscall(SYS_open, NULL, 0); +#endif openat(AT_FDCWD, input[0], O_CREAT | O_RDWR | O_SYNC, 0321); openat(AT_FDCWD, input[0], 0, 0321); openat(AT_FDCWD, NULL, all_o_flags, 0777); @@ -479,7 +481,9 @@ main(int argc, char **argv) truncate(input[0], 4); ftruncate(3, 3); +#ifdef SYS_getdents syscall(SYS_getdents, 4, p0, 1); +#endif syscall(SYS_getdents64, 4, p0, 1); setup_buffers(); @@ -493,15 +497,21 @@ main(int argc, char **argv) renameat(AT_FDCWD, input[0], 7, input[1]); renameat(9, input[0], AT_FDCWD, input[1]); +#ifdef SYS_mkdir syscall(SYS_mkdir, input[0], 0644); +#endif syscall(SYS_mkdirat, AT_FDCWD, input[0], 0644); mkdirat(33, input[0], 0644); mkdirat(33, NULL, 0555); +#ifdef SYS_rmdir syscall(SYS_rmdir, input[0]); syscall(SYS_rmdir, NULL); +#endif /* libc implementations might translate creat to open with O_CREAT */ +#ifdef SYS_creat syscall(SYS_creat, input[0], 0644); +#endif link(input[0], input[1]); linkat(1, input[0], 2, input[1], 0); @@ -597,7 +607,9 @@ main(int argc, char **argv) mknodat(1, input[0], 1, 2); mknodat(AT_FDCWD, input[0], 1, 2); +#ifdef SYS_ustat syscall(SYS_ustat, 2, p0); +#endif statfs(input[0], p0); fstatfs(4, p0); @@ -616,12 +628,16 @@ main(int argc, char **argv) vhangup(); +#ifdef SYS_modify_ldt syscall(SYS_modify_ldt, 1, p0, 1); +#endif setup_buffers(); syscall(SYS_pivot_root, input[0], buffer[0]); +#ifdef SYS__sysctl syscall(SYS__sysctl, p0); +#endif prctl(PR_CAPBSET_DROP, 1, 2, 3, 4); #ifdef SYS_arch_prctl @@ -682,12 +698,18 @@ main(int argc, char **argv) syscall(SYS_tkill, 44, SIGSTOP); syscall(SYS_tgkill, 44, 55, SIGSTOP); +#ifdef SYS_time syscall(SYS_time, p0); +#endif syscall(SYS_futex, p0, FUTEX_WAKE, 7L, p0, p1, 1L); +#ifdef SYS_set_thread_area syscall(SYS_set_thread_area, p0); +#endif +#ifdef SYS_get_thread_area syscall(SYS_get_thread_area, p0); +#endif syscall(SYS_io_setup, 1, p0); syscall(SYS_io_destroy, 77); @@ -700,7 +722,9 @@ main(int argc, char **argv) epoll_create(7); epoll_create1(0); epoll_create1(EPOLL_CLOEXEC); +#ifdef SYS_epoll_wait syscall(SYS_epoll_wait, 2L, p0, 4L, 5L); +#endif syscall(SYS_epoll_pwait, 2L, p0, 4L, 5L, p1, 6L); epoll_ctl(2L, 3L, 4L, p0); @@ -769,14 +793,18 @@ main(int argc, char **argv) sync_file_range(2, 3, 4, 0); sync_file_range(2, 3, 4, SYNC_FILE_RANGE_WAIT_BEFORE); +#ifdef SYS_signalfd syscall(SYS_signalfd, 1, p0, 12); +#endif syscall(SYS_signalfd4, 1, p0, 13, SFD_NONBLOCK); timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC); timerfd_settime(1, TFD_TIMER_ABSTIME, p0, p1); timerfd_gettime(2, p0); +#ifdef SYS_eventfd syscall(SYS_eventfd, 45); +#endif syscall(SYS_eventfd2, 47, EFD_SEMAPHORE); fallocate(1, FALLOC_FL_PUNCH_HOLE, 3, 4); diff --git a/test/syscall_format.log.match b/test/syscall_format.log.match index a92d684..21238b8 100644 --- a/test/syscall_format.log.match +++ b/test/syscall_format.log.match @@ -32,20 +32,20 @@ $(S) $(XX) -- pwritev(1, 0x123000, 0x4, 0x1000) = ? $(S) $(XX) -- pwritev(1, 0x123000, 0x4, 0x1000) = 22 $(S) $(XX) -- pwritev(1, 0x0, 0x4, 0x1000) = ? $(S) $(XX) -- pwritev(1, 0x0, 0x4, 0x1000) = 22 -$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = ? -$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = 22 -$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? -$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDONLY) = 22 -$(S) $(XX) -- open((null), O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = ? -$(S) $(XX) -- open((null), O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = 22 -$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = ? -$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = 22 -$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_NONBLOCK) = ? -$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_NONBLOCK) = 22 -$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? -$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDONLY) = 22 -$(S) $(XX) -- open((null), O_RDONLY) = ? -$(S) $(XX) -- open((null), O_RDONLY) = 22 +$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = ? +$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = 22 +$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? +$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDONLY) = 22 +$(OPT)$(S) $(XX) -- open((null), O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = ? +$(OPT)$(S) $(XX) -- open((null), O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = 22 +$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = ? +$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = 22 +$(OPT)$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_NONBLOCK) = ? +$(OPT)$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_NONBLOCK) = 22 +$(OPT)$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? +$(OPT)$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDONLY) = 22 +$(OPT)$(S) $(XX) -- open((null), O_RDONLY) = ? +$(OPT)$(S) $(XX) -- open((null), O_RDONLY) = 22 $(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = ? $(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = 22 $(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? @@ -318,8 +318,8 @@ $(S) $(XX) -- truncate("input_data\x01\x02\x03\n\r\t", 0x4) = ? $(S) $(XX) -- truncate("input_data\x01\x02\x03\n\r\t", 0x4) = 22 $(S) $(XX) -- ftruncate(3, 0x3) = ? $(S) $(XX) -- ftruncate(3, 0x3) = 22 -$(S) $(XX) -- getdents(4, 0x123000, 0x1) = ? -$(S) $(XX) -- getdents(4, 0x123000, 0x1) = 22 +$(OPT)$(S) $(XX) -- getdents(4, 0x123000, 0x1) = ? +$(OPT)$(S) $(XX) -- getdents(4, 0x123000, 0x1) = 22 $(S) $(XX) -- getdents64(4, 0x123000, 0x1) = ? $(S) $(XX) -- getdents64(4, 0x123000, 0x1) = 22 $(S) $(XX) -- getcwd($(XX), 0x9) = ? @@ -336,20 +336,20 @@ $(S) $(XX) -- renameat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input $(S) $(XX) -- renameat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t") = 22 $(S) $(XX) -- renameat(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = ? $(S) $(XX) -- renameat(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = 22 -$(S) $(XX) -- mkdir("input_data\x01\x02\x03\n\r\t", 0644) = ? -$(S) $(XX) -- mkdir("input_data\x01\x02\x03\n\r\t", 0644) = 22 +$(OPT)$(S) $(XX) -- mkdir("input_data\x01\x02\x03\n\r\t", 0644) = ? +$(OPT)$(S) $(XX) -- mkdir("input_data\x01\x02\x03\n\r\t", 0644) = 22 $(S) $(XX) -- mkdirat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0644) = ? $(S) $(XX) -- mkdirat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0644) = 22 $(S) $(XX) -- mkdirat(33, "input_data\x01\x02\x03\n\r\t", 0644) = ? $(S) $(XX) -- mkdirat(33, "input_data\x01\x02\x03\n\r\t", 0644) = 22 $(S) $(XX) -- mkdirat(33, (null), 0555) = ? $(S) $(XX) -- mkdirat(33, (null), 0555) = 22 -$(S) $(XX) -- rmdir("input_data\x01\x02\x03\n\r\t") = ? -$(S) $(XX) -- rmdir("input_data\x01\x02\x03\n\r\t") = 22 -$(S) $(XX) -- rmdir((null)) = ? -$(S) $(XX) -- rmdir((null)) = 22 -$(S) $(XX) -- creat("input_data\x01\x02\x03\n\r\t", 0644) = ? -$(S) $(XX) -- creat("input_data\x01\x02\x03\n\r\t", 0644) = 22 +$(OPT)$(S) $(XX) -- rmdir("input_data\x01\x02\x03\n\r\t") = ? +$(OPT)$(S) $(XX) -- rmdir("input_data\x01\x02\x03\n\r\t") = 22 +$(OPT)$(S) $(XX) -- rmdir((null)) = ? +$(OPT)$(S) $(XX) -- rmdir((null)) = 22 +$(OPT)$(S) $(XX) -- creat("input_data\x01\x02\x03\n\r\t", 0644) = ? +$(OPT)$(S) $(XX) -- creat("input_data\x01\x02\x03\n\r\t", 0644) = 22 $(S) $(XX) -- link("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = ? $(S) $(XX) -- link("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = 22 $(S) $(XX) -- linkat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? @@ -502,8 +502,8 @@ $(S) $(XX) -- mknodat(1, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = ? $(S) $(XX) -- mknodat(1, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = 22 $(S) $(XX) -- mknodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = ? $(S) $(XX) -- mknodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = 22 -$(S) $(XX) -- ustat(0x2, 0x123000) = ? -$(S) $(XX) -- ustat(0x2, 0x123000) = 22 +$(OPT)$(S) $(XX) -- ustat(0x2, 0x123000) = ? +$(OPT)$(S) $(XX) -- ustat(0x2, 0x123000) = 22 $(S) $(XX) -- statfs("input_data\x01\x02\x03\n\r\t", 0x123000) = ? $(S) $(XX) -- statfs("input_data\x01\x02\x03\n\r\t", 0x123000) = 22 $(S) $(XX) -- fstatfs(4, 0x123000) = ? @@ -532,12 +532,12 @@ $(S) $(XX) -- sched_getaffinity(0x4d, 0x4, 0x123000) = ? $(S) $(XX) -- sched_getaffinity(0x4d, 0x4, 0x123000) = 22 $(S) $(XX) -- vhangup() = ? $(S) $(XX) -- vhangup() = 22 -$(S) $(XX) -- modify_ldt(0x1, 0x123000, 0x1) = ? -$(S) $(XX) -- modify_ldt(0x1, 0x123000, 0x1) = 22 +$(OPT)$(S) $(XX) -- modify_ldt(0x1, 0x123000, 0x1) = ? +$(OPT)$(S) $(XX) -- modify_ldt(0x1, 0x123000, 0x1) = 22 $(S) $(XX) -- pivot_root("input_data\x01\x02\x03\n\r\t", $(XX)) = ? $(S) $(XX) -- pivot_root("input_data\x01\x02\x03\n\r\t", $(XX)) = 22 -$(S) $(XX) -- _sysctl(0x123000) = ? -$(S) $(XX) -- _sysctl(0x123000) = 22 +$(OPT)$(S) $(XX) -- _sysctl(0x123000) = ? +$(OPT)$(S) $(XX) -- _sysctl(0x123000) = 22 $(S) $(XX) -- prctl(0x18, 0x1, 0x2, 0x3, 0x4) = ? $(S) $(XX) -- prctl(0x18, 0x1, 0x2, 0x3, 0x4) = 22 $(OPT)$(S) $(XX) -- arch_prctl(0x1002, 0x123000, $(XX)) = ? @@ -620,14 +620,14 @@ $(S) $(XX) -- tkill(0x2c, 0x13) = ? $(S) $(XX) -- tkill(0x2c, 0x13) = 22 $(S) $(XX) -- tgkill(0x2c, 0x37, 0x13) = ? $(S) $(XX) -- tgkill(0x2c, 0x37, 0x13) = 22 -$(S) $(XX) -- time(0x123000) = ? -$(S) $(XX) -- time(0x123000) = 22 +$(OPT)$(S) $(XX) -- time(0x123000) = ? +$(OPT)$(S) $(XX) -- time(0x123000) = 22 $(S) $(XX) -- futex(0x123000, 0x1, 0x7, 0x123000, 0x234000, 0x1) = ? $(S) $(XX) -- futex(0x123000, 0x1, 0x7, 0x123000, 0x234000, 0x1) = 22 -$(S) $(XX) -- set_thread_area(0x123000) = ? -$(S) $(XX) -- set_thread_area(0x123000) = 22 -$(S) $(XX) -- get_thread_area(0x123000) = ? -$(S) $(XX) -- get_thread_area(0x123000) = 22 +$(OPT)$(S) $(XX) -- set_thread_area(0x123000) = ? +$(OPT)$(S) $(XX) -- set_thread_area(0x123000) = 22 +$(OPT)$(S) $(XX) -- get_thread_area(0x123000) = ? +$(OPT)$(S) $(XX) -- get_thread_area(0x123000) = 22 $(S) $(XX) -- io_setup(0x1, 0x123000) = ? $(S) $(XX) -- io_setup(0x1, 0x123000) = 22 $(S) $(XX) -- io_destroy(0x4d) = ? @@ -646,8 +646,8 @@ $(S) $(XX) -- epoll_create1(0x0) = ? $(S) $(XX) -- epoll_create1(0x0) = 22 $(S) $(XX) -- epoll_create1(0x80000) = ? $(S) $(XX) -- epoll_create1(0x80000) = 22 -$(S) $(XX) -- epoll_wait(2, 0x123000, 0x4, 0x5) = ? -$(S) $(XX) -- epoll_wait(2, 0x123000, 0x4, 0x5) = 22 +$(OPT)$(S) $(XX) -- epoll_wait(2, 0x123000, 0x4, 0x5) = ? +$(OPT)$(S) $(XX) -- epoll_wait(2, 0x123000, 0x4, 0x5) = 22 $(S) $(XX) -- epoll_pwait(2, 0x123000, 0x4, 0x5, 0x234000, 0x6) = ? $(S) $(XX) -- epoll_pwait(2, 0x123000, 0x4, 0x5, 0x234000, 0x6) = 22 $(S) $(XX) -- epoll_ctl(2, 0x3, 4, 0x123000) = ? @@ -744,8 +744,8 @@ $(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x0) = ? $(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x0) = 22 $(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x1) = ? $(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x1) = 22 -$(S) $(XX) -- signalfd(1, 0x123000, 0xc) = ? -$(S) $(XX) -- signalfd(1, 0x123000, 0xc) = 22 +$(OPT)$(S) $(XX) -- signalfd(1, 0x123000, 0xc) = ? +$(OPT)$(S) $(XX) -- signalfd(1, 0x123000, 0xc) = 22 $(S) $(XX) -- signalfd4(1, 0x123000, 0xd, 0x800, $(XX)) = ? $(S) $(XX) -- signalfd4(1, 0x123000, 0xd, 0x800, $(XX)) = 22 $(S) $(XX) -- timerfd_create(0x0, 0x80000) = ? @@ -754,8 +754,8 @@ $(S) $(XX) -- timerfd_settime(1, 0x1, 0x123000, 0x234000) = ? $(S) $(XX) -- timerfd_settime(1, 0x1, 0x123000, 0x234000) = 22 $(S) $(XX) -- timerfd_gettime(2, 0x123000) = ? $(S) $(XX) -- timerfd_gettime(2, 0x123000) = 22 -$(S) $(XX) -- eventfd(0x2d) = ? -$(S) $(XX) -- eventfd(0x2d) = 22 +$(OPT)$(S) $(XX) -- eventfd(0x2d) = ? +$(OPT)$(S) $(XX) -- eventfd(0x2d) = 22 $(S) $(XX) -- eventfd2(0x2f, 0x1) = ? $(S) $(XX) -- eventfd2(0x2f, 0x1) = 22 $(S) $(XX) -- fallocate(1, 0x2, 0x3, 0x4) = ? From 4f99e4fc89762a77a415000f3d0200e417235479 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 15 Jul 2025 20:04:43 +0200 Subject: [PATCH 112/143] moved vfork test to x86_64 tests directory --- test/CMakeLists.txt | 13 --- test/arch/x86_64/CMakeLists.txt | 19 +++- test/arch/x86_64/check_log.cmake | 93 +++++++++++++++++++ .../x86_64}/libcintercept2.log.match | 0 test/{ => arch/x86_64}/vfork_logging.c | 0 5 files changed, 111 insertions(+), 14 deletions(-) create mode 100644 test/arch/x86_64/check_log.cmake rename test/{ => arch/x86_64}/libcintercept2.log.match (100%) rename test/{ => arch/x86_64}/vfork_logging.c (100%) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index dd66c24..0a8108b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -173,19 +173,6 @@ set_tests_properties("clone_thread" add_library(intercept_sys_write SHARED intercept_sys_write.c) target_link_libraries(intercept_sys_write PRIVATE syscall_intercept_shared) -add_executable(vfork_logging vfork_logging.c) -add_test(NAME "vfork_logging" - COMMAND ${CMAKE_COMMAND} - -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} - -DTEST_PROG=$ - -DLIB_FILE=$ - -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept2.log.match - -DTEST_NAME=vfork_logging - ${CHECK_LOG_COMMON_ARGS}) -set_tests_properties("vfork_logging" - PROPERTIES PASS_REGULAR_EXPRESSION "in_child_created_using_vfork") - - add_executable(syscall_format syscall_format.c) target_link_libraries(syscall_format PRIVATE syscall_intercept_shared) add_test(NAME "syscall_format_logging" diff --git a/test/arch/x86_64/CMakeLists.txt b/test/arch/x86_64/CMakeLists.txt index d6bdd2a..3eb8b8e 100644 --- a/test/arch/x86_64/CMakeLists.txt +++ b/test/arch/x86_64/CMakeLists.txt @@ -32,6 +32,11 @@ # See: https://cmake.org/Wiki/CMake/Testing_With_CTest +set(CHECK_LOG_COMMON_ARGS_VFORK + -DMATCH_SCRIPT=${PROJECT_SOURCE_DIR}/utils/match.pl + -DEXPECT_SPURIOUS_SYSCALLS=${EXPECT_SPURIOUS_SYSCALLS} + -P ${CMAKE_CURRENT_SOURCE_DIR}/check_log.cmake) + set(CMAKE_ASM_CREATE_SHARED_LIBRARY ${CMAKE_C_CREATE_SHARED_LIBRARY}) add_executable(asm_pattern asm_pattern.c @@ -181,4 +186,16 @@ add_test(NAME "prog_no_pie_intercept_all" -DTEST_PROG_ARGS=original_syscall -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) set_tests_properties("prog_no_pie_intercept_all" - PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") \ No newline at end of file + PROPERTIES PASS_REGULAR_EXPRESSION "intercepted_call") + +add_executable(vfork_logging vfork_logging.c) +add_test(NAME "vfork_logging" + COMMAND ${CMAKE_COMMAND} + -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} + -DTEST_PROG=$ + -DLIB_FILE=$ + -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/libcintercept2.log.match + -DTEST_NAME=vfork_logging + ${CHECK_LOG_COMMON_ARGS_VFORK}) +set_tests_properties("vfork_logging" + PROPERTIES PASS_REGULAR_EXPRESSION "in_child_created_using_vfork") \ No newline at end of file diff --git a/test/arch/x86_64/check_log.cmake b/test/arch/x86_64/check_log.cmake new file mode 100644 index 0000000..56c89ab --- /dev/null +++ b/test/arch/x86_64/check_log.cmake @@ -0,0 +1,93 @@ +# +# Copyright 2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +# XXX ask for a unique tempfile from cmake for LOG_OUTPUT +set(LOG_OUTPUT .log.${TEST_NAME}) + +execute_process(COMMAND ${CMAKE_COMMAND} -E remove -f ${LOG_OUTPUT}) + +set(ENV{INTERCEPT_ALL_OBJS} 1) + +if(HAS_SECOND_LOG) + set(SECOND_LOG_OUTPUT .log.2.${TEST_NAME}) + execute_process(COMMAND ${CMAKE_COMMAND} -E remove -f ${SECOND_LOG_OUTPUT}) +endif() + +if(HAS_SECOND_LOG) + message("Executing: LD_PRELOAD=${LIB_FILE} + INTERCEPT_ALL_OBJS=1 + ${TEST_PROG} ${TEST_PROG_ARG} ${LOG_OUTPUT} ${SECOND_LOG_OUTPUT}") + if(TEST_EXTRA_PRELOAD) + set(ENV{LD_PRELOAD} ${TEST_EXTRA_PRELOAD}:${LIB_FILE}) + else() + set(ENV{LD_PRELOAD} ${LIB_FILE}) + endif() + execute_process(COMMAND ${TEST_PROG} + ${TEST_PROG_ARG} ${LOG_OUTPUT} ${SECOND_LOG_OUTPUT} + RESULT_VARIABLE HAD_ERROR) + unset(ENV{LD_PRELOAD}) +else() + message("Executing: LD_PRELOAD=${LIB_FILE} + INTERCEPT_ALL_OBJS=1 + ${TEST_PROG} ${TEST_PROG_ARG} ${LOG_OUTPUT}") + if(TEST_EXTRA_PRELOAD) + set(ENV{LD_PRELOAD} ${TEST_EXTRA_PRELOAD}:${LIB_FILE}) + else() + set(ENV{LD_PRELOAD} ${LIB_FILE}) + endif() + execute_process(COMMAND ${TEST_PROG} ${TEST_PROG_ARG} ${LOG_OUTPUT} + RESULT_VARIABLE HAD_ERROR) + unset(ENV{LD_PRELOAD}) +endif() + +if(HAD_ERROR) + message(FATAL_ERROR "Test failed: ${HAD_ERROR}") +endif() + +if(NOT EXPECT_SPURIOUS_SYSCALLS) + execute_process(COMMAND + ${MATCH_SCRIPT} -o ${LOG_OUTPUT} ${MATCH_FILE} + RESULT_VARIABLE MATCH_ERROR) + + if(MATCH_ERROR) + message(FATAL_ERROR "Log does not match! ${MATCH_ERROR}") + endif() + + if(HAS_SECOND_LOG) + execute_process(COMMAND + ${MATCH_SCRIPT} -o ${SECOND_LOG_OUTPUT} ${SECOND_MATCH_FILE} + RESULT_VARIABLE MATCH_ERROR) + if(MATCH_ERROR) + message(FATAL_ERROR "Second log does not match! ${MATCH_ERROR}") + endif() + endif() +endif() diff --git a/test/libcintercept2.log.match b/test/arch/x86_64/libcintercept2.log.match similarity index 100% rename from test/libcintercept2.log.match rename to test/arch/x86_64/libcintercept2.log.match diff --git a/test/vfork_logging.c b/test/arch/x86_64/vfork_logging.c similarity index 100% rename from test/vfork_logging.c rename to test/arch/x86_64/vfork_logging.c From 63d7d6707c55a922ed798adb740cf43ad4e2a458 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 15 Jul 2025 22:39:36 +0200 Subject: [PATCH 113/143] Test suite is built with cmake on both x86_64 and RISC-V --- .github/workflows/main.yml | 2 +- .gitignore | 5 +- README.md | 10 +- riscv_test/Makefile | 69 -------------- riscv_test/src/clone_test.c | 84 ---------------- riscv_test/src/fork_test.c | 76 --------------- riscv_test/src/intercept_sys_clone.c | 69 -------------- riscv_test/src/intercept_sys_fork.c | 69 -------------- riscv_test/src/intercept_sys_mkdirat.c | 64 ------------- riscv_test/src/intercept_sys_statx.c | 61 ------------ riscv_test/src/intercept_sys_write.c | 83 ---------------- riscv_test/src/statx_test.c | 56 ----------- test/CMakeLists.txt | 28 +++++- test/Makefile | 95 +++++++++++++++++++ {riscv_test => test}/README.md | 0 test/{riscv/src => }/clone_test.c | 4 +- {riscv_test/src => test}/fcntl_test.c | 0 test/{riscv/src => }/intercept_sys_clone.c | 8 ++ .../src => test}/intercept_sys_fcntl.c | 2 + test/{riscv/src => }/intercept_sys_mkdirat.c | 2 + .../src => test}/intercept_sys_openat.c | 1 + {riscv_test/src => test}/intercept_sys_read.c | 11 ++- test/{riscv/src => }/intercept_sys_statx.c | 2 + {riscv_test/src => test}/mkdirat_test.c | 0 {riscv_test/src => test}/openat_test.c | 0 {riscv_test/src => test}/read_test.c | 0 test/riscv/Makefile | 65 ------------- test/riscv/README.md | 35 ------- test/riscv/src/fcntl_test.c | 49 ---------- test/riscv/src/intercept_sys_fcntl.c | 58 ----------- test/riscv/src/intercept_sys_openat.c | 69 -------------- test/riscv/src/intercept_sys_read.c | 64 ------------- test/riscv/src/intercept_sys_write.c | 83 ---------------- test/riscv/src/mkdirat_test.c | 56 ----------- test/riscv/src/openat_test.c | 55 ----------- test/riscv/src/read_test.c | 46 --------- test/riscv/src/write_test.c | 62 ------------ test/{riscv/src => }/statx_test.c | 8 +- {riscv_test/src => test}/write_test.c | 0 39 files changed, 154 insertions(+), 1297 deletions(-) delete mode 100644 riscv_test/Makefile delete mode 100644 riscv_test/src/clone_test.c delete mode 100644 riscv_test/src/fork_test.c delete mode 100644 riscv_test/src/intercept_sys_clone.c delete mode 100644 riscv_test/src/intercept_sys_fork.c delete mode 100644 riscv_test/src/intercept_sys_mkdirat.c delete mode 100644 riscv_test/src/intercept_sys_statx.c delete mode 100644 riscv_test/src/intercept_sys_write.c delete mode 100644 riscv_test/src/statx_test.c create mode 100644 test/Makefile rename {riscv_test => test}/README.md (100%) rename test/{riscv/src => }/clone_test.c (98%) rename {riscv_test/src => test}/fcntl_test.c (100%) rename test/{riscv/src => }/intercept_sys_clone.c (94%) rename {riscv_test/src => test}/intercept_sys_fcntl.c (99%) rename test/{riscv/src => }/intercept_sys_mkdirat.c (99%) rename {riscv_test/src => test}/intercept_sys_openat.c (99%) rename {riscv_test/src => test}/intercept_sys_read.c (94%) rename test/{riscv/src => }/intercept_sys_statx.c (99%) rename {riscv_test/src => test}/mkdirat_test.c (100%) rename {riscv_test/src => test}/openat_test.c (100%) rename {riscv_test/src => test}/read_test.c (100%) delete mode 100644 test/riscv/Makefile delete mode 100644 test/riscv/README.md delete mode 100644 test/riscv/src/fcntl_test.c delete mode 100644 test/riscv/src/intercept_sys_fcntl.c delete mode 100644 test/riscv/src/intercept_sys_openat.c delete mode 100644 test/riscv/src/intercept_sys_read.c delete mode 100644 test/riscv/src/intercept_sys_write.c delete mode 100644 test/riscv/src/mkdirat_test.c delete mode 100644 test/riscv/src/openat_test.c delete mode 100644 test/riscv/src/read_test.c delete mode 100644 test/riscv/src/write_test.c rename test/{riscv/src => }/statx_test.c (92%) rename {riscv_test/src => test}/write_test.c (100%) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8c25272..1281cb9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,7 +15,7 @@ jobs: # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. # You can convert this to a matrix build if you need cross-platform coverage. # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - runs-on: [ubuntu-22.04] + runs-on: [ubuntu-24.04] steps: - uses: actions/checkout@v3 diff --git a/.gitignore b/.gitignore index 617e59e..2a19d30 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,5 @@ build/ .idea/ cmake-build-debug/ test/*.so -riscv_test/bin/ -riscv_test/build/ -riscv_test/*.txt +test/bin/ +test/build/ diff --git a/README.md b/README.md index b9f33f0..67da8a1 100644 --- a/README.md +++ b/README.md @@ -60,19 +60,11 @@ There is an install target. For now, all it does, is cp. make install ``` -Testing on **x86_64**: +Running test suite: ```shell make test ``` -Testing on **RISC-V**: -```shell -# From the project root directory -cd riscv_test/ -make -make test -``` - # Synopsis # diff --git a/riscv_test/Makefile b/riscv_test/Makefile deleted file mode 100644 index fa1b7c9..0000000 --- a/riscv_test/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -CC = gcc -CFLAGS += -I../include -CFLAGS += -L../build -CFLAGS += -lsyscall_intercept -CFLAGS += -fpic -shared - -BIN_DIR = bin -BUILD_DIR = build -SRC_DIR = src - -LD_LIBRARY_PATH = ./build:../build -LD_PRELOAD = ./build - -TESTS += mkdirat -TESTS += fcntl -TESTS += openat -TESTS += read -TESTS += statx -TESTS += write -TESTS += clone -TESTS += fork - -EXECUTABLES += $(BIN_DIR)/mkdirat_test -EXECUTABLES += $(BIN_DIR)/fcntl_test -EXECUTABLES += $(BIN_DIR)/openat_test -EXECUTABLES += $(BIN_DIR)/read_test -EXECUTABLES += $(BIN_DIR)/statx_test -EXECUTABLES += $(BIN_DIR)/write_test -EXECUTABLES += $(BIN_DIR)/clone_test -EXECUTABLES += $(BIN_DIR)/fork_test - -INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_mkdirat.so -INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_fcntl.so -INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_openat.so -INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_read.so -INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_statx.so -INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_write.so -INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_clone.so -INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_fork.so - -all: $(BIN_DIR) $(BUILD_DIR) $(EXECUTABLES) $(INTERCEPT_LIBS) - -$(BUILD_DIR)/%.so: $(SRC_DIR)/%.c - $(CC) -o $@ $< $(CFLAGS) - -$(BIN_DIR)/%: $(SRC_DIR)/%.c - $(CC) $< -o $@ - -test: $(TESTS) - -$(TESTS): - @echo "Running test: $@" - @LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) LD_PRELOAD=$(LD_PRELOAD)/intercept_sys_$@.so $(BIN_DIR)/$@_test \ - && echo "Test $@ - \033[32mPASSED\033[0m" \ - || echo "Test $@ - \033[31mFAILED\033[0m" - @echo - -clean: - rm -f $(BIN_DIR)/* - rm -f $(BUILD_DIR)/* - rm -f *.txt - rm -rf wrongdir/ - rm -rf testdir/ - -$(BIN_DIR): - mkdir -p $(BIN_DIR) - -$(BUILD_DIR): - mkdir -p $(BUILD_DIR) diff --git a/riscv_test/src/clone_test.c b/riscv_test/src/clone_test.c deleted file mode 100644 index 176c201..0000000 --- a/riscv_test/src/clone_test.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2025, University of Turin - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int child_func(void *arg) { - int fd = openat(AT_FDCWD, "testfile.txt", O_RDONLY); - char buf[128]; - int n = read(fd, buf, sizeof(buf)); - buf[n] = '\0'; - n = atoi(buf); - assert(n == getpid()); - return 0; -} - -int main() { - int fd = openat(AT_FDCWD, "testfile.txt", O_CREAT | O_TRUNC | O_RDWR, 0666); - int fd2 = openat(AT_FDCWD, "testfile2.txt", O_CREAT | O_TRUNC | O_RDWR, 0666); - - char child_stack[8192]; - - pid_t pid = clone(child_func, child_stack + sizeof(child_stack), - SIGCHLD, NULL); - - if (pid == -1) { - perror("Clone failed"); - return 1; - } - - int status; - wait(&status); - if (WIFSIGNALED(status) && WTERMSIG(status) == SIGABRT) { - fprintf(stderr, "Child assertion failed\n"); - return 1; - } - - char buf[128]; - int n = read(fd2, buf, sizeof(buf)); - buf[n] = '\0'; - n = atoi(buf); - assert(n == getpid()); - write(1, "CLONE TEST - OK\n", 16); - return 0; -} - - diff --git a/riscv_test/src/fork_test.c b/riscv_test/src/fork_test.c deleted file mode 100644 index 3a00c71..0000000 --- a/riscv_test/src/fork_test.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2025, University of Turin - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include - -int main() { - - int fd = openat(AT_FDCWD, "testfile.txt", O_CREAT | O_TRUNC | O_RDWR, 0666); - int fd2 = openat(AT_FDCWD, "testfile2.txt", O_CREAT | O_TRUNC | O_RDWR, 0666); - - pid_t pid = fork(); - int n, n2; - char buf[128]; - char buf2[128]; - - switch(pid) { - case -1: - perror("fork failed\n"); - break; - case 0: - n = read(fd, buf, sizeof(buf)); - buf[n] = '\0'; - n = atoi(buf); - assert(n == getpid()); - exit(EXIT_SUCCESS); - break; - default: - n2 = read(fd2, buf2, sizeof(buf2)); - buf2[n2] = '\0'; - n2 = atoi(buf2); - assert(n2 == getpid()); - int status; - wait(&status); - if (WIFSIGNALED(status) && WTERMSIG(status) == SIGABRT) { - fprintf(stderr, "Child assertion failed\n"); - return 1; - } - - break; - } - return 0; -} diff --git a/riscv_test/src/intercept_sys_clone.c b/riscv_test/src/intercept_sys_clone.c deleted file mode 100644 index 543d21f..0000000 --- a/riscv_test/src/intercept_sys_clone.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2025, University of Turin - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "libsyscall_intercept_hook_point.h" -#include -#include -#include -#include - -static int hook(long syscall_number, - long arg0, long arg1, - long arg2, long arg3, - long arg4, long arg5, - long *result) -{ - if (syscall_number == SYS_clone) { - printf("Clone intercepted - Flags: 0x%lx - PID: %d\n", arg0, getpid()); - } - return 1; -} - -static void hook_clone_parent(long child_pid) -{ - int fd = openat(AT_FDCWD, "testfile2.txt", O_WRONLY); - dprintf(fd, "%d\n", getpid()); -} - -static void hook_clone_child(void) -{ - int fd = openat(AT_FDCWD, "testfile.txt", O_WRONLY); - dprintf(fd, "%d\n", getpid()); -} - -static __attribute__((constructor)) void -init(void) -{ - intercept_hook_point = hook; - intercept_hook_point_clone_child = hook_clone_child; - intercept_hook_point_clone_parent = hook_clone_parent; -} diff --git a/riscv_test/src/intercept_sys_fork.c b/riscv_test/src/intercept_sys_fork.c deleted file mode 100644 index 0cf2d41..0000000 --- a/riscv_test/src/intercept_sys_fork.c +++ /dev/null @@ -1,69 +0,0 @@ -/* -* Copyright 2025, University of Turin - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "libsyscall_intercept_hook_point.h" -#include -#include -#include -#include - -static int hook(long syscall_number, - long arg0, long arg1, - long arg2, long arg3, - long arg4, long arg5, - long *result) -{ - if (syscall_number == SYS_clone) { - printf("Fork intercepted - Flags: 0x%lx - PID: %d\n", arg0, getpid()); - } - return 1; -} - -static void hook_clone_parent(long child_pid) -{ - int fd = openat(AT_FDCWD, "testfile2.txt", O_WRONLY); - dprintf(fd, "%d\n", getpid()); -} - -static void hook_clone_child(void) -{ - int fd = openat(AT_FDCWD, "testfile.txt", O_WRONLY); - dprintf(fd, "%d\n", getpid()); -} - -static __attribute__((constructor)) void -init(void) -{ - intercept_hook_point = hook; - intercept_hook_point_clone_child = hook_clone_child; - intercept_hook_point_clone_parent = hook_clone_parent; -} diff --git a/riscv_test/src/intercept_sys_mkdirat.c b/riscv_test/src/intercept_sys_mkdirat.c deleted file mode 100644 index 41d311d..0000000 --- a/riscv_test/src/intercept_sys_mkdirat.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2025, University of Turin - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "libsyscall_intercept_hook_point.h" - -#include -#include -#include -#include -#include - - -static int hook(long syscall_number, - long arg0, long arg1, - long arg2, long arg3, - long arg4, long arg5, - long *result) -{ - if (syscall_number == SYS_mkdirat) { - char buf[128] = "wrongdir/"; - char *tmp = buf; - if (strcmp((char *)arg1, tmp) == 0) { - const char testdir[] = "testdir/"; - syscall_no_intercept(syscall_number, arg0, (uintptr_t)testdir, arg2, - arg3, arg4, arg5); - return 0; - } - } - return 1; -} - -static __attribute__((constructor)) void init(void) -{ - intercept_hook_point = hook; -} diff --git a/riscv_test/src/intercept_sys_statx.c b/riscv_test/src/intercept_sys_statx.c deleted file mode 100644 index 6c7112c..0000000 --- a/riscv_test/src/intercept_sys_statx.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2025, University of Turin - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "libsyscall_intercept_hook_point.h" - -#include -#include -#include - - -static int hook(long syscall_number, - long arg0, long arg1, - long arg2, long arg3, - long arg4, long arg5, - long *result) -{ - if (syscall_number == SYS_statx) { - const char file2[] = "testfile2.txt"; - const char *tmp = file2; - if (strcmp((char *)arg1, tmp) == 0) { - const char testfile[] = "testfile.txt"; - syscall_no_intercept(syscall_number, arg0, testfile, arg2, arg3, arg4, arg5, result); - return 0; - } - } - return 1; -} - -static __attribute__((constructor)) void init(void) -{ - intercept_hook_point = hook; -} diff --git a/riscv_test/src/intercept_sys_write.c b/riscv_test/src/intercept_sys_write.c deleted file mode 100644 index 103d0a6..0000000 --- a/riscv_test/src/intercept_sys_write.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2017, Intel Corporation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "libsyscall_intercept_hook_point.h" - -#include -#include -#include - -static int -hook(long syscall_number, - long arg0, long arg1, - long arg2, long arg3, - long arg4, long arg5, - long *result) -{ - (void) arg0; - (void) arg2; - (void) arg3; - (void) arg4; - (void) arg5; - (void) result; - - if (syscall_number == SYS_write) { - const char test[] = "WRITE TEST - OK\n"; - const char *tmp = test; - if (strcmp((char *)arg1, tmp) == 0) return 1; - - const char interc[] = "intercepted_"; - const char *src = interc; - - /* write(fd, buf, len) */ - size_t len = (size_t)arg2; - char *buf = (char *)arg1; - -#ifdef EXPECT_SPURIOUS_SYSCALLS - if (strcmp(buf, "original_syscall") != 0) - return 1; -#endif - - if (len > sizeof(interc)) { - while (*src != '\0') - *buf++ = *src++; - } - } - - return 1; -} - -static __attribute__((constructor)) void -init(void) -{ - intercept_hook_point = hook; -} diff --git a/riscv_test/src/statx_test.c b/riscv_test/src/statx_test.c deleted file mode 100644 index 3e2c922..0000000 --- a/riscv_test/src/statx_test.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2025, University of Turin - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include - -int main() { - int fd = openat(AT_FDCWD, "testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); - struct statx stx; - statx(AT_FDCWD, "testfile.txt", 0, STATX_BASIC_STATS | STATX_BTIME, &stx); - - int fd2 = openat(AT_FDCWD, "testfile2.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); - struct statx stx2; - statx(AT_FDCWD, "testfile2.txt", 0, STATX_BASIC_STATS | STATX_BTIME, &stx2); - - assert(stx.stx_ino == stx2.stx_ino); - write(1, "STATX TEST - OK\n", 16); - - return 0; -} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0a8108b..290c8fb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -170,9 +170,6 @@ add_test(NAME "clone_thread" set_tests_properties("clone_thread" PROPERTIES PASS_REGULAR_EXPRESSION "clone_hook_child called") -add_library(intercept_sys_write SHARED intercept_sys_write.c) -target_link_libraries(intercept_sys_write PRIVATE syscall_intercept_shared) - add_executable(syscall_format syscall_format.c) target_link_libraries(syscall_format PRIVATE syscall_intercept_shared) add_test(NAME "syscall_format_logging" @@ -183,3 +180,28 @@ add_test(NAME "syscall_format_logging" -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/syscall_format.log.match -DTEST_NAME=syscall_format_logging ${CHECK_LOG_COMMON_ARGS}) + +set(GENERIC_TESTS + clone + fcntl + mkdirat + openat + read + statx + write +) + +foreach(test_name IN LISTS GENERIC_TESTS) + add_library(intercept_sys_${test_name} SHARED intercept_sys_${test_name}.c) + target_link_libraries(intercept_sys_${test_name} PRIVATE syscall_intercept_shared) + + add_executable(${test_name}_test ${test_name}_test.c) + target_link_libraries(${test_name}_test PRIVATE syscall_intercept_shared) + + add_test(NAME "${test_name}_generic" + COMMAND ${CMAKE_COMMAND} -E env + LD_LIBRARY_PATH=$:$ + LD_PRELOAD=$ + $ + ) +endforeach() diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..fa2aff8 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,95 @@ +# +# Copyright 2025, University of Turin +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +CC = gcc +CFLAGS += -I../include +CFLAGS += -L../build +CFLAGS += -lsyscall_intercept +CFLAGS += -fpic -shared + +BIN_DIR = ./bin +BUILD_DIR = ./build +SRC_DIR = src + +LD_LIBRARY_PATH = ./build:../build +LD_PRELOAD = ./build + +TESTS += clone +TESTS += fcntl +TESTS += mkdirat +TESTS += openat +TESTS += read +TESTS += statx +TESTS += write + +EXECUTABLES += $(BIN_DIR)/clone_test +EXECUTABLES += $(BIN_DIR)/fcntl_test +EXECUTABLES += $(BIN_DIR)/mkdirat_test +EXECUTABLES += $(BIN_DIR)/openat_test +EXECUTABLES += $(BIN_DIR)/read_test +EXECUTABLES += $(BIN_DIR)/statx_test +EXECUTABLES += $(BIN_DIR)/write_test + +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_clone.so +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_fcntl.so +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_mkdirat.so +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_openat.so +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_read.so +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_statx.so +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_write.so + +all: $(BIN_DIR) $(BUILD_DIR) $(EXECUTABLES) $(INTERCEPT_LIBS) + +$(BUILD_DIR)/%.so: $(SRC_DIR)/%.c + $(CC) -o $@ $< $(CFLAGS) + +$(BIN_DIR)/%: $(SRC_DIR)/%.c + $(CC) $< -o $@ + +test: $(TESTS) + +$(TESTS): + @echo "Running test: $@" + @LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) LD_PRELOAD=$(LD_PRELOAD)/intercept_sys_$@.so $(BIN_DIR)/$@_test \ + && echo "Test $@ - \033[32mPASSED\033[0m" \ + || echo "Test $@ - \033[31mFAILED\033[0m" + @echo + +clean: + rm -rf $(BIN_DIR)/ + rm -rf $(BUILD_DIR)/ + rm -rf wrongdir/ + +$(BIN_DIR): + mkdir -p $(BIN_DIR) + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) diff --git a/riscv_test/README.md b/test/README.md similarity index 100% rename from riscv_test/README.md rename to test/README.md diff --git a/test/riscv/src/clone_test.c b/test/clone_test.c similarity index 98% rename from test/riscv/src/clone_test.c rename to test/clone_test.c index 84d376f..e09be50 100644 --- a/test/riscv/src/clone_test.c +++ b/test/clone_test.c @@ -29,8 +29,10 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif + #include #include #include diff --git a/riscv_test/src/fcntl_test.c b/test/fcntl_test.c similarity index 100% rename from riscv_test/src/fcntl_test.c rename to test/fcntl_test.c diff --git a/test/riscv/src/intercept_sys_clone.c b/test/intercept_sys_clone.c similarity index 94% rename from test/riscv/src/intercept_sys_clone.c rename to test/intercept_sys_clone.c index 854dc79..ad822e3 100644 --- a/test/riscv/src/intercept_sys_clone.c +++ b/test/intercept_sys_clone.c @@ -42,6 +42,14 @@ static int hook(long syscall_number, long arg4, long arg5, long *result) { + (void) arg0; + (void) arg1; + (void) arg2; + (void) arg3; + (void) arg4; + (void) arg5; + (void) result; + if (syscall_number == SYS_clone) { int fd = openat(AT_FDCWD, "testfile.txt", O_CREAT | O_TRUNC | O_RDWR, 0666); dprintf(fd,"%d\n",getpid()); diff --git a/riscv_test/src/intercept_sys_fcntl.c b/test/intercept_sys_fcntl.c similarity index 99% rename from riscv_test/src/intercept_sys_fcntl.c rename to test/intercept_sys_fcntl.c index 2470a74..f388007 100644 --- a/riscv_test/src/intercept_sys_fcntl.c +++ b/test/intercept_sys_fcntl.c @@ -42,6 +42,8 @@ hook(long syscall_number, long arg4, long arg5, long *result) { + (void) arg0; + if (syscall_number == SYS_fcntl) { int fd = openat(AT_FDCWD, "testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); int ret = syscall_no_intercept(syscall_number, fd, arg1, arg2, arg3, arg4, arg5); diff --git a/test/riscv/src/intercept_sys_mkdirat.c b/test/intercept_sys_mkdirat.c similarity index 99% rename from test/riscv/src/intercept_sys_mkdirat.c rename to test/intercept_sys_mkdirat.c index 41d311d..5ba5c45 100644 --- a/test/riscv/src/intercept_sys_mkdirat.c +++ b/test/intercept_sys_mkdirat.c @@ -45,6 +45,8 @@ static int hook(long syscall_number, long arg4, long arg5, long *result) { + (void) result; + if (syscall_number == SYS_mkdirat) { char buf[128] = "wrongdir/"; char *tmp = buf; diff --git a/riscv_test/src/intercept_sys_openat.c b/test/intercept_sys_openat.c similarity index 99% rename from riscv_test/src/intercept_sys_openat.c rename to test/intercept_sys_openat.c index 7c38553..34f8ed8 100644 --- a/riscv_test/src/intercept_sys_openat.c +++ b/test/intercept_sys_openat.c @@ -48,6 +48,7 @@ static int hook(long syscall_number, long arg4, long arg5, long *result) { + (void) arg2; if (syscall_number == SYS_openat) { const char non_existing[] = "non_existing.txt"; diff --git a/riscv_test/src/intercept_sys_read.c b/test/intercept_sys_read.c similarity index 94% rename from riscv_test/src/intercept_sys_read.c rename to test/intercept_sys_read.c index f9a2482..46e5c4c 100644 --- a/riscv_test/src/intercept_sys_read.c +++ b/test/intercept_sys_read.c @@ -44,10 +44,13 @@ static int hook(long syscall_number, long arg4, long arg5, long *result) { - (void)arg3; - (void)arg4; - (void)arg5; - (void)result; + (void) arg0; + (void) arg1; + (void) arg2; + (void) arg3; + (void) arg4; + (void) arg5; + (void) result; if (syscall_number == SYS_read) { int fd = openat(AT_FDCWD, "testfile.txt", O_WRONLY); diff --git a/test/riscv/src/intercept_sys_statx.c b/test/intercept_sys_statx.c similarity index 99% rename from test/riscv/src/intercept_sys_statx.c rename to test/intercept_sys_statx.c index 6c7112c..53c6ada 100644 --- a/test/riscv/src/intercept_sys_statx.c +++ b/test/intercept_sys_statx.c @@ -43,6 +43,8 @@ static int hook(long syscall_number, long arg4, long arg5, long *result) { + (void) result; + if (syscall_number == SYS_statx) { const char file2[] = "testfile2.txt"; const char *tmp = file2; diff --git a/riscv_test/src/mkdirat_test.c b/test/mkdirat_test.c similarity index 100% rename from riscv_test/src/mkdirat_test.c rename to test/mkdirat_test.c diff --git a/riscv_test/src/openat_test.c b/test/openat_test.c similarity index 100% rename from riscv_test/src/openat_test.c rename to test/openat_test.c diff --git a/riscv_test/src/read_test.c b/test/read_test.c similarity index 100% rename from riscv_test/src/read_test.c rename to test/read_test.c diff --git a/test/riscv/Makefile b/test/riscv/Makefile deleted file mode 100644 index cacedc2..0000000 --- a/test/riscv/Makefile +++ /dev/null @@ -1,65 +0,0 @@ -CC = gcc -CFLAGS += -I../../include -CFLAGS += -L../../build -CFLAGS += -lsyscall_intercept -CFLAGS += -fpic -shared - -BIN_DIR = bin -BUILD_DIR = build -SRC_DIR = src - -LD_LIBRARY_PATH = ./build:../../build -LD_PRELOAD = ./build - -TESTS += clone -TESTS += fcntl -TESTS += mkdirat -TESTS += openat -TESTS += read -TESTS += statx -TESTS += write - -EXECUTABLES += $(BIN_DIR)/clone_test -EXECUTABLES += $(BIN_DIR)/fcntl_test -EXECUTABLES += $(BIN_DIR)/mkdirat_test -EXECUTABLES += $(BIN_DIR)/openat_test -EXECUTABLES += $(BIN_DIR)/read_test -EXECUTABLES += $(BIN_DIR)/statx_test -EXECUTABLES += $(BIN_DIR)/write_test - -INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_clone.so -INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_fcntl.so -INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_mkdirat.so -INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_openat.so -INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_read.so -INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_statx.so -INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_write.so - -all: $(BIN_DIR) $(BUILD_DIR) $(EXECUTABLES) $(INTERCEPT_LIBS) - -$(BUILD_DIR)/%.so: $(SRC_DIR)/%.c - $(CC) -o $@ $< $(CFLAGS) - -$(BIN_DIR)/%: $(SRC_DIR)/%.c - $(CC) $< -o $@ - -test: $(TESTS) - -$(TESTS): - @echo "Running test: $@" - @LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) LD_PRELOAD=$(LD_PRELOAD)/intercept_sys_$@.so $(BIN_DIR)/$@_test \ - && echo "Test $@ - \033[32mPASSED\033[0m" \ - || echo "Test $@ - \033[31mFAILED\033[0m" - @echo - -clean: - rm -f $(BIN_DIR)/* - rm -f $(BUILD_DIR)/* - rm -f *.txt - rm -rf wrongdir/ - -$(BIN_DIR): - mkdir -p $(BIN_DIR) - -$(BUILD_DIR): - mkdir -p $(BUILD_DIR) diff --git a/test/riscv/README.md b/test/riscv/README.md deleted file mode 100644 index 7cad175..0000000 --- a/test/riscv/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Testing on RISC-V # - -The tests inside `./src` must be considered as couples containing an executable -and an initialization library, named as follows: -- `_test.c` -- `intercept_sys_.c` - -They can be compiled with -```shell -make -``` -and executed with -```shell -make test -``` -Alternatively, it is possible to execute a specific test with the following -command, where syscall-name must be replaced with one of the entries in -the TESTS variable in the Makefile -``` -make -``` - -## How these test work ## - -These tests basically assert a condition which can't possibly be true unless -the hook function is executed as expected thanks to a correct interception of -the tested system call. As an example, the `write` test writes a string to a -file, then reads the written string from that file and in the end asserts that -the two strings are perfectly equal. By looking at the content of -[write_test.c](src/write_test.c) it is obvious how the assertion could never be -true since the written string and the expected string are different. The hook -function which will be executed before forwarding the system call to the kernel -will make sure to modify the string that is going to be written to the file so -that the actual written string and the expected string match. -All the tests implement the described pattern. \ No newline at end of file diff --git a/test/riscv/src/fcntl_test.c b/test/riscv/src/fcntl_test.c deleted file mode 100644 index 3c54cf2..0000000 --- a/test/riscv/src/fcntl_test.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2025, University of Turin - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -int main() { - int fd = openat(AT_FDCWD, "testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); - int fd2 = openat(AT_FDCWD, "testfile2.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); - int fd2_dup = fcntl(fd2, F_DUPFD, 0); - char buf[128] = "writing to fd2_dup\n"; - write(fd2_dup, buf, strlen(buf)); - char dst_buf[128]; - int n = read(fd, dst_buf, sizeof(buf)); - dst_buf[n] = '\0'; - assert(strcmp(buf, dst_buf) == 0); - write(1, "FCNTL TEST - OK\n",16); -} diff --git a/test/riscv/src/intercept_sys_fcntl.c b/test/riscv/src/intercept_sys_fcntl.c deleted file mode 100644 index 2470a74..0000000 --- a/test/riscv/src/intercept_sys_fcntl.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2025, University of Turin - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "libsyscall_intercept_hook_point.h" -#include -#include -#include - -static int -hook(long syscall_number, - long arg0, long arg1, - long arg2, long arg3, - long arg4, long arg5, - long *result) -{ - if (syscall_number == SYS_fcntl) { - int fd = openat(AT_FDCWD, "testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); - int ret = syscall_no_intercept(syscall_number, fd, arg1, arg2, arg3, arg4, arg5); - *result = ret; - return 0; - } - return 1; -} - -static __attribute__((constructor)) void -init(void) -{ - intercept_hook_point = hook; -} \ No newline at end of file diff --git a/test/riscv/src/intercept_sys_openat.c b/test/riscv/src/intercept_sys_openat.c deleted file mode 100644 index 7c38553..0000000 --- a/test/riscv/src/intercept_sys_openat.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2025, University of Turin - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * see openat_test.c for details about this test library, which must be compiled with - * gcc -o intercept_sys_openat.so intercept_sys_write.c -I../include -L../build -lsyscall_intercept -fpic -shared - */ - -#include "libsyscall_intercept_hook_point.h" -#include -#include -#include -#include - - -static int hook(long syscall_number, - long arg0, long arg1, - long arg2, long arg3, - long arg4, long arg5, - long *result) -{ - - if (syscall_number == SYS_openat) { - const char non_existing[] = "non_existing.txt"; - const char *tmp = non_existing; - if (strcmp((char *)arg1, tmp) == 0) { - const char testfile[] = "testfile.txt"; - long flags = O_WRONLY; - *result = syscall_no_intercept(SYS_openat, arg0, (uintptr_t)testfile, - flags, arg3, arg4, arg5); - return 0; - } - } - return 1; -} - -static __attribute__((constructor)) void init(void) -{ - intercept_hook_point = hook; -} diff --git a/test/riscv/src/intercept_sys_read.c b/test/riscv/src/intercept_sys_read.c deleted file mode 100644 index f9a2482..0000000 --- a/test/riscv/src/intercept_sys_read.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2025, University of Turin - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "libsyscall_intercept_hook_point.h" -#include -#include -#include -#include -#include - - -static int hook(long syscall_number, - long arg0, long arg1, - long arg2, long arg3, - long arg4, long arg5, - long *result) -{ - (void)arg3; - (void)arg4; - (void)arg5; - (void)result; - - if (syscall_number == SYS_read) { - int fd = openat(AT_FDCWD, "testfile.txt", O_WRONLY); - char buf[128] = "write from read hook\n"; - write(fd, buf, strlen(buf)); - lseek(fd, 0, SEEK_SET); - } - return 1; -} - -static __attribute__((constructor)) void init(void) -{ - intercept_hook_point = hook; -} diff --git a/test/riscv/src/intercept_sys_write.c b/test/riscv/src/intercept_sys_write.c deleted file mode 100644 index 103d0a6..0000000 --- a/test/riscv/src/intercept_sys_write.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2017, Intel Corporation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "libsyscall_intercept_hook_point.h" - -#include -#include -#include - -static int -hook(long syscall_number, - long arg0, long arg1, - long arg2, long arg3, - long arg4, long arg5, - long *result) -{ - (void) arg0; - (void) arg2; - (void) arg3; - (void) arg4; - (void) arg5; - (void) result; - - if (syscall_number == SYS_write) { - const char test[] = "WRITE TEST - OK\n"; - const char *tmp = test; - if (strcmp((char *)arg1, tmp) == 0) return 1; - - const char interc[] = "intercepted_"; - const char *src = interc; - - /* write(fd, buf, len) */ - size_t len = (size_t)arg2; - char *buf = (char *)arg1; - -#ifdef EXPECT_SPURIOUS_SYSCALLS - if (strcmp(buf, "original_syscall") != 0) - return 1; -#endif - - if (len > sizeof(interc)) { - while (*src != '\0') - *buf++ = *src++; - } - } - - return 1; -} - -static __attribute__((constructor)) void -init(void) -{ - intercept_hook_point = hook; -} diff --git a/test/riscv/src/mkdirat_test.c b/test/riscv/src/mkdirat_test.c deleted file mode 100644 index 5700a1f..0000000 --- a/test/riscv/src/mkdirat_test.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2025, University of Turin - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * The following test assumes 4096 bytes as the smallest page size. It - * therefore makes sense on those architectures compliant with that - * assumption, as both amd64 and riscv64 are. Following that assumption, - * a brk(0) would result in an increase of the program break by 4096 bytes - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -int main() { - mkdirat(AT_FDCWD,"wrongdir/", 0777); - int fd = openat(AT_FDCWD, "testdir/testdirfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); - assert(fd != -1); - system("rm -rf testdir/"); - write(1, "MKDIRAT TEST - OK\n", 18); - return 0; -} diff --git a/test/riscv/src/openat_test.c b/test/riscv/src/openat_test.c deleted file mode 100644 index d663fd1..0000000 --- a/test/riscv/src/openat_test.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2025, University of Turin - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * execution of this test must be preloaded with the corresponding interception - * library, i.e. from the syscall_intercept/test directory - * LD_LIBRARY_PATH=.:../build LD_PRELOAD=intercept_sys_openat.so ./openat_test - */ - -#include -#include -#include -#include - -int main() { - int create_fd = openat(AT_FDCWD, "testfile.txt", O_CREAT | O_TRUNC | O_RDONLY, 0666); - int test_fd = openat(AT_FDCWD, "non_existing.txt", O_RDONLY); - char buf[128] = "impossible write rerouted on testfile.txt"; - write(test_fd, buf, strlen(buf)); - char test_buf[128]; - int n = read(create_fd, test_buf, strlen(buf)); - test_buf[n] = '\0'; - assert(strcmp(test_buf, buf) == 0); - write(1, "OPENAT TEST - OK\n", 17); - return 0; -} \ No newline at end of file diff --git a/test/riscv/src/read_test.c b/test/riscv/src/read_test.c deleted file mode 100644 index d396e13..0000000 --- a/test/riscv/src/read_test.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2025, University of Turin - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -int main() { - int fd = openat(AT_FDCWD, "testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); - char buf[128]; - char expected_string[] = "write from read hook\n"; - int n = read(fd, buf, strlen(expected_string)); - buf[n] = '\0'; - assert(strcmp(buf,expected_string) == 0); - write(1, "READ TEST - OK\n",15); -} diff --git a/test/riscv/src/write_test.c b/test/riscv/src/write_test.c deleted file mode 100644 index 4aa7615..0000000 --- a/test/riscv/src/write_test.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2025, University of Turin - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * execution of this test must be preloaded with the corresponding interception - * library, i.e. from the syscall_intercept/test directory - * LD_LIBRARY_PATH=.:../build LD_PRELOAD=intercept_sys_write.so ./write_test - */ - -#include -#include -#include -#include -#include -#include - -int main() { - int test_fd = openat(AT_FDCWD, "testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); - if (test_fd == -1) { - printf("intercepted_openat error nr: %d\n", errno); - return 1; - } - char buf[128] = "original_syscall\n"; - write(test_fd, buf, strlen(buf)); - lseek(test_fd, 0, SEEK_SET); - char test_buf[128]; - int n = read(test_fd, test_buf, strlen(buf)); - test_buf[n] = '\0'; - assert(strcmp(test_buf, "intercepted_call\n") == 0); - char test_ok[128] = "WRITE TEST - OK\n"; - write(1, test_ok, strlen(test_ok)); - return 0; -} diff --git a/test/riscv/src/statx_test.c b/test/statx_test.c similarity index 92% rename from test/riscv/src/statx_test.c rename to test/statx_test.c index 3e2c922..d82884a 100644 --- a/test/riscv/src/statx_test.c +++ b/test/statx_test.c @@ -29,8 +29,10 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif + #include #include #include @@ -41,11 +43,11 @@ #include int main() { - int fd = openat(AT_FDCWD, "testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + openat(AT_FDCWD, "testfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); struct statx stx; statx(AT_FDCWD, "testfile.txt", 0, STATX_BASIC_STATS | STATX_BTIME, &stx); - int fd2 = openat(AT_FDCWD, "testfile2.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); + openat(AT_FDCWD, "testfile2.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); struct statx stx2; statx(AT_FDCWD, "testfile2.txt", 0, STATX_BASIC_STATS | STATX_BTIME, &stx2); diff --git a/riscv_test/src/write_test.c b/test/write_test.c similarity index 100% rename from riscv_test/src/write_test.c rename to test/write_test.c From 7f320617c4f4cba5be6ac78eb29f5e8f46ab6c55 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Tue, 15 Jul 2025 22:54:42 +0200 Subject: [PATCH 114/143] solved unused variables warnings --- test/clone_test.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/clone_test.c b/test/clone_test.c index e09be50..48d93fc 100644 --- a/test/clone_test.c +++ b/test/clone_test.c @@ -51,6 +51,7 @@ int child_func(void *arg) { buf[n] = '\0'; n = atoi(buf); assert(n == ppid); + (void) ppid; return 0; } @@ -58,7 +59,7 @@ int main() { char child_stack[8192]; pid_t ppid = getpid(); pid_t pid = clone(child_func, child_stack + sizeof(child_stack), - CLONE_VM | SIGCHLD, &ppid); + SIGCHLD, &ppid); if (pid == -1) { perror("Clone failed"); @@ -72,7 +73,8 @@ int main() { return 1; } - write(1, "CLONE TEST - OK\n", 16); + int res = write(1, "CLONE TEST - OK\n", 16); + (void) res; return 0; } From ed4bd5e0e96daa05b050032f84a9c59d43c15b47 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 16 Jul 2025 00:45:32 +0200 Subject: [PATCH 115/143] added -Wno-unused-result for tests --- test/CMakeLists.txt | 3 ++ test/clone_test.c | 4 +- test/fcntl_test.c | 6 ++- test/fork_test.c | 78 +++++++++++++++++++++++++++++++++++++++ test/intercept_sys_fork.c | 77 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 test/fork_test.c create mode 100644 test/intercept_sys_fork.c diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 290c8fb..60f6637 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -39,6 +39,8 @@ find_package(Threads) include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/test) +add_compile_options(-Wno-unused-result) + if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86(_64)?)$") add_subdirectory(arch/x86_64) endif() @@ -184,6 +186,7 @@ add_test(NAME "syscall_format_logging" set(GENERIC_TESTS clone fcntl + fork mkdirat openat read diff --git a/test/clone_test.c b/test/clone_test.c index 48d93fc..9b38d8a 100644 --- a/test/clone_test.c +++ b/test/clone_test.c @@ -51,7 +51,6 @@ int child_func(void *arg) { buf[n] = '\0'; n = atoi(buf); assert(n == ppid); - (void) ppid; return 0; } @@ -73,8 +72,7 @@ int main() { return 1; } - int res = write(1, "CLONE TEST - OK\n", 16); - (void) res; + write(1, "CLONE TEST - OK\n", 16); return 0; } diff --git a/test/fcntl_test.c b/test/fcntl_test.c index 3c54cf2..464f58b 100644 --- a/test/fcntl_test.c +++ b/test/fcntl_test.c @@ -40,10 +40,14 @@ int main() { int fd2 = openat(AT_FDCWD, "testfile2.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); int fd2_dup = fcntl(fd2, F_DUPFD, 0); char buf[128] = "writing to fd2_dup\n"; - write(fd2_dup, buf, strlen(buf)); + write(fd2_dup, buf, strlen(buf)); char dst_buf[128]; int n = read(fd, dst_buf, sizeof(buf)); dst_buf[n] = '\0'; assert(strcmp(buf, dst_buf) == 0); write(1, "FCNTL TEST - OK\n",16); + close(fd); + close(fd2); + close(fd2_dup); + return 0; } diff --git a/test/fork_test.c b/test/fork_test.c new file mode 100644 index 0000000..687a776 --- /dev/null +++ b/test/fork_test.c @@ -0,0 +1,78 @@ +/* + * Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include + +int main() { + + int fd = openat(AT_FDCWD, "testfile.txt", O_CREAT | O_TRUNC | O_RDWR, 0666); + int fd2 = openat(AT_FDCWD, "testfile2.txt", O_CREAT | O_TRUNC | O_RDWR, 0666); + + pid_t pid = fork(); + int n, n2; + char buf[128]; + char buf2[128]; + + switch(pid) { + case -1: + perror("fork failed\n"); + break; + case 0: + n = read(fd, buf, sizeof(buf)); + buf[n] = '\0'; + n = atoi(buf); + assert(n == getpid()); + exit(EXIT_SUCCESS); + break; + default: + n2 = read(fd2, buf2, sizeof(buf2)); + buf2[n2] = '\0'; + n2 = atoi(buf2); + assert(n2 == getpid()); + int status; + wait(&status); + if (WIFSIGNALED(status) && WTERMSIG(status) == SIGABRT) { + fprintf(stderr, "Child assertion failed\n"); + return 1; + } + + break; + } + return 0; +} diff --git a/test/intercept_sys_fork.c b/test/intercept_sys_fork.c new file mode 100644 index 0000000..a41e1b0 --- /dev/null +++ b/test/intercept_sys_fork.c @@ -0,0 +1,77 @@ +/* +* Copyright 2025, University of Turin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libsyscall_intercept_hook_point.h" +#include +#include +#include +#include + +static int hook(long syscall_number, + long arg0, long arg1, + long arg2, long arg3, + long arg4, long arg5, + long *result) +{ + (void) arg1; + (void) arg2; + (void) arg3; + (void) arg4; + (void) arg5; + (void) result; + + if (syscall_number == SYS_clone) { + printf("Fork intercepted - Flags: 0x%lx - PID: %d\n", arg0, getpid()); + } + return 1; +} + +static void hook_clone_parent(long child_pid) +{ + (void) child_pid; + int fd = openat(AT_FDCWD, "testfile2.txt", O_WRONLY); + dprintf(fd, "%d\n", getpid()); +} + +static void hook_clone_child(void) +{ + int fd = openat(AT_FDCWD, "testfile.txt", O_WRONLY); + dprintf(fd, "%d\n", getpid()); +} + +static __attribute__((constructor)) void +init(void) +{ + intercept_hook_point = hook; + intercept_hook_point_clone_child = hook_clone_child; + intercept_hook_point_clone_parent = hook_clone_parent; +} From ff4fe29ac6bf95b2bc60144be0582c83b872471b Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 16 Jul 2025 00:48:05 +0200 Subject: [PATCH 116/143] added -Wno-unused-variable for test --- test/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 60f6637..76ffe57 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -40,6 +40,7 @@ find_package(Threads) include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/test) add_compile_options(-Wno-unused-result) +add_compile_options(-Wno-unused-variable) if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86(_64)?)$") add_subdirectory(arch/x86_64) From e4a1321a3b891194f25bd648a023b8b36286f033 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 16 Jul 2025 00:57:48 +0200 Subject: [PATCH 117/143] fine-tuning for cmake-independent execution --- test/Makefile | 10 +++++++--- test/mkdirat_test.c | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/test/Makefile b/test/Makefile index fa2aff8..86293bb 100644 --- a/test/Makefile +++ b/test/Makefile @@ -44,6 +44,7 @@ LD_PRELOAD = ./build TESTS += clone TESTS += fcntl +TESTS += fork TESTS += mkdirat TESTS += openat TESTS += read @@ -52,6 +53,7 @@ TESTS += write EXECUTABLES += $(BIN_DIR)/clone_test EXECUTABLES += $(BIN_DIR)/fcntl_test +EXECUTABLES += $(BIN_DIR)/fork_test EXECUTABLES += $(BIN_DIR)/mkdirat_test EXECUTABLES += $(BIN_DIR)/openat_test EXECUTABLES += $(BIN_DIR)/read_test @@ -60,6 +62,7 @@ EXECUTABLES += $(BIN_DIR)/write_test INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_clone.so INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_fcntl.so +INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_fork.so INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_mkdirat.so INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_openat.so INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_read.so @@ -68,10 +71,10 @@ INTERCEPT_LIBS += $(BUILD_DIR)/intercept_sys_write.so all: $(BIN_DIR) $(BUILD_DIR) $(EXECUTABLES) $(INTERCEPT_LIBS) -$(BUILD_DIR)/%.so: $(SRC_DIR)/%.c +$(BUILD_DIR)/%.so: %.c $(CC) -o $@ $< $(CFLAGS) -$(BIN_DIR)/%: $(SRC_DIR)/%.c +$(BIN_DIR)/%: %.c $(CC) $< -o $@ test: $(TESTS) @@ -86,7 +89,8 @@ $(TESTS): clean: rm -rf $(BIN_DIR)/ rm -rf $(BUILD_DIR)/ - rm -rf wrongdir/ + rm -rf testdir/ + rm -f testfile.txt testfile2.txt $(BIN_DIR): mkdir -p $(BIN_DIR) diff --git a/test/mkdirat_test.c b/test/mkdirat_test.c index 5700a1f..821014d 100644 --- a/test/mkdirat_test.c +++ b/test/mkdirat_test.c @@ -47,10 +47,10 @@ #include int main() { + system("rm -rf testdir/"); mkdirat(AT_FDCWD,"wrongdir/", 0777); int fd = openat(AT_FDCWD, "testdir/testdirfile.txt", O_RDWR | O_CREAT | O_TRUNC, 0666); assert(fd != -1); - system("rm -rf testdir/"); write(1, "MKDIRAT TEST - OK\n", 18); return 0; } From 185d3f764a05750ed016cbcef27fdcb110e79ceb Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 16 Jul 2025 01:01:42 +0200 Subject: [PATCH 118/143] excluded generic test generated files and directories --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 2a19d30..9774347 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ cmake-build-debug/ test/*.so test/bin/ test/build/ +test/testdir/ +test/testfile.txt +test/testfile2.txt From f38bb29a98d3bafd9426a4bd85380c46a3c8f7ce Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Wed, 16 Jul 2025 12:27:55 +0200 Subject: [PATCH 119/143] Updated tests description --- test/README.md | 95 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 18 deletions(-) diff --git a/test/README.md b/test/README.md index 7cad175..f708496 100644 --- a/test/README.md +++ b/test/README.md @@ -1,11 +1,83 @@ -# Testing on RISC-V # +# Test directory # -The tests inside `./src` must be considered as couples containing an executable +All the source files for executables and initialization libraries and utility +files for testing are stored here. In the current directory only architecture +agnostic tests are present, while architecture specific tests are stored in a +dedicated directory inside `arch/`. As an example, inside `arch/x86_64/` some +assembly tests are stored, which must be optionally compiled just when building +on amd64 CPUs. + + +**RISC-V specific tests are coming soon**. However, the architecture agnostic +test suite can be run properly. + +# How to build # + +Tests are automatically built when building the library. If the library still +has to be built, from the root directory of the project run +```shell +mkdir build +cd build +cmake .. +make +``` + +[CMakeLists.txt](CMakeLists.txt) is written to automatically detect the CPU +architecture and select which tests must be compiled accordingly. + +In the end, running +```shell +make test +``` +will run the compiled test suite. + +# Testing logic # + +Different approaches are used to test syscall_intercept but an overall +distinction can be made between high-level and low-level coded tests. +- **Matching tests**: these tests verify the correct execution of the system + call interception. Some of them use the library logging logic to produce a + log file which gets then inspected to make sure it matches the expected output. + I.e., [syscall_format.c](syscall_format.c) makes a lot of system calls of + in a mock context just to create a log file which will be compared to + [syscall_format.log.match](syscall_format.log.match). One mismatch is enough + to fail the test.
Since system calls implementation may vary across + different glibc versions, the .match files could need to be updated to grant + a correct testing process. Depending on the glibc versions an `fstat` system + call could actually call `fstat` or `newfstatat`, or a `fstat` call with a + negative file descriptor could be forwarded to the kernel (invoking + syscall_intercept logic) or return before invoking the kernel (not invoking + syscall_intercept logic at all, and so the logging). Current .match files are + designed with glibc 2.35 and 2.39 versions in mind, which are the default + shipped versions with Ubuntu 22.04 and 24.04 respectively. Moreover, even the + same version on different architectures could involve different implementations. +
For these reasons, failing of a test of such type does not necessarily + imply that syscall_intercept is malfunctioning. +- **Assertion tests**: these tests basically assert a condition which can't possibly be true unless + the hook function is executed as expected thanks to a correct interception of + the tested system call. As an example, the `write` test writes a string to a + file, then reads the written string from that file and in the end asserts that + the two strings are perfectly equal. By looking at the content of + [write_test.c](src/write_test.c) it is obvious how the assertion could never be + true since the written string and the expected string are different. The hook + function which will be executed before forwarding the system call to the kernel + will make sure to modify the string that is going to be written to the file so + that the actual written string and the expected string match. + All the tests implementing such pattern are named in the suite as `_generic`. +- **Patching tests**: these tests verify the correct execution of the patching + process. They work in couples with an input and an output pattern file, both + coded in assembly. The input object file will be patched by syscall_intercept + producing a patched binary which will be compared with the output file by + `memcmp()`. Failing of such tests implies that the patching process is not + writing the expected binary code.
**RISC-V tests of such type are coming soon.** + +Assertion tests must be considered as couples containing an executable and an initialization library, named as follows: - `_test.c` - `intercept_sys_.c` -They can be compiled with +Granted that syscall_intercept is already built, assertion tests can alternatively +be compiled in this directory with ```shell make ``` @@ -13,23 +85,10 @@ and executed with ```shell make test ``` + Alternatively, it is possible to execute a specific test with the following command, where syscall-name must be replaced with one of the entries in the TESTS variable in the Makefile ``` make -``` - -## How these test work ## - -These tests basically assert a condition which can't possibly be true unless -the hook function is executed as expected thanks to a correct interception of -the tested system call. As an example, the `write` test writes a string to a -file, then reads the written string from that file and in the end asserts that -the two strings are perfectly equal. By looking at the content of -[write_test.c](src/write_test.c) it is obvious how the assertion could never be -true since the written string and the expected string are different. The hook -function which will be executed before forwarding the system call to the kernel -will make sure to modify the string that is going to be written to the file so -that the actual written string and the expected string match. -All the tests implement the described pattern. \ No newline at end of file +``` \ No newline at end of file From 732fc31f0d25d76686a907a7b53c293b846eeebb Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Thu, 17 Jul 2025 14:32:46 +0200 Subject: [PATCH 120/143] removed lines added by github merge --- src/intercept.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/intercept.c b/src/intercept.c index 6d5b443..9a127a4 100644 --- a/src/intercept.c +++ b/src/intercept.c @@ -717,7 +717,7 @@ intercept_routine(struct context *context) * the clone_child_intercept_routine instead, executing * it on the new child threads stack, then returns to libc. */ -#if defined(__x86_64__) || defined(_M_X64) + if (desc.nr == SYS_clone && desc.args[1] != 0) { return (struct wrapper_ret){ FIRST_RET_REG = SYSCALL_NR, SECOND_RET_REG = 2 }; @@ -730,7 +730,7 @@ intercept_routine(struct context *context) } #endif else -#endif + result = syscall_no_intercept(desc.nr, desc.args[0], desc.args[1], From fb6c8fd1481fabaa4670ec53693c9dc4e8cf3f88 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 18 Jul 2025 14:11:29 +0200 Subject: [PATCH 121/143] poll and ppoll test logging fine-tuning --- src/syscall_formats.c | 6 +++--- test/syscall_format.log.match | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/syscall_formats.c b/src/syscall_formats.c index f1be30c..39fdfc9 100644 --- a/src/syscall_formats.c +++ b/src/syscall_formats.c @@ -56,7 +56,7 @@ static const struct syscall_format formats[] = { SARGS(lstat, rdec, arg_cstr, arg_pointer), #endif #ifdef SYS_poll - SARGS(poll, rdec, arg_pointer, arg_, arg_), + SARGS(poll, rdec, arg_pointer, arg_dec, arg_dec), #endif SARGS(lseek, rdec, arg_fd, arg_dec, arg_seek_whence), SARGS(mmap, rpointer, arg_pointer, arg_, arg_, arg_, arg_fd, arg_), @@ -118,7 +118,7 @@ static const struct syscall_format formats[] = { SARGS(socketpair, rdec, arg_, arg_, arg_, arg_), SARGS(setsockopt, rdec, arg_fd, arg_, arg_, arg_, arg_), SARGS(getsockopt, rdec, arg_fd, arg_, arg_, arg_, arg_), - SARGS(clone, rdec, arg_clone_flags, arg_pointer, arg_pointer, arg_pointer, arg_), + SARGS(clone, rdec, arg_clone_flags, arg_pointer, arg_pointer, arg_, arg_), #ifdef SYS_fork SARGS(fork, rdec, arg_none), #endif @@ -383,7 +383,7 @@ static const struct syscall_format formats[] = { SARGS(fchmodat, rdec, arg_atfd, arg_cstr, arg_oct_mode), SARGS(faccessat, rdec, arg_atfd, arg_cstr, arg_oct_mode), SARGS(pselect6, rdec, arg_, arg_, arg_, arg_, arg_, arg_), - SARGS(ppoll, rdec, arg_, arg_, arg_, arg_, arg_), + SARGS(ppoll, rdec, arg_pointer, arg_dec, arg_, arg_, arg_dec), SARGS(unshare, rdec, arg_), SARGS(set_robust_list, rdec, arg_, arg_dec), SARGS(get_robust_list, rdec, arg_, arg_, arg_), diff --git a/test/syscall_format.log.match b/test/syscall_format.log.match index 21238b8..de7ddaf 100644 --- a/test/syscall_format.log.match +++ b/test/syscall_format.log.match @@ -98,12 +98,12 @@ $(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = ? $(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX), 0x100) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX), 0x100) = 22 -$(S) $(XX) -- poll((null), 0x0, 0x7) = ? -$(S) $(XX) -- poll((null), 0x0, 0x7) = 22 -$(S) $(XX) -- poll($(XX), 0x3, 0x7) = ? -$(S) $(XX) -- poll($(XX), 0x3, 0x7) = 22 -$(S) $(XX) -- ppoll($(XX), 0x2, 0x123000, 0x234000, 0x2) = ? -$(S) $(XX) -- ppoll($(XX), 0x2, 0x123000, 0x234000, 0x2) = 22 +$(S) $(XX) -- $(*)poll((null), 0, $(*)) = ? +$(S) $(XX) -- $(*)poll((null), 0, $(*)) = 22 +$(S) $(XX) -- $(*)poll($(XX), 3, $(*)) = ? +$(S) $(XX) -- $(*)poll($(XX), 3, $(*)) = 22 +$(S) $(XX) -- ppoll($(XX), 2, 0x123000, 0x234000, 2) = ? +$(S) $(XX) -- ppoll($(XX), 2, 0x123000, 0x234000, 2) = 22 $(S) $(XX) -- lseek(0, 0, SEEK_SET) = ? $(S) $(XX) -- lseek(0, 0, SEEK_SET) = 22 $(S) $(XX) -- lseek(0, 0, SEEK_CUR) = ? From 8e545545216c6ea42dcd4db682b2f1d1dbf1fac5 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 18 Jul 2025 16:21:17 +0200 Subject: [PATCH 122/143] faccessat test logging fixed --- src/syscall_formats.c | 2 +- test/syscall_format.log.match | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/syscall_formats.c b/src/syscall_formats.c index 39fdfc9..99a1503 100644 --- a/src/syscall_formats.c +++ b/src/syscall_formats.c @@ -381,7 +381,7 @@ static const struct syscall_format formats[] = { SARGS(symlinkat, rdec, arg_cstr, arg_atfd, arg_cstr), SARGS(readlinkat, rdec, arg_atfd, arg_cstr, arg_buf_out, arg_dec), SARGS(fchmodat, rdec, arg_atfd, arg_cstr, arg_oct_mode), - SARGS(faccessat, rdec, arg_atfd, arg_cstr, arg_oct_mode), + SARGS(faccessat, rdec, arg_atfd, arg_cstr, arg_access_mode), SARGS(pselect6, rdec, arg_, arg_, arg_, arg_, arg_, arg_), SARGS(ppoll, rdec, arg_pointer, arg_dec, arg_, arg_, arg_dec), SARGS(unshare, rdec, arg_), diff --git a/test/syscall_format.log.match b/test/syscall_format.log.match index de7ddaf..a0597f3 100644 --- a/test/syscall_format.log.match +++ b/test/syscall_format.log.match @@ -186,14 +186,14 @@ $(S) $(XX) -- rt_sigprocmask(0x2, 0x0000000000123000, 0x0000000000234000, 10) = $(S) $(XX) -- rt_sigprocmask(0x2, 0x0000000000123000, 0x0000000000234000, 10) = 22 $(S) $(XX) -- ioctl(1, 0x4d, 0x0000000000234000) = ? $(S) $(XX) -- ioctl(1, 0x4d, 0x0000000000234000) = 22 -$(S) $(XX) -- access((null), F_OK) = ? -$(S) $(XX) -- access((null), F_OK) = 22 -$(S) $(XX) -- access("input_data\x01\x02\x03\n\r\t", X_OK) = ? -$(S) $(XX) -- access("input_data\x01\x02\x03\n\r\t", X_OK) = 22 -$(S) $(XX) -- access("", R_OK | W_OK) = ? -$(S) $(XX) -- access("", R_OK | W_OK) = 22 -$(S) $(XX) -- access("input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = ? -$(S) $(XX) -- access("input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = 22 +$(S) $(XX) -- $(*)access$(*)($(*)(null), F_OK) = ? +$(S) $(XX) -- $(*)access$(*)($(*)(null), F_OK) = 22 +$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", X_OK) = ? +$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", X_OK) = 22 +$(S) $(XX) -- $(*)access$(*)($(*)"", R_OK | W_OK) = ? +$(S) $(XX) -- $(*)access$(*)($(*)"", R_OK | W_OK) = 22 +$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = ? +$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = 22 $(S) $(XX) -- faccessat2(AT_FDCWD, (null), 00, $(XX)) = ? $(S) $(XX) -- faccessat2(AT_FDCWD, (null), 00, $(XX)) = 22 $(S) $(XX) -- faccessat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, $(XX)) = ? From 107221fd025db5584204bcf2b045bf0ef9ca23b7 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 18 Jul 2025 16:28:52 +0200 Subject: [PATCH 123/143] dup2/dup3 logging test discrepancy solved --- test/syscall_format.log.match | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/syscall_format.log.match b/test/syscall_format.log.match index a0597f3..d7edb85 100644 --- a/test/syscall_format.log.match +++ b/test/syscall_format.log.match @@ -222,8 +222,8 @@ $(S) $(XX) -- shmdt(0x123000) = ? $(S) $(XX) -- shmdt(0x123000) = 22 $(S) $(XX) -- dup(4) = ? $(S) $(XX) -- dup(4) = 22 -$(S) $(XX) -- dup2(4, 5) = ? -$(S) $(XX) -- dup2(4, 5) = 22 +$(S) $(XX) -- dup$(N)(4, 5$(*)) = ? +$(S) $(XX) -- dup$(N)(4, 5$(*)) = 22 $(S) $(XX) -- dup3(4, 5, 0x0) = ? $(S) $(XX) -- dup3(4, 5, 0x0) = 22 $(S) $(XX) -- dup3(4, 5, 0x80000) = ? From eb3713c7baa7de8f6f57ea0771ea86bf123335bb Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 18 Jul 2025 16:42:03 +0200 Subject: [PATCH 124/143] replaced token with where just letters can be present --- test/libcintercept0.log.match | 8 +++--- test/libcintercept0_child.log.match | 8 +++--- test/syscall_format.log.match | 44 ++++++++++++++--------------- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/test/libcintercept0.log.match b/test/libcintercept0.log.match index 546c085..ee3cd30 100644 --- a/test/libcintercept0.log.match +++ b/test/libcintercept0.log.match @@ -11,16 +11,16 @@ $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = $(N) $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = $(N) -$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = ? -$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = 0 +$(S) $(XX) -- $(S)fstat$(S)($(N), $(*)) = ? +$(S) $(XX) -- $(S)fstat$(S)($(N), $(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(S) $(XX) -- read($(N), $(XX), $(N)) = ? $(S) $(XX) -- read($(N), "/*\n * Copyright 2016-2017, Intel Corporation\n *\n * Redistribution and use in source and binary forms, with or without\n...", $(N)) = $(N) -$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = ? -$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = 0 +$(S) $(XX) -- $(S)fstat$(S)(1, $(*)) = ? +$(S) $(XX) -- $(S)fstat$(S)(1, $(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? diff --git a/test/libcintercept0_child.log.match b/test/libcintercept0_child.log.match index 4f8478c..46a3a66 100644 --- a/test/libcintercept0_child.log.match +++ b/test/libcintercept0_child.log.match @@ -2,16 +2,16 @@ $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = $(N) $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = $(N) -$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = ? -$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = 0 +$(S) $(XX) -- $(S)fstat$(S)($(N), $(*)) = ? +$(S) $(XX) -- $(S)fstat$(S)($(N), $(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(S) $(XX) -- read($(N), $(XX), $(N)) = ? $(S) $(XX) -- read($(N), "/*\n * Copyright 2016-2017, Intel Corporation\n *\n * Redistribution and use in source and binary forms, with or without\n...", $(N)) = $(N) -$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = ? -$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = 0 +$(S) $(XX) -- $(S)fstat$(S)(1, $(*)) = ? +$(S) $(XX) -- $(S)fstat$(S)(1, $(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? diff --git a/test/syscall_format.log.match b/test/syscall_format.log.match index d7edb85..31a86a3 100644 --- a/test/syscall_format.log.match +++ b/test/syscall_format.log.match @@ -74,14 +74,14 @@ $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 -$(S) $(XX) -- $(*)fstat$(*)(0, $(*)) = ? -$(S) $(XX) -- $(*)fstat$(*)(0, $(*)) = 22 -$(OPT)$(S) $(XX) -- $(*)fstat$(*)(-1, $(*)) = ? -$(OPT)$(S) $(XX) -- $(*)fstat$(*)(-1, $(*)) = 22 -$(OPT)$(S) $(XX) -- $(*)fstat$(*)(AT_FDCWD, $(*)) = ? -$(OPT)$(S) $(XX) -- $(*)fstat$(*)(AT_FDCWD, $(*)) = 22 -$(S) $(XX) -- $(*)fstat$(*)(2, $(*)) = ? -$(S) $(XX) -- $(*)fstat$(*)(2, $(*)) = 22 +$(S) $(XX) -- $(S)fstat$(S)(0, $(*)) = ? +$(S) $(XX) -- $(S)fstat$(S)(0, $(*)) = 22 +$(OPT)$(S) $(XX) -- $(S)fstat$(S)(-1, $(*)) = ? +$(OPT)$(S) $(XX) -- $(S)fstat$(S)(-1, $(*)) = 22 +$(OPT)$(S) $(XX) -- $(S)fstat$(S)(AT_FDCWD, $(*)) = ? +$(OPT)$(S) $(XX) -- $(S)fstat$(S)(AT_FDCWD, $(*)) = 22 +$(S) $(XX) -- $(S)fstat$(S)(2, $(*)) = ? +$(S) $(XX) -- $(S)fstat$(S)(2, $(*)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? @@ -98,10 +98,10 @@ $(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = ? $(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX), 0x100) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX), 0x100) = 22 -$(S) $(XX) -- $(*)poll((null), 0, $(*)) = ? -$(S) $(XX) -- $(*)poll((null), 0, $(*)) = 22 -$(S) $(XX) -- $(*)poll($(XX), 3, $(*)) = ? -$(S) $(XX) -- $(*)poll($(XX), 3, $(*)) = 22 +$(S) $(XX) -- $(S)poll((null), 0, $(*)) = ? +$(S) $(XX) -- $(S)poll((null), 0, $(*)) = 22 +$(S) $(XX) -- $(S)poll($(XX), 3, $(*)) = ? +$(S) $(XX) -- $(S)poll($(XX), 3, $(*)) = 22 $(S) $(XX) -- ppoll($(XX), 2, 0x123000, 0x234000, 2) = ? $(S) $(XX) -- ppoll($(XX), 2, 0x123000, 0x234000, 2) = 22 $(S) $(XX) -- lseek(0, 0, SEEK_SET) = ? @@ -186,14 +186,14 @@ $(S) $(XX) -- rt_sigprocmask(0x2, 0x0000000000123000, 0x0000000000234000, 10) = $(S) $(XX) -- rt_sigprocmask(0x2, 0x0000000000123000, 0x0000000000234000, 10) = 22 $(S) $(XX) -- ioctl(1, 0x4d, 0x0000000000234000) = ? $(S) $(XX) -- ioctl(1, 0x4d, 0x0000000000234000) = 22 -$(S) $(XX) -- $(*)access$(*)($(*)(null), F_OK) = ? -$(S) $(XX) -- $(*)access$(*)($(*)(null), F_OK) = 22 -$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", X_OK) = ? -$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", X_OK) = 22 -$(S) $(XX) -- $(*)access$(*)($(*)"", R_OK | W_OK) = ? -$(S) $(XX) -- $(*)access$(*)($(*)"", R_OK | W_OK) = 22 -$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = ? -$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = 22 +$(S) $(XX) -- $(S)access$(S)($(*)(null), F_OK) = ? +$(S) $(XX) -- $(S)access$(S)($(*)(null), F_OK) = 22 +$(S) $(XX) -- $(S)access$(S)($(*)"input_data\x01\x02\x03\n\r\t", X_OK) = ? +$(S) $(XX) -- $(S)access$(S)($(*)"input_data\x01\x02\x03\n\r\t", X_OK) = 22 +$(S) $(XX) -- $(S)access$(S)($(*)"", R_OK | W_OK) = ? +$(S) $(XX) -- $(S)access$(S)($(*)"", R_OK | W_OK) = 22 +$(S) $(XX) -- $(S)access$(S)($(*)"input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = ? +$(S) $(XX) -- $(S)access$(S)($(*)"input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = 22 $(S) $(XX) -- faccessat2(AT_FDCWD, (null), 00, $(XX)) = ? $(S) $(XX) -- faccessat2(AT_FDCWD, (null), 00, $(XX)) = 22 $(S) $(XX) -- faccessat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, $(XX)) = ? @@ -228,8 +228,8 @@ $(S) $(XX) -- dup3(4, 5, 0x0) = ? $(S) $(XX) -- dup3(4, 5, 0x0) = 22 $(S) $(XX) -- dup3(4, 5, 0x80000) = ? $(S) $(XX) -- dup3(4, 5, 0x80000) = 22 -$(S) $(XX) -- pause() = ? -$(S) $(XX) -- pause() = 22 +$(S) $(XX) -- p$(S)($(*)) = ? +$(S) $(XX) -- p$(S)($(*)) = 22 $(S) $(XX) -- clock_nanosleep(0x0, 0x0, 0x123000, 0x234000) = ? $(S) $(XX) -- clock_nanosleep(0x0, 0x0, 0x123000, 0x234000) = 22 $(S) $(XX) -- getitimer(0x3, 0x123000) = ? From 77fd75a1d46d4f70f7718245bcf765e19cb933c0 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 18 Jul 2025 16:48:35 +0200 Subject: [PATCH 125/143] revert token substitution --- test/libcintercept0.log.match | 8 ++++---- test/libcintercept0_child.log.match | 8 ++++---- test/syscall_format.log.match | 24 ++++++++++++------------ 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/test/libcintercept0.log.match b/test/libcintercept0.log.match index ee3cd30..546c085 100644 --- a/test/libcintercept0.log.match +++ b/test/libcintercept0.log.match @@ -11,16 +11,16 @@ $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = $(N) $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = $(N) -$(S) $(XX) -- $(S)fstat$(S)($(N), $(*)) = ? -$(S) $(XX) -- $(S)fstat$(S)($(N), $(*)) = 0 +$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(S) $(XX) -- read($(N), $(XX), $(N)) = ? $(S) $(XX) -- read($(N), "/*\n * Copyright 2016-2017, Intel Corporation\n *\n * Redistribution and use in source and binary forms, with or without\n...", $(N)) = $(N) -$(S) $(XX) -- $(S)fstat$(S)(1, $(*)) = ? -$(S) $(XX) -- $(S)fstat$(S)(1, $(*)) = 0 +$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? diff --git a/test/libcintercept0_child.log.match b/test/libcintercept0_child.log.match index 46a3a66..4f8478c 100644 --- a/test/libcintercept0_child.log.match +++ b/test/libcintercept0_child.log.match @@ -2,16 +2,16 @@ $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = $(N) $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = $(N) -$(S) $(XX) -- $(S)fstat$(S)($(N), $(*)) = ? -$(S) $(XX) -- $(S)fstat$(S)($(N), $(*)) = 0 +$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(S) $(XX) -- read($(N), $(XX), $(N)) = ? $(S) $(XX) -- read($(N), "/*\n * Copyright 2016-2017, Intel Corporation\n *\n * Redistribution and use in source and binary forms, with or without\n...", $(N)) = $(N) -$(S) $(XX) -- $(S)fstat$(S)(1, $(*)) = ? -$(S) $(XX) -- $(S)fstat$(S)(1, $(*)) = 0 +$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? diff --git a/test/syscall_format.log.match b/test/syscall_format.log.match index 31a86a3..de64dd8 100644 --- a/test/syscall_format.log.match +++ b/test/syscall_format.log.match @@ -98,10 +98,10 @@ $(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = ? $(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX), 0x100) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX), 0x100) = 22 -$(S) $(XX) -- $(S)poll((null), 0, $(*)) = ? -$(S) $(XX) -- $(S)poll((null), 0, $(*)) = 22 -$(S) $(XX) -- $(S)poll($(XX), 3, $(*)) = ? -$(S) $(XX) -- $(S)poll($(XX), 3, $(*)) = 22 +$(S) $(XX) -- $(*)poll((null), 0, $(*)) = ? +$(S) $(XX) -- $(*)poll((null), 0, $(*)) = 22 +$(S) $(XX) -- $(*)poll($(XX), 3, $(*)) = ? +$(S) $(XX) -- $(*)poll($(XX), 3, $(*)) = 22 $(S) $(XX) -- ppoll($(XX), 2, 0x123000, 0x234000, 2) = ? $(S) $(XX) -- ppoll($(XX), 2, 0x123000, 0x234000, 2) = 22 $(S) $(XX) -- lseek(0, 0, SEEK_SET) = ? @@ -186,14 +186,14 @@ $(S) $(XX) -- rt_sigprocmask(0x2, 0x0000000000123000, 0x0000000000234000, 10) = $(S) $(XX) -- rt_sigprocmask(0x2, 0x0000000000123000, 0x0000000000234000, 10) = 22 $(S) $(XX) -- ioctl(1, 0x4d, 0x0000000000234000) = ? $(S) $(XX) -- ioctl(1, 0x4d, 0x0000000000234000) = 22 -$(S) $(XX) -- $(S)access$(S)($(*)(null), F_OK) = ? -$(S) $(XX) -- $(S)access$(S)($(*)(null), F_OK) = 22 -$(S) $(XX) -- $(S)access$(S)($(*)"input_data\x01\x02\x03\n\r\t", X_OK) = ? -$(S) $(XX) -- $(S)access$(S)($(*)"input_data\x01\x02\x03\n\r\t", X_OK) = 22 -$(S) $(XX) -- $(S)access$(S)($(*)"", R_OK | W_OK) = ? -$(S) $(XX) -- $(S)access$(S)($(*)"", R_OK | W_OK) = 22 -$(S) $(XX) -- $(S)access$(S)($(*)"input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = ? -$(S) $(XX) -- $(S)access$(S)($(*)"input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = 22 +$(S) $(XX) -- $(*)access$(*)($(*)(null), F_OK) = ? +$(S) $(XX) -- $(*)access$(*)($(*)(null), F_OK) = 22 +$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", X_OK) = ? +$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", X_OK) = 22 +$(S) $(XX) -- $(*)access$(*)($(*)"", R_OK | W_OK) = ? +$(S) $(XX) -- $(*)access$(*)($(*)"", R_OK | W_OK) = 22 +$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = ? +$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = 22 $(S) $(XX) -- faccessat2(AT_FDCWD, (null), 00, $(XX)) = ? $(S) $(XX) -- faccessat2(AT_FDCWD, (null), 00, $(XX)) = 22 $(S) $(XX) -- faccessat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, $(XX)) = ? From 489606b6436e67cc4439dfbd68ad23c2f5f9c698 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 18 Jul 2025 17:27:59 +0200 Subject: [PATCH 126/143] Created different log match files for each arch --- test/CMakeLists.txt | 8 +- test/arch/riscv/syscall_format.log.match | 782 ++++++++++++++++++++++ test/arch/x86_64/syscall_format.log.match | 782 ++++++++++++++++++++++ test/libcintercept0.log.match | 8 +- test/libcintercept0_child.log.match | 8 +- 5 files changed, 1579 insertions(+), 9 deletions(-) create mode 100644 test/arch/riscv/syscall_format.log.match create mode 100644 test/arch/x86_64/syscall_format.log.match diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 76ffe57..b181c5b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -173,6 +173,12 @@ add_test(NAME "clone_thread" set_tests_properties("clone_thread" PROPERTIES PASS_REGULAR_EXPRESSION "clone_hook_child called") +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86(_64)?)$") + set(MATCH_FILE ${CMAKE_CURRENT_SOURCE_DIR}/arch/x86_64/syscall_format.log.match) +elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv(32|64))$") + set(MATCH_FILE ${CMAKE_CURRENT_SOURCE_DIR}/arch/riscv/syscall_format.log.match) +endif() + add_executable(syscall_format syscall_format.c) target_link_libraries(syscall_format PRIVATE syscall_intercept_shared) add_test(NAME "syscall_format_logging" @@ -180,7 +186,7 @@ add_test(NAME "syscall_format_logging" -DTEST_EXTRA_PRELOAD=${TEST_EXTRA_PRELOAD} -DTEST_PROG=$ -DLIB_FILE= - -DMATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/syscall_format.log.match + -DMATCH_FILE=${MATCH_FILE} -DTEST_NAME=syscall_format_logging ${CHECK_LOG_COMMON_ARGS}) diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match new file mode 100644 index 0000000..de64dd8 --- /dev/null +++ b/test/arch/riscv/syscall_format.log.match @@ -0,0 +1,782 @@ +$(S) $(XX) -- read(9, (null), 44) = ? +$(S) $(XX) -- read(9, (null), 44) = 22 +$(S) $(XX) -- read(7, $(XX), 19) = ? +$(S) $(XX) -- read(7, "expected_output_data\x06\xff", 19) = 22 +$(S) $(XX) -- write(7, "input_data\x01\x02\x03\n\r\t\0\0\0\0", 20) = ? +$(S) $(XX) -- write(7, "input_data\x01\x02\x03\n\r\t\0\0\0\0", 20) = 22 +$(S) $(XX) -- pread64(7, $(XX), 19, 4294967311) = ? +$(S) $(XX) -- pread64(7, "expected_output_data\x06\xff", 19, 4294967311) = 22 +$(S) $(XX) -- pread64(-99, $(XX), 18, 0) = ? +$(S) $(XX) -- pread64(-99, "expected_output_data\x06\xff", 18, 0) = 22 +$(S) $(XX) -- pread64(8, (null), 18, 0) = ? +$(S) $(XX) -- pread64(8, (null), 18, 0) = 22 +$(S) $(XX) -- pwrite64(7, "input_data\x01\x02\x03\n\r\t\0\0\0", 19, 4294967311) = ? +$(S) $(XX) -- pwrite64(7, "input_data\x01\x02\x03\n\r\t\0\0\0", 19, 4294967311) = 22 +$(S) $(XX) -- pwrite64(-99, "input_data\x01\x02\x03\n\r\t\0\0", 18, 0) = ? +$(S) $(XX) -- pwrite64(-99, "input_data\x01\x02\x03\n\r\t\0\0", 18, 0) = 22 +$(S) $(XX) -- pwrite64(-100, (null), 18, -1) = ? +$(S) $(XX) -- pwrite64(-100, (null), 18, -1) = 22 +$(S) $(XX) -- readv(1, 0x0000000000123000, 4) = ? +$(S) $(XX) -- readv(1, 0x0000000000123000, 4) = 22 +$(S) $(XX) -- readv(1, (null), 4) = ? +$(S) $(XX) -- readv(1, (null), 4) = 22 +$(S) $(XX) -- writev(1, 0x0000000000123000, 4) = ? +$(S) $(XX) -- writev(1, 0x0000000000123000, 4) = 22 +$(S) $(XX) -- writev(1, (null), 4) = ? +$(S) $(XX) -- writev(1, (null), 4) = 22 +$(S) $(XX) -- preadv(1, 0x123000, 0x4, 0x1000) = ? +$(S) $(XX) -- preadv(1, 0x123000, 0x4, 0x1000) = 22 +$(S) $(XX) -- preadv(1, 0x0, 0x4, 0x1000) = ? +$(S) $(XX) -- preadv(1, 0x0, 0x4, 0x1000) = 22 +$(S) $(XX) -- pwritev(1, 0x123000, 0x4, 0x1000) = ? +$(S) $(XX) -- pwritev(1, 0x123000, 0x4, 0x1000) = 22 +$(S) $(XX) -- pwritev(1, 0x0, 0x4, 0x1000) = ? +$(S) $(XX) -- pwritev(1, 0x0, 0x4, 0x1000) = 22 +$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = ? +$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = 22 +$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? +$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDONLY) = 22 +$(OPT)$(S) $(XX) -- open((null), O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = ? +$(OPT)$(S) $(XX) -- open((null), O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = 22 +$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = ? +$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = 22 +$(OPT)$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_NONBLOCK) = ? +$(OPT)$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_NONBLOCK) = 22 +$(OPT)$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? +$(OPT)$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDONLY) = 22 +$(OPT)$(S) $(XX) -- open((null), O_RDONLY) = ? +$(OPT)$(S) $(XX) -- open((null), O_RDONLY) = 22 +$(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = ? +$(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = 22 +$(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? +$(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDONLY) = 22 +$(S) $(XX) -- openat(AT_FDCWD, (null), O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = ? +$(S) $(XX) -- openat(AT_FDCWD, (null), O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = 22 +$(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = ? +$(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = 22 +$(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_NONBLOCK) = ? +$(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_NONBLOCK) = 22 +$(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? +$(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDONLY) = 22 +$(S) $(XX) -- openat(AT_FDCWD, (null), O_RDONLY) = ? +$(S) $(XX) -- openat(AT_FDCWD, (null), O_RDONLY) = 22 +$(S) $(XX) -- openat(99, "input_data\x01\x02\x03\n\r\t", O_RDONLY | O_CREAT, 0777) = ? +$(S) $(XX) -- openat(99, "input_data\x01\x02\x03\n\r\t", O_RDONLY | O_CREAT, 0777) = 22 +$(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_TMPFILE, 0333) = ? +$(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_TMPFILE, 0333) = 22 +$(S) $(XX) -- close(9) = ? +$(S) $(XX) -- close(9) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 +$(S) $(XX) -- $(S)fstat$(S)(0, $(*)) = ? +$(S) $(XX) -- $(S)fstat$(S)(0, $(*)) = 22 +$(OPT)$(S) $(XX) -- $(S)fstat$(S)(-1, $(*)) = ? +$(OPT)$(S) $(XX) -- $(S)fstat$(S)(-1, $(*)) = 22 +$(OPT)$(S) $(XX) -- $(S)fstat$(S)(AT_FDCWD, $(*)) = ? +$(OPT)$(S) $(XX) -- $(S)fstat$(S)(AT_FDCWD, $(*)) = 22 +$(S) $(XX) -- $(S)fstat$(S)(2, $(*)) = ? +$(S) $(XX) -- $(S)fstat$(S)(2, $(*)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x0, 0x0) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x0, 0x0) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), 0x0, 0x0) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), 0x0, 0x0) = 22 +$(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = ? +$(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX), 0x100) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX), 0x100) = 22 +$(S) $(XX) -- $(*)poll((null), 0, $(*)) = ? +$(S) $(XX) -- $(*)poll((null), 0, $(*)) = 22 +$(S) $(XX) -- $(*)poll($(XX), 3, $(*)) = ? +$(S) $(XX) -- $(*)poll($(XX), 3, $(*)) = 22 +$(S) $(XX) -- ppoll($(XX), 2, 0x123000, 0x234000, 2) = ? +$(S) $(XX) -- ppoll($(XX), 2, 0x123000, 0x234000, 2) = 22 +$(S) $(XX) -- lseek(0, 0, SEEK_SET) = ? +$(S) $(XX) -- lseek(0, 0, SEEK_SET) = 22 +$(S) $(XX) -- lseek(0, 0, SEEK_CUR) = ? +$(S) $(XX) -- lseek(0, 0, SEEK_CUR) = 22 +$(S) $(XX) -- lseek(0, 0, SEEK_END) = ? +$(S) $(XX) -- lseek(0, 0, SEEK_END) = 22 +$(S) $(XX) -- lseek(0, 0, SEEK_HOLE) = ? +$(S) $(XX) -- lseek(0, 0, SEEK_HOLE) = 22 +$(S) $(XX) -- lseek(0, 0, SEEK_DATA) = ? +$(S) $(XX) -- lseek(0, 0, SEEK_DATA) = 22 +$(S) $(XX) -- lseek(2, -1, SEEK_SET) = ? +$(S) $(XX) -- lseek(2, -1, SEEK_SET) = 22 +$(S) $(XX) -- lseek(2, -1, SEEK_CUR) = ? +$(S) $(XX) -- lseek(2, -1, SEEK_CUR) = 22 +$(S) $(XX) -- lseek(2, -1, SEEK_END) = ? +$(S) $(XX) -- lseek(2, -1, SEEK_END) = 22 +$(S) $(XX) -- lseek(2, -1, SEEK_HOLE) = ? +$(S) $(XX) -- lseek(2, -1, SEEK_HOLE) = 22 +$(S) $(XX) -- lseek(2, -1, SEEK_DATA) = ? +$(S) $(XX) -- lseek(2, -1, SEEK_DATA) = 22 +$(S) $(XX) -- lseek(-100, 99999, SEEK_SET) = ? +$(S) $(XX) -- lseek(-100, 99999, SEEK_SET) = 22 +$(S) $(XX) -- lseek(-100, 99999, SEEK_CUR) = ? +$(S) $(XX) -- lseek(-100, 99999, SEEK_CUR) = 22 +$(S) $(XX) -- lseek(-100, 99999, SEEK_END) = ? +$(S) $(XX) -- lseek(-100, 99999, SEEK_END) = 22 +$(S) $(XX) -- lseek(-100, 99999, SEEK_HOLE) = ? +$(S) $(XX) -- lseek(-100, 99999, SEEK_HOLE) = 22 +$(S) $(XX) -- lseek(-100, 99999, SEEK_DATA) = ? +$(S) $(XX) -- lseek(-100, 99999, SEEK_DATA) = 22 +$(S) $(XX) -- mmap((null), 0x0, 0x0, 0x0, 0, 0x0) = ? +$(S) $(XX) -- mmap((null), 0x0, 0x0, 0x0, 0, 0x0) = -22 EINVAL (Invalid argument) +$(S) $(XX) -- mmap(0x0000000000123000, 0x8000, 0x4, 0x1, 99, 0x1000) = ? +$(S) $(XX) -- mmap(0x0000000000123000, 0x8000, 0x4, 0x1, 99, 0x1000) = 0x0000000000000016 +$(S) $(XX) -- mprotect(0x0000000000123000, 0x4000, 0x1) = ? +$(S) $(XX) -- mprotect(0x0000000000123000, 0x4000, 0x1) = 22 +$(S) $(XX) -- mprotect((null), 0x4000, 0x2) = ? +$(S) $(XX) -- mprotect((null), 0x4000, 0x2) = 22 +$(S) $(XX) -- munmap(0x0000000000123000, 0x4000) = ? +$(S) $(XX) -- munmap(0x0000000000123000, 0x4000) = 22 +$(S) $(XX) -- munmap((null), 0x4000) = ? +$(S) $(XX) -- munmap((null), 0x4000) = 22 +$(S) $(XX) -- brk($(N)) = ? +$(S) $(XX) -- brk($(N)) = 22 +$(S) $(XX) -- brk(0) = ? +$(S) $(XX) -- brk(0) = 22 +$(S) $(XX) -- mremap(0x0000000000123000, 4294967302, 4294967372, 1, $(XX)) = ? +$(S) $(XX) -- mremap(0x0000000000123000, 4294967302, 4294967372, 1, $(XX)) = 0x0000000000000016 +$(S) $(XX) -- msync(0x0000000000123000, 0, 1) = ? +$(S) $(XX) -- msync(0x0000000000123000, 0, 1) = 22 +$(S) $(XX) -- msync((null), 888, 2) = ? +$(S) $(XX) -- msync((null), 888, 2) = 22 +$(S) $(XX) -- mincore(0x0000000000123000, 99, 0x0000000000234000) = ? +$(S) $(XX) -- mincore(0x0000000000123000, 99, 0x0000000000234000) = 22 +$(S) $(XX) -- mincore(0x0000000000234000, 1234, (null)) = ? +$(S) $(XX) -- mincore(0x0000000000234000, 1234, (null)) = 22 +$(S) $(XX) -- mincore((null), 0, 0x0000000000123000) = ? +$(S) $(XX) -- mincore((null), 0, 0x0000000000123000) = 22 +$(S) $(XX) -- madvise(0x0000000000123000, 99, 0) = ? +$(S) $(XX) -- madvise(0x0000000000123000, 99, 0) = 22 +$(S) $(XX) -- madvise(0x0000000000234000, 1234, 4) = ? +$(S) $(XX) -- madvise(0x0000000000234000, 1234, 4) = 22 +$(S) $(XX) -- madvise((null), 0, 2) = ? +$(S) $(XX) -- madvise((null), 0, 2) = 22 +$(S) $(XX) -- mlock(0x123000, 0x3000) = ? +$(S) $(XX) -- mlock(0x123000, 0x3000) = 22 +$(OPT)$(S) $(XX) -- mlock2(0x123000, 0x3000, 0x0) = ? +$(OPT)$(S) $(XX) -- mlock2(0x123000, 0x3000, 0x0) = 22 +$(S) $(XX) -- munlock(0x123000, 0x3000) = ? +$(S) $(XX) -- munlock(0x123000, 0x3000) = 22 +$(S) $(XX) -- mlockall(0x1) = ? +$(S) $(XX) -- mlockall(0x1) = 22 +$(S) $(XX) -- mlockall(0x2) = ? +$(S) $(XX) -- mlockall(0x2) = 22 +$(S) $(XX) -- munlockall() = ? +$(S) $(XX) -- munlockall() = 22 +$(S) $(XX) -- rt_sigaction(2, 0x0000000000123000, 0x0000000000234000, 10) = ? +$(S) $(XX) -- rt_sigaction(2, 0x0000000000123000, 0x0000000000234000, 10) = 22 +$(S) $(XX) -- rt_sigprocmask(0x2, 0x0000000000123000, 0x0000000000234000, 10) = ? +$(S) $(XX) -- rt_sigprocmask(0x2, 0x0000000000123000, 0x0000000000234000, 10) = 22 +$(S) $(XX) -- ioctl(1, 0x4d, 0x0000000000234000) = ? +$(S) $(XX) -- ioctl(1, 0x4d, 0x0000000000234000) = 22 +$(S) $(XX) -- $(*)access$(*)($(*)(null), F_OK) = ? +$(S) $(XX) -- $(*)access$(*)($(*)(null), F_OK) = 22 +$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", X_OK) = ? +$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", X_OK) = 22 +$(S) $(XX) -- $(*)access$(*)($(*)"", R_OK | W_OK) = ? +$(S) $(XX) -- $(*)access$(*)($(*)"", R_OK | W_OK) = 22 +$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = ? +$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = 22 +$(S) $(XX) -- faccessat2(AT_FDCWD, (null), 00, $(XX)) = ? +$(S) $(XX) -- faccessat2(AT_FDCWD, (null), 00, $(XX)) = 22 +$(S) $(XX) -- faccessat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, $(XX)) = ? +$(S) $(XX) -- faccessat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, $(XX)) = 22 +$(S) $(XX) -- faccessat2(AT_FDCWD, "", 06, $(XX)) = ? +$(S) $(XX) -- faccessat2(AT_FDCWD, "", 06, $(XX)) = 22 +$(S) $(XX) -- faccessat2(9, "input_data\x01\x02\x03\n\r\t", 07, $(XX)) = ? +$(S) $(XX) -- faccessat2(9, "input_data\x01\x02\x03\n\r\t", 07, $(XX)) = 22 +$(S) $(XX) -- pipe2($(XX), $(N)) = ? +$(S) $(XX) -- pipe2([123, 234], $(N)) = 22 +$(S) $(XX) -- pipe2($(XX), 0) = ? +$(S) $(XX) -- pipe2([123, 234], 0) = 22 +$(S) $(XX) -- pselect6(0x2, 0x123000, 0x234000, 0x456000, $(XX), $(XX)) = ? +$(S) $(XX) -- pselect6(0x2, 0x123000, 0x234000, 0x456000, $(XX), $(XX)) = 22 +$(S) $(XX) -- pselect6(0x2, 0x123000, 0x234000, 0x123000, 0x234000, 0x123000) = ? +$(S) $(XX) -- pselect6(0x2, 0x123000, 0x234000, 0x123000, 0x234000, 0x123000) = 22 +$(S) $(XX) -- sched_yield() = ? +$(S) $(XX) -- sched_yield() = 22 +$(S) $(XX) -- shmget(0x3, 0x4, 0x5) = ? +$(S) $(XX) -- shmget(0x3, 0x4, 0x5) = 22 +$(S) $(XX) -- shmat(0x3, 0x123000, 0x5) = ? +$(S) $(XX) -- shmat(0x3, 0x123000, 0x5) = 0x16 +$(S) $(XX) -- shmctl(0x3, 0xe, 0x123000) = ? +$(S) $(XX) -- shmctl(0x3, 0xe, 0x123000) = 22 +$(S) $(XX) -- shmdt(0x123000) = ? +$(S) $(XX) -- shmdt(0x123000) = 22 +$(S) $(XX) -- dup(4) = ? +$(S) $(XX) -- dup(4) = 22 +$(S) $(XX) -- dup$(N)(4, 5$(*)) = ? +$(S) $(XX) -- dup$(N)(4, 5$(*)) = 22 +$(S) $(XX) -- dup3(4, 5, 0x0) = ? +$(S) $(XX) -- dup3(4, 5, 0x0) = 22 +$(S) $(XX) -- dup3(4, 5, 0x80000) = ? +$(S) $(XX) -- dup3(4, 5, 0x80000) = 22 +$(S) $(XX) -- p$(S)($(*)) = ? +$(S) $(XX) -- p$(S)($(*)) = 22 +$(S) $(XX) -- clock_nanosleep(0x0, 0x0, 0x123000, 0x234000) = ? +$(S) $(XX) -- clock_nanosleep(0x0, 0x0, 0x123000, 0x234000) = 22 +$(S) $(XX) -- getitimer(0x3, 0x123000) = ? +$(S) $(XX) -- getitimer(0x3, 0x123000) = 22 +$(S) $(XX) -- alarm(0x4) = ? +$(S) $(XX) -- alarm(0x4) = 22 +$(S) $(XX) -- setitimer(0x6, 0x123000, 0x234000) = ? +$(S) $(XX) -- setitimer(0x6, 0x123000, 0x234000) = 22 +$(S) $(XX) -- getpid() = ? +$(S) $(XX) -- getpid() = 22 +$(S) $(XX) -- sendfile(6, 7, 0x123000, 0x63) = ? +$(S) $(XX) -- sendfile(6, 7, 0x123000, 0x63) = 22 +$(S) $(XX) -- socket(0x2, 0x800, 0x0) = ? +$(S) $(XX) -- socket(0x2, 0x800, 0x0) = 22 +$(S) $(XX) -- connect(8, 0x123000, 0xc) = ? +$(S) $(XX) -- connect(8, 0x123000, 0xc) = 22 +$(S) $(XX) -- accept(4, 0x123000, 0x234000) = ? +$(S) $(XX) -- accept(4, 0x123000, 0x234000) = 22 +$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x0, 0x234000) = ? +$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x0, 0x234000) = 22 +$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x234000) = ? +$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x234000) = 22 +$(S) $(XX) -- sendto(5, 0x123000, 0xc, 0x4) = ? +$(S) $(XX) -- sendto(5, 0x123000, 0xc, 0x4) = 22 +$(S) $(XX) -- recvfrom(5, 0x123000, 0xc, 0x4, 0x234000, 0x234000) = ? +$(S) $(XX) -- recvfrom(5, 0x123000, 0xc, 0x4, 0x234000, 0x234000) = 22 +$(S) $(XX) -- recvmsg(2, 0x123000, 0x2) = ? +$(S) $(XX) -- recvmsg(2, 0x123000, 0x2) = 22 +$(S) $(XX) -- recvmmsg(2, 0x123000, 0xc, 0x10000, 0x234000) = ? +$(S) $(XX) -- recvmmsg(2, 0x123000, 0xc, 0x10000, 0x234000) = 22 +$(S) $(XX) -- sendmsg(2, 0x123000, 0x4000) = ? +$(S) $(XX) -- sendmsg(2, 0x123000, 0x4000) = 22 +$(S) $(XX) -- sendmmsg(2, 0x123000, 0xc, 0x4000) = ? +$(S) $(XX) -- sendmmsg(2, 0x123000, 0xc, 0x4000) = 22 +$(S) $(XX) -- shutdown(3, 0x0) = ? +$(S) $(XX) -- shutdown(3, 0x0) = 22 +$(S) $(XX) -- bind(6, 0x123000, 0x9) = ? +$(S) $(XX) -- bind(6, 0x123000, 0x9) = 22 +$(S) $(XX) -- listen(5, 0x3) = ? +$(S) $(XX) -- listen(5, 0x3) = 22 +$(S) $(XX) -- getsockname(4, 0x123000, 0x234000) = ? +$(S) $(XX) -- getsockname(4, 0x123000, 0x234000) = 22 +$(S) $(XX) -- getpeername(4, 0x123000, 0x234000) = ? +$(S) $(XX) -- getpeername(4, 0x123000, 0x234000) = 22 +$(S) $(XX) -- socketpair(0x4, 0x5, 0x6, 0x123000) = ? +$(S) $(XX) -- socketpair(0x4, 0x5, 0x6, 0x123000) = 22 +$(S) $(XX) -- setsockopt(4, 0x5, 0x6, 0x123000, 0x7) = ? +$(S) $(XX) -- setsockopt(4, 0x5, 0x6, 0x123000, 0x7) = 22 +$(S) $(XX) -- getsockopt(4, 0x5, 0x6, 0x123000, $(XX)) = ? +$(S) $(XX) -- getsockopt(4, 0x5, 0x6, 0x123000, $(XX)) = 22 +$(S) $(XX) -- wait4(7, 0x123000, 0x0, 0x234000) = ? +$(S) $(XX) -- wait4(7, 0x123000, 0x0, 0x234000) = 22 +$(S) $(XX) -- kill(0x4, 0x2) = ? +$(S) $(XX) -- kill(0x4, 0x2) = 22 +$(S) $(XX) -- uname($(XX)) = ? +$(S) $(XX) -- uname($(XX)) = 22 +$(S) $(XX) -- semget(0x4, 0x1, 0x200) = ? +$(S) $(XX) -- semget(0x4, 0x1, 0x200) = 22 +$(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x0) = ? +$(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x0) = 22 +$(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x234000) = ? +$(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x234000) = 22 +$(S) $(XX) -- semctl(0x1, 0x2, 0x3, $(XX), $(XX), 0x234000) = ? +$(S) $(XX) -- semctl(0x1, 0x2, 0x3, $(XX), $(XX), 0x234000) = 22 +$(S) $(XX) -- msgget(0x1, 0x200) = ? +$(S) $(XX) -- msgget(0x1, 0x200) = 22 +$(S) $(XX) -- msgsnd(0x1, 0x123000, 0x3, 0x3) = ? +$(S) $(XX) -- msgsnd(0x1, 0x123000, 0x3, 0x3) = 22 +$(S) $(XX) -- msgrcv(0x1, 0x123000, 0x1, 0x1, 0x1) = ? +$(S) $(XX) -- msgrcv(0x1, 0x123000, 0x1, 0x1, 0x1) = 22 +$(S) $(XX) -- msgctl(0x1, 0x2, 0x123000) = ? +$(S) $(XX) -- msgctl(0x1, 0x2, 0x123000) = 22 +$(S) $(XX) -- fcntl(1, 1030 (F_DUPFD_CLOEXEC), 0x3) = ? +$(S) $(XX) -- fcntl(1, 1030 (F_DUPFD_CLOEXEC), 0x3) = 22 +$(S) $(XX) -- fcntl(10, 4 (F_SETFL), 0x40000) = ? +$(S) $(XX) -- fcntl(10, 4 (F_SETFL), 0x40000) = 22 +$(S) $(XX) -- fcntl(11, 6 (F_SETLK), $(XX) ({.l_type = 1 (F_WRLCK), .l_whence = 2 (SEEK_END), .l_start = 123, .l_len = 456, .l_pid = 768})) = ? +$(S) $(XX) -- fcntl(11, 6 (F_SETLK), $(XX) ({.l_type = 1 (F_WRLCK), .l_whence = 2 (SEEK_END), .l_start = 123, .l_len = 456, .l_pid = 768})) = 22 +$(S) $(XX) -- flock(1, 0x2) = ? +$(S) $(XX) -- flock(1, 0x2) = 22 +$(S) $(XX) -- fsync(2) = ? +$(S) $(XX) -- fsync(2) = 22 +$(S) $(XX) -- fdatasync(2) = ? +$(S) $(XX) -- fdatasync(2) = 22 +$(S) $(XX) -- truncate("input_data\x01\x02\x03\n\r\t", 0x4) = ? +$(S) $(XX) -- truncate("input_data\x01\x02\x03\n\r\t", 0x4) = 22 +$(S) $(XX) -- ftruncate(3, 0x3) = ? +$(S) $(XX) -- ftruncate(3, 0x3) = 22 +$(OPT)$(S) $(XX) -- getdents(4, 0x123000, 0x1) = ? +$(OPT)$(S) $(XX) -- getdents(4, 0x123000, 0x1) = 22 +$(S) $(XX) -- getdents64(4, 0x123000, 0x1) = ? +$(S) $(XX) -- getdents64(4, 0x123000, 0x1) = 22 +$(S) $(XX) -- getcwd($(XX), 0x9) = ? +$(S) $(XX) -- getcwd($(XX), 0x9) = 22 +$(S) $(XX) -- chdir("input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- chdir("input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- fchdir(6) = ? +$(S) $(XX) -- fchdir(6) = 22 +$(S) $(XX) -- rename("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- rename("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- renameat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- renameat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- renameat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- renameat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- renameat(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- renameat(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = 22 +$(OPT)$(S) $(XX) -- mkdir("input_data\x01\x02\x03\n\r\t", 0644) = ? +$(OPT)$(S) $(XX) -- mkdir("input_data\x01\x02\x03\n\r\t", 0644) = 22 +$(S) $(XX) -- mkdirat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0644) = ? +$(S) $(XX) -- mkdirat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0644) = 22 +$(S) $(XX) -- mkdirat(33, "input_data\x01\x02\x03\n\r\t", 0644) = ? +$(S) $(XX) -- mkdirat(33, "input_data\x01\x02\x03\n\r\t", 0644) = 22 +$(S) $(XX) -- mkdirat(33, (null), 0555) = ? +$(S) $(XX) -- mkdirat(33, (null), 0555) = 22 +$(OPT)$(S) $(XX) -- rmdir("input_data\x01\x02\x03\n\r\t") = ? +$(OPT)$(S) $(XX) -- rmdir("input_data\x01\x02\x03\n\r\t") = 22 +$(OPT)$(S) $(XX) -- rmdir((null)) = ? +$(OPT)$(S) $(XX) -- rmdir((null)) = 22 +$(OPT)$(S) $(XX) -- creat("input_data\x01\x02\x03\n\r\t", 0644) = ? +$(OPT)$(S) $(XX) -- creat("input_data\x01\x02\x03\n\r\t", 0644) = 22 +$(S) $(XX) -- link("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- link("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- linkat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? +$(S) $(XX) -- linkat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x0) = 22 +$(S) $(XX) -- linkat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x400) = ? +$(S) $(XX) -- linkat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x400) = 22 +$(S) $(XX) -- linkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x400) = ? +$(S) $(XX) -- linkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x400) = 22 +$(S) $(XX) -- linkat(7, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? +$(S) $(XX) -- linkat(7, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = 22 +$(S) $(XX) -- unlink("input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- unlink("input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- unlinkat(0, "input_data\x01\x02\x03\n\r\t", 0x0) = ? +$(S) $(XX) -- unlinkat(0, "input_data\x01\x02\x03\n\r\t", 0x0) = 22 +$(S) $(XX) -- unlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x200) = ? +$(S) $(XX) -- unlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x200) = 22 +$(S) $(XX) -- unlinkat(9, "other_input_data\x01\x02\x03\n\r\t", 0x200) = ? +$(S) $(XX) -- unlinkat(9, "other_input_data\x01\x02\x03\n\r\t", 0x200) = 22 +$(S) $(XX) -- symlink("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- symlink("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", AT_FDCWD, (null)) = ? +$(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", AT_FDCWD, (null)) = 22 +$(S) $(XX) -- readlink("input_data\x01\x02\x03\n\r\t", $(XX), 16) = ? +$(S) $(XX) -- readlink("input_data\x01\x02\x03\n\r\t", "expected_output_data\x06\xff", 16) = 22 +$(S) $(XX) -- readlinkat(2, "input_data\x01\x02\x03\n\r\t", $(XX), 16) = ? +$(S) $(XX) -- readlinkat(2, "input_data\x01\x02\x03\n\r\t", "expected_output_data\x06\xff", 16) = 22 +$(S) $(XX) -- readlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), 16) = ? +$(S) $(XX) -- readlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", "expected_output_data\x06\xff", 16) = 22 +$(S) $(XX) -- chmod("input_data\x01\x02\x03\n\r\t", 0644) = ? +$(S) $(XX) -- chmod("input_data\x01\x02\x03\n\r\t", 0644) = 22 +$(S) $(XX) -- fchmod(4, 0644) = ? +$(S) $(XX) -- fchmod(4, 0644) = 22 +$(S) $(XX) -- fchmodat(0, "input_data\x01\x02\x03\n\r\t", 0644) = ? +$(S) $(XX) -- fchmodat(0, "input_data\x01\x02\x03\n\r\t", 0644) = 22 +$(S) $(XX) -- fchmodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0111) = ? +$(S) $(XX) -- fchmodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0111) = 22 +$(S) $(XX) -- chown("input_data\x01\x02\x03\n\r\t", 0x2, 0x3) = ? +$(S) $(XX) -- chown("input_data\x01\x02\x03\n\r\t", 0x2, 0x3) = 22 +$(S) $(XX) -- fchown(4, 0x2, 0x3) = ? +$(S) $(XX) -- fchown(4, 0x2, 0x3) = 22 +$(S) $(XX) -- fchownat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x0) = ? +$(S) $(XX) -- fchownat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x0) = 22 +$(S) $(XX) -- fchownat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x100) = ? +$(S) $(XX) -- fchownat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x100) = 22 +$(S) $(XX) -- fchownat(99, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x1000) = ? +$(S) $(XX) -- fchownat(99, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x1000) = 22 +$(S) $(XX) -- lchown("input_data\x01\x02\x03\n\r\t", 0x2, 0x3) = ? +$(S) $(XX) -- lchown("input_data\x01\x02\x03\n\r\t", 0x2, 0x3) = 22 +$(S) $(XX) -- umask(0222) = ? +$(S) $(XX) -- umask(0222) = 026 +$(S) $(XX) -- gettimeofday(0x123000, 0x234000) = ? +$(S) $(XX) -- gettimeofday(0x123000, 0x234000) = 22 +$(S) $(XX) -- gettimeofday(0x0, 0x0) = ? +$(S) $(XX) -- gettimeofday(0x0, 0x0) = 22 +$(S) $(XX) -- settimeofday(0x123000, 0x234000) = ? +$(S) $(XX) -- settimeofday(0x123000, 0x234000) = 22 +$(S) $(XX) -- getrlimit(0x4, 0x234000) = ? +$(S) $(XX) -- getrlimit(0x4, 0x234000) = 22 +$(S) $(XX) -- getrlimit(0x1, 0x234000) = ? +$(S) $(XX) -- getrlimit(0x1, 0x234000) = 22 +$(S) $(XX) -- prlimit64(0x9, 0x4, 0x123000, 0x234000) = ? +$(S) $(XX) -- prlimit64(0x9, 0x4, 0x123000, 0x234000) = 22 +$(S) $(XX) -- prlimit64(0x8, 0x1, 0x123000, 0x234000) = ? +$(S) $(XX) -- prlimit64(0x8, 0x1, 0x123000, 0x234000) = 22 +$(S) $(XX) -- setrlimit(0x0, 0x123000) = ? +$(S) $(XX) -- setrlimit(0x0, 0x123000) = 22 +$(S) $(XX) -- getrusage(0x0, 0x123000) = ? +$(S) $(XX) -- getrusage(0x0, 0x123000) = 22 +$(S) $(XX) -- sysinfo(0x123000, 0x123000) = ? +$(S) $(XX) -- sysinfo(0x123000, 0x123000) = 22 +$(S) $(XX) -- times(0x0) = ? +$(S) $(XX) -- times(0x0) = 22 +$(S) $(XX) -- times(0x123000) = ? +$(S) $(XX) -- times(0x123000) = 22 +$(S) $(XX) -- getuid() = ? +$(S) $(XX) -- getuid() = 22 +$(S) $(XX) -- getgid() = ? +$(S) $(XX) -- getgid() = 22 +$(S) $(XX) -- setuid(0x7b) = ? +$(S) $(XX) -- setuid(0x7b) = 22 +$(S) $(XX) -- setgid(0x7b) = ? +$(S) $(XX) -- setgid(0x7b) = 22 +$(S) $(XX) -- geteuid() = ? +$(S) $(XX) -- geteuid() = 22 +$(S) $(XX) -- getegid() = ? +$(S) $(XX) -- getegid() = 22 +$(S) $(XX) -- setpgid() = ? +$(S) $(XX) -- setpgid() = 22 +$(S) $(XX) -- syscall(110, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? +$(S) $(XX) -- syscall(110, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 +$(S) $(XX) -- getpgrp() = ? +$(S) $(XX) -- getpgrp() = 22 +$(S) $(XX) -- setsid() = ? +$(S) $(XX) -- setsid() = 22 +$(S) $(XX) -- setreuid(0x3, 0x4) = ? +$(S) $(XX) -- setreuid(0x3, 0x4) = 22 +$(S) $(XX) -- setregid(0x6, 0x7) = ? +$(S) $(XX) -- setregid(0x6, 0x7) = 22 +$(S) $(XX) -- getgroups(0x9, 0x123000) = ? +$(S) $(XX) -- getgroups(0x9, 0x123000) = 22 +$(S) $(XX) -- setgroups(0x9, 0x123000) = ? +$(S) $(XX) -- setgroups(0x9, 0x123000) = 22 +$(S) $(XX) -- setresuid(0x1, 0x2, 0x3) = ? +$(S) $(XX) -- setresuid(0x1, 0x2, 0x3) = 22 +$(S) $(XX) -- getresuid(0x123000, 0x234000, 0x234000) = ? +$(S) $(XX) -- getresuid(0x123000, 0x234000, 0x234000) = 22 +$(S) $(XX) -- setresgid(0x1, 0x2, 0x3) = ? +$(S) $(XX) -- setresgid(0x1, 0x2, 0x3) = 22 +$(S) $(XX) -- getresgid(0x123000, 0x234000, 0x234000) = ? +$(S) $(XX) -- getresgid(0x123000, 0x234000, 0x234000) = 22 +$(S) $(XX) -- getpgid(0x63) = ? +$(S) $(XX) -- getpgid(0x63) = 22 +$(S) $(XX) -- setfsuid(0x58) = ? +$(S) $(XX) -- setfsuid(0x58) = 22 +$(S) $(XX) -- setfsgid(0x4d) = ? +$(S) $(XX) -- setfsgid(0x4d) = 22 +$(S) $(XX) -- getsid(0x42) = ? +$(S) $(XX) -- getsid(0x42) = 22 +$(S) $(XX) -- syslog(0x5c, $(XX), 0x3) = ? +$(S) $(XX) -- syslog(0x5c, $(XX), 0x3) = 22 +$(S) $(XX) -- capget(0x123000, 0x234000) = ? +$(S) $(XX) -- capget(0x123000, 0x234000) = 22 +$(S) $(XX) -- capset(0x123000, 0x234000) = ? +$(S) $(XX) -- capset(0x123000, 0x234000) = 22 +$(S) $(XX) -- rt_sigpending(0x123000) = ? +$(S) $(XX) -- rt_sigpending(0x123000) = 22 +$(S) $(XX) -- rt_sigtimedwait(0x123000, 0x234000, 0x234000, 0x2) = ? +$(S) $(XX) -- rt_sigtimedwait(0x123000, 0x234000, 0x234000, 0x2) = 22 +$(S) $(XX) -- rt_sigqueueinfo(0x4d, 0x4, 0x123000) = ? +$(S) $(XX) -- rt_sigqueueinfo(0x4d, 0x4, 0x123000) = 22 +$(S) $(XX) -- rt_tgsigqueueinfo(0x4d, 0x58, 0xc, 0x123000) = ? +$(S) $(XX) -- rt_tgsigqueueinfo(0x4d, 0x58, 0xc, 0x123000) = 22 +$(S) $(XX) -- rt_sigsuspend(0x123000, 0x3) = ? +$(S) $(XX) -- rt_sigsuspend(0x123000, 0x3) = 22 +$(S) $(XX) -- sigaltstack(0x123000, 0x234000) = ? +$(S) $(XX) -- sigaltstack(0x123000, 0x234000) = 22 +$(S) $(XX) -- utimensat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = ? +$(S) $(XX) -- utimensat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = 22 +$(S) $(XX) -- utimensat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = ? +$(S) $(XX) -- utimensat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = 22 +$(S) $(XX) -- utimensat(4, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = ? +$(S) $(XX) -- utimensat(4, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = 22 +$(S) $(XX) -- mknodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = ? +$(S) $(XX) -- mknodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = 22 +$(S) $(XX) -- mknodat(1, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = ? +$(S) $(XX) -- mknodat(1, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = 22 +$(S) $(XX) -- mknodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = ? +$(S) $(XX) -- mknodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = 22 +$(OPT)$(S) $(XX) -- ustat(0x2, 0x123000) = ? +$(OPT)$(S) $(XX) -- ustat(0x2, 0x123000) = 22 +$(S) $(XX) -- statfs("input_data\x01\x02\x03\n\r\t", 0x123000) = ? +$(S) $(XX) -- statfs("input_data\x01\x02\x03\n\r\t", 0x123000) = 22 +$(S) $(XX) -- fstatfs(4, 0x123000) = ? +$(S) $(XX) -- fstatfs(4, 0x123000) = 22 +$(S) $(XX) -- getpriority(0x1, 0x2) = ? +$(S) $(XX) -- getpriority(0x1, 0x2) = 22 +$(S) $(XX) -- setpriority(0x1, 0x2, 0x3) = ? +$(S) $(XX) -- setpriority(0x1, 0x2, 0x3) = 22 +$(S) $(XX) -- sched_setparam(0x1, 0x123000) = ? +$(S) $(XX) -- sched_setparam(0x1, 0x123000) = 22 +$(S) $(XX) -- sched_getparam(0x1, 0x123000) = ? +$(S) $(XX) -- sched_getparam(0x1, 0x123000) = 22 +$(S) $(XX) -- sched_setscheduler(0x1, 0x3, 0x123000) = ? +$(S) $(XX) -- sched_setscheduler(0x1, 0x3, 0x123000) = 22 +$(S) $(XX) -- sched_getscheduler(0x1) = ? +$(S) $(XX) -- sched_getscheduler(0x1) = 22 +$(S) $(XX) -- sched_get_priority_max(0x2) = ? +$(S) $(XX) -- sched_get_priority_max(0x2) = 22 +$(S) $(XX) -- sched_get_priority_min(0x2) = ? +$(S) $(XX) -- sched_get_priority_min(0x2) = 22 +$(S) $(XX) -- sched_rr_get_interval(0x1, 0x123000) = ? +$(S) $(XX) -- sched_rr_get_interval(0x1, 0x123000) = 22 +$(S) $(XX) -- sched_setaffinity(0x4d, 0x4, 0x123000) = ? +$(S) $(XX) -- sched_setaffinity(0x4d, 0x4, 0x123000) = 22 +$(S) $(XX) -- sched_getaffinity(0x4d, 0x4, 0x123000) = ? +$(S) $(XX) -- sched_getaffinity(0x4d, 0x4, 0x123000) = 22 +$(S) $(XX) -- vhangup() = ? +$(S) $(XX) -- vhangup() = 22 +$(OPT)$(S) $(XX) -- modify_ldt(0x1, 0x123000, 0x1) = ? +$(OPT)$(S) $(XX) -- modify_ldt(0x1, 0x123000, 0x1) = 22 +$(S) $(XX) -- pivot_root("input_data\x01\x02\x03\n\r\t", $(XX)) = ? +$(S) $(XX) -- pivot_root("input_data\x01\x02\x03\n\r\t", $(XX)) = 22 +$(OPT)$(S) $(XX) -- _sysctl(0x123000) = ? +$(OPT)$(S) $(XX) -- _sysctl(0x123000) = 22 +$(S) $(XX) -- prctl(0x18, 0x1, 0x2, 0x3, 0x4) = ? +$(S) $(XX) -- prctl(0x18, 0x1, 0x2, 0x3, 0x4) = 22 +$(OPT)$(S) $(XX) -- arch_prctl(0x1002, 0x123000, $(XX)) = ? +$(OPT)$(S) $(XX) -- arch_prctl(0x1002, 0x123000, $(XX)) = 22 +$(S) $(XX) -- clock_adjtime(0x0, 0x123000) = ? +$(S) $(XX) -- clock_adjtime(0x0, 0x123000) = 22 +$(S) $(XX) -- chroot("input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- chroot("input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- sync() = ? +$(S) $(XX) -- sync() = 22 +$(S) $(XX) -- syncfs(3) = ? +$(S) $(XX) -- syncfs(3) = 22 +$(S) $(XX) -- acct("input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- acct("input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- mount("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", 0x123000, 0x80, 0x234000) = ? +$(S) $(XX) -- mount("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", 0x123000, 0x80, 0x234000) = 22 +$(S) $(XX) -- umount2("input_data\x01\x02\x03\n\r\t", 0x0) = ? +$(S) $(XX) -- umount2("input_data\x01\x02\x03\n\r\t", 0x0) = 22 +$(S) $(XX) -- umount2("input_data\x01\x02\x03\n\r\t", 0x2) = ? +$(S) $(XX) -- umount2("input_data\x01\x02\x03\n\r\t", 0x2) = 22 +$(S) $(XX) -- swapon("input_data\x01\x02\x03\n\r\t", 0x8000) = ? +$(S) $(XX) -- swapon("input_data\x01\x02\x03\n\r\t", 0x8000) = 22 +$(S) $(XX) -- swapoff("input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- swapoff("input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- sethostname($(XX), 0x10) = ? +$(S) $(XX) -- sethostname($(XX), 0x10) = 22 +$(S) $(XX) -- setdomainname($(XX), 0x10) = ? +$(S) $(XX) -- setdomainname($(XX), 0x10) = 22 +$(OPT)$(S) $(XX) -- iopl(0x1) = ? +$(OPT)$(S) $(XX) -- iopl(0x1) = 22 +$(OPT)$(S) $(XX) -- ioperm(0x3, 0x4, 0x1) = ? +$(OPT)$(S) $(XX) -- ioperm(0x3, 0x4, 0x1) = 22 +$(S) $(XX) -- syscall(175, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? +$(S) $(XX) -- syscall(175, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 +$(S) $(XX) -- finit_module(3, 0x123000, 0x0) = ? +$(S) $(XX) -- finit_module(3, 0x123000, 0x0) = 22 +$(S) $(XX) -- syscall(176, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? +$(S) $(XX) -- syscall(176, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 +$(S) $(XX) -- syscall(179, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? +$(S) $(XX) -- syscall(179, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 +$(S) $(XX) -- gettid() = ? +$(S) $(XX) -- gettid() = 22 +$(S) $(XX) -- readahead(4, 17185, 123) = ? +$(S) $(XX) -- readahead(4, 17185, 123) = 22 +$(S) $(XX) -- setxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x1) = ? +$(S) $(XX) -- setxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x1) = 22 +$(S) $(XX) -- setxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x2) = ? +$(S) $(XX) -- setxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x2) = 22 +$(S) $(XX) -- lsetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x1) = ? +$(S) $(XX) -- lsetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x1) = 22 +$(S) $(XX) -- lsetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x2) = ? +$(S) $(XX) -- lsetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x2) = 22 +$(S) $(XX) -- fsetxattr(4, "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x2) = ? +$(S) $(XX) -- fsetxattr(4, "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x2) = 22 +$(S) $(XX) -- getxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = ? +$(S) $(XX) -- getxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = 22 +$(S) $(XX) -- getxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = ? +$(S) $(XX) -- getxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = 22 +$(S) $(XX) -- lgetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = ? +$(S) $(XX) -- lgetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = 22 +$(S) $(XX) -- lgetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = ? +$(S) $(XX) -- lgetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = 22 +$(S) $(XX) -- fgetxattr(4, "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = ? +$(S) $(XX) -- fgetxattr(4, "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = 22 +$(S) $(XX) -- listxattr("input_data\x01\x02\x03\n\r\t", 0x0000000000123000, 4) = ? +$(S) $(XX) -- listxattr("input_data\x01\x02\x03\n\r\t", 0x0000000000123000, 4) = 22 +$(S) $(XX) -- llistxattr("input_data\x01\x02\x03\n\r\t", 0x0000000000123000, 4) = ? +$(S) $(XX) -- llistxattr("input_data\x01\x02\x03\n\r\t", 0x0000000000123000, 4) = 22 +$(S) $(XX) -- flistxattr(5, 0x0000000000123000, 4) = ? +$(S) $(XX) -- flistxattr(5, 0x0000000000123000, 4) = 22 +$(S) $(XX) -- flistxattr(-100, 0x0000000000123000, 4) = ? +$(S) $(XX) -- flistxattr(-100, 0x0000000000123000, 4) = 22 +$(S) $(XX) -- removexattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- removexattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- lremovexattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- lremovexattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- fremovexattr(7, "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- fremovexattr(7, "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- tkill(0x2c, 0x13) = ? +$(S) $(XX) -- tkill(0x2c, 0x13) = 22 +$(S) $(XX) -- tgkill(0x2c, 0x37, 0x13) = ? +$(S) $(XX) -- tgkill(0x2c, 0x37, 0x13) = 22 +$(OPT)$(S) $(XX) -- time(0x123000) = ? +$(OPT)$(S) $(XX) -- time(0x123000) = 22 +$(S) $(XX) -- futex(0x123000, 0x1, 0x7, 0x123000, 0x234000, 0x1) = ? +$(S) $(XX) -- futex(0x123000, 0x1, 0x7, 0x123000, 0x234000, 0x1) = 22 +$(OPT)$(S) $(XX) -- set_thread_area(0x123000) = ? +$(OPT)$(S) $(XX) -- set_thread_area(0x123000) = 22 +$(OPT)$(S) $(XX) -- get_thread_area(0x123000) = ? +$(OPT)$(S) $(XX) -- get_thread_area(0x123000) = 22 +$(S) $(XX) -- io_setup(0x1, 0x123000) = ? +$(S) $(XX) -- io_setup(0x1, 0x123000) = 22 +$(S) $(XX) -- io_destroy(0x4d) = ? +$(S) $(XX) -- io_destroy(0x4d) = 22 +$(S) $(XX) -- io_getevents(0x1, 0x2, 0x3, 0x123000, 0x234000) = ? +$(S) $(XX) -- io_getevents(0x1, 0x2, 0x3, 0x123000, 0x234000) = 22 +$(S) $(XX) -- io_submit(0x1, 0x2, 0x123000) = ? +$(S) $(XX) -- io_submit(0x1, 0x2, 0x123000) = 22 +$(S) $(XX) -- io_cancel(0x1, 0x123000, 0x234000) = ? +$(S) $(XX) -- io_cancel(0x1, 0x123000, 0x234000) = 22 +$(S) $(XX) -- lookup_dcookie(0x7b, 0x123000, 0xc) = ? +$(S) $(XX) -- lookup_dcookie(0x7b, 0x123000, 0xc) = 22 +$(S) $(XX) -- epoll_create(0x7) = ? +$(S) $(XX) -- epoll_create(0x7) = 22 +$(S) $(XX) -- epoll_create1(0x0) = ? +$(S) $(XX) -- epoll_create1(0x0) = 22 +$(S) $(XX) -- epoll_create1(0x80000) = ? +$(S) $(XX) -- epoll_create1(0x80000) = 22 +$(OPT)$(S) $(XX) -- epoll_wait(2, 0x123000, 0x4, 0x5) = ? +$(OPT)$(S) $(XX) -- epoll_wait(2, 0x123000, 0x4, 0x5) = 22 +$(S) $(XX) -- epoll_pwait(2, 0x123000, 0x4, 0x5, 0x234000, 0x6) = ? +$(S) $(XX) -- epoll_pwait(2, 0x123000, 0x4, 0x5, 0x234000, 0x6) = 22 +$(S) $(XX) -- epoll_ctl(2, 0x3, 4, 0x123000) = ? +$(S) $(XX) -- epoll_ctl(2, 0x3, 4, 0x123000) = 22 +$(S) $(XX) -- set_tid_address(0x123000) = ? +$(S) $(XX) -- set_tid_address(0x123000) = 22 +$(S) $(XX) -- fadvise64(3, 0x64, 0x63, 0x2) = ? +$(S) $(XX) -- fadvise64(3, 0x64, 0x63, 0x2) = 22 +$(S) $(XX) -- timer_create(0x3, 0x123000, 0x234000) = ? +$(S) $(XX) -- timer_create(0x3, 0x123000, 0x234000) = 22 +$(S) $(XX) -- timer_settime(0x4, 0x0, 0x123000, 0x234000) = ? +$(S) $(XX) -- timer_settime(0x4, 0x0, 0x123000, 0x234000) = 22 +$(S) $(XX) -- timer_settime(0x4, 0x1, 0x123000, 0x234000) = ? +$(S) $(XX) -- timer_settime(0x4, 0x1, 0x123000, 0x234000) = 22 +$(S) $(XX) -- timer_gettime(0x3, 0x123000) = ? +$(S) $(XX) -- timer_gettime(0x3, 0x123000) = 22 +$(S) $(XX) -- timer_getoverrun(0x3) = ? +$(S) $(XX) -- timer_getoverrun(0x3) = 22 +$(S) $(XX) -- timer_delete(0x3) = ? +$(S) $(XX) -- timer_delete(0x3) = 22 +$(S) $(XX) -- clock_settime(0x7, 0x123000) = ? +$(S) $(XX) -- clock_settime(0x7, 0x123000) = 22 +$(S) $(XX) -- clock_gettime(0x7, 0x123000) = ? +$(S) $(XX) -- clock_gettime(0x7, 0x123000) = 22 +$(S) $(XX) -- clock_getres(0x3, 0x123000) = ? +$(S) $(XX) -- clock_getres(0x3, 0x123000) = 22 +$(S) $(XX) -- clock_nanosleep(0x1, 0x1, 0x123000, 0x234000) = ? +$(S) $(XX) -- clock_nanosleep(0x1, 0x1, 0x123000, 0x234000) = 22 +$(S) $(XX) -- mbind(0x123000, 0x0, 0x8002, 0x234000, 0x4) = ? +$(S) $(XX) -- mbind(0x123000, 0x0, 0x8002, 0x234000, 0x4) = 22 +$(S) $(XX) -- set_mempolicy(0x8000, 0x123000, 0x5) = ? +$(S) $(XX) -- set_mempolicy(0x8000, 0x123000, 0x5) = 22 +$(S) $(XX) -- get_mempolicy(0x123000, 0x234000, 0x6, 0x123000, 0x0) = ? +$(S) $(XX) -- get_mempolicy(0x123000, 0x234000, 0x6, 0x123000, 0x0) = 22 +$(S) $(XX) -- mq_open("input_data\x01\x02\x03\n\r\t", 0x42, 0x1ff, 0x123000, $(XX)) = ? +$(S) $(XX) -- mq_open("input_data\x01\x02\x03\n\r\t", 0x42, 0x1ff, 0x123000, $(XX)) = 22 +$(S) $(XX) -- mq_unlink("input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- mq_unlink("input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- mq_timedsend(0x1, $(XX), 0x10, 0x3, 0x123000) = ? +$(S) $(XX) -- mq_timedsend(0x1, $(XX), 0x10, 0x3, 0x123000) = 22 +$(S) $(XX) -- mq_timedreceive(0x1, $(XX), 0x10, 0x3, 0x123000) = ? +$(S) $(XX) -- mq_timedreceive(0x1, $(XX), 0x10, 0x3, 0x123000) = 22 +$(S) $(XX) -- mq_notify(0x1, 0x123000) = ? +$(S) $(XX) -- mq_notify(0x1, 0x123000) = 22 +$(S) $(XX) -- mq_getsetattr(0x1, 0x123000, 0x234000) = ? +$(S) $(XX) -- mq_getsetattr(0x1, 0x123000, 0x234000) = 22 +$(S) $(XX) -- kexec_load(0x1, 0x2, 0x123000, 0x2) = ? +$(S) $(XX) -- kexec_load(0x1, 0x2, 0x123000, 0x2) = 22 +$(OPT)$(S) $(XX) -- kexec_file_load(0x1, 0x2, 0x3, $(XX), 0x2) = ? +$(OPT)$(S) $(XX) -- kexec_file_load(0x1, 0x2, 0x3, $(XX), 0x2) = 22 +$(S) $(XX) -- waitid(0x1, 0x2, 0x123000, 0x4) = ? +$(S) $(XX) -- waitid(0x1, 0x2, 0x123000, 0x4) = 22 +$(S) $(XX) -- add_key(0x123000, 0x234000, 0x123000, 0x234000, 0x1) = ? +$(S) $(XX) -- add_key(0x123000, 0x234000, 0x123000, 0x234000, 0x1) = 22 +$(S) $(XX) -- request_key(0x123000, 0x234000, 0x123000, 0x1) = ? +$(S) $(XX) -- request_key(0x123000, 0x234000, 0x123000, 0x1) = 22 +$(S) $(XX) -- keyctl(0x0, 0x1, 0x2, 0x3, 0x4) = ? +$(S) $(XX) -- keyctl(0x0, 0x1, 0x2, 0x3, 0x4) = 22 +$(S) $(XX) -- ioprio_set(0x1, 0x3, 0x7b) = ? +$(S) $(XX) -- ioprio_set(0x1, 0x3, 0x7b) = 22 +$(S) $(XX) -- ioprio_get(0x1, 0x3) = ? +$(S) $(XX) -- ioprio_get(0x1, 0x3) = 22 +$(S) $(XX) -- inotify_init() = ? +$(S) $(XX) -- inotify_init() = 22 +$(S) $(XX) -- inotify_init1(0x800) = ? +$(S) $(XX) -- inotify_init1(0x800) = 22 +$(S) $(XX) -- inotify_init1(0x80000) = ? +$(S) $(XX) -- inotify_init1(0x80000) = 22 +$(S) $(XX) -- inotify_add_watch(7, "input_data\x01\x02\x03\n\r\t", 0x7b) = ? +$(S) $(XX) -- inotify_add_watch(7, "input_data\x01\x02\x03\n\r\t", 0x7b) = 22 +$(S) $(XX) -- inotify_rm_watch(7, 0x8) = ? +$(S) $(XX) -- inotify_rm_watch(7, 0x8) = 22 +$(S) $(XX) -- migrate_pages(0x1, 0x2, 0x123000, 0x234000) = ? +$(S) $(XX) -- migrate_pages(0x1, 0x2, 0x123000, 0x234000) = 22 +$(S) $(XX) -- unshare(0x20400) = ? +$(S) $(XX) -- unshare(0x20400) = 22 +$(S) $(XX) -- set_robust_list(0x123000, 33) = ? +$(S) $(XX) -- set_robust_list(0x123000, 33) = 22 +$(S) $(XX) -- get_robust_list(0x2c, 0x123000, 0x234000) = ? +$(S) $(XX) -- get_robust_list(0x2c, 0x123000, 0x234000) = 22 +$(S) $(XX) -- splice(2, 0x123000, 3, 0x234000, 0x7b, 0x1) = ? +$(S) $(XX) -- splice(2, 0x123000, 3, 0x234000, 0x7b, 0x1) = 22 +$(S) $(XX) -- splice(2, 0x123000, 3, 0x234000, 0x0, 0x4) = ? +$(S) $(XX) -- splice(2, 0x123000, 3, 0x234000, 0x0, 0x4) = 22 +$(S) $(XX) -- vmsplice(1, 0x123000, 0x2, 0x3) = ? +$(S) $(XX) -- vmsplice(1, 0x123000, 0x2, 0x3) = 22 +$(S) $(XX) -- tee(1, 2, 0x3, 0x0) = ? +$(S) $(XX) -- tee(1, 2, 0x3, 0x0) = 22 +$(S) $(XX) -- tee(1, 2, 0x3, 0x1) = ? +$(S) $(XX) -- tee(1, 2, 0x3, 0x1) = 22 +$(S) $(XX) -- tee(1, 2, 0x3, 0x2) = ? +$(S) $(XX) -- tee(1, 2, 0x3, 0x2) = 22 +$(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x0) = ? +$(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x0) = 22 +$(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x1) = ? +$(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x1) = 22 +$(OPT)$(S) $(XX) -- signalfd(1, 0x123000, 0xc) = ? +$(OPT)$(S) $(XX) -- signalfd(1, 0x123000, 0xc) = 22 +$(S) $(XX) -- signalfd4(1, 0x123000, 0xd, 0x800, $(XX)) = ? +$(S) $(XX) -- signalfd4(1, 0x123000, 0xd, 0x800, $(XX)) = 22 +$(S) $(XX) -- timerfd_create(0x0, 0x80000) = ? +$(S) $(XX) -- timerfd_create(0x0, 0x80000) = 22 +$(S) $(XX) -- timerfd_settime(1, 0x1, 0x123000, 0x234000) = ? +$(S) $(XX) -- timerfd_settime(1, 0x1, 0x123000, 0x234000) = 22 +$(S) $(XX) -- timerfd_gettime(2, 0x123000) = ? +$(S) $(XX) -- timerfd_gettime(2, 0x123000) = 22 +$(OPT)$(S) $(XX) -- eventfd(0x2d) = ? +$(OPT)$(S) $(XX) -- eventfd(0x2d) = 22 +$(S) $(XX) -- eventfd2(0x2f, 0x1) = ? +$(S) $(XX) -- eventfd2(0x2f, 0x1) = 22 +$(S) $(XX) -- fallocate(1, 0x2, 0x3, 0x4) = ? +$(S) $(XX) -- fallocate(1, 0x2, 0x3, 0x4) = 22 +$(S) $(XX) -- perf_event_open(0x123000, 0x1, 0x2, 0x3, 0x4) = ? +$(S) $(XX) -- perf_event_open(0x123000, 0x1, 0x2, 0x3, 0x4) = 22 +$(S) $(XX) -- fanotify_init(0x9, 0x2) = ? +$(S) $(XX) -- fanotify_init(0x9, 0x2) = 22 +$(S) $(XX) -- fanotify_mark(0x2, 0x2, 0x4000, 0x3, $(XX)) = ? +$(S) $(XX) -- fanotify_mark(0x2, 0x2, 0x4000, 0x3, $(XX)) = 22 +$(S) $(XX) -- name_to_handle_at(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x123000, 0x234000, 0x0) = ? +$(S) $(XX) -- name_to_handle_at(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x123000, 0x234000, 0x0) = 22 +$(S) $(XX) -- open_by_handle_at(3, 0x0000000000123000, 0) = ? +$(S) $(XX) -- open_by_handle_at(3, 0x0000000000123000, 0) = 22 +$(S) $(XX) -- setns(2, 0x0) = ? +$(S) $(XX) -- setns(2, 0x0) = 22 +$(S) $(XX) -- getcpu(0x123000, 0x123000, 0x234000) = ? +$(S) $(XX) -- getcpu(0x123000, 0x123000, 0x234000) = 22 +$(S) $(XX) -- process_vm_readv(0x1, 0x2, 0x3, 0x4, 0x5, 0x6) = ? +$(S) $(XX) -- process_vm_readv(0x1, 0x2, 0x3, 0x4, 0x5, 0x6) = 22 +$(S) $(XX) -- process_vm_writev(0x1, 0x2, 0x3, 0x4, 0x5, 0x6) = ? +$(S) $(XX) -- process_vm_writev(0x1, 0x2, 0x3, 0x4, 0x5, 0x6) = 22 +$(S) $(XX) -- kcmp(0x1, 0x2, 0x3, 0x4, 0x5) = ? +$(S) $(XX) -- kcmp(0x1, 0x2, 0x3, 0x4, 0x5) = 22 diff --git a/test/arch/x86_64/syscall_format.log.match b/test/arch/x86_64/syscall_format.log.match new file mode 100644 index 0000000..3ea07b6 --- /dev/null +++ b/test/arch/x86_64/syscall_format.log.match @@ -0,0 +1,782 @@ +$(S) $(XX) -- read(9, (null), 44) = ? +$(S) $(XX) -- read(9, (null), 44) = 22 +$(S) $(XX) -- read(7, $(XX), 19) = ? +$(S) $(XX) -- read(7, "expected_output_data\x06\xff", 19) = 22 +$(S) $(XX) -- write(7, "input_data\x01\x02\x03\n\r\t\0\0\0\0", 20) = ? +$(S) $(XX) -- write(7, "input_data\x01\x02\x03\n\r\t\0\0\0\0", 20) = 22 +$(S) $(XX) -- pread64(7, $(XX), 19, 4294967311) = ? +$(S) $(XX) -- pread64(7, "expected_output_data\x06\xff", 19, 4294967311) = 22 +$(S) $(XX) -- pread64(-99, $(XX), 18, 0) = ? +$(S) $(XX) -- pread64(-99, "expected_output_data\x06\xff", 18, 0) = 22 +$(S) $(XX) -- pread64(8, (null), 18, 0) = ? +$(S) $(XX) -- pread64(8, (null), 18, 0) = 22 +$(S) $(XX) -- pwrite64(7, "input_data\x01\x02\x03\n\r\t\0\0\0", 19, 4294967311) = ? +$(S) $(XX) -- pwrite64(7, "input_data\x01\x02\x03\n\r\t\0\0\0", 19, 4294967311) = 22 +$(S) $(XX) -- pwrite64(-99, "input_data\x01\x02\x03\n\r\t\0\0", 18, 0) = ? +$(S) $(XX) -- pwrite64(-99, "input_data\x01\x02\x03\n\r\t\0\0", 18, 0) = 22 +$(S) $(XX) -- pwrite64(-100, (null), 18, -1) = ? +$(S) $(XX) -- pwrite64(-100, (null), 18, -1) = 22 +$(S) $(XX) -- readv(1, 0x0000000000123000, 4) = ? +$(S) $(XX) -- readv(1, 0x0000000000123000, 4) = 22 +$(S) $(XX) -- readv(1, (null), 4) = ? +$(S) $(XX) -- readv(1, (null), 4) = 22 +$(S) $(XX) -- writev(1, 0x0000000000123000, 4) = ? +$(S) $(XX) -- writev(1, 0x0000000000123000, 4) = 22 +$(S) $(XX) -- writev(1, (null), 4) = ? +$(S) $(XX) -- writev(1, (null), 4) = 22 +$(S) $(XX) -- preadv(1, 0x123000, 0x4, 0x1000) = ? +$(S) $(XX) -- preadv(1, 0x123000, 0x4, 0x1000) = 22 +$(S) $(XX) -- preadv(1, 0x0, 0x4, 0x1000) = ? +$(S) $(XX) -- preadv(1, 0x0, 0x4, 0x1000) = 22 +$(S) $(XX) -- pwritev(1, 0x123000, 0x4, 0x1000) = ? +$(S) $(XX) -- pwritev(1, 0x123000, 0x4, 0x1000) = 22 +$(S) $(XX) -- pwritev(1, 0x0, 0x4, 0x1000) = ? +$(S) $(XX) -- pwritev(1, 0x0, 0x4, 0x1000) = 22 +$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = ? +$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = 22 +$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? +$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDONLY) = 22 +$(S) $(XX) -- open((null), O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = ? +$(S) $(XX) -- open((null), O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = 22 +$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = ? +$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = 22 +$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_NONBLOCK) = ? +$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_NONBLOCK) = 22 +$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? +$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDONLY) = 22 +$(S) $(XX) -- open((null), O_RDONLY) = ? +$(S) $(XX) -- open((null), O_RDONLY) = 22 +$(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = ? +$(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = 22 +$(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? +$(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDONLY) = 22 +$(S) $(XX) -- openat(AT_FDCWD, (null), O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = ? +$(S) $(XX) -- openat(AT_FDCWD, (null), O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = 22 +$(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = ? +$(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = 22 +$(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_NONBLOCK) = ? +$(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_NONBLOCK) = 22 +$(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? +$(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDONLY) = 22 +$(S) $(XX) -- openat(AT_FDCWD, (null), O_RDONLY) = ? +$(S) $(XX) -- openat(AT_FDCWD, (null), O_RDONLY) = 22 +$(S) $(XX) -- openat(99, "input_data\x01\x02\x03\n\r\t", O_RDONLY | O_CREAT, 0777) = ? +$(S) $(XX) -- openat(99, "input_data\x01\x02\x03\n\r\t", O_RDONLY | O_CREAT, 0777) = 22 +$(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_TMPFILE, 0333) = ? +$(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_TMPFILE, 0333) = 22 +$(S) $(XX) -- close(9) = ? +$(S) $(XX) -- close(9) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(0, "", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(0, "", $(XX), $(XX)) = 22 +$(OPT)$(S) $(XX) -- newfstatat(-1, "", $(XX), $(XX)) = ? +$(OPT)$(S) $(XX) -- newfstatat(-1, "", $(XX), $(XX)) = 22 +$(OPT)$(S) $(XX) -- newfstatat(AT_FDCWD, "", $(XX), $(XX)) = ? +$(OPT)$(S) $(XX) -- newfstatat(AT_FDCWD, "", $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(2, "", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(2, "", $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x0, 0x0) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x0, 0x0) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), 0x0, 0x0) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), 0x0, 0x0) = 22 +$(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = ? +$(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX), 0x100) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX), 0x100) = 22 +$(S) $(XX) -- poll((null), 0, 7) = ? +$(S) $(XX) -- poll((null), 0, 7) = 22 +$(S) $(XX) -- poll($(XX), 3, 7) = ? +$(S) $(XX) -- poll($(XX), 3, 7) = 22 +$(S) $(XX) -- ppoll($(XX), 2, 0x123000, 0x234000, 2) = ? +$(S) $(XX) -- ppoll($(XX), 2, 0x123000, 0x234000, 2) = 22 +$(S) $(XX) -- lseek(0, 0, SEEK_SET) = ? +$(S) $(XX) -- lseek(0, 0, SEEK_SET) = 22 +$(S) $(XX) -- lseek(0, 0, SEEK_CUR) = ? +$(S) $(XX) -- lseek(0, 0, SEEK_CUR) = 22 +$(S) $(XX) -- lseek(0, 0, SEEK_END) = ? +$(S) $(XX) -- lseek(0, 0, SEEK_END) = 22 +$(S) $(XX) -- lseek(0, 0, SEEK_HOLE) = ? +$(S) $(XX) -- lseek(0, 0, SEEK_HOLE) = 22 +$(S) $(XX) -- lseek(0, 0, SEEK_DATA) = ? +$(S) $(XX) -- lseek(0, 0, SEEK_DATA) = 22 +$(S) $(XX) -- lseek(2, -1, SEEK_SET) = ? +$(S) $(XX) -- lseek(2, -1, SEEK_SET) = 22 +$(S) $(XX) -- lseek(2, -1, SEEK_CUR) = ? +$(S) $(XX) -- lseek(2, -1, SEEK_CUR) = 22 +$(S) $(XX) -- lseek(2, -1, SEEK_END) = ? +$(S) $(XX) -- lseek(2, -1, SEEK_END) = 22 +$(S) $(XX) -- lseek(2, -1, SEEK_HOLE) = ? +$(S) $(XX) -- lseek(2, -1, SEEK_HOLE) = 22 +$(S) $(XX) -- lseek(2, -1, SEEK_DATA) = ? +$(S) $(XX) -- lseek(2, -1, SEEK_DATA) = 22 +$(S) $(XX) -- lseek(-100, 99999, SEEK_SET) = ? +$(S) $(XX) -- lseek(-100, 99999, SEEK_SET) = 22 +$(S) $(XX) -- lseek(-100, 99999, SEEK_CUR) = ? +$(S) $(XX) -- lseek(-100, 99999, SEEK_CUR) = 22 +$(S) $(XX) -- lseek(-100, 99999, SEEK_END) = ? +$(S) $(XX) -- lseek(-100, 99999, SEEK_END) = 22 +$(S) $(XX) -- lseek(-100, 99999, SEEK_HOLE) = ? +$(S) $(XX) -- lseek(-100, 99999, SEEK_HOLE) = 22 +$(S) $(XX) -- lseek(-100, 99999, SEEK_DATA) = ? +$(S) $(XX) -- lseek(-100, 99999, SEEK_DATA) = 22 +$(S) $(XX) -- mmap((null), 0x0, 0x0, 0x0, 0, 0x0) = ? +$(S) $(XX) -- mmap((null), 0x0, 0x0, 0x0, 0, 0x0) = -22 EINVAL (Invalid argument) +$(S) $(XX) -- mmap(0x0000000000123000, 0x8000, 0x4, 0x1, 99, 0x1000) = ? +$(S) $(XX) -- mmap(0x0000000000123000, 0x8000, 0x4, 0x1, 99, 0x1000) = 0x0000000000000016 +$(S) $(XX) -- mprotect(0x0000000000123000, 0x4000, 0x1) = ? +$(S) $(XX) -- mprotect(0x0000000000123000, 0x4000, 0x1) = 22 +$(S) $(XX) -- mprotect((null), 0x4000, 0x2) = ? +$(S) $(XX) -- mprotect((null), 0x4000, 0x2) = 22 +$(S) $(XX) -- munmap(0x0000000000123000, 0x4000) = ? +$(S) $(XX) -- munmap(0x0000000000123000, 0x4000) = 22 +$(S) $(XX) -- munmap((null), 0x4000) = ? +$(S) $(XX) -- munmap((null), 0x4000) = 22 +$(S) $(XX) -- brk($(N)) = ? +$(S) $(XX) -- brk($(N)) = 22 +$(S) $(XX) -- brk(0) = ? +$(S) $(XX) -- brk(0) = 22 +$(S) $(XX) -- mremap(0x0000000000123000, 4294967302, 4294967372, 1, $(XX)) = ? +$(S) $(XX) -- mremap(0x0000000000123000, 4294967302, 4294967372, 1, $(XX)) = 0x0000000000000016 +$(S) $(XX) -- msync(0x0000000000123000, 0, 1) = ? +$(S) $(XX) -- msync(0x0000000000123000, 0, 1) = 22 +$(S) $(XX) -- msync((null), 888, 2) = ? +$(S) $(XX) -- msync((null), 888, 2) = 22 +$(S) $(XX) -- mincore(0x0000000000123000, 99, 0x0000000000234000) = ? +$(S) $(XX) -- mincore(0x0000000000123000, 99, 0x0000000000234000) = 22 +$(S) $(XX) -- mincore(0x0000000000234000, 1234, (null)) = ? +$(S) $(XX) -- mincore(0x0000000000234000, 1234, (null)) = 22 +$(S) $(XX) -- mincore((null), 0, 0x0000000000123000) = ? +$(S) $(XX) -- mincore((null), 0, 0x0000000000123000) = 22 +$(S) $(XX) -- madvise(0x0000000000123000, 99, 0) = ? +$(S) $(XX) -- madvise(0x0000000000123000, 99, 0) = 22 +$(S) $(XX) -- madvise(0x0000000000234000, 1234, 4) = ? +$(S) $(XX) -- madvise(0x0000000000234000, 1234, 4) = 22 +$(S) $(XX) -- madvise((null), 0, 2) = ? +$(S) $(XX) -- madvise((null), 0, 2) = 22 +$(S) $(XX) -- mlock(0x123000, 0x3000) = ? +$(S) $(XX) -- mlock(0x123000, 0x3000) = 22 +$(OPT)$(S) $(XX) -- mlock2(0x123000, 0x3000, 0x0) = ? +$(OPT)$(S) $(XX) -- mlock2(0x123000, 0x3000, 0x0) = 22 +$(S) $(XX) -- munlock(0x123000, 0x3000) = ? +$(S) $(XX) -- munlock(0x123000, 0x3000) = 22 +$(S) $(XX) -- mlockall(0x1) = ? +$(S) $(XX) -- mlockall(0x1) = 22 +$(S) $(XX) -- mlockall(0x2) = ? +$(S) $(XX) -- mlockall(0x2) = 22 +$(S) $(XX) -- munlockall() = ? +$(S) $(XX) -- munlockall() = 22 +$(S) $(XX) -- rt_sigaction(2, 0x0000000000123000, 0x0000000000234000, 10) = ? +$(S) $(XX) -- rt_sigaction(2, 0x0000000000123000, 0x0000000000234000, 10) = 22 +$(S) $(XX) -- rt_sigprocmask(0x2, 0x0000000000123000, 0x0000000000234000, 10) = ? +$(S) $(XX) -- rt_sigprocmask(0x2, 0x0000000000123000, 0x0000000000234000, 10) = 22 +$(S) $(XX) -- ioctl(1, 0x4d, 0x0000000000234000) = ? +$(S) $(XX) -- ioctl(1, 0x4d, 0x0000000000234000) = 22 +$(S) $(XX) -- access((null), F_OK) = ? +$(S) $(XX) -- access((null), F_OK) = 22 +$(S) $(XX) -- access("input_data\x01\x02\x03\n\r\t", X_OK) = ? +$(S) $(XX) -- access("input_data\x01\x02\x03\n\r\t", X_OK) = 22 +$(S) $(XX) -- access("", R_OK | W_OK) = ? +$(S) $(XX) -- access("", R_OK | W_OK) = 22 +$(S) $(XX) -- access("input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = ? +$(S) $(XX) -- access("input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = 22 +$(S) $(XX) -- faccessat2(AT_FDCWD, (null), 00, $(XX)) = ? +$(S) $(XX) -- faccessat2(AT_FDCWD, (null), 00, $(XX)) = 22 +$(S) $(XX) -- faccessat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, $(XX)) = ? +$(S) $(XX) -- faccessat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, $(XX)) = 22 +$(S) $(XX) -- faccessat2(AT_FDCWD, "", 06, $(XX)) = ? +$(S) $(XX) -- faccessat2(AT_FDCWD, "", 06, $(XX)) = 22 +$(S) $(XX) -- faccessat2(9, "input_data\x01\x02\x03\n\r\t", 07, $(XX)) = ? +$(S) $(XX) -- faccessat2(9, "input_data\x01\x02\x03\n\r\t", 07, $(XX)) = 22 +$(S) $(XX) -- pipe2($(XX), $(N)) = ? +$(S) $(XX) -- pipe2([123, 234], $(N)) = 22 +$(S) $(XX) -- pipe2($(XX), 0) = ? +$(S) $(XX) -- pipe2([123, 234], 0) = 22 +$(S) $(XX) -- pselect6(0x2, 0x123000, 0x234000, 0x456000, $(XX), $(XX)) = ? +$(S) $(XX) -- pselect6(0x2, 0x123000, 0x234000, 0x456000, $(XX), $(XX)) = 22 +$(S) $(XX) -- pselect6(0x2, 0x123000, 0x234000, 0x123000, 0x234000, 0x123000) = ? +$(S) $(XX) -- pselect6(0x2, 0x123000, 0x234000, 0x123000, 0x234000, 0x123000) = 22 +$(S) $(XX) -- sched_yield() = ? +$(S) $(XX) -- sched_yield() = 22 +$(S) $(XX) -- shmget(0x3, 0x4, 0x5) = ? +$(S) $(XX) -- shmget(0x3, 0x4, 0x5) = 22 +$(S) $(XX) -- shmat(0x3, 0x123000, 0x5) = ? +$(S) $(XX) -- shmat(0x3, 0x123000, 0x5) = 0x16 +$(S) $(XX) -- shmctl(0x3, 0xe, 0x123000) = ? +$(S) $(XX) -- shmctl(0x3, 0xe, 0x123000) = 22 +$(S) $(XX) -- shmdt(0x123000) = ? +$(S) $(XX) -- shmdt(0x123000) = 22 +$(S) $(XX) -- dup(4) = ? +$(S) $(XX) -- dup(4) = 22 +$(S) $(XX) -- dup2(4, 5) = ? +$(S) $(XX) -- dup2(4, 5) = 22 +$(S) $(XX) -- dup3(4, 5, 0x0) = ? +$(S) $(XX) -- dup3(4, 5, 0x0) = 22 +$(S) $(XX) -- dup3(4, 5, 0x80000) = ? +$(S) $(XX) -- dup3(4, 5, 0x80000) = 22 +$(S) $(XX) -- pause() = ? +$(S) $(XX) -- pause() = 22 +$(S) $(XX) -- clock_nanosleep(0x0, 0x0, 0x123000, 0x234000) = ? +$(S) $(XX) -- clock_nanosleep(0x0, 0x0, 0x123000, 0x234000) = 22 +$(S) $(XX) -- getitimer(0x3, 0x123000) = ? +$(S) $(XX) -- getitimer(0x3, 0x123000) = 22 +$(S) $(XX) -- alarm(0x4) = ? +$(S) $(XX) -- alarm(0x4) = 22 +$(S) $(XX) -- setitimer(0x6, 0x123000, 0x234000) = ? +$(S) $(XX) -- setitimer(0x6, 0x123000, 0x234000) = 22 +$(S) $(XX) -- getpid() = ? +$(S) $(XX) -- getpid() = 22 +$(S) $(XX) -- sendfile(6, 7, 0x123000, 0x63) = ? +$(S) $(XX) -- sendfile(6, 7, 0x123000, 0x63) = 22 +$(S) $(XX) -- socket(0x2, 0x800, 0x0) = ? +$(S) $(XX) -- socket(0x2, 0x800, 0x0) = 22 +$(S) $(XX) -- connect(8, 0x123000, 0xc) = ? +$(S) $(XX) -- connect(8, 0x123000, 0xc) = 22 +$(S) $(XX) -- accept(4, 0x123000, 0x234000) = ? +$(S) $(XX) -- accept(4, 0x123000, 0x234000) = 22 +$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x0, 0x234000) = ? +$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x0, 0x234000) = 22 +$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x234000) = ? +$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x234000) = 22 +$(S) $(XX) -- sendto(5, 0x123000, 0xc, 0x4) = ? +$(S) $(XX) -- sendto(5, 0x123000, 0xc, 0x4) = 22 +$(S) $(XX) -- recvfrom(5, 0x123000, 0xc, 0x4, 0x234000, 0x234000) = ? +$(S) $(XX) -- recvfrom(5, 0x123000, 0xc, 0x4, 0x234000, 0x234000) = 22 +$(S) $(XX) -- recvmsg(2, 0x123000, 0x2) = ? +$(S) $(XX) -- recvmsg(2, 0x123000, 0x2) = 22 +$(S) $(XX) -- recvmmsg(2, 0x123000, 0xc, 0x10000, 0x234000) = ? +$(S) $(XX) -- recvmmsg(2, 0x123000, 0xc, 0x10000, 0x234000) = 22 +$(S) $(XX) -- sendmsg(2, 0x123000, 0x4000) = ? +$(S) $(XX) -- sendmsg(2, 0x123000, 0x4000) = 22 +$(S) $(XX) -- sendmmsg(2, 0x123000, 0xc, 0x4000) = ? +$(S) $(XX) -- sendmmsg(2, 0x123000, 0xc, 0x4000) = 22 +$(S) $(XX) -- shutdown(3, 0x0) = ? +$(S) $(XX) -- shutdown(3, 0x0) = 22 +$(S) $(XX) -- bind(6, 0x123000, 0x9) = ? +$(S) $(XX) -- bind(6, 0x123000, 0x9) = 22 +$(S) $(XX) -- listen(5, 0x3) = ? +$(S) $(XX) -- listen(5, 0x3) = 22 +$(S) $(XX) -- getsockname(4, 0x123000, 0x234000) = ? +$(S) $(XX) -- getsockname(4, 0x123000, 0x234000) = 22 +$(S) $(XX) -- getpeername(4, 0x123000, 0x234000) = ? +$(S) $(XX) -- getpeername(4, 0x123000, 0x234000) = 22 +$(S) $(XX) -- socketpair(0x4, 0x5, 0x6, 0x123000) = ? +$(S) $(XX) -- socketpair(0x4, 0x5, 0x6, 0x123000) = 22 +$(S) $(XX) -- setsockopt(4, 0x5, 0x6, 0x123000, 0x7) = ? +$(S) $(XX) -- setsockopt(4, 0x5, 0x6, 0x123000, 0x7) = 22 +$(S) $(XX) -- getsockopt(4, 0x5, 0x6, 0x123000, $(XX)) = ? +$(S) $(XX) -- getsockopt(4, 0x5, 0x6, 0x123000, $(XX)) = 22 +$(S) $(XX) -- wait4(7, 0x123000, 0x0, 0x234000) = ? +$(S) $(XX) -- wait4(7, 0x123000, 0x0, 0x234000) = 22 +$(S) $(XX) -- kill(0x4, 0x2) = ? +$(S) $(XX) -- kill(0x4, 0x2) = 22 +$(S) $(XX) -- uname($(XX)) = ? +$(S) $(XX) -- uname($(XX)) = 22 +$(S) $(XX) -- semget(0x4, 0x1, 0x200) = ? +$(S) $(XX) -- semget(0x4, 0x1, 0x200) = 22 +$(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x0) = ? +$(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x0) = 22 +$(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x234000) = ? +$(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x234000) = 22 +$(S) $(XX) -- semctl(0x1, 0x2, 0x3, $(XX), $(XX), 0x234000) = ? +$(S) $(XX) -- semctl(0x1, 0x2, 0x3, $(XX), $(XX), 0x234000) = 22 +$(S) $(XX) -- msgget(0x1, 0x200) = ? +$(S) $(XX) -- msgget(0x1, 0x200) = 22 +$(S) $(XX) -- msgsnd(0x1, 0x123000, 0x3, 0x3) = ? +$(S) $(XX) -- msgsnd(0x1, 0x123000, 0x3, 0x3) = 22 +$(S) $(XX) -- msgrcv(0x1, 0x123000, 0x1, 0x1, 0x1) = ? +$(S) $(XX) -- msgrcv(0x1, 0x123000, 0x1, 0x1, 0x1) = 22 +$(S) $(XX) -- msgctl(0x1, 0x2, 0x123000) = ? +$(S) $(XX) -- msgctl(0x1, 0x2, 0x123000) = 22 +$(S) $(XX) -- fcntl(1, 1030 (F_DUPFD_CLOEXEC), 0x3) = ? +$(S) $(XX) -- fcntl(1, 1030 (F_DUPFD_CLOEXEC), 0x3) = 22 +$(S) $(XX) -- fcntl(10, 4 (F_SETFL), 0x40000) = ? +$(S) $(XX) -- fcntl(10, 4 (F_SETFL), 0x40000) = 22 +$(S) $(XX) -- fcntl(11, 6 (F_SETLK), $(XX) ({.l_type = 1 (F_WRLCK), .l_whence = 2 (SEEK_END), .l_start = 123, .l_len = 456, .l_pid = 768})) = ? +$(S) $(XX) -- fcntl(11, 6 (F_SETLK), $(XX) ({.l_type = 1 (F_WRLCK), .l_whence = 2 (SEEK_END), .l_start = 123, .l_len = 456, .l_pid = 768})) = 22 +$(S) $(XX) -- flock(1, 0x2) = ? +$(S) $(XX) -- flock(1, 0x2) = 22 +$(S) $(XX) -- fsync(2) = ? +$(S) $(XX) -- fsync(2) = 22 +$(S) $(XX) -- fdatasync(2) = ? +$(S) $(XX) -- fdatasync(2) = 22 +$(S) $(XX) -- truncate("input_data\x01\x02\x03\n\r\t", 0x4) = ? +$(S) $(XX) -- truncate("input_data\x01\x02\x03\n\r\t", 0x4) = 22 +$(S) $(XX) -- ftruncate(3, 0x3) = ? +$(S) $(XX) -- ftruncate(3, 0x3) = 22 +$(S) $(XX) -- getdents(4, 0x123000, 0x1) = ? +$(S) $(XX) -- getdents(4, 0x123000, 0x1) = 22 +$(S) $(XX) -- getdents64(4, 0x123000, 0x1) = ? +$(S) $(XX) -- getdents64(4, 0x123000, 0x1) = 22 +$(S) $(XX) -- getcwd($(XX), 0x9) = ? +$(S) $(XX) -- getcwd($(XX), 0x9) = 22 +$(S) $(XX) -- chdir("input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- chdir("input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- fchdir(6) = ? +$(S) $(XX) -- fchdir(6) = 22 +$(S) $(XX) -- rename("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- rename("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- renameat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- renameat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- renameat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- renameat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- renameat(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- renameat(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- mkdir("input_data\x01\x02\x03\n\r\t", 0644) = ? +$(S) $(XX) -- mkdir("input_data\x01\x02\x03\n\r\t", 0644) = 22 +$(S) $(XX) -- mkdirat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0644) = ? +$(S) $(XX) -- mkdirat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0644) = 22 +$(S) $(XX) -- mkdirat(33, "input_data\x01\x02\x03\n\r\t", 0644) = ? +$(S) $(XX) -- mkdirat(33, "input_data\x01\x02\x03\n\r\t", 0644) = 22 +$(S) $(XX) -- mkdirat(33, (null), 0555) = ? +$(S) $(XX) -- mkdirat(33, (null), 0555) = 22 +$(S) $(XX) -- rmdir("input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- rmdir("input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- rmdir((null)) = ? +$(S) $(XX) -- rmdir((null)) = 22 +$(S) $(XX) -- creat("input_data\x01\x02\x03\n\r\t", 0644) = ? +$(S) $(XX) -- creat("input_data\x01\x02\x03\n\r\t", 0644) = 22 +$(S) $(XX) -- link("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- link("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- linkat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? +$(S) $(XX) -- linkat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x0) = 22 +$(S) $(XX) -- linkat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x400) = ? +$(S) $(XX) -- linkat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x400) = 22 +$(S) $(XX) -- linkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x400) = ? +$(S) $(XX) -- linkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x400) = 22 +$(S) $(XX) -- linkat(7, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? +$(S) $(XX) -- linkat(7, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = 22 +$(S) $(XX) -- unlink("input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- unlink("input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- unlinkat(0, "input_data\x01\x02\x03\n\r\t", 0x0) = ? +$(S) $(XX) -- unlinkat(0, "input_data\x01\x02\x03\n\r\t", 0x0) = 22 +$(S) $(XX) -- unlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x200) = ? +$(S) $(XX) -- unlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x200) = 22 +$(S) $(XX) -- unlinkat(9, "other_input_data\x01\x02\x03\n\r\t", 0x200) = ? +$(S) $(XX) -- unlinkat(9, "other_input_data\x01\x02\x03\n\r\t", 0x200) = 22 +$(S) $(XX) -- symlink("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- symlink("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", AT_FDCWD, (null)) = ? +$(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", AT_FDCWD, (null)) = 22 +$(S) $(XX) -- readlink("input_data\x01\x02\x03\n\r\t", $(XX), 16) = ? +$(S) $(XX) -- readlink("input_data\x01\x02\x03\n\r\t", "expected_output_data\x06\xff", 16) = 22 +$(S) $(XX) -- readlinkat(2, "input_data\x01\x02\x03\n\r\t", $(XX), 16) = ? +$(S) $(XX) -- readlinkat(2, "input_data\x01\x02\x03\n\r\t", "expected_output_data\x06\xff", 16) = 22 +$(S) $(XX) -- readlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), 16) = ? +$(S) $(XX) -- readlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", "expected_output_data\x06\xff", 16) = 22 +$(S) $(XX) -- chmod("input_data\x01\x02\x03\n\r\t", 0644) = ? +$(S) $(XX) -- chmod("input_data\x01\x02\x03\n\r\t", 0644) = 22 +$(S) $(XX) -- fchmod(4, 0644) = ? +$(S) $(XX) -- fchmod(4, 0644) = 22 +$(S) $(XX) -- fchmodat(0, "input_data\x01\x02\x03\n\r\t", 0644) = ? +$(S) $(XX) -- fchmodat(0, "input_data\x01\x02\x03\n\r\t", 0644) = 22 +$(S) $(XX) -- fchmodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0111) = ? +$(S) $(XX) -- fchmodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0111) = 22 +$(S) $(XX) -- chown("input_data\x01\x02\x03\n\r\t", 0x2, 0x3) = ? +$(S) $(XX) -- chown("input_data\x01\x02\x03\n\r\t", 0x2, 0x3) = 22 +$(S) $(XX) -- fchown(4, 0x2, 0x3) = ? +$(S) $(XX) -- fchown(4, 0x2, 0x3) = 22 +$(S) $(XX) -- fchownat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x0) = ? +$(S) $(XX) -- fchownat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x0) = 22 +$(S) $(XX) -- fchownat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x100) = ? +$(S) $(XX) -- fchownat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x100) = 22 +$(S) $(XX) -- fchownat(99, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x1000) = ? +$(S) $(XX) -- fchownat(99, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x1000) = 22 +$(S) $(XX) -- lchown("input_data\x01\x02\x03\n\r\t", 0x2, 0x3) = ? +$(S) $(XX) -- lchown("input_data\x01\x02\x03\n\r\t", 0x2, 0x3) = 22 +$(S) $(XX) -- umask(0222) = ? +$(S) $(XX) -- umask(0222) = 026 +$(S) $(XX) -- gettimeofday(0x123000, 0x234000) = ? +$(S) $(XX) -- gettimeofday(0x123000, 0x234000) = 22 +$(S) $(XX) -- gettimeofday(0x0, 0x0) = ? +$(S) $(XX) -- gettimeofday(0x0, 0x0) = 22 +$(S) $(XX) -- settimeofday(0x123000, 0x234000) = ? +$(S) $(XX) -- settimeofday(0x123000, 0x234000) = 22 +$(S) $(XX) -- getrlimit(0x4, 0x234000) = ? +$(S) $(XX) -- getrlimit(0x4, 0x234000) = 22 +$(S) $(XX) -- getrlimit(0x1, 0x234000) = ? +$(S) $(XX) -- getrlimit(0x1, 0x234000) = 22 +$(S) $(XX) -- prlimit64(0x9, 0x4, 0x123000, 0x234000) = ? +$(S) $(XX) -- prlimit64(0x9, 0x4, 0x123000, 0x234000) = 22 +$(S) $(XX) -- prlimit64(0x8, 0x1, 0x123000, 0x234000) = ? +$(S) $(XX) -- prlimit64(0x8, 0x1, 0x123000, 0x234000) = 22 +$(S) $(XX) -- setrlimit(0x0, 0x123000) = ? +$(S) $(XX) -- setrlimit(0x0, 0x123000) = 22 +$(S) $(XX) -- getrusage(0x0, 0x123000) = ? +$(S) $(XX) -- getrusage(0x0, 0x123000) = 22 +$(S) $(XX) -- sysinfo(0x123000, 0x123000) = ? +$(S) $(XX) -- sysinfo(0x123000, 0x123000) = 22 +$(S) $(XX) -- times(0x0) = ? +$(S) $(XX) -- times(0x0) = 22 +$(S) $(XX) -- times(0x123000) = ? +$(S) $(XX) -- times(0x123000) = 22 +$(S) $(XX) -- getuid() = ? +$(S) $(XX) -- getuid() = 22 +$(S) $(XX) -- getgid() = ? +$(S) $(XX) -- getgid() = 22 +$(S) $(XX) -- setuid(0x7b) = ? +$(S) $(XX) -- setuid(0x7b) = 22 +$(S) $(XX) -- setgid(0x7b) = ? +$(S) $(XX) -- setgid(0x7b) = 22 +$(S) $(XX) -- geteuid() = ? +$(S) $(XX) -- geteuid() = 22 +$(S) $(XX) -- getegid() = ? +$(S) $(XX) -- getegid() = 22 +$(S) $(XX) -- setpgid() = ? +$(S) $(XX) -- setpgid() = 22 +$(S) $(XX) -- syscall(110, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? +$(S) $(XX) -- syscall(110, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 +$(S) $(XX) -- getpgrp() = ? +$(S) $(XX) -- getpgrp() = 22 +$(S) $(XX) -- setsid() = ? +$(S) $(XX) -- setsid() = 22 +$(S) $(XX) -- setreuid(0x3, 0x4) = ? +$(S) $(XX) -- setreuid(0x3, 0x4) = 22 +$(S) $(XX) -- setregid(0x6, 0x7) = ? +$(S) $(XX) -- setregid(0x6, 0x7) = 22 +$(S) $(XX) -- getgroups(0x9, 0x123000) = ? +$(S) $(XX) -- getgroups(0x9, 0x123000) = 22 +$(S) $(XX) -- setgroups(0x9, 0x123000) = ? +$(S) $(XX) -- setgroups(0x9, 0x123000) = 22 +$(S) $(XX) -- setresuid(0x1, 0x2, 0x3) = ? +$(S) $(XX) -- setresuid(0x1, 0x2, 0x3) = 22 +$(S) $(XX) -- getresuid(0x123000, 0x234000, 0x234000) = ? +$(S) $(XX) -- getresuid(0x123000, 0x234000, 0x234000) = 22 +$(S) $(XX) -- setresgid(0x1, 0x2, 0x3) = ? +$(S) $(XX) -- setresgid(0x1, 0x2, 0x3) = 22 +$(S) $(XX) -- getresgid(0x123000, 0x234000, 0x234000) = ? +$(S) $(XX) -- getresgid(0x123000, 0x234000, 0x234000) = 22 +$(S) $(XX) -- getpgid(0x63) = ? +$(S) $(XX) -- getpgid(0x63) = 22 +$(S) $(XX) -- setfsuid(0x58) = ? +$(S) $(XX) -- setfsuid(0x58) = 22 +$(S) $(XX) -- setfsgid(0x4d) = ? +$(S) $(XX) -- setfsgid(0x4d) = 22 +$(S) $(XX) -- getsid(0x42) = ? +$(S) $(XX) -- getsid(0x42) = 22 +$(S) $(XX) -- syslog(0x5c, $(XX), 0x3) = ? +$(S) $(XX) -- syslog(0x5c, $(XX), 0x3) = 22 +$(S) $(XX) -- capget(0x123000, 0x234000) = ? +$(S) $(XX) -- capget(0x123000, 0x234000) = 22 +$(S) $(XX) -- capset(0x123000, 0x234000) = ? +$(S) $(XX) -- capset(0x123000, 0x234000) = 22 +$(S) $(XX) -- rt_sigpending(0x123000) = ? +$(S) $(XX) -- rt_sigpending(0x123000) = 22 +$(S) $(XX) -- rt_sigtimedwait(0x123000, 0x234000, 0x234000, 0x2) = ? +$(S) $(XX) -- rt_sigtimedwait(0x123000, 0x234000, 0x234000, 0x2) = 22 +$(S) $(XX) -- rt_sigqueueinfo(0x4d, 0x4, 0x123000) = ? +$(S) $(XX) -- rt_sigqueueinfo(0x4d, 0x4, 0x123000) = 22 +$(S) $(XX) -- rt_tgsigqueueinfo(0x4d, 0x58, 0xc, 0x123000) = ? +$(S) $(XX) -- rt_tgsigqueueinfo(0x4d, 0x58, 0xc, 0x123000) = 22 +$(S) $(XX) -- rt_sigsuspend(0x123000, 0x3) = ? +$(S) $(XX) -- rt_sigsuspend(0x123000, 0x3) = 22 +$(S) $(XX) -- sigaltstack(0x123000, 0x234000) = ? +$(S) $(XX) -- sigaltstack(0x123000, 0x234000) = 22 +$(S) $(XX) -- utimensat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = ? +$(S) $(XX) -- utimensat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = 22 +$(S) $(XX) -- utimensat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = ? +$(S) $(XX) -- utimensat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = 22 +$(S) $(XX) -- utimensat(4, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = ? +$(S) $(XX) -- utimensat(4, "input_data\x01\x02\x03\n\r\t", $(XX), $(XX)) = 22 +$(S) $(XX) -- mknodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = ? +$(S) $(XX) -- mknodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = 22 +$(S) $(XX) -- mknodat(1, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = ? +$(S) $(XX) -- mknodat(1, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = 22 +$(S) $(XX) -- mknodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = ? +$(S) $(XX) -- mknodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = 22 +$(S) $(XX) -- ustat(0x2, 0x123000) = ? +$(S) $(XX) -- ustat(0x2, 0x123000) = 22 +$(S) $(XX) -- statfs("input_data\x01\x02\x03\n\r\t", 0x123000) = ? +$(S) $(XX) -- statfs("input_data\x01\x02\x03\n\r\t", 0x123000) = 22 +$(S) $(XX) -- fstatfs(4, 0x123000) = ? +$(S) $(XX) -- fstatfs(4, 0x123000) = 22 +$(S) $(XX) -- getpriority(0x1, 0x2) = ? +$(S) $(XX) -- getpriority(0x1, 0x2) = 22 +$(S) $(XX) -- setpriority(0x1, 0x2, 0x3) = ? +$(S) $(XX) -- setpriority(0x1, 0x2, 0x3) = 22 +$(S) $(XX) -- sched_setparam(0x1, 0x123000) = ? +$(S) $(XX) -- sched_setparam(0x1, 0x123000) = 22 +$(S) $(XX) -- sched_getparam(0x1, 0x123000) = ? +$(S) $(XX) -- sched_getparam(0x1, 0x123000) = 22 +$(S) $(XX) -- sched_setscheduler(0x1, 0x3, 0x123000) = ? +$(S) $(XX) -- sched_setscheduler(0x1, 0x3, 0x123000) = 22 +$(S) $(XX) -- sched_getscheduler(0x1) = ? +$(S) $(XX) -- sched_getscheduler(0x1) = 22 +$(S) $(XX) -- sched_get_priority_max(0x2) = ? +$(S) $(XX) -- sched_get_priority_max(0x2) = 22 +$(S) $(XX) -- sched_get_priority_min(0x2) = ? +$(S) $(XX) -- sched_get_priority_min(0x2) = 22 +$(S) $(XX) -- sched_rr_get_interval(0x1, 0x123000) = ? +$(S) $(XX) -- sched_rr_get_interval(0x1, 0x123000) = 22 +$(S) $(XX) -- sched_setaffinity(0x4d, 0x4, 0x123000) = ? +$(S) $(XX) -- sched_setaffinity(0x4d, 0x4, 0x123000) = 22 +$(S) $(XX) -- sched_getaffinity(0x4d, 0x4, 0x123000) = ? +$(S) $(XX) -- sched_getaffinity(0x4d, 0x4, 0x123000) = 22 +$(S) $(XX) -- vhangup() = ? +$(S) $(XX) -- vhangup() = 22 +$(S) $(XX) -- modify_ldt(0x1, 0x123000, 0x1) = ? +$(S) $(XX) -- modify_ldt(0x1, 0x123000, 0x1) = 22 +$(S) $(XX) -- pivot_root("input_data\x01\x02\x03\n\r\t", $(XX)) = ? +$(S) $(XX) -- pivot_root("input_data\x01\x02\x03\n\r\t", $(XX)) = 22 +$(S) $(XX) -- _sysctl(0x123000) = ? +$(S) $(XX) -- _sysctl(0x123000) = 22 +$(S) $(XX) -- prctl(0x18, 0x1, 0x2, 0x3, 0x4) = ? +$(S) $(XX) -- prctl(0x18, 0x1, 0x2, 0x3, 0x4) = 22 +$(S) $(XX) -- arch_prctl(0x1002, 0x123000, $(XX)) = ? +$(S) $(XX) -- arch_prctl(0x1002, 0x123000, $(XX)) = 22 +$(S) $(XX) -- clock_adjtime(0x0, 0x123000) = ? +$(S) $(XX) -- clock_adjtime(0x0, 0x123000) = 22 +$(S) $(XX) -- chroot("input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- chroot("input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- sync() = ? +$(S) $(XX) -- sync() = 22 +$(S) $(XX) -- syncfs(3) = ? +$(S) $(XX) -- syncfs(3) = 22 +$(S) $(XX) -- acct("input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- acct("input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- mount("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", 0x123000, 0x80, 0x234000) = ? +$(S) $(XX) -- mount("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", 0x123000, 0x80, 0x234000) = 22 +$(S) $(XX) -- umount2("input_data\x01\x02\x03\n\r\t", 0x0) = ? +$(S) $(XX) -- umount2("input_data\x01\x02\x03\n\r\t", 0x0) = 22 +$(S) $(XX) -- umount2("input_data\x01\x02\x03\n\r\t", 0x2) = ? +$(S) $(XX) -- umount2("input_data\x01\x02\x03\n\r\t", 0x2) = 22 +$(S) $(XX) -- swapon("input_data\x01\x02\x03\n\r\t", 0x8000) = ? +$(S) $(XX) -- swapon("input_data\x01\x02\x03\n\r\t", 0x8000) = 22 +$(S) $(XX) -- swapoff("input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- swapoff("input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- sethostname($(XX), 0x10) = ? +$(S) $(XX) -- sethostname($(XX), 0x10) = 22 +$(S) $(XX) -- setdomainname($(XX), 0x10) = ? +$(S) $(XX) -- setdomainname($(XX), 0x10) = 22 +$(S) $(XX) -- iopl(0x1) = ? +$(S) $(XX) -- iopl(0x1) = 22 +$(S) $(XX) -- ioperm(0x3, 0x4, 0x1) = ? +$(S) $(XX) -- ioperm(0x3, 0x4, 0x1) = 22 +$(S) $(XX) -- syscall(175, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? +$(S) $(XX) -- syscall(175, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 +$(S) $(XX) -- finit_module(3, 0x123000, 0x0) = ? +$(S) $(XX) -- finit_module(3, 0x123000, 0x0) = 22 +$(S) $(XX) -- syscall(176, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? +$(S) $(XX) -- syscall(176, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 +$(S) $(XX) -- syscall(179, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? +$(S) $(XX) -- syscall(179, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 +$(S) $(XX) -- gettid() = ? +$(S) $(XX) -- gettid() = 22 +$(S) $(XX) -- readahead(4, 17185, 123) = ? +$(S) $(XX) -- readahead(4, 17185, 123) = 22 +$(S) $(XX) -- setxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x1) = ? +$(S) $(XX) -- setxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x1) = 22 +$(S) $(XX) -- setxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x2) = ? +$(S) $(XX) -- setxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x2) = 22 +$(S) $(XX) -- lsetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x1) = ? +$(S) $(XX) -- lsetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x1) = 22 +$(S) $(XX) -- lsetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x2) = ? +$(S) $(XX) -- lsetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x2) = 22 +$(S) $(XX) -- fsetxattr(4, "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x2) = ? +$(S) $(XX) -- fsetxattr(4, "other_input_data\x01\x02\x03\n\r\t", "oth", 3, 0x2) = 22 +$(S) $(XX) -- getxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = ? +$(S) $(XX) -- getxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = 22 +$(S) $(XX) -- getxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = ? +$(S) $(XX) -- getxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = 22 +$(S) $(XX) -- lgetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = ? +$(S) $(XX) -- lgetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = 22 +$(S) $(XX) -- lgetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = ? +$(S) $(XX) -- lgetxattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = 22 +$(S) $(XX) -- fgetxattr(4, "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = ? +$(S) $(XX) -- fgetxattr(4, "other_input_data\x01\x02\x03\n\r\t", $(N), 0x3) = 22 +$(S) $(XX) -- listxattr("input_data\x01\x02\x03\n\r\t", 0x0000000000123000, 4) = ? +$(S) $(XX) -- listxattr("input_data\x01\x02\x03\n\r\t", 0x0000000000123000, 4) = 22 +$(S) $(XX) -- llistxattr("input_data\x01\x02\x03\n\r\t", 0x0000000000123000, 4) = ? +$(S) $(XX) -- llistxattr("input_data\x01\x02\x03\n\r\t", 0x0000000000123000, 4) = 22 +$(S) $(XX) -- flistxattr(5, 0x0000000000123000, 4) = ? +$(S) $(XX) -- flistxattr(5, 0x0000000000123000, 4) = 22 +$(S) $(XX) -- flistxattr(-100, 0x0000000000123000, 4) = ? +$(S) $(XX) -- flistxattr(-100, 0x0000000000123000, 4) = 22 +$(S) $(XX) -- removexattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- removexattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- lremovexattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- lremovexattr("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- fremovexattr(7, "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- fremovexattr(7, "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- tkill(0x2c, 0x13) = ? +$(S) $(XX) -- tkill(0x2c, 0x13) = 22 +$(S) $(XX) -- tgkill(0x2c, 0x37, 0x13) = ? +$(S) $(XX) -- tgkill(0x2c, 0x37, 0x13) = 22 +$(S) $(XX) -- time(0x123000) = ? +$(S) $(XX) -- time(0x123000) = 22 +$(S) $(XX) -- futex(0x123000, 0x1, 0x7, 0x123000, 0x234000, 0x1) = ? +$(S) $(XX) -- futex(0x123000, 0x1, 0x7, 0x123000, 0x234000, 0x1) = 22 +$(S) $(XX) -- set_thread_area(0x123000) = ? +$(S) $(XX) -- set_thread_area(0x123000) = 22 +$(S) $(XX) -- get_thread_area(0x123000) = ? +$(S) $(XX) -- get_thread_area(0x123000) = 22 +$(S) $(XX) -- io_setup(0x1, 0x123000) = ? +$(S) $(XX) -- io_setup(0x1, 0x123000) = 22 +$(S) $(XX) -- io_destroy(0x4d) = ? +$(S) $(XX) -- io_destroy(0x4d) = 22 +$(S) $(XX) -- io_getevents(0x1, 0x2, 0x3, 0x123000, 0x234000) = ? +$(S) $(XX) -- io_getevents(0x1, 0x2, 0x3, 0x123000, 0x234000) = 22 +$(S) $(XX) -- io_submit(0x1, 0x2, 0x123000) = ? +$(S) $(XX) -- io_submit(0x1, 0x2, 0x123000) = 22 +$(S) $(XX) -- io_cancel(0x1, 0x123000, 0x234000) = ? +$(S) $(XX) -- io_cancel(0x1, 0x123000, 0x234000) = 22 +$(S) $(XX) -- lookup_dcookie(0x7b, 0x123000, 0xc) = ? +$(S) $(XX) -- lookup_dcookie(0x7b, 0x123000, 0xc) = 22 +$(S) $(XX) -- epoll_create(0x7) = ? +$(S) $(XX) -- epoll_create(0x7) = 22 +$(S) $(XX) -- epoll_create1(0x0) = ? +$(S) $(XX) -- epoll_create1(0x0) = 22 +$(S) $(XX) -- epoll_create1(0x80000) = ? +$(S) $(XX) -- epoll_create1(0x80000) = 22 +$(S) $(XX) -- epoll_wait(2, 0x123000, 0x4, 0x5) = ? +$(S) $(XX) -- epoll_wait(2, 0x123000, 0x4, 0x5) = 22 +$(S) $(XX) -- epoll_pwait(2, 0x123000, 0x4, 0x5, 0x234000, 0x6) = ? +$(S) $(XX) -- epoll_pwait(2, 0x123000, 0x4, 0x5, 0x234000, 0x6) = 22 +$(S) $(XX) -- epoll_ctl(2, 0x3, 4, 0x123000) = ? +$(S) $(XX) -- epoll_ctl(2, 0x3, 4, 0x123000) = 22 +$(S) $(XX) -- set_tid_address(0x123000) = ? +$(S) $(XX) -- set_tid_address(0x123000) = 22 +$(S) $(XX) -- fadvise64(3, 0x64, 0x63, 0x2) = ? +$(S) $(XX) -- fadvise64(3, 0x64, 0x63, 0x2) = 22 +$(S) $(XX) -- timer_create(0x3, 0x123000, 0x234000) = ? +$(S) $(XX) -- timer_create(0x3, 0x123000, 0x234000) = 22 +$(S) $(XX) -- timer_settime(0x4, 0x0, 0x123000, 0x234000) = ? +$(S) $(XX) -- timer_settime(0x4, 0x0, 0x123000, 0x234000) = 22 +$(S) $(XX) -- timer_settime(0x4, 0x1, 0x123000, 0x234000) = ? +$(S) $(XX) -- timer_settime(0x4, 0x1, 0x123000, 0x234000) = 22 +$(S) $(XX) -- timer_gettime(0x3, 0x123000) = ? +$(S) $(XX) -- timer_gettime(0x3, 0x123000) = 22 +$(S) $(XX) -- timer_getoverrun(0x3) = ? +$(S) $(XX) -- timer_getoverrun(0x3) = 22 +$(S) $(XX) -- timer_delete(0x3) = ? +$(S) $(XX) -- timer_delete(0x3) = 22 +$(S) $(XX) -- clock_settime(0x7, 0x123000) = ? +$(S) $(XX) -- clock_settime(0x7, 0x123000) = 22 +$(S) $(XX) -- clock_gettime(0x7, 0x123000) = ? +$(S) $(XX) -- clock_gettime(0x7, 0x123000) = 22 +$(S) $(XX) -- clock_getres(0x3, 0x123000) = ? +$(S) $(XX) -- clock_getres(0x3, 0x123000) = 22 +$(S) $(XX) -- clock_nanosleep(0x1, 0x1, 0x123000, 0x234000) = ? +$(S) $(XX) -- clock_nanosleep(0x1, 0x1, 0x123000, 0x234000) = 22 +$(S) $(XX) -- mbind(0x123000, 0x0, 0x8002, 0x234000, 0x4) = ? +$(S) $(XX) -- mbind(0x123000, 0x0, 0x8002, 0x234000, 0x4) = 22 +$(S) $(XX) -- set_mempolicy(0x8000, 0x123000, 0x5) = ? +$(S) $(XX) -- set_mempolicy(0x8000, 0x123000, 0x5) = 22 +$(S) $(XX) -- get_mempolicy(0x123000, 0x234000, 0x6, 0x123000, 0x0) = ? +$(S) $(XX) -- get_mempolicy(0x123000, 0x234000, 0x6, 0x123000, 0x0) = 22 +$(S) $(XX) -- mq_open("input_data\x01\x02\x03\n\r\t", 0x42, 0x1ff, 0x123000, $(XX)) = ? +$(S) $(XX) -- mq_open("input_data\x01\x02\x03\n\r\t", 0x42, 0x1ff, 0x123000, $(XX)) = 22 +$(S) $(XX) -- mq_unlink("input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- mq_unlink("input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- mq_timedsend(0x1, $(XX), 0x10, 0x3, 0x123000) = ? +$(S) $(XX) -- mq_timedsend(0x1, $(XX), 0x10, 0x3, 0x123000) = 22 +$(S) $(XX) -- mq_timedreceive(0x1, $(XX), 0x10, 0x3, 0x123000) = ? +$(S) $(XX) -- mq_timedreceive(0x1, $(XX), 0x10, 0x3, 0x123000) = 22 +$(S) $(XX) -- mq_notify(0x1, 0x123000) = ? +$(S) $(XX) -- mq_notify(0x1, 0x123000) = 22 +$(S) $(XX) -- mq_getsetattr(0x1, 0x123000, 0x234000) = ? +$(S) $(XX) -- mq_getsetattr(0x1, 0x123000, 0x234000) = 22 +$(S) $(XX) -- kexec_load(0x1, 0x2, 0x123000, 0x2) = ? +$(S) $(XX) -- kexec_load(0x1, 0x2, 0x123000, 0x2) = 22 +$(S) $(XX) -- kexec_file_load(0x1, 0x2, 0x3, $(XX), 0x2) = ? +$(S) $(XX) -- kexec_file_load(0x1, 0x2, 0x3, $(XX), 0x2) = 22 +$(S) $(XX) -- waitid(0x1, 0x2, 0x123000, 0x4) = ? +$(S) $(XX) -- waitid(0x1, 0x2, 0x123000, 0x4) = 22 +$(S) $(XX) -- add_key(0x123000, 0x234000, 0x123000, 0x234000, 0x1) = ? +$(S) $(XX) -- add_key(0x123000, 0x234000, 0x123000, 0x234000, 0x1) = 22 +$(S) $(XX) -- request_key(0x123000, 0x234000, 0x123000, 0x1) = ? +$(S) $(XX) -- request_key(0x123000, 0x234000, 0x123000, 0x1) = 22 +$(S) $(XX) -- keyctl(0x0, 0x1, 0x2, 0x3, 0x4) = ? +$(S) $(XX) -- keyctl(0x0, 0x1, 0x2, 0x3, 0x4) = 22 +$(S) $(XX) -- ioprio_set(0x1, 0x3, 0x7b) = ? +$(S) $(XX) -- ioprio_set(0x1, 0x3, 0x7b) = 22 +$(S) $(XX) -- ioprio_get(0x1, 0x3) = ? +$(S) $(XX) -- ioprio_get(0x1, 0x3) = 22 +$(S) $(XX) -- inotify_init() = ? +$(S) $(XX) -- inotify_init() = 22 +$(S) $(XX) -- inotify_init1(0x800) = ? +$(S) $(XX) -- inotify_init1(0x800) = 22 +$(S) $(XX) -- inotify_init1(0x80000) = ? +$(S) $(XX) -- inotify_init1(0x80000) = 22 +$(S) $(XX) -- inotify_add_watch(7, "input_data\x01\x02\x03\n\r\t", 0x7b) = ? +$(S) $(XX) -- inotify_add_watch(7, "input_data\x01\x02\x03\n\r\t", 0x7b) = 22 +$(S) $(XX) -- inotify_rm_watch(7, 0x8) = ? +$(S) $(XX) -- inotify_rm_watch(7, 0x8) = 22 +$(S) $(XX) -- migrate_pages(0x1, 0x2, 0x123000, 0x234000) = ? +$(S) $(XX) -- migrate_pages(0x1, 0x2, 0x123000, 0x234000) = 22 +$(S) $(XX) -- unshare(0x20400) = ? +$(S) $(XX) -- unshare(0x20400) = 22 +$(S) $(XX) -- set_robust_list(0x123000, 33) = ? +$(S) $(XX) -- set_robust_list(0x123000, 33) = 22 +$(S) $(XX) -- get_robust_list(0x2c, 0x123000, 0x234000) = ? +$(S) $(XX) -- get_robust_list(0x2c, 0x123000, 0x234000) = 22 +$(S) $(XX) -- splice(2, 0x123000, 3, 0x234000, 0x7b, 0x1) = ? +$(S) $(XX) -- splice(2, 0x123000, 3, 0x234000, 0x7b, 0x1) = 22 +$(S) $(XX) -- splice(2, 0x123000, 3, 0x234000, 0x0, 0x4) = ? +$(S) $(XX) -- splice(2, 0x123000, 3, 0x234000, 0x0, 0x4) = 22 +$(S) $(XX) -- vmsplice(1, 0x123000, 0x2, 0x3) = ? +$(S) $(XX) -- vmsplice(1, 0x123000, 0x2, 0x3) = 22 +$(S) $(XX) -- tee(1, 2, 0x3, 0x0) = ? +$(S) $(XX) -- tee(1, 2, 0x3, 0x0) = 22 +$(S) $(XX) -- tee(1, 2, 0x3, 0x1) = ? +$(S) $(XX) -- tee(1, 2, 0x3, 0x1) = 22 +$(S) $(XX) -- tee(1, 2, 0x3, 0x2) = ? +$(S) $(XX) -- tee(1, 2, 0x3, 0x2) = 22 +$(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x0) = ? +$(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x0) = 22 +$(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x1) = ? +$(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x1) = 22 +$(S) $(XX) -- signalfd(1, 0x123000, 0xc) = ? +$(S) $(XX) -- signalfd(1, 0x123000, 0xc) = 22 +$(S) $(XX) -- signalfd4(1, 0x123000, 0xd, 0x800, $(XX)) = ? +$(S) $(XX) -- signalfd4(1, 0x123000, 0xd, 0x800, $(XX)) = 22 +$(S) $(XX) -- timerfd_create(0x0, 0x80000) = ? +$(S) $(XX) -- timerfd_create(0x0, 0x80000) = 22 +$(S) $(XX) -- timerfd_settime(1, 0x1, 0x123000, 0x234000) = ? +$(S) $(XX) -- timerfd_settime(1, 0x1, 0x123000, 0x234000) = 22 +$(S) $(XX) -- timerfd_gettime(2, 0x123000) = ? +$(S) $(XX) -- timerfd_gettime(2, 0x123000) = 22 +$(S) $(XX) -- eventfd(0x2d) = ? +$(S) $(XX) -- eventfd(0x2d) = 22 +$(S) $(XX) -- eventfd2(0x2f, 0x1) = ? +$(S) $(XX) -- eventfd2(0x2f, 0x1) = 22 +$(S) $(XX) -- fallocate(1, 0x2, 0x3, 0x4) = ? +$(S) $(XX) -- fallocate(1, 0x2, 0x3, 0x4) = 22 +$(S) $(XX) -- perf_event_open(0x123000, 0x1, 0x2, 0x3, 0x4) = ? +$(S) $(XX) -- perf_event_open(0x123000, 0x1, 0x2, 0x3, 0x4) = 22 +$(S) $(XX) -- fanotify_init(0x9, 0x2) = ? +$(S) $(XX) -- fanotify_init(0x9, 0x2) = 22 +$(S) $(XX) -- fanotify_mark(0x2, 0x2, 0x4000, 0x3, $(XX)) = ? +$(S) $(XX) -- fanotify_mark(0x2, 0x2, 0x4000, 0x3, $(XX)) = 22 +$(S) $(XX) -- name_to_handle_at(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x123000, 0x234000, 0x0) = ? +$(S) $(XX) -- name_to_handle_at(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x123000, 0x234000, 0x0) = 22 +$(S) $(XX) -- open_by_handle_at(3, 0x0000000000123000, 0) = ? +$(S) $(XX) -- open_by_handle_at(3, 0x0000000000123000, 0) = 22 +$(S) $(XX) -- setns(2, 0x0) = ? +$(S) $(XX) -- setns(2, 0x0) = 22 +$(S) $(XX) -- getcpu(0x123000, 0x123000, 0x234000) = ? +$(S) $(XX) -- getcpu(0x123000, 0x123000, 0x234000) = 22 +$(S) $(XX) -- process_vm_readv(0x1, 0x2, 0x3, 0x4, 0x5, 0x6) = ? +$(S) $(XX) -- process_vm_readv(0x1, 0x2, 0x3, 0x4, 0x5, 0x6) = 22 +$(S) $(XX) -- process_vm_writev(0x1, 0x2, 0x3, 0x4, 0x5, 0x6) = ? +$(S) $(XX) -- process_vm_writev(0x1, 0x2, 0x3, 0x4, 0x5, 0x6) = 22 +$(S) $(XX) -- kcmp(0x1, 0x2, 0x3, 0x4, 0x5) = ? +$(S) $(XX) -- kcmp(0x1, 0x2, 0x3, 0x4, 0x5) = 22 diff --git a/test/libcintercept0.log.match b/test/libcintercept0.log.match index 546c085..9a91cea 100644 --- a/test/libcintercept0.log.match +++ b/test/libcintercept0.log.match @@ -11,16 +11,16 @@ $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = $(N) $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = $(N) -$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = ? -$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = 0 +$(S) $(XX) -- newfstatat($(N), "", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat($(N), "", $(XX), $(XX)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(S) $(XX) -- read($(N), $(XX), $(N)) = ? $(S) $(XX) -- read($(N), "/*\n * Copyright 2016-2017, Intel Corporation\n *\n * Redistribution and use in source and binary forms, with or without\n...", $(N)) = $(N) -$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = ? -$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = 0 +$(S) $(XX) -- newfstatat(1, "", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(1, "", $(XX), $(XX)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? diff --git a/test/libcintercept0_child.log.match b/test/libcintercept0_child.log.match index 4f8478c..b8fba9f 100644 --- a/test/libcintercept0_child.log.match +++ b/test/libcintercept0_child.log.match @@ -2,16 +2,16 @@ $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = $(N) $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = $(N) -$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = ? -$(S) $(XX) -- $(*)fstat$(*)($(N), $(*)) = 0 +$(S) $(XX) -- newfstatat($(N), "", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat($(N), "", $(XX), $(XX)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(S) $(XX) -- read($(N), $(XX), $(N)) = ? $(S) $(XX) -- read($(N), "/*\n * Copyright 2016-2017, Intel Corporation\n *\n * Redistribution and use in source and binary forms, with or without\n...", $(N)) = $(N) -$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = ? -$(S) $(XX) -- $(*)fstat$(*)(1, $(*)) = 0 +$(S) $(XX) -- newfstatat(1, "", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(1, "", $(XX), $(XX)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? From 10755aad8979ae0f49c07b22580ea79700c6be0a Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 18 Jul 2025 18:42:02 +0200 Subject: [PATCH 127/143] Fine-tuned riscv syscall format logging match file --- src/syscall_formats.c | 5 + test/arch/riscv/syscall_format.log.match | 148 ++++++++--------------- 2 files changed, 55 insertions(+), 98 deletions(-) diff --git a/src/syscall_formats.c b/src/syscall_formats.c index 99a1503..d6654e9 100644 --- a/src/syscall_formats.c +++ b/src/syscall_formats.c @@ -200,6 +200,7 @@ static const struct syscall_format formats[] = { SARGS(geteuid, rdec, arg_none), SARGS(getegid, rdec, arg_none), SARGS(setpgid, rdec, arg_none), + SARGS(getppid, rdec, arg_none), #ifdef SYS_getpgrp SARGS(getpgrp, rdec, arg_none), #endif @@ -285,6 +286,10 @@ static const struct syscall_format formats[] = { #ifdef SYS_ioperm SARGS(ioperm, rdec, arg_, arg_, arg_), #endif + SARGS(create_module, rpointer, arg_pointer, arg_dec), + SARGS(init_module, rdec, arg_pointer, arg_dec, arg_pointer), + SARGS(delete_module, rdec, arg_cstr, arg_), + SARGS(quotactl, rdec, arg_dec, arg_pointer, arg_dec, arg_pointer), SARGS(gettid, rdec, arg_none), SARGS(readahead, rdec, arg_fd, arg_dec, arg_dec), SARGS(setxattr, rdec, arg_cstr, arg_cstr, arg_buf_in, arg_dec, arg_), diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match index de64dd8..62c9975 100644 --- a/test/arch/riscv/syscall_format.log.match +++ b/test/arch/riscv/syscall_format.log.match @@ -32,20 +32,6 @@ $(S) $(XX) -- pwritev(1, 0x123000, 0x4, 0x1000) = ? $(S) $(XX) -- pwritev(1, 0x123000, 0x4, 0x1000) = 22 $(S) $(XX) -- pwritev(1, 0x0, 0x4, 0x1000) = ? $(S) $(XX) -- pwritev(1, 0x0, 0x4, 0x1000) = 22 -$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = ? -$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = 22 -$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? -$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDONLY) = 22 -$(OPT)$(S) $(XX) -- open((null), O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = ? -$(OPT)$(S) $(XX) -- open((null), O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = 22 -$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = ? -$(OPT)$(S) $(XX) -- open("input_data\x01\x02\x03\n\r\t", O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT | O_DIRECTORY | O_DSYNC | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_RSYNC | O_TRUNC, 0777) = 22 -$(OPT)$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_NONBLOCK) = ? -$(OPT)$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_NONBLOCK) = 22 -$(OPT)$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? -$(OPT)$(S) $(XX) -- open("other_input_data\x01\x02\x03\n\r\t", O_RDONLY) = 22 -$(OPT)$(S) $(XX) -- open((null), O_RDONLY) = ? -$(OPT)$(S) $(XX) -- open((null), O_RDONLY) = 22 $(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = ? $(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDWR | O_CREAT | O_DSYNC | O_RSYNC, 0321) = 22 $(S) $(XX) -- openat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", O_RDONLY) = ? @@ -74,14 +60,14 @@ $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 -$(S) $(XX) -- $(S)fstat$(S)(0, $(*)) = ? -$(S) $(XX) -- $(S)fstat$(S)(0, $(*)) = 22 -$(OPT)$(S) $(XX) -- $(S)fstat$(S)(-1, $(*)) = ? -$(OPT)$(S) $(XX) -- $(S)fstat$(S)(-1, $(*)) = 22 -$(OPT)$(S) $(XX) -- $(S)fstat$(S)(AT_FDCWD, $(*)) = ? -$(OPT)$(S) $(XX) -- $(S)fstat$(S)(AT_FDCWD, $(*)) = 22 -$(S) $(XX) -- $(S)fstat$(S)(2, $(*)) = ? -$(S) $(XX) -- $(S)fstat$(S)(2, $(*)) = 22 +$(S) $(XX) -- newfstatat(0, "", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(0, "", $(XX), $(XX)) = 22 +$(OPT)$(S) $(XX) -- newfstatat(-1, "", $(XX), $(XX)) = ? +$(OPT)$(S) $(XX) -- newfstatat(-1, "", $(XX), $(XX)) = 22 +$(OPT)$(S) $(XX) -- newfstatat(AT_FDCWD, "", $(XX), $(XX)) = ? +$(OPT)$(S) $(XX) -- newfstatat(AT_FDCWD, "", $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(2, "", $(XX), $(XX)) = ? +$(S) $(XX) -- newfstatat(2, "", $(XX), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? @@ -98,10 +84,10 @@ $(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = ? $(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX), 0x100) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX), 0x100) = 22 -$(S) $(XX) -- $(*)poll((null), 0, $(*)) = ? -$(S) $(XX) -- $(*)poll((null), 0, $(*)) = 22 -$(S) $(XX) -- $(*)poll($(XX), 3, $(*)) = ? -$(S) $(XX) -- $(*)poll($(XX), 3, $(*)) = 22 +$(S) $(XX) -- ppoll((null), 0, $(XX), $(XX), $(N)) = ? +$(S) $(XX) -- ppoll((null), 0, $(XX), $(XX), $(N)) = 22 +$(S) $(XX) -- ppoll($(XX), 3, $(XX), $(XX), $(N)) = ? +$(S) $(XX) -- ppoll($(XX), 3, $(XX), $(XX), $(N)) = 22 $(S) $(XX) -- ppoll($(XX), 2, 0x123000, 0x234000, 2) = ? $(S) $(XX) -- ppoll($(XX), 2, 0x123000, 0x234000, 2) = 22 $(S) $(XX) -- lseek(0, 0, SEEK_SET) = ? @@ -170,8 +156,8 @@ $(S) $(XX) -- madvise((null), 0, 2) = ? $(S) $(XX) -- madvise((null), 0, 2) = 22 $(S) $(XX) -- mlock(0x123000, 0x3000) = ? $(S) $(XX) -- mlock(0x123000, 0x3000) = 22 -$(OPT)$(S) $(XX) -- mlock2(0x123000, 0x3000, 0x0) = ? -$(OPT)$(S) $(XX) -- mlock2(0x123000, 0x3000, 0x0) = 22 +$(S) $(XX) -- mlock2(0x123000, 0x3000, 0x0) = ? +$(S) $(XX) -- mlock2(0x123000, 0x3000, 0x0) = 22 $(S) $(XX) -- munlock(0x123000, 0x3000) = ? $(S) $(XX) -- munlock(0x123000, 0x3000) = 22 $(S) $(XX) -- mlockall(0x1) = ? @@ -186,14 +172,14 @@ $(S) $(XX) -- rt_sigprocmask(0x2, 0x0000000000123000, 0x0000000000234000, 10) = $(S) $(XX) -- rt_sigprocmask(0x2, 0x0000000000123000, 0x0000000000234000, 10) = 22 $(S) $(XX) -- ioctl(1, 0x4d, 0x0000000000234000) = ? $(S) $(XX) -- ioctl(1, 0x4d, 0x0000000000234000) = 22 -$(S) $(XX) -- $(*)access$(*)($(*)(null), F_OK) = ? -$(S) $(XX) -- $(*)access$(*)($(*)(null), F_OK) = 22 -$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", X_OK) = ? -$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", X_OK) = 22 -$(S) $(XX) -- $(*)access$(*)($(*)"", R_OK | W_OK) = ? -$(S) $(XX) -- $(*)access$(*)($(*)"", R_OK | W_OK) = 22 -$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = ? -$(S) $(XX) -- $(*)access$(*)($(*)"input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = 22 +$(S) $(XX) -- faccessat(AT_FDCWD, (null), F_OK) = ? +$(S) $(XX) -- faccessat(AT_FDCWD, (null), F_OK) = 22 +$(S) $(XX) -- faccessat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", X_OK) = ? +$(S) $(XX) -- faccessat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", X_OK) = 22 +$(S) $(XX) -- faccessat(AT_FDCWD, "", R_OK | W_OK) = ? +$(S) $(XX) -- faccessat(AT_FDCWD, "", R_OK | W_OK) = 22 +$(S) $(XX) -- faccessat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = ? +$(S) $(XX) -- faccessat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", R_OK | W_OK | X_OK) = 22 $(S) $(XX) -- faccessat2(AT_FDCWD, (null), 00, $(XX)) = ? $(S) $(XX) -- faccessat2(AT_FDCWD, (null), 00, $(XX)) = 22 $(S) $(XX) -- faccessat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, $(XX)) = ? @@ -222,20 +208,20 @@ $(S) $(XX) -- shmdt(0x123000) = ? $(S) $(XX) -- shmdt(0x123000) = 22 $(S) $(XX) -- dup(4) = ? $(S) $(XX) -- dup(4) = 22 -$(S) $(XX) -- dup$(N)(4, 5$(*)) = ? -$(S) $(XX) -- dup$(N)(4, 5$(*)) = 22 +$(S) $(XX) -- dup3(4, 5, 0x0) = ? +$(S) $(XX) -- dup3(4, 5, 0x0) = 22 $(S) $(XX) -- dup3(4, 5, 0x0) = ? $(S) $(XX) -- dup3(4, 5, 0x0) = 22 $(S) $(XX) -- dup3(4, 5, 0x80000) = ? $(S) $(XX) -- dup3(4, 5, 0x80000) = 22 -$(S) $(XX) -- p$(S)($(*)) = ? -$(S) $(XX) -- p$(S)($(*)) = 22 +$(S) $(XX) -- ppoll((null), 0, 0x0, 0x0, $(N) = ? +$(S) $(XX) -- ppoll((null), 0, 0x0, 0x0, $(N) = 22 $(S) $(XX) -- clock_nanosleep(0x0, 0x0, 0x123000, 0x234000) = ? $(S) $(XX) -- clock_nanosleep(0x0, 0x0, 0x123000, 0x234000) = 22 $(S) $(XX) -- getitimer(0x3, 0x123000) = ? $(S) $(XX) -- getitimer(0x3, 0x123000) = 22 -$(S) $(XX) -- alarm(0x4) = ? -$(S) $(XX) -- alarm(0x4) = 22 +$(S) $(XX) -- setitimer(0x0, $(XX), $(XX)) = ? +$(S) $(XX) -- setitimer(0x0, $(XX), $(XX)) = 22 $(S) $(XX) -- setitimer(0x6, 0x123000, 0x234000) = ? $(S) $(XX) -- setitimer(0x6, 0x123000, 0x234000) = 22 $(S) $(XX) -- getpid() = ? @@ -318,8 +304,6 @@ $(S) $(XX) -- truncate("input_data\x01\x02\x03\n\r\t", 0x4) = ? $(S) $(XX) -- truncate("input_data\x01\x02\x03\n\r\t", 0x4) = 22 $(S) $(XX) -- ftruncate(3, 0x3) = ? $(S) $(XX) -- ftruncate(3, 0x3) = 22 -$(OPT)$(S) $(XX) -- getdents(4, 0x123000, 0x1) = ? -$(OPT)$(S) $(XX) -- getdents(4, 0x123000, 0x1) = 22 $(S) $(XX) -- getdents64(4, 0x123000, 0x1) = ? $(S) $(XX) -- getdents64(4, 0x123000, 0x1) = 22 $(S) $(XX) -- getcwd($(XX), 0x9) = ? @@ -336,22 +320,14 @@ $(S) $(XX) -- renameat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input $(S) $(XX) -- renameat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t") = 22 $(S) $(XX) -- renameat(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = ? $(S) $(XX) -- renameat(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = 22 -$(OPT)$(S) $(XX) -- mkdir("input_data\x01\x02\x03\n\r\t", 0644) = ? -$(OPT)$(S) $(XX) -- mkdir("input_data\x01\x02\x03\n\r\t", 0644) = 22 $(S) $(XX) -- mkdirat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0644) = ? $(S) $(XX) -- mkdirat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0644) = 22 $(S) $(XX) -- mkdirat(33, "input_data\x01\x02\x03\n\r\t", 0644) = ? $(S) $(XX) -- mkdirat(33, "input_data\x01\x02\x03\n\r\t", 0644) = 22 $(S) $(XX) -- mkdirat(33, (null), 0555) = ? $(S) $(XX) -- mkdirat(33, (null), 0555) = 22 -$(OPT)$(S) $(XX) -- rmdir("input_data\x01\x02\x03\n\r\t") = ? -$(OPT)$(S) $(XX) -- rmdir("input_data\x01\x02\x03\n\r\t") = 22 -$(OPT)$(S) $(XX) -- rmdir((null)) = ? -$(OPT)$(S) $(XX) -- rmdir((null)) = 22 -$(OPT)$(S) $(XX) -- creat("input_data\x01\x02\x03\n\r\t", 0644) = ? -$(OPT)$(S) $(XX) -- creat("input_data\x01\x02\x03\n\r\t", 0644) = 22 -$(S) $(XX) -- link("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = ? -$(S) $(XX) -- link("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- linkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? +$(S) $(XX) -- linkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = 22 $(S) $(XX) -- linkat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? $(S) $(XX) -- linkat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x0) = 22 $(S) $(XX) -- linkat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x400) = ? @@ -360,38 +336,38 @@ $(S) $(XX) -- linkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 2, "other_input_d $(S) $(XX) -- linkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x400) = 22 $(S) $(XX) -- linkat(7, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? $(S) $(XX) -- linkat(7, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = 22 -$(S) $(XX) -- unlink("input_data\x01\x02\x03\n\r\t") = ? -$(S) $(XX) -- unlink("input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- unlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x0) = ? +$(S) $(XX) -- unlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x0) = 22 $(S) $(XX) -- unlinkat(0, "input_data\x01\x02\x03\n\r\t", 0x0) = ? $(S) $(XX) -- unlinkat(0, "input_data\x01\x02\x03\n\r\t", 0x0) = 22 $(S) $(XX) -- unlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x200) = ? $(S) $(XX) -- unlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x200) = 22 $(S) $(XX) -- unlinkat(9, "other_input_data\x01\x02\x03\n\r\t", 0x200) = ? $(S) $(XX) -- unlinkat(9, "other_input_data\x01\x02\x03\n\r\t", 0x200) = 22 -$(S) $(XX) -- symlink("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = ? -$(S) $(XX) -- symlink("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = ? +$(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = 22 $(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t") = ? $(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t") = 22 $(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = ? $(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = 22 $(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", AT_FDCWD, (null)) = ? $(S) $(XX) -- symlinkat("input_data\x01\x02\x03\n\r\t", AT_FDCWD, (null)) = 22 -$(S) $(XX) -- readlink("input_data\x01\x02\x03\n\r\t", $(XX), 16) = ? -$(S) $(XX) -- readlink("input_data\x01\x02\x03\n\r\t", "expected_output_data\x06\xff", 16) = 22 +$(S) $(XX) -- readlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), 16) = ? +$(S) $(XX) -- readlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", "expected_output_data\x06\xff", 16) = 22 $(S) $(XX) -- readlinkat(2, "input_data\x01\x02\x03\n\r\t", $(XX), 16) = ? $(S) $(XX) -- readlinkat(2, "input_data\x01\x02\x03\n\r\t", "expected_output_data\x06\xff", 16) = 22 $(S) $(XX) -- readlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", $(XX), 16) = ? $(S) $(XX) -- readlinkat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", "expected_output_data\x06\xff", 16) = 22 -$(S) $(XX) -- chmod("input_data\x01\x02\x03\n\r\t", 0644) = ? -$(S) $(XX) -- chmod("input_data\x01\x02\x03\n\r\t", 0644) = 22 +$(S) $(XX) -- fchmodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0644) = ? +$(S) $(XX) -- fchmodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0644) = 22 $(S) $(XX) -- fchmod(4, 0644) = ? $(S) $(XX) -- fchmod(4, 0644) = 22 $(S) $(XX) -- fchmodat(0, "input_data\x01\x02\x03\n\r\t", 0644) = ? $(S) $(XX) -- fchmodat(0, "input_data\x01\x02\x03\n\r\t", 0644) = 22 $(S) $(XX) -- fchmodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0111) = ? $(S) $(XX) -- fchmodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0111) = 22 -$(S) $(XX) -- chown("input_data\x01\x02\x03\n\r\t", 0x2, 0x3) = ? -$(S) $(XX) -- chown("input_data\x01\x02\x03\n\r\t", 0x2, 0x3) = 22 +$(S) $(XX) -- fchownat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x0) = ? +$(S) $(XX) -- fchownat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x0) = 22 $(S) $(XX) -- fchown(4, 0x2, 0x3) = ? $(S) $(XX) -- fchown(4, 0x2, 0x3) = 22 $(S) $(XX) -- fchownat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x0) = ? @@ -400,8 +376,8 @@ $(S) $(XX) -- fchownat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x100 $(S) $(XX) -- fchownat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x100) = 22 $(S) $(XX) -- fchownat(99, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x1000) = ? $(S) $(XX) -- fchownat(99, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x1000) = 22 -$(S) $(XX) -- lchown("input_data\x01\x02\x03\n\r\t", 0x2, 0x3) = ? -$(S) $(XX) -- lchown("input_data\x01\x02\x03\n\r\t", 0x2, 0x3) = 22 +$(S) $(XX) -- fchownat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x100) = ? +$(S) $(XX) -- fchownat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x2, 0x3, 0x100) = 22 $(S) $(XX) -- umask(0222) = ? $(S) $(XX) -- umask(0222) = 026 $(S) $(XX) -- gettimeofday(0x123000, 0x234000) = ? @@ -442,10 +418,10 @@ $(S) $(XX) -- getegid() = ? $(S) $(XX) -- getegid() = 22 $(S) $(XX) -- setpgid() = ? $(S) $(XX) -- setpgid() = 22 -$(S) $(XX) -- syscall(110, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? -$(S) $(XX) -- syscall(110, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 -$(S) $(XX) -- getpgrp() = ? -$(S) $(XX) -- getpgrp() = 22 +$(S) $(XX) -- getppid() = ? +$(S) $(XX) -- getppid() = 22 +$(S) $(XX) -- getpgid(0x0) = ? +$(S) $(XX) -- getpgid(0x0) = 22 $(S) $(XX) -- setsid() = ? $(S) $(XX) -- setsid() = 22 $(S) $(XX) -- setreuid(0x3, 0x4) = ? @@ -502,8 +478,6 @@ $(S) $(XX) -- mknodat(1, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = ? $(S) $(XX) -- mknodat(1, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = 22 $(S) $(XX) -- mknodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = ? $(S) $(XX) -- mknodat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 01, 0x2) = 22 -$(OPT)$(S) $(XX) -- ustat(0x2, 0x123000) = ? -$(OPT)$(S) $(XX) -- ustat(0x2, 0x123000) = 22 $(S) $(XX) -- statfs("input_data\x01\x02\x03\n\r\t", 0x123000) = ? $(S) $(XX) -- statfs("input_data\x01\x02\x03\n\r\t", 0x123000) = 22 $(S) $(XX) -- fstatfs(4, 0x123000) = ? @@ -532,16 +506,10 @@ $(S) $(XX) -- sched_getaffinity(0x4d, 0x4, 0x123000) = ? $(S) $(XX) -- sched_getaffinity(0x4d, 0x4, 0x123000) = 22 $(S) $(XX) -- vhangup() = ? $(S) $(XX) -- vhangup() = 22 -$(OPT)$(S) $(XX) -- modify_ldt(0x1, 0x123000, 0x1) = ? -$(OPT)$(S) $(XX) -- modify_ldt(0x1, 0x123000, 0x1) = 22 $(S) $(XX) -- pivot_root("input_data\x01\x02\x03\n\r\t", $(XX)) = ? $(S) $(XX) -- pivot_root("input_data\x01\x02\x03\n\r\t", $(XX)) = 22 -$(OPT)$(S) $(XX) -- _sysctl(0x123000) = ? -$(OPT)$(S) $(XX) -- _sysctl(0x123000) = 22 $(S) $(XX) -- prctl(0x18, 0x1, 0x2, 0x3, 0x4) = ? $(S) $(XX) -- prctl(0x18, 0x1, 0x2, 0x3, 0x4) = 22 -$(OPT)$(S) $(XX) -- arch_prctl(0x1002, 0x123000, $(XX)) = ? -$(OPT)$(S) $(XX) -- arch_prctl(0x1002, 0x123000, $(XX)) = 22 $(S) $(XX) -- clock_adjtime(0x0, 0x123000) = ? $(S) $(XX) -- clock_adjtime(0x0, 0x123000) = 22 $(S) $(XX) -- chroot("input_data\x01\x02\x03\n\r\t") = ? @@ -566,12 +534,8 @@ $(S) $(XX) -- sethostname($(XX), 0x10) = ? $(S) $(XX) -- sethostname($(XX), 0x10) = 22 $(S) $(XX) -- setdomainname($(XX), 0x10) = ? $(S) $(XX) -- setdomainname($(XX), 0x10) = 22 -$(OPT)$(S) $(XX) -- iopl(0x1) = ? -$(OPT)$(S) $(XX) -- iopl(0x1) = 22 -$(OPT)$(S) $(XX) -- ioperm(0x3, 0x4, 0x1) = ? -$(OPT)$(S) $(XX) -- ioperm(0x3, 0x4, 0x1) = 22 -$(S) $(XX) -- syscall(175, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? -$(S) $(XX) -- syscall(175, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 +$(S) $(XX) -- init_module($(XX), 16, $(XX)) = ? +$(S) $(XX) -- init_module($(XX), 16, $(XX)) = 22 $(S) $(XX) -- finit_module(3, 0x123000, 0x0) = ? $(S) $(XX) -- finit_module(3, 0x123000, 0x0) = 22 $(S) $(XX) -- syscall(176, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? @@ -620,14 +584,8 @@ $(S) $(XX) -- tkill(0x2c, 0x13) = ? $(S) $(XX) -- tkill(0x2c, 0x13) = 22 $(S) $(XX) -- tgkill(0x2c, 0x37, 0x13) = ? $(S) $(XX) -- tgkill(0x2c, 0x37, 0x13) = 22 -$(OPT)$(S) $(XX) -- time(0x123000) = ? -$(OPT)$(S) $(XX) -- time(0x123000) = 22 $(S) $(XX) -- futex(0x123000, 0x1, 0x7, 0x123000, 0x234000, 0x1) = ? $(S) $(XX) -- futex(0x123000, 0x1, 0x7, 0x123000, 0x234000, 0x1) = 22 -$(OPT)$(S) $(XX) -- set_thread_area(0x123000) = ? -$(OPT)$(S) $(XX) -- set_thread_area(0x123000) = 22 -$(OPT)$(S) $(XX) -- get_thread_area(0x123000) = ? -$(OPT)$(S) $(XX) -- get_thread_area(0x123000) = 22 $(S) $(XX) -- io_setup(0x1, 0x123000) = ? $(S) $(XX) -- io_setup(0x1, 0x123000) = 22 $(S) $(XX) -- io_destroy(0x4d) = ? @@ -646,8 +604,6 @@ $(S) $(XX) -- epoll_create1(0x0) = ? $(S) $(XX) -- epoll_create1(0x0) = 22 $(S) $(XX) -- epoll_create1(0x80000) = ? $(S) $(XX) -- epoll_create1(0x80000) = 22 -$(OPT)$(S) $(XX) -- epoll_wait(2, 0x123000, 0x4, 0x5) = ? -$(OPT)$(S) $(XX) -- epoll_wait(2, 0x123000, 0x4, 0x5) = 22 $(S) $(XX) -- epoll_pwait(2, 0x123000, 0x4, 0x5, 0x234000, 0x6) = ? $(S) $(XX) -- epoll_pwait(2, 0x123000, 0x4, 0x5, 0x234000, 0x6) = 22 $(S) $(XX) -- epoll_ctl(2, 0x3, 4, 0x123000) = ? @@ -696,8 +652,8 @@ $(S) $(XX) -- mq_getsetattr(0x1, 0x123000, 0x234000) = ? $(S) $(XX) -- mq_getsetattr(0x1, 0x123000, 0x234000) = 22 $(S) $(XX) -- kexec_load(0x1, 0x2, 0x123000, 0x2) = ? $(S) $(XX) -- kexec_load(0x1, 0x2, 0x123000, 0x2) = 22 -$(OPT)$(S) $(XX) -- kexec_file_load(0x1, 0x2, 0x3, $(XX), 0x2) = ? -$(OPT)$(S) $(XX) -- kexec_file_load(0x1, 0x2, 0x3, $(XX), 0x2) = 22 +$(S) $(XX) -- kexec_file_load(0x1, 0x2, 0x3, $(XX), 0x2) = ? +$(S) $(XX) -- kexec_file_load(0x1, 0x2, 0x3, $(XX), 0x2) = 22 $(S) $(XX) -- waitid(0x1, 0x2, 0x123000, 0x4) = ? $(S) $(XX) -- waitid(0x1, 0x2, 0x123000, 0x4) = 22 $(S) $(XX) -- add_key(0x123000, 0x234000, 0x123000, 0x234000, 0x1) = ? @@ -744,8 +700,6 @@ $(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x0) = ? $(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x0) = 22 $(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x1) = ? $(S) $(XX) -- sync_file_range(2, 0x3, 0x4, 0x1) = 22 -$(OPT)$(S) $(XX) -- signalfd(1, 0x123000, 0xc) = ? -$(OPT)$(S) $(XX) -- signalfd(1, 0x123000, 0xc) = 22 $(S) $(XX) -- signalfd4(1, 0x123000, 0xd, 0x800, $(XX)) = ? $(S) $(XX) -- signalfd4(1, 0x123000, 0xd, 0x800, $(XX)) = 22 $(S) $(XX) -- timerfd_create(0x0, 0x80000) = ? @@ -754,8 +708,6 @@ $(S) $(XX) -- timerfd_settime(1, 0x1, 0x123000, 0x234000) = ? $(S) $(XX) -- timerfd_settime(1, 0x1, 0x123000, 0x234000) = 22 $(S) $(XX) -- timerfd_gettime(2, 0x123000) = ? $(S) $(XX) -- timerfd_gettime(2, 0x123000) = 22 -$(OPT)$(S) $(XX) -- eventfd(0x2d) = ? -$(OPT)$(S) $(XX) -- eventfd(0x2d) = 22 $(S) $(XX) -- eventfd2(0x2f, 0x1) = ? $(S) $(XX) -- eventfd2(0x2f, 0x1) = 22 $(S) $(XX) -- fallocate(1, 0x2, 0x3, 0x4) = ? From 51e070c1f0db760ed8cf26ae68674dbf9d7c52a7 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Fri, 18 Jul 2025 18:49:34 +0200 Subject: [PATCH 128/143] create_module format declaration is now optional --- src/syscall_formats.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/syscall_formats.c b/src/syscall_formats.c index d6654e9..6203651 100644 --- a/src/syscall_formats.c +++ b/src/syscall_formats.c @@ -286,7 +286,9 @@ static const struct syscall_format formats[] = { #ifdef SYS_ioperm SARGS(ioperm, rdec, arg_, arg_, arg_), #endif +#ifdef SYS_create_module SARGS(create_module, rpointer, arg_pointer, arg_dec), +#endif SARGS(init_module, rdec, arg_pointer, arg_dec, arg_pointer), SARGS(delete_module, rdec, arg_cstr, arg_), SARGS(quotactl, rdec, arg_dec, arg_pointer, arg_dec, arg_pointer), From cafd156bd4973779f9fdde18cb34269528601a3e Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sat, 19 Jul 2025 02:18:22 +0200 Subject: [PATCH 129/143] typo fix --- test/arch/riscv/syscall_format.log.match | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match index 62c9975..6b69d43 100644 --- a/test/arch/riscv/syscall_format.log.match +++ b/test/arch/riscv/syscall_format.log.match @@ -214,8 +214,8 @@ $(S) $(XX) -- dup3(4, 5, 0x0) = ? $(S) $(XX) -- dup3(4, 5, 0x0) = 22 $(S) $(XX) -- dup3(4, 5, 0x80000) = ? $(S) $(XX) -- dup3(4, 5, 0x80000) = 22 -$(S) $(XX) -- ppoll((null), 0, 0x0, 0x0, $(N) = ? -$(S) $(XX) -- ppoll((null), 0, 0x0, 0x0, $(N) = 22 +$(S) $(XX) -- ppoll((null), 0, 0x0, 0x0, $(N)) = ? +$(S) $(XX) -- ppoll((null), 0, 0x0, 0x0, $(N)) = 22 $(S) $(XX) -- clock_nanosleep(0x0, 0x0, 0x123000, 0x234000) = ? $(S) $(XX) -- clock_nanosleep(0x0, 0x0, 0x123000, 0x234000) = 22 $(S) $(XX) -- getitimer(0x3, 0x123000) = ? From 15a38d87caabb20bd94c93d8d1724be5abe0218f Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sat, 19 Jul 2025 02:39:50 +0200 Subject: [PATCH 130/143] fixed accpt4 expetations --- test/arch/riscv/syscall_format.log.match | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match index 6b69d43..3c08b0c 100644 --- a/test/arch/riscv/syscall_format.log.match +++ b/test/arch/riscv/syscall_format.log.match @@ -234,8 +234,8 @@ $(S) $(XX) -- connect(8, 0x123000, 0xc) = ? $(S) $(XX) -- connect(8, 0x123000, 0xc) = 22 $(S) $(XX) -- accept(4, 0x123000, 0x234000) = ? $(S) $(XX) -- accept(4, 0x123000, 0x234000) = 22 -$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x0, 0x234000) = ? -$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x0, 0x234000) = 22 +$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x0, 0x0) = ? +$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x0, 0x0) = 22 $(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x234000) = ? $(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x234000) = 22 $(S) $(XX) -- sendto(5, 0x123000, 0xc, 0x4) = ? From 8bcc45e5ca45503bf46699654c1fe4c2ed0cfd0c Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sat, 19 Jul 2025 02:43:16 +0200 Subject: [PATCH 131/143] fixed accept4 expectations --- test/arch/riscv/syscall_format.log.match | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match index 3c08b0c..9097370 100644 --- a/test/arch/riscv/syscall_format.log.match +++ b/test/arch/riscv/syscall_format.log.match @@ -236,8 +236,8 @@ $(S) $(XX) -- accept(4, 0x123000, 0x234000) = ? $(S) $(XX) -- accept(4, 0x123000, 0x234000) = 22 $(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x0, 0x0) = ? $(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x0, 0x0) = 22 -$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x234000) = ? -$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x234000) = 22 +$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x123000 = ? +$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x123000 = 22 $(S) $(XX) -- sendto(5, 0x123000, 0xc, 0x4) = ? $(S) $(XX) -- sendto(5, 0x123000, 0xc, 0x4) = 22 $(S) $(XX) -- recvfrom(5, 0x123000, 0xc, 0x4, 0x234000, 0x234000) = ? From 3a369aad9453c012179406668b59216d17138577 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sat, 19 Jul 2025 02:44:09 +0200 Subject: [PATCH 132/143] typo fix --- test/arch/riscv/syscall_format.log.match | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match index 9097370..9c4680e 100644 --- a/test/arch/riscv/syscall_format.log.match +++ b/test/arch/riscv/syscall_format.log.match @@ -236,8 +236,8 @@ $(S) $(XX) -- accept(4, 0x123000, 0x234000) = ? $(S) $(XX) -- accept(4, 0x123000, 0x234000) = 22 $(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x0, 0x0) = ? $(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x0, 0x0) = 22 -$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x123000 = ? -$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x123000 = 22 +$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x123000) = ? +$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x123000)= 22 $(S) $(XX) -- sendto(5, 0x123000, 0xc, 0x4) = ? $(S) $(XX) -- sendto(5, 0x123000, 0xc, 0x4) = 22 $(S) $(XX) -- recvfrom(5, 0x123000, 0xc, 0x4, 0x234000, 0x234000) = ? From 5ac4f5537e39e25fd2345564c75a35dc04c94a43 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sat, 19 Jul 2025 02:45:15 +0200 Subject: [PATCH 133/143] typo fix --- test/arch/riscv/syscall_format.log.match | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match index 9c4680e..1ad524a 100644 --- a/test/arch/riscv/syscall_format.log.match +++ b/test/arch/riscv/syscall_format.log.match @@ -237,7 +237,7 @@ $(S) $(XX) -- accept(4, 0x123000, 0x234000) = 22 $(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x0, 0x0) = ? $(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x0, 0x0) = 22 $(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x123000) = ? -$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x123000)= 22 +$(S) $(XX) -- accept4(4, 0x123000, 0x234000, 0x80800, 0x123000) = 22 $(S) $(XX) -- sendto(5, 0x123000, 0xc, 0x4) = ? $(S) $(XX) -- sendto(5, 0x123000, 0xc, 0x4) = 22 $(S) $(XX) -- recvfrom(5, 0x123000, 0xc, 0x4, 0x234000, 0x234000) = ? From c1f160c2a40b76bf664ff47e1fb312634509ff8a Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sun, 20 Jul 2025 16:28:06 +0200 Subject: [PATCH 134/143] Full test suite passed with glibc 2.39 on x64 --- src/syscall_formats.c | 2 +- test/arch/x86_64/syscall_format.log.match | 56 +++++++++++------------ test/libcintercept0.log.match | 8 ++-- test/libcintercept0_child.log.match | 8 ++-- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/syscall_formats.c b/src/syscall_formats.c index 6203651..9df4e6d 100644 --- a/src/syscall_formats.c +++ b/src/syscall_formats.c @@ -379,7 +379,7 @@ static const struct syscall_format formats[] = { #ifdef SYS_futimesat SARGS(futimesat, rdec, arg_atfd, arg_cstr, arg_), #endif - SARGS(newfstatat, rdec, arg_atfd, arg_cstr, arg_, arg_), + SARGS(newfstatat, rdec, arg_atfd, arg_cstr, arg_pointer, arg_), SARGS(unlinkat, rdec, arg_atfd, arg_cstr, arg_), #ifdef SYS_renameat SARGS(renameat, rdec, arg_atfd, arg_cstr, arg_atfd, arg_cstr), diff --git a/test/arch/x86_64/syscall_format.log.match b/test/arch/x86_64/syscall_format.log.match index 3ea07b6..716037b 100644 --- a/test/arch/x86_64/syscall_format.log.match +++ b/test/arch/x86_64/syscall_format.log.match @@ -66,34 +66,34 @@ $(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_ $(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_TMPFILE, 0333) = 22 $(S) $(XX) -- close(9) = ? $(S) $(XX) -- close(9) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), (null), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), (null), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", (null), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", (null), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 +$(S) $(XX) -- $(*)fstat$(*)(0, $(*)(null)$(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)(0, $(*)(null)$(*)) = 22 +$(OPT)$(S) $(XX) -- $(*)fstat$(*)(-1, $(*)(null)$(*)) = ? +$(OPT)$(S) $(XX) -- $(*)fstat$(*)(-1, $(*)(null)$(*)) = 22 +$(OPT)$(S) $(XX) -- $(*)fstat$(*)(AT_FDCWD, $(*)$(XX)$(*)) = ? +$(OPT)$(S) $(XX) -- $(*)fstat$(*)(AT_FDCWD, $(*)$(XX)$(*)) = 22 +$(S) $(XX) -- $(*)fstat$(*)(2, $(*)$(XX)$(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)(2, $(*)$(XX)$(*)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), (null), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), (null), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", (null), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", (null), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(0, "", $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(0, "", $(XX), $(XX)) = 22 -$(OPT)$(S) $(XX) -- newfstatat(-1, "", $(XX), $(XX)) = ? -$(OPT)$(S) $(XX) -- newfstatat(-1, "", $(XX), $(XX)) = 22 -$(OPT)$(S) $(XX) -- newfstatat(AT_FDCWD, "", $(XX), $(XX)) = ? -$(OPT)$(S) $(XX) -- newfstatat(AT_FDCWD, "", $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(2, "", $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(2, "", $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x0, 0x0) = ? -$(S) $(XX) -- newfstatat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x0, 0x0) = 22 -$(S) $(XX) -- newfstatat(AT_FDCWD, (null), 0x0, 0x0) = ? -$(S) $(XX) -- newfstatat(AT_FDCWD, (null), 0x0, 0x0) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", (null), 0x0) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", (null), 0x0) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), (null), 0x0) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), (null), 0x0) = 22 $(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = ? $(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX), 0x100) = ? @@ -442,8 +442,8 @@ $(S) $(XX) -- getegid() = ? $(S) $(XX) -- getegid() = 22 $(S) $(XX) -- setpgid() = ? $(S) $(XX) -- setpgid() = 22 -$(S) $(XX) -- syscall(110, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? -$(S) $(XX) -- syscall(110, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 +$(S) $(XX) -- getppid() = ? +$(S) $(XX) -- getppid() = 22 $(S) $(XX) -- getpgrp() = ? $(S) $(XX) -- getpgrp() = 22 $(S) $(XX) -- setsid() = ? @@ -570,14 +570,14 @@ $(S) $(XX) -- iopl(0x1) = ? $(S) $(XX) -- iopl(0x1) = 22 $(S) $(XX) -- ioperm(0x3, 0x4, 0x1) = ? $(S) $(XX) -- ioperm(0x3, 0x4, 0x1) = 22 -$(S) $(XX) -- syscall(175, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? -$(S) $(XX) -- syscall(175, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 +$(S) $(XX) -- init_module($(XX), 16, $(XX)) = ? +$(S) $(XX) -- init_module($(XX), 16, $(XX)) = 22 $(S) $(XX) -- finit_module(3, 0x123000, 0x0) = ? $(S) $(XX) -- finit_module(3, 0x123000, 0x0) = 22 -$(S) $(XX) -- syscall(176, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? -$(S) $(XX) -- syscall(176, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 -$(S) $(XX) -- syscall(179, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? -$(S) $(XX) -- syscall(179, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 +$(S) $(XX) -- delete_module($(S), $(XX)) = ? +$(S) $(XX) -- delete_module($(S), $(XX)) = 22 +$(S) $(XX) -- quotactl($(N), $(XX), $(N), $(XX)) = ? +$(S) $(XX) -- quotactl($(N), $(XX), $(N), $(XX)) = 22 $(S) $(XX) -- gettid() = ? $(S) $(XX) -- gettid() = 22 $(S) $(XX) -- readahead(4, 17185, 123) = ? diff --git a/test/libcintercept0.log.match b/test/libcintercept0.log.match index 9a91cea..d7721f4 100644 --- a/test/libcintercept0.log.match +++ b/test/libcintercept0.log.match @@ -11,16 +11,16 @@ $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = $(N) $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = $(N) -$(S) $(XX) -- newfstatat($(N), "", $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat($(N), "", $(XX), $(XX)) = 0 +$(S) $(XX) -- $(*)fstat$(*)($(N),$(*)$(XX)$(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)($(N),$(*)$(XX)$(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(S) $(XX) -- read($(N), $(XX), $(N)) = ? $(S) $(XX) -- read($(N), "/*\n * Copyright 2016-2017, Intel Corporation\n *\n * Redistribution and use in source and binary forms, with or without\n...", $(N)) = $(N) -$(S) $(XX) -- newfstatat(1, "", $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(1, "", $(XX), $(XX)) = 0 +$(S) $(XX) -- $(*)fstat$(*)(1,$(*)$(XX)$(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)(1,$(*)$(XX)$(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? diff --git a/test/libcintercept0_child.log.match b/test/libcintercept0_child.log.match index b8fba9f..401a0bf 100644 --- a/test/libcintercept0_child.log.match +++ b/test/libcintercept0_child.log.match @@ -2,16 +2,16 @@ $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- open($(S), O_RDONLY) = $(N) $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = ? $(OPT)$(S) $(XX) -- openat(AT_FDCWD, $(S), O_RDONLY) = $(N) -$(S) $(XX) -- newfstatat($(N), "", $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat($(N), "", $(XX), $(XX)) = 0 +$(S) $(XX) -- $(*)fstat$(*)($(N),$(*)$(XX)$(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)($(N),$(*)$(XX)$(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(S) $(XX) -- read($(N), $(XX), $(N)) = ? $(S) $(XX) -- read($(N), "/*\n * Copyright 2016-2017, Intel Corporation\n *\n * Redistribution and use in source and binary forms, with or without\n...", $(N)) = $(N) -$(S) $(XX) -- newfstatat(1, "", $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(1, "", $(XX), $(XX)) = 0 +$(S) $(XX) -- $(*)fstat$(*)(1,$(*)$(XX)$(*)) = ? +$(S) $(XX) -- $(*)fstat$(*)(1,$(*)$(XX)$(*)) = 0 $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = $(N) $(OPT)$(S) $(XX) -- mmap($(XX), $(N), $(N), $(N), $(N), $(XX)) = ? From df43ff0be5c4200bde9e2d98d797d6a9ddc0ea05 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sun, 20 Jul 2025 16:50:58 +0200 Subject: [PATCH 135/143] Updated riscv syscall_format_log match file --- test/arch/riscv/syscall_format.log.match | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match index 1ad524a..7759ab8 100644 --- a/test/arch/riscv/syscall_format.log.match +++ b/test/arch/riscv/syscall_format.log.match @@ -52,34 +52,34 @@ $(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_ $(S) $(XX) -- openat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", O_RDWR | O_TMPFILE, 0333) = 22 $(S) $(XX) -- close(9) = ? $(S) $(XX) -- close(9) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), (null), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), (null), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", (null), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", (null), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(0, "", $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(0, "", $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(0, "", (null)), $(XX)) = ? +$(S) $(XX) -- newfstatat(0, "", (null)), $(XX)) = 22 $(OPT)$(S) $(XX) -- newfstatat(-1, "", $(XX), $(XX)) = ? $(OPT)$(S) $(XX) -- newfstatat(-1, "", $(XX), $(XX)) = 22 $(OPT)$(S) $(XX) -- newfstatat(AT_FDCWD, "", $(XX), $(XX)) = ? $(OPT)$(S) $(XX) -- newfstatat(AT_FDCWD, "", $(XX), $(XX)) = 22 $(S) $(XX) -- newfstatat(2, "", $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(2, "", $(XX), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), (null), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), (null), $(XX)) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", (null), $(XX)) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "/", (null), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? -$(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x0, 0x0) = ? -$(S) $(XX) -- newfstatat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0x0, 0x0) = 22 -$(S) $(XX) -- newfstatat(AT_FDCWD, (null), 0x0, 0x0) = ? -$(S) $(XX) -- newfstatat(AT_FDCWD, (null), 0x0, 0x0) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", (null), 0x0) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", (null), 0x0) = 22 +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), (null), 0x0) = ? +$(S) $(XX) -- newfstatat(AT_FDCWD, (null), (null), 0x0) = 22 $(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = ? $(S) $(XX) -- newfstatat(-1000, "", $(XX), 0x0) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX), 0x100) = ? From ea36858d1f9832b5d134221ea6aa4b2ed55516b9 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sun, 20 Jul 2025 16:52:23 +0200 Subject: [PATCH 136/143] typo fix --- test/arch/riscv/syscall_format.log.match | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match index 7759ab8..b5b5815 100644 --- a/test/arch/riscv/syscall_format.log.match +++ b/test/arch/riscv/syscall_format.log.match @@ -60,8 +60,8 @@ $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, (null), $(XX), $(XX)) = 22 $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = ? $(S) $(XX) -- newfstatat(AT_FDCWD, "/", $(XX), $(XX)) = 22 -$(S) $(XX) -- newfstatat(0, "", (null)), $(XX)) = ? -$(S) $(XX) -- newfstatat(0, "", (null)), $(XX)) = 22 +$(S) $(XX) -- newfstatat(0, "", (null), $(XX)) = ? +$(S) $(XX) -- newfstatat(0, "", (null), $(XX)) = 22 $(OPT)$(S) $(XX) -- newfstatat(-1, "", $(XX), $(XX)) = ? $(OPT)$(S) $(XX) -- newfstatat(-1, "", $(XX), $(XX)) = 22 $(OPT)$(S) $(XX) -- newfstatat(AT_FDCWD, "", $(XX), $(XX)) = ? From 962291d620c5bd0ac83747d760a1d872f5fd8b6c Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sun, 20 Jul 2025 17:35:34 +0200 Subject: [PATCH 137/143] Fixed semctl args expectations --- test/arch/riscv/syscall_format.log.match | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match index b5b5815..b10de7f 100644 --- a/test/arch/riscv/syscall_format.log.match +++ b/test/arch/riscv/syscall_format.log.match @@ -278,8 +278,8 @@ $(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x0) = ? $(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x0) = 22 $(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x234000) = ? $(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x234000) = 22 -$(S) $(XX) -- semctl(0x1, 0x2, 0x3, $(XX), $(XX), 0x234000) = ? -$(S) $(XX) -- semctl(0x1, 0x2, 0x3, $(XX), $(XX), 0x234000) = 22 +$(S) $(XX) -- semctl(0x1, 0x2, 0x3, $(XX), $(XX), $(XX) = ? +$(S) $(XX) -- semctl(0x1, 0x2, 0x3, $(XX), $(XX), $(XX) = 22 $(S) $(XX) -- msgget(0x1, 0x200) = ? $(S) $(XX) -- msgget(0x1, 0x200) = 22 $(S) $(XX) -- msgsnd(0x1, 0x123000, 0x3, 0x3) = ? From d5d316b99b1de0883b32d3c8efa77af4000da20f Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sun, 20 Jul 2025 17:36:34 +0200 Subject: [PATCH 138/143] typo fix --- test/arch/riscv/syscall_format.log.match | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match index b10de7f..d598386 100644 --- a/test/arch/riscv/syscall_format.log.match +++ b/test/arch/riscv/syscall_format.log.match @@ -278,8 +278,8 @@ $(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x0) = ? $(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x0) = 22 $(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x234000) = ? $(S) $(XX) -- semtimedop(0x4, 0x123000, 0x1, 0x234000) = 22 -$(S) $(XX) -- semctl(0x1, 0x2, 0x3, $(XX), $(XX), $(XX) = ? -$(S) $(XX) -- semctl(0x1, 0x2, 0x3, $(XX), $(XX), $(XX) = 22 +$(S) $(XX) -- semctl(0x1, 0x2, 0x3, $(XX), $(XX), $(XX)) = ? +$(S) $(XX) -- semctl(0x1, 0x2, 0x3, $(XX), $(XX), $(XX)) = 22 $(S) $(XX) -- msgget(0x1, 0x200) = ? $(S) $(XX) -- msgget(0x1, 0x200) = 22 $(S) $(XX) -- msgsnd(0x1, 0x123000, 0x3, 0x3) = ? From 170fd6cd53cc0932de0f3beab0ad27c2e80c4ff3 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sun, 20 Jul 2025 18:00:16 +0200 Subject: [PATCH 139/143] fixed renameat2 log expectations --- test/arch/riscv/syscall_format.log.match | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match index d598386..20d1e3c 100644 --- a/test/arch/riscv/syscall_format.log.match +++ b/test/arch/riscv/syscall_format.log.match @@ -312,14 +312,14 @@ $(S) $(XX) -- chdir("input_data\x01\x02\x03\n\r\t") = ? $(S) $(XX) -- chdir("input_data\x01\x02\x03\n\r\t") = 22 $(S) $(XX) -- fchdir(6) = ? $(S) $(XX) -- fchdir(6) = 22 -$(S) $(XX) -- rename("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = ? -$(S) $(XX) -- rename("input_data\x01\x02\x03\n\r\t", "other_input_data\x01\x02\x03\n\r\t") = 22 -$(S) $(XX) -- renameat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t") = ? -$(S) $(XX) -- renameat(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t") = 22 -$(S) $(XX) -- renameat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t") = ? -$(S) $(XX) -- renameat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t") = 22 -$(S) $(XX) -- renameat(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = ? -$(S) $(XX) -- renameat(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t") = 22 +$(S) $(XX) -- renameat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? +$(S) $(XX) -- renameat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = 22 +$(S) $(XX) -- renameat2(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? +$(S) $(XX) -- renameat2(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x0) = 22 +$(S) $(XX) -- renameat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? +$(S) $(XX) -- renameat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t", 0x0) = 22 +$(S) $(XX) -- renameat2(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? +$(S) $(XX) -- renameat2(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = 22 $(S) $(XX) -- mkdirat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0644) = ? $(S) $(XX) -- mkdirat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0644) = 22 $(S) $(XX) -- mkdirat(33, "input_data\x01\x02\x03\n\r\t", 0644) = ? From 09c0637531650282d78898240a07427ae7b586d1 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sun, 20 Jul 2025 18:01:27 +0200 Subject: [PATCH 140/143] fixed renameat2 log expectations --- test/arch/riscv/syscall_format.log.match | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match index 20d1e3c..2cc673d 100644 --- a/test/arch/riscv/syscall_format.log.match +++ b/test/arch/riscv/syscall_format.log.match @@ -312,14 +312,14 @@ $(S) $(XX) -- chdir("input_data\x01\x02\x03\n\r\t") = ? $(S) $(XX) -- chdir("input_data\x01\x02\x03\n\r\t") = 22 $(S) $(XX) -- fchdir(6) = ? $(S) $(XX) -- fchdir(6) = 22 -$(S) $(XX) -- renameat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? -$(S) $(XX) -- renameat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = 22 -$(S) $(XX) -- renameat2(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? -$(S) $(XX) -- renameat2(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", 0x0) = 22 -$(S) $(XX) -- renameat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? -$(S) $(XX) -- renameat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t", 0x0) = 22 -$(S) $(XX) -- renameat2(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = ? -$(S) $(XX) -- renameat2(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", 0x0) = 22 +$(S) $(XX) -- renameat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX)) = ? +$(S) $(XX) -- renameat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX)) = 22 +$(S) $(XX) -- renameat2(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", $(XX)) = ? +$(S) $(XX) -- renameat2(1, "input_data\x01\x02\x03\n\r\t", 2, "other_input_data\x01\x02\x03\n\r\t", $(XX)) = 22 +$(S) $(XX) -- renameat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t", $(XX)) = ? +$(S) $(XX) -- renameat2(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 7, "other_input_data\x01\x02\x03\n\r\t", $(XX)) = 22 +$(S) $(XX) -- renameat2(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX)) = ? +$(S) $(XX) -- renameat2(9, "input_data\x01\x02\x03\n\r\t", AT_FDCWD, "other_input_data\x01\x02\x03\n\r\t", $(XX)) = 22 $(S) $(XX) -- mkdirat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0644) = ? $(S) $(XX) -- mkdirat(AT_FDCWD, "input_data\x01\x02\x03\n\r\t", 0644) = 22 $(S) $(XX) -- mkdirat(33, "input_data\x01\x02\x03\n\r\t", 0644) = ? From 132ae5d4e011c09af1d1a61e705af3abf9764a7f Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sun, 20 Jul 2025 18:04:40 +0200 Subject: [PATCH 141/143] added delete_module and quotactl to log match file --- test/arch/riscv/syscall_format.log.match | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match index 2cc673d..91573c6 100644 --- a/test/arch/riscv/syscall_format.log.match +++ b/test/arch/riscv/syscall_format.log.match @@ -538,10 +538,10 @@ $(S) $(XX) -- init_module($(XX), 16, $(XX)) = ? $(S) $(XX) -- init_module($(XX), 16, $(XX)) = 22 $(S) $(XX) -- finit_module(3, 0x123000, 0x0) = ? $(S) $(XX) -- finit_module(3, 0x123000, 0x0) = 22 -$(S) $(XX) -- syscall(176, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? -$(S) $(XX) -- syscall(176, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 -$(S) $(XX) -- syscall(179, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = ? -$(S) $(XX) -- syscall(179, $(XX), $(XX), $(XX), $(XX), $(XX), $(XX)) = 22 +$(S) $(XX) -- delete_module($(S), $(XX)) = ? +$(S) $(XX) -- delete_module($(S), $(XX)) = 22 +$(S) $(XX) -- quotactl($(N), $(XX), $(N), $(XX)) = ? +$(S) $(XX) -- quotactl($(N), $(XX), $(N), $(XX)) = 22 $(S) $(XX) -- gettid() = ? $(S) $(XX) -- gettid() = 22 $(S) $(XX) -- readahead(4, 17185, 123) = ? From cfece63de5930a1c1f68a86d280392646c598935 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sun, 20 Jul 2025 18:08:26 +0200 Subject: [PATCH 142/143] fixed epoll_create log expectation --- test/arch/riscv/syscall_format.log.match | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match index 91573c6..0e67131 100644 --- a/test/arch/riscv/syscall_format.log.match +++ b/test/arch/riscv/syscall_format.log.match @@ -598,8 +598,8 @@ $(S) $(XX) -- io_cancel(0x1, 0x123000, 0x234000) = ? $(S) $(XX) -- io_cancel(0x1, 0x123000, 0x234000) = 22 $(S) $(XX) -- lookup_dcookie(0x7b, 0x123000, 0xc) = ? $(S) $(XX) -- lookup_dcookie(0x7b, 0x123000, 0xc) = 22 -$(S) $(XX) -- epoll_create(0x7) = ? -$(S) $(XX) -- epoll_create(0x7) = 22 +$(S) $(XX) -- epoll_create1(0x0) = ? +$(S) $(XX) -- epoll_create1(0x0) = 22 $(S) $(XX) -- epoll_create1(0x0) = ? $(S) $(XX) -- epoll_create1(0x0) = 22 $(S) $(XX) -- epoll_create1(0x80000) = ? From 9271486fa5cf21610d93930d87b09dccab02ce02 Mon Sep 17 00:00:00 2001 From: Ottavio Monticelli Date: Sun, 20 Jul 2025 18:10:04 +0200 Subject: [PATCH 143/143] fixed inotify_init log expectation --- test/arch/riscv/syscall_format.log.match | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/arch/riscv/syscall_format.log.match b/test/arch/riscv/syscall_format.log.match index 0e67131..2c90270 100644 --- a/test/arch/riscv/syscall_format.log.match +++ b/test/arch/riscv/syscall_format.log.match @@ -666,8 +666,8 @@ $(S) $(XX) -- ioprio_set(0x1, 0x3, 0x7b) = ? $(S) $(XX) -- ioprio_set(0x1, 0x3, 0x7b) = 22 $(S) $(XX) -- ioprio_get(0x1, 0x3) = ? $(S) $(XX) -- ioprio_get(0x1, 0x3) = 22 -$(S) $(XX) -- inotify_init() = ? -$(S) $(XX) -- inotify_init() = 22 +$(S) $(XX) -- inotify_init1(0x0) = ? +$(S) $(XX) -- inotify_init1(0x0) = 22 $(S) $(XX) -- inotify_init1(0x800) = ? $(S) $(XX) -- inotify_init1(0x800) = 22 $(S) $(XX) -- inotify_init1(0x80000) = ?