GHSA-m779-jvp3-pmqr: GUIX binary resource loader reads past the end of a resource, because no length for it ever reaches the loader
GHSA ID |
|
|---|---|
CVE ID |
CVE‑2026‑92446 |
Severity |
High |
CVSS score |
7.1 ( |
CWE |
|
Published |
2026‑10‑02 |
Last updated |
2026‑10‑02 |
Description
Summary
gx_binres_theme_load() and gx_binres_font_load() take the resource as a bare GX_UBYTE * with no length, and GX_BINRES_DATA_INFO has no field to carry one. Every read is therefore performed at an offset the file itself chose, against a buffer whose extent the loader does not know. A resource that declares more data than it contains is read past its end, and an offset stored in the file is turned into a pointer without being bounded.
This is a distinct defect from GHSA-hgcj-22cg-4hfv, which was an underflowed glyph count. It needs no underflow and no wrapped multiply: a perfectly well-formed, narrow glyph range reaches it.
Details
1. Declared record counts are not bounded by the resource. A font page header declares a glyph range, and the loader reads one glyph record per glyph in that range straight out of the resource. Nothing compares the resulting read offset with the end of the file, because the end of the file is not known. A page declaring 101 glyphs in a 193-byte resource holding one record reads off the end at _gx_binres_glyph_header_load():
The reporter reproduced this with a 193 byte theme whose single font page declares glyphs 0x00 to 0x64 while the file carries one glyph record: the walk reads one byte past the end of the resource in _gx_binres_glyph_header_load.
The per-record magic number check on each record rejects a record only after it has been read, so it bounds how far the walk continues but not whether any single read was in range.
2. A file-supplied offset becomes a pointer, unbounded. In the same loop, a glyph’s map offset is added to the resource base and stored in the font:
glyphs[index].gx_glyph_map = (GX_UBYTE *)(info -> gx_binres_root_address + header.gx_glyph_header_map_offset);
gx_glyph_header_map_offset is a ULONG read verbatim from the file and is never compared against anything. The resulting pointer is not dereferenced during the load, so it survives into the loaded GX_FONT and is followed later, when the glyph is drawn. An attacker chooses the offset, so an attacker chooses what memory is read and rendered.
The same input behaves identically on a tree carrying the fix for GHSA-hgcj-22cg-4hfv, which is how the two defects were told apart.
Impact
An untrusted or truncated resource file gives an out-of-bounds read. The bounded form is a read just past the resource and a likely crash. The map-offset form is worse: it yields a read at an attacker-chosen displacement from the resource, whose contents are then drawn to the screen, so process memory can be disclosed rather than merely crashed on. The threat model is the same as for GHSA-hgcj-22cg-4hfv: a firmware asset from an unverified source, a downloaded or user-supplied theme, or an OTA-delivered resource bundle.
Affected configurations
GX_BINARY_RESOURCE_SUPPORT is opt-out rather than opt-in, so the loader is compiled in unless an integrator removed it. Neither the extended-Unicode configuration nor any particular glyph format is required.
Every GUIX release up to and including 6.5.1.202602a. Per the project security policy the fix ships in 6.5.x, with no backport to 6.4.x.
Severity
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:H, 7.1, High.
Confidentiality is high because of the map offset form: the pointer it builds is followed when the glyph is drawn, so memory at an attacker chosen displacement is rendered to the screen rather than merely read. Integrity is none because nothing on this path writes. Availability is high because the bounded form reads past the resource and is a likely crash.
Patches
Fixed in GUIX 6.5.2.202603. GX_BINRES_DATA_INFO carries the extent of the resource, and every header the loaders read, every offset the resource supplies for its font and pixelmap data, the standalone offset table and the string table walks are checked against it.
Six entry points take the length from the caller: gx_binres_theme_load_ext, gx_binres_font_load_ext, gx_binres_pixelmap_load_ext, gx_binres_language_count_get_ext, gx_binres_language_info_load_ext and gx_binres_language_table_load_ext2. Applications that load resources they do not fully control should move to them.
The existing entry points keep working and are deprecated; GX_DISABLE_DEPRECATED_BINRES_API compiles them out. gx_binres_theme_load and the language services derive an extent from the size the resource declares, which catches a truncated file but not one built to mislead, since the same attacker chose that size. gx_binres_font_load and gx_binres_pixelmap_load read a standalone format that carries no total size, so they derive nothing and remain unbounded; only their _ext forms are protected.
Workarounds
Load binary resources only from sources the product controls. Where binary resources are not used at all, building with GX_DISABLE_BINARY_RESOURCE_SUPPORT removes the loaders entirely.
Credits
Surfaced by @adawn0106, whose regression inputs for GHSA-hgcj-22cg-4hfv reached this read as well, and whose reporting separated it from the glyph count underflow. Fixed by Frédéric Desbiens.
The fix and regression tests were produced with AI assistance under human review, in accordance with the Eclipse Foundation’s Generative AI Usage Guidelines.