DF-3685 / null_subtable_deref.c
/* * DF-3685 harness: parse-legal NULL subtables reach unconditional derefs at * smu7 backend init. This is a control-flow reproduction (no fault is * executed) of the chain: * * 1. process_pptables_v1_0.c init_clock_voltage_dependency (:794-845) only * fills vdd_dep_on_sclk/mclk, mm_dep_table, pcie_table when the * corresponding VBIOS offset != 0; result stays 0 otherwise -> * pp_tables_v1_0_initialize SUCCEEDS with NULL subtables. * 2. init_dpm_2_parameters (:281-297) only fills vddc/vddgfx_lookup_table * when usVddcLookupTableOffset / usVddgfxLookupTableOffset != 0. * 3. get_cac_tdp_table only runs when usPowerTuneTableOffset != 0 -> * table_info->cac_dtp_table NULL. * 4. smu7_hwmgr_backend_init (:2560-2566) calls smu7_complete_dependency_tables() * and smu7_set_private_data_based_on_pptable_v1() and IGNORES both return * values; smu7_complete_dependency_tables unconditionally dereferences * table_info->mm_dep_table->count (:1878), vddc_lookup_table->entries[] * (:1862/1868/1875/1881) via smu7_patch_lookup_table_with_leakage * (:1823). * * The harness emulates the parser side (offset==0 => NULL, rc=0) and then * walks the same dereference chain, flagging each NULL deref point. */ #include <stdio.h> #include <stddef.h> struct dep_table { int dummy; }; struct mm_table { int dummy; }; struct lookup_table { int dummy; }; struct phm_ppt_v1_information { struct dep_table *vdd_dep_on_sclk; struct dep_table *vdd_dep_on_mclk; struct mm_table *mm_dep_table; struct lookup_table *vddc_lookup_table; struct lookup_table *vddgfx_lookup_table; struct { int x; } *cac_dtp_table; }; /* parser: offset==0 -> subtable stays NULL, result stays 0 (verbatim logic) */ static int init_clock_voltage_dependency(struct phm_ppt_v1_information *ti, unsigned short mm_off, unsigned short sclk_off, unsigned short mclk_off, unsigned short pt_off) { ti->vdd_dep_on_sclk = NULL; ti->vdd_dep_on_mclk = NULL; ti->mm_dep_table = NULL; if (mm_off != 0) ti->mm_dep_table = (struct mm_table *)1; /* would parse */ if (sclk_off != 0) ti->vdd_dep_on_sclk = (struct dep_table *)1; if (mclk_off != 0) ti->vdd_dep_on_mclk = (struct dep_table *)1; if (pt_off != 0) ti->cac_dtp_table = (void *)1; return 0; /* success regardless */ } static int deref_at(int *p, const char *site) { if (!p) { printf(" NULL DEREF at %s\n", site); return 1; } return 0; } int main(void) { struct phm_ppt_v1_information ti = {0}; int faults = 0; /* crafted VBIOS: MM/PowerTune/lookup offsets zeroed, SCLK dep present */ int rc = init_clock_voltage_dependency(&ti, /*mm*/0, /*sclk*/0x100, /*mclk*/0x200, /*powertune*/0); printf("pp_tables_v1_0_initialize returned %d (parse SUCCEEDS)\n", rc); printf("smu7_complete_dependency_tables (smu7_hwmgr.c:2047):\n"); /* :1878 */ faults += deref_at((int *)ti.mm_dep_table, "smu7_hwmgr.c:1878 mm_table->count"); /* :1823 via :2036-37 */ faults += deref_at((int *)ti.vddc_lookup_table, "smu7_hwmgr.c:1823 vddc_lookup_table->count (via :2036)"); /* :2027-28 */ faults += deref_at((int *)ti.vddgfx_lookup_table, "smu7_hwmgr.c:1823 vddgfx_lookup_table->count (via :2027)"); printf("smu7_thermal_parameter_init (smu7_hwmgr.c:2590 -> :2183):\n"); faults += deref_at((int *)ti.cac_dtp_table, "smu7_hwmgr.c:2183 cac_dtp_table->usDefaultTargetOperatingTemp"); printf("smu7_get_thermal_temperature_range (sysfs temp read -> :4764):\n"); faults += deref_at((int *)ti.cac_dtp_table, "smu7_hwmgr.c:4764 cac_dtp_table->usSoftwareShutdownTemp"); if (faults) { printf("RESULT: %d NULL-deref sites reachable at load/runtime with a " "parse-legal crafted VBIOS (kernel panics; return codes at " ":2560-2566 are ignored)\n", faults); return 0; } fprintf(stderr, "RESULT: no reachable NULL deref\n"); return 1; } |