Commit 00e4845b authored by Marcin Slusarz's avatar Marcin Slusarz Committed by Ben Skeggs

drm/nouveau: validate vbios size

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: default avatarHeinz Diehl <htd@fritha.org>
Signed-off-by: default avatarMarcin Slusarz <marcin.slusarz@gmail.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 0bab097a
...@@ -72,7 +72,7 @@ nouveau_bios_shadow_of(struct nouveau_bios *bios) ...@@ -72,7 +72,7 @@ nouveau_bios_shadow_of(struct nouveau_bios *bios)
} }
data = of_get_property(dn, "NVDA,BMP", &size); data = of_get_property(dn, "NVDA,BMP", &size);
if (data) { if (data && size) {
bios->size = size; bios->size = size;
bios->data = kmalloc(bios->size, GFP_KERNEL); bios->data = kmalloc(bios->size, GFP_KERNEL);
if (bios->data) if (bios->data)
...@@ -104,6 +104,9 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios) ...@@ -104,6 +104,9 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios)
goto out; goto out;
bios->size = nv_rd08(bios, 0x700002) * 512; bios->size = nv_rd08(bios, 0x700002) * 512;
if (!bios->size)
goto out;
bios->data = kmalloc(bios->size, GFP_KERNEL); bios->data = kmalloc(bios->size, GFP_KERNEL);
if (bios->data) { if (bios->data) {
for (i = 0; i < bios->size; i++) for (i = 0; i < bios->size; i++)
...@@ -155,6 +158,9 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios) ...@@ -155,6 +158,9 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
/* read entire bios image to system memory */ /* read entire bios image to system memory */
bios->size = nv_rd08(bios, 0x300002) * 512; bios->size = nv_rd08(bios, 0x300002) * 512;
if (!bios->size)
goto out;
bios->data = kmalloc(bios->size, GFP_KERNEL); bios->data = kmalloc(bios->size, GFP_KERNEL);
if (bios->data) { if (bios->data) {
for (i = 0; i < bios->size; i++) for (i = 0; i < bios->size; i++)
...@@ -196,6 +202,8 @@ nouveau_bios_shadow_acpi(struct nouveau_bios *bios) ...@@ -196,6 +202,8 @@ nouveau_bios_shadow_acpi(struct nouveau_bios *bios)
bios->size = 0; bios->size = 0;
if (nouveau_acpi_get_bios_chunk(data, 0, 3) == 3) if (nouveau_acpi_get_bios_chunk(data, 0, 3) == 3)
bios->size = data[2] * 512; bios->size = data[2] * 512;
if (!bios->size)
return;
bios->data = kmalloc(bios->size, GFP_KERNEL); bios->data = kmalloc(bios->size, GFP_KERNEL);
for (i = 0; bios->data && i < bios->size; i += cnt) { for (i = 0; bios->data && i < bios->size; i += cnt) {
...@@ -231,12 +239,14 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios) ...@@ -231,12 +239,14 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios)
static int static int
nouveau_bios_score(struct nouveau_bios *bios, const bool writeable) 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"); nv_info(bios, "... signature not found\n");
return 0; 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"); nv_info(bios, "... checksum invalid\n");
/* if a ro image is somewhat bad, it's probably all rubbish */ /* if a ro image is somewhat bad, it's probably all rubbish */
return writeable ? 2 : 1; return writeable ? 2 : 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment