From 4d4e9907ff572bb1d1c0f6913ad6e3d6d4525077 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 22 Jun 2016 12:10:00 +1000 Subject: [PATCH] drm/nouveau/bios: guard against out-of-bounds accesses to image Signed-off-by: Ben Skeggs --- .../drm/nouveau/include/nvkm/subdev/bios.h | 7 ++-- .../gpu/drm/nouveau/nvkm/subdev/bios/base.c | 34 +++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios.h index e39a1fea930b..6137de829b8f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios.h @@ -22,10 +22,9 @@ struct nvkm_bios { u8 nvbios_checksum(const u8 *data, int size); u16 nvbios_findstr(const u8 *data, int size, const char *str, int len); int nvbios_memcmp(struct nvkm_bios *, u32 addr, const char *, u32 len); - -#define nvbios_rd08(b,o) (b)->data[(o)] -#define nvbios_rd16(b,o) get_unaligned_le16(&(b)->data[(o)]) -#define nvbios_rd32(b,o) get_unaligned_le32(&(b)->data[(o)]) +u8 nvbios_rd08(struct nvkm_bios *, u32 addr); +u16 nvbios_rd16(struct nvkm_bios *, u32 addr); +u32 nvbios_rd32(struct nvkm_bios *, u32 addr); int nvkm_bios_new(struct nvkm_device *, int, struct nvkm_bios **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c index e15b9627b07e..db5fa009a619 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c @@ -27,6 +27,40 @@ #include #include +static bool +nvbios_addr(struct nvkm_bios *bios, u32 *addr, u8 size) +{ + if (unlikely(*addr + size >= bios->size)) { + nvkm_error(&bios->subdev, "OOB %d %08x\n", size, *addr); + return false; + } + return true; +} + +u8 +nvbios_rd08(struct nvkm_bios *bios, u32 addr) +{ + if (likely(nvbios_addr(bios, &addr, 1))) + return bios->data[addr]; + return 0x00; +} + +u16 +nvbios_rd16(struct nvkm_bios *bios, u32 addr) +{ + if (likely(nvbios_addr(bios, &addr, 2))) + return get_unaligned_le16(&bios->data[addr]); + return 0x0000; +} + +u32 +nvbios_rd32(struct nvkm_bios *bios, u32 addr) +{ + if (likely(nvbios_addr(bios, &addr, 4))) + return get_unaligned_le32(&bios->data[addr]); + return 0x00000000; +} + u8 nvbios_checksum(const u8 *data, int size) { -- 2.39.5