Commit 23da752
committed
gfx/drivers: fix OOM NULL-derefs and munmap(MAP_FAILED) in legacy platform drivers
Three related bugs in older embedded gfx backends:
=== gfx/drivers/dispmanx_gfx.c: dispmanx_surface_setup ===
*sp = calloc(1, sizeof(struct dispmanx_surface));
surface = *sp;
surface->numpages = numpages; /* NULL-deref on OOM */
...
surface->pages = calloc(surface->numpages, sizeof(struct dispmanx_page));
for (i = 0; i < surface->numpages; i++)
{
surface->pages[i].used = false; /* NULL-deref on OOM */
...
}
Two unchecked callocs back-to-back, each followed by unconditional
field writes / array indexing. Function is void-returning, so
callers can't see an error code - they just hand us an output
pointer via 'sp' and trust it gets filled in. None of the three
current callers (lines 367, 464, 518 - main/menu/back surface
setup) check *sp after the call.
=== gfx/drivers/drm_gfx.c: drm_surface_setup ===
Identical sibling drift to the dispmanx bug above. The two
routines share the same shape (output-ptr via sp, void return,
outer surface calloc then inner pages calloc) and both were
missing the same NULL checks.
Fix (both files): NULL-check each calloc. On outer failure just
return; on inner failure free the outer allocation and set
*sp = NULL so callers get a consistent 'setup didn't produce a
surface' signal. Note: this doesn't fully plug the OOM path -
downstream helpers (dispmanx_surface_update_async,
drm_surface_update, dispmanx_surface_free, drm_surface_free)
do NOT NULL-check 'surface' either, so a caller that ignores
*sp and then calls into those helpers would still crash.
Fixing every call-site pattern is a bigger churn across the
driver than this patch is trying to do; the surface_setup fix
here at least stops setup itself from being the crash site
and gives callers consistent post-condition semantics (*sp is
NULL iff setup failed).
=== gfx/drivers/omap_gfx.c: omapfb_backup_state - munmap(MAP_FAILED) ===
pdata->saved_state->mem = malloc(pdata->saved_state->mi.size);
mem = mmap(NULL, pdata->saved_state->mi.size, ...);
if (!pdata->saved_state->mem || mem == MAP_FAILED)
{
RARCH_ERR("[Omap] Backup layer (mem backup) failed.\n");
munmap(mem, pdata->saved_state->mi.size); /* UB on MAP_FAILED */
return -1;
}
If mmap fails, 'mem' equals MAP_FAILED ((void*)-1). Calling
munmap() on that is explicitly undefined behaviour per POSIX -
glibc happens to return -1 with EINVAL today but there is no
guarantee, and a future libc / sanitiser is entirely within its
rights to trap.
Fix: guard the munmap with 'if (mem != MAP_FAILED)'. The
malloc-failure path (saved_state->mem == NULL) is separately
fine: the memory never got allocated so there's nothing to
munmap, and saved_state itself is freed later by omapfb_free()
when the caller's fail_omapfb label runs.
=== Thread-safety ===
None of the three functions cross threads. dispmanx and drm
surface setup run during video-driver init; omap backup_state
also runs at init. No lock discipline changes.
=== Reachability ===
All three files are embedded-platform gfx backends with narrow
audience:
- dispmanx_gfx: Raspberry Pi legacy VideoCore IV
- drm_gfx: bare-metal DRM/KMS (PiKISS, some retro handhelds)
- omap_gfx: TI OMAP (N900, Pandora, older Beagleboard)
OOM on these platforms is realistic - they typically have
128-512MB of total RAM and run on top of memory-tight minimal
images. The dispmanx/drm OOM paths are hit on initial video
init and also on every core-triggered surface re-setup for
resolution changes.1 parent b2e3dfd commit 23da752
3 files changed
Lines changed: 53 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
239 | 239 | | |
240 | 240 | | |
241 | 241 | | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
242 | 254 | | |
243 | 255 | | |
244 | 256 | | |
| |||
255 | 267 | | |
256 | 268 | | |
257 | 269 | | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
258 | 282 | | |
259 | 283 | | |
260 | 284 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
232 | 232 | | |
233 | 233 | | |
234 | 234 | | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
235 | 245 | | |
236 | 246 | | |
237 | 247 | | |
| |||
252 | 262 | | |
253 | 263 | | |
254 | 264 | | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
255 | 275 | | |
256 | 276 | | |
257 | 277 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
370 | 370 | | |
371 | 371 | | |
372 | 372 | | |
373 | | - | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
374 | 382 | | |
375 | 383 | | |
376 | 384 | | |
| |||
0 commit comments