The legacy BIT parser finds the BIT signature and then reads the
entry shape and entry array directly from the VBIOS image. The signature
does not prove that the complete header, entry array or referenced table
payload fits in the image.

Validate each extent before use. Preserve the legacy zero-offset meaning
for zero-length entries, but reject non-empty entries with a null or
out-of-range offset.

Fixes: 6ee738610f41 ("drm/nouveau: Add DRM driver for NVIDIA GPUs")
Assisted-by: Codex:gpt-5
Signed-off-by: Pengpeng Hou <[email protected]>
---
Changes since v1: 
https://lore.kernel.org/all/[email protected]/
- validate the complete BIT header and entry array
- validate each referenced payload extent
- preserve zero-offset semantics for zero-length entries only

The legacy BIT and ROMPTR contracts were reviewed statically; no malformed
VBIOS image was exercised.

 drivers/gpu/drm/nouveau/nouveau_bios.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c 
b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 38032bb95826..a4ef62928ba3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -972,24 +972,39 @@ bit_table(struct drm_device *dev, u8 id, struct bit_entry 
*bit)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nvbios *bios = &drm->vbios;
-       u8 entries, *entry;
+       u32 entry_size, entries, offset;
+       u8 *entry;
 
        if (bios->type != NVBIOS_BIT)
                return -ENODEV;
 
+       if (bios->offset > bios->length || bios->length - bios->offset < 12)
+               return -EINVAL;
+
+       entry_size = bios->data[bios->offset + 9];
        entries = bios->data[bios->offset + 10];
-       entry   = &bios->data[bios->offset + 12];
+       if (entry_size < 6 ||
+           entries > (bios->length - bios->offset - 12) / entry_size)
+               return -EINVAL;
+
+       entry = &bios->data[bios->offset + 12];
        while (entries--) {
                if (entry[0] == id) {
                        bit->id = entry[0];
                        bit->version = entry[1];
                        bit->length = ROM16(entry[2]);
                        bit->offset = ROM16(entry[4]);
+
+                       offset = bit->offset;
+                       if ((bit->length && !offset) || offset > bios->length ||
+                           bit->length > bios->length - offset)
+                               return -EINVAL;
+
                        bit->data = ROMPTR(dev, entry[4]);
                        return 0;
                }
 
-               entry += bios->data[bios->offset + 9];
+               entry += entry_size;
        }
 
        return -ENOENT;
-- 
2.50.1 (Apple Git-155)

Reply via email to