Robert Zieba | 3f01cd1 | 2022-04-14 10:36:15 -0600 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | #include <arch/breakpoint.h> |
| 3 | #include <arch/null_breakpoint.h> |
Arthur Heymans | 6fc1254 | 2022-05-14 10:40:24 +0200 | [diff] [blame] | 4 | #include <bootstate.h> |
Robert Zieba | 3f01cd1 | 2022-04-14 10:36:15 -0600 | [diff] [blame] | 5 | #include <console/console.h> |
| 6 | #include <stdint.h> |
| 7 | |
| 8 | static struct breakpoint_handle null_deref_bp; |
| 9 | static struct breakpoint_handle null_fetch_bp; |
| 10 | |
| 11 | static int handle_fetch_breakpoint(struct breakpoint_handle handle, struct eregs *regs) |
| 12 | { |
| 13 | printk(BIOS_ERR, "Instruction fetch from address zero\n"); |
| 14 | return CONFIG(DEBUG_NULL_DEREF_HALT); |
| 15 | } |
| 16 | |
| 17 | static int handle_deref_breakpoint(struct breakpoint_handle handle, struct eregs *regs) |
| 18 | { |
| 19 | #if ENV_X86_64 |
Paul Menzel | 7151e0e | 2022-05-30 12:08:31 +0200 | [diff] [blame] | 20 | printk(BIOS_ERR, "Null dereference at rip: 0x%llx\n", regs->rip); |
Robert Zieba | 3f01cd1 | 2022-04-14 10:36:15 -0600 | [diff] [blame] | 21 | #else |
Paul Menzel | 7151e0e | 2022-05-30 12:08:31 +0200 | [diff] [blame] | 22 | printk(BIOS_ERR, "Null dereference at eip: 0x%x\n", regs->eip); |
Robert Zieba | 3f01cd1 | 2022-04-14 10:36:15 -0600 | [diff] [blame] | 23 | #endif |
| 24 | return CONFIG(DEBUG_NULL_DEREF_HALT); |
| 25 | } |
| 26 | |
| 27 | static void create_deref_breakpoint(void) |
| 28 | { |
| 29 | enum breakpoint_result res = |
| 30 | breakpoint_create_data(&null_deref_bp, NULL, sizeof(uintptr_t), false); |
| 31 | |
| 32 | if (res != BREAKPOINT_RES_OK) { |
| 33 | printk(BIOS_ERR, "Failed to create NULL dereference breakpoint\n"); |
| 34 | return; |
| 35 | } |
| 36 | |
| 37 | breakpoint_set_handler(null_deref_bp, &handle_deref_breakpoint); |
| 38 | breakpoint_enable(null_deref_bp, true); |
| 39 | } |
| 40 | |
| 41 | static void create_instruction_breakpoint(void) |
| 42 | { |
| 43 | enum breakpoint_result res = breakpoint_create_instruction(&null_fetch_bp, NULL); |
| 44 | |
| 45 | if (res != BREAKPOINT_RES_OK) { |
| 46 | printk(BIOS_ERR, "Failed to create address zero instruction fetch breakpoint\n"); |
| 47 | return; |
| 48 | } |
| 49 | |
| 50 | breakpoint_set_handler(null_fetch_bp, &handle_fetch_breakpoint); |
| 51 | breakpoint_enable(null_fetch_bp, true); |
| 52 | } |
| 53 | |
| 54 | void null_breakpoint_init(void) |
| 55 | { |
| 56 | create_deref_breakpoint(); |
| 57 | create_instruction_breakpoint(); |
| 58 | } |
Arthur Heymans | 6fc1254 | 2022-05-14 10:40:24 +0200 | [diff] [blame] | 59 | |
Arthur Heymans | fdf6d12 | 2022-05-17 13:07:30 +0200 | [diff] [blame^] | 60 | void null_breakpoint_disable(void) |
Arthur Heymans | 6fc1254 | 2022-05-14 10:40:24 +0200 | [diff] [blame] | 61 | { |
| 62 | breakpoint_remove(null_fetch_bp); |
| 63 | breakpoint_remove(null_deref_bp); |
| 64 | } |
| 65 | |
Arthur Heymans | fdf6d12 | 2022-05-17 13:07:30 +0200 | [diff] [blame^] | 66 | static void null_breakpoint_disable_hook(void *unused) |
| 67 | { |
| 68 | null_breakpoint_disable(); |
| 69 | } |
| 70 | |
| 71 | BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, null_breakpoint_disable_hook, NULL); |
| 72 | BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, null_breakpoint_disable_hook, NULL); |