DF-1585 / harness.c
/* DF-1585: intel_fbc compressed_llb UAF harness. * __intel_fbc_cleanup_cfb frees compressed_llb but does NOT NULL it. * Second call re-enters the if() with dangling pointer -> * i915_gem_stolen_remove_node(dev_priv, fbc->compressed_llb) UAF. */ #include <stdio.h> #include <stdlib.h> #include <string.h> static int fixed = 0; struct llb { int x; }; /* mock */ struct dev_priv { struct llb *compressed_llb; int freed_already; }; static void stolen_remove(struct llb *p) { if (!p) return; if (p->x == 0xdead) printf("UAF: reused freed memory at %p\n", (void*)p); } static void cleanup_cfb(struct dev_priv *dp) { if (dp->compressed_llb) { stolen_remove(dp->compressed_llb); free(dp->compressed_llb); if (fixed) dp->compressed_llb = NULL; } } int main(int argc, char **argv) { if (argc > 1 && !strcmp(argv[1], "--fixed")) fixed = 1; struct dev_priv dp = {0}; dp.compressed_llb = malloc(sizeof(struct llb)); dp.compressed_llb->x = 42; /* first cleanup (suspend/CRTC teardown) */ cleanup_cfb(&dp); if (!fixed) { /* simulate the dangling-pointer case: alloc something else that * reoccupies the freed slab slot, marked with canary */ struct llb *interloper = malloc(sizeof(struct llb)); interloper->x = 0xdead; /* second cleanup (driver unload): re-enters if(), UAF */ cleanup_cfb(&dp); free(interloper); printf("RESULT: BUGGY - 2nd cleanup re-entered with dangling ptr\n"); } else { cleanup_cfb(&dp); printf("RESULT: PATCHED - 2nd cleanup no-op (compressed_llb=NULL)\n"); } return 0; } |