Skip to content

Commit

Permalink
drm/nouveau: validate vbios size
Browse files Browse the repository at this point in the history
Without checking, we could detect vbios size as 0, allocate 0-byte array
(kmalloc returns invalid pointer for such allocation) and crash in
nouveau_bios_score while checking for vbios signature.

Reported-by: Heinz Diehl <htd@fritha.org>
Signed-off-by: Marcin Slusarz <marcin.slusarz@gmail.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Marcin Slusarz authored and Ben Skeggs committed Oct 22, 2012
1 parent 0bab097 commit 00e4845
Showing 1 changed file with 13 additions and 3 deletions.
16 changes: 13 additions & 3 deletions drivers/gpu/drm/nouveau/core/subdev/bios/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ nouveau_bios_shadow_of(struct nouveau_bios *bios)
}

data = of_get_property(dn, "NVDA,BMP", &size);
if (data) {
if (data && size) {
bios->size = size;
bios->data = kmalloc(bios->size, GFP_KERNEL);
if (bios->data)
Expand Down Expand Up @@ -104,6 +104,9 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios)
goto out;

bios->size = nv_rd08(bios, 0x700002) * 512;
if (!bios->size)
goto out;

bios->data = kmalloc(bios->size, GFP_KERNEL);
if (bios->data) {
for (i = 0; i < bios->size; i++)
Expand Down Expand Up @@ -155,6 +158,9 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)

/* read entire bios image to system memory */
bios->size = nv_rd08(bios, 0x300002) * 512;
if (!bios->size)
goto out;

bios->data = kmalloc(bios->size, GFP_KERNEL);
if (bios->data) {
for (i = 0; i < bios->size; i++)
Expand Down Expand Up @@ -196,6 +202,8 @@ nouveau_bios_shadow_acpi(struct nouveau_bios *bios)
bios->size = 0;
if (nouveau_acpi_get_bios_chunk(data, 0, 3) == 3)
bios->size = data[2] * 512;
if (!bios->size)
return;

bios->data = kmalloc(bios->size, GFP_KERNEL);
for (i = 0; bios->data && i < bios->size; i += cnt) {
Expand Down Expand Up @@ -231,12 +239,14 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios)
static int
nouveau_bios_score(struct nouveau_bios *bios, const bool writeable)
{
if (!bios->data || bios->data[0] != 0x55 || bios->data[1] != 0xAA) {
if (bios->size < 3 || !bios->data || bios->data[0] != 0x55 ||
bios->data[1] != 0xAA) {
nv_info(bios, "... signature not found\n");
return 0;
}

if (nvbios_checksum(bios->data, bios->data[2] * 512)) {
if (nvbios_checksum(bios->data,
min_t(u32, bios->data[2] * 512, bios->size))) {
nv_info(bios, "... checksum invalid\n");
/* if a ro image is somewhat bad, it's probably all rubbish */
return writeable ? 2 : 1;
Expand Down

0 comments on commit 00e4845

Please sign in to comment.