diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2024-02-04 20:18:49 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2024-02-04 20:18:49 +0000 |
commit | 76c1f761c8f4607e603ae6463e56703970a35aa8 (patch) | |
tree | c32c9f848cfa4d7f4d74914f74c81fc5294c0080 | |
parent | 58638fccb5c83957b241b8eaf703e40c28963bf8 (diff) |
Tweak codepatch_control_flow():
* it should be in .cptext so it gets unmapped when codepatching is done
* when doing a JMP, fill the area after it with INT3s instead of NOPs
ok deraadt@
-rw-r--r-- | sys/arch/amd64/amd64/codepatch.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/sys/arch/amd64/amd64/codepatch.c b/sys/arch/amd64/amd64/codepatch.c index 1ed1dd993e2..4bc3852ba59 100644 --- a/sys/arch/amd64/amd64/codepatch.c +++ b/sys/arch/amd64/amd64/codepatch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: codepatch.c,v 1.10 2023/07/31 01:33:57 guenther Exp $ */ +/* $OpenBSD: codepatch.c,v 1.11 2024/02/04 20:18:48 guenther Exp $ */ /* * Copyright (c) 2014-2015 Stefan Fritsch <sf@sfritsch.de> * @@ -39,8 +39,9 @@ extern struct codepatch codepatch_end; extern char __cptext_start[]; extern char __cptext_end[]; -void codepatch_control_flow(uint16_t _tag, void *_func, int _opcode, - const char *_op); +enum op_type { OP_CALL, OP_JMP }; +__cptext void codepatch_control_flow(uint16_t _tag, void *_func, + enum op_type _type); void codepatch_fill_nop(void *caddr, uint16_t len) @@ -155,26 +156,27 @@ codepatch_replace(uint16_t tag, const void *code, size_t len) void codepatch_call(uint16_t tag, void *func) { - /* 0xe8 == call near */ - codepatch_control_flow(tag, func, 0xe8, "call"); + codepatch_control_flow(tag, func, OP_CALL); } void codepatch_jmp(uint16_t tag, void *func) { - /* 0xe9 == jmp near */ - codepatch_control_flow(tag, func, 0xe9, "jmp"); + codepatch_control_flow(tag, func, OP_JMP); } /* Patch with call or jump to func */ void -codepatch_control_flow(uint16_t tag, void *func, int opcode, const char *op) +codepatch_control_flow(uint16_t tag, void *func, enum op_type type) { struct codepatch *patch; unsigned char *rwaddr; int32_t offset; int i = 0; vaddr_t rwmap = 0; + const char *op = type == OP_JMP ? "jmp" : "call"; + char opcode = type == OP_JMP ? 0xe9 /* jmp near */ + : 0xe8 /* call near */; DBGPRINT("patching tag %u with %s %p", tag, op, func); @@ -189,7 +191,10 @@ codepatch_control_flow(uint16_t tag, void *func, int opcode, const char *op) rwaddr = codepatch_maprw(&rwmap, patch->addr); rwaddr[0] = opcode; memcpy(rwaddr + 1, &offset, sizeof(offset)); - codepatch_fill_nop(rwaddr + 5, patch->len - 5); + if (type == OP_CALL) + codepatch_fill_nop(rwaddr + 5, patch->len - 5); + else /* OP_JMP */ + memset(rwaddr + 5, 0xCC /* int3 */, patch->len - 5); i++; } codepatch_unmaprw(rwmap); |