Commit dd3204d
committed
gfx/drivers_context/{wayland,w,x}_vk_ctx: fix UAF + double-free + CI
Found during the audit of the Vulkan context shims after f5c7df5.
Adds an AddressSanitizer regression test under samples/gfx/
vulkan_ctx_double_free/ wired into the Linux-samples-gfx CI
workflow as a sixth step.
Three of the five Vulkan context drivers' set_video_mode hooks
called their own destroy() (or destroy_resources() + free()) on
ctx_data before returning false:
wayland_vk_ctx.c:218 gfx_ctx_wl_destroy(data)
w_vk_ctx.c:229 gfx_ctx_w_vk_destroy(data)
x_vk_ctx.c:489-499 destroy_resources + free
The caller in gfx/drivers/vulkan.c::vulkan_init treats a false
return from set_video_mode (line 4938) as a failed in-flight
vk_t construction and `goto error`s into vulkan_free() (line
5120), which at line 4665 calls
vk->ctx_driver->destroy(vk->ctx_data);
-- on the very pointer the inner set_video_mode just freed.
The ctx_driver->destroy hook then walks the freed struct
(gfx_ctx_wl_destroy_resources / gfx_ctx_x_vk_destroy_resources
dereference fields off the freed pointer) and free()s the same
pointer a second time.
On glibc with default malloc the second free is detected
(`double free or corruption`) and the process aborts. Under
jemalloc / mimalloc / older glibc the second free silently
corrupts the heap, with a write-what-where primitive controlled
by the allocator's freelist layout.
Reachability: vulkan_surface_create() failure (missing extension
or driver-level Vulkan error), Wayland's set_video_mode_common_*
helpers failing, X11's XGetVisualInfo returning NULL or
x11_input_ctx_new failing, win32_set_video_mode failing. None
are common but all are reachable on misconfigured systems,
headless tests, or CI environments without a working display.
* gfx/drivers_context/wayland_vk_ctx.c
* gfx/drivers_context/w_vk_ctx.c
* gfx/drivers_context/x_vk_ctx.c
Drop the destroy/free call from each set_video_mode error
path. Cocoa (cocoa_vk_ctx.m) and Android (android_vk_ctx.c)
already implement this correctly: just `return false` and
let the caller's vulkan_free chain do the single cleanup.
This makes the other three match.
X11's local XFree(vi) and `g_x11_screen = 0` reset are
preserved -- those are local-resource and global-state
cleanups respectively, not duplicates of the upper-layer
destroy. Wayland and Win32 had no such locals to preserve.
Each error-path edit carries an inline comment naming the
upper-layer cleanup site (gfx/drivers/vulkan.c::vulkan_free
line 4665) so a future maintainer who wonders why the inner
destroy is absent doesn't reintroduce it.
* samples/gfx/vulkan_ctx_double_free/,
.github/workflows/Linux-samples-gfx.yml
Regression test following the convention of the v3 vulkan/
tests, the v4 slang test, the v5 mailbox-leak test, and the
security regression tests under samples/tasks/. Models the
lifecycle contract abstractly rather than building any one
driver -- the bug is the shape of the cleanup flow, not a
driver-specific quirk.
Five probes: post-fix success path (1 alloc / 1 destroy);
post-fix failure path (the smoking gun: 1 alloc / 1 destroy,
no double-free, no UAF); 16 back-to-back failures (no
accumulation, no leaks); interleaved success/failure; and a
documentation probe describing how a maintainer can swap the
function pointer to re-trigger the pre-fix UAF.
Verified pre/post-patch discrimination: under the pre-fix
shape ASan reports `double-free` at the upper-layer destroy
with the freed allocation traced back to set_video_mode's
inner destroy. Under the post-fix shape all five probes
pass clean.
Wires into Linux-samples-gfx.yml as a sixth step, modeled on
the existing five with the same per-step explanation of what
the test is regression-testing and the "verbatim copy must
follow" reminder.1 parent dcf3ae3 commit dd3204d
6 files changed
Lines changed: 455 additions & 6 deletions
File tree
- .github/workflows
- gfx/drivers_context
- samples/gfx/vulkan_ctx_double_free
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
172 | 172 | | |
173 | 173 | | |
174 | 174 | | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
226 | 226 | | |
227 | 227 | | |
228 | 228 | | |
229 | | - | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
230 | 237 | | |
231 | 238 | | |
232 | 239 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
216 | 216 | | |
217 | 217 | | |
218 | 218 | | |
219 | | - | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
220 | 229 | | |
221 | 230 | | |
222 | 231 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
490 | 490 | | |
491 | 491 | | |
492 | 492 | | |
493 | | - | |
494 | | - | |
495 | | - | |
496 | | - | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
497 | 503 | | |
498 | 504 | | |
499 | 505 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
0 commit comments