DF-4605 / generated_guard_test.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | /* * DF-4605 control-flow harness. The two #include fragments below are * sed-extracted verbatim from the guest's live kernel source: * guard.inc = amdgpu_acpi.c lines 374-385 (the gutted guard) * deref.inc = amdgpu_acpi.c line 387 (the first deref) * Struct definitions replicate sys/dev/drm/amd/amdgpu/amdgpu_acpi.c:38-75 * byte-for-byte in size/offset (ACPI_HANDLE = pointer, bool = 1 byte), * so `functions.sbios_requests` sits at offset 18 (0x12), exactly as in * the kernel build. */ #include <stdio.h> #include <signal.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <unistd.h> typedef unsigned int UINT32; struct amdgpu_atif_notification_cfg { char enabled; int command_code; }; struct amdgpu_atif_notifications { char display_switch, expansion_mode_change, thermal_state, forced_power_state, system_power_state, display_conf_change, px_gfx_switch, brightness_change, dgpu_display_event; /* 9 x 1B */ }; struct amdgpu_atif_functions { char system_params, sbios_requests, select_active_disp, lid_state, get_tv_standard, set_tv_standard, get_panel_expansion_mode, set_panel_expansion_mode, temperature_change, graphics_device_types; /* 10 x 1B */ }; struct amdgpu_atif { void *handle; /* ACPI_HANDLE @0 */ struct amdgpu_atif_notifications notifications; /* @8..16 */ struct amdgpu_atif_functions functions; /* @17..26 */ struct amdgpu_atif_notification_cfg notification_cfg; }; static int fixed_mode = 0; /* * Opaque barrier: prevents the optimizer from proving atif==NULL and * deleting the deref as dead code (UB elision). In the kernel, atif comes * from adev->atif at notify-dispatch time and is never foldable. */ static struct amdgpu_atif * volatile atif_arg = NULL; __attribute__((noinline)) static void handler_under_test(struct amdgpu_atif *atif, UINT32 type) { if (fixed_mode) { #include "guard_fixed.inc" } else { #include "guard.inc" } #include "deref.inc" /* kernel body (amdgpu_acpi.c:388-431) calls amdgpu_atif_get_sbios_requests() * โ a real side effect. The sink replicates that so the compiler cannot * drop the (dead-looking) empty-guard + load. */ printf("KERNEL-EQUIV: sbios_requests path entered " "(kernel evaluates ATIF GET_SYSTEM_BIOS_REQUESTS here)\n"); } } static void segv(int sig, siginfo_t *si, void *uc) { (void)sig; (void)uc; printf("RESULT: SIGSEGV at address %p " "(=&atif->functions.sbios_requests with atif==NULL, expected 0x12)\n", si->si_addr); if (fixed_mode) printf("FIXED-MODE FAULT: unexpected โ fix did NOT work\n"); else printf("VERDICT: guard body compiled to NOTHING; control fell " "through the if() into the NULL deref\n"); exit(fixed_mode ? 1 : 42); } int main(int argc, char **argv) { struct sigaction sa; fixed_mode = (argc > 1); memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = segv; sa.sa_flags = SA_SIGINFO; sigaction(SIGSEGV, &sa, NULL); printf("sizeof(struct amdgpu_atif)=%zu " "offsetof(functions.sbios_requests)=%zu\n", sizeof(struct amdgpu_atif), (size_t)&((struct amdgpu_atif *)0)->functions.sbios_requests); /* exactly the kernel state on ATIF-less systems: adev->atif == NULL. * The NULL is produced at RUNTIME (getenv) so the optimizer cannot * constant-fold it and delete the deref as UB-dead-code (which gcc 8 * demonstrably does otherwise โ see VERDICT.md; in the kernel atif is * adev->atif, an opaque heap field, equally unfoldable). */ { const char *e = getenv("DF4605_ATIF"); struct amdgpu_atif *atif = (struct amdgpu_atif *)(uintptr_t)(e ? strtol(e, NULL, 0) : 0); handler_under_test(atif, 0x81); } printf("RESULT: no fault โ guard returned early (finding REFUTED in this mode)\n"); return 0; } |