mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
staging: gs_fpgaboot: add buffer overflow checks
Four fields in struct fpgaimage are char arrays of length MAX_STR (256). The amount of data read into these buffers is controlled by a length field in the bitstream file read from userspace. If a corrupt or malicious firmware file was supplied, kernel data beyond these buffers can be overwritten arbitrarily. This patch adds a check of the bitstream's length value to ensure it fits within the bounds of the allocated buffers. An error condition is returned from gs_read_bitstream if any of the reads fail. Signed-off-by: Jacob von Chorus <jacobvonchorus@cwphoto.ca> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
ee714b80ea
commit
a46393aba7
@ -23,6 +23,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "gs_fpgaboot.h"
|
||||
#include "io.h"
|
||||
@ -47,7 +48,7 @@ static void read_bitstream(char *bitdata, char *buf, int *offset, int rdsize)
|
||||
*offset += rdsize;
|
||||
}
|
||||
|
||||
static void readinfo_bitstream(char *bitdata, char *buf, int *offset)
|
||||
static int readinfo_bitstream(char *bitdata, char *buf, int size, int *offset)
|
||||
{
|
||||
char tbuf[64];
|
||||
s32 len;
|
||||
@ -58,10 +59,16 @@ static void readinfo_bitstream(char *bitdata, char *buf, int *offset)
|
||||
/* read length */
|
||||
read_bitstream(bitdata, tbuf, offset, 2);
|
||||
|
||||
len = tbuf[0] << 8 | tbuf[1];
|
||||
len = get_unaligned_be16(tbuf);
|
||||
if (len >= size) {
|
||||
pr_err("error: readinfo buffer too small\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
read_bitstream(bitdata, buf, offset, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -83,8 +90,7 @@ static int readlength_bitstream(char *bitdata, int *lendata, int *offset)
|
||||
/* read 4bytes length */
|
||||
read_bitstream(bitdata, tbuf, offset, 4);
|
||||
|
||||
*lendata = tbuf[0] << 24 | tbuf[1] << 16 |
|
||||
tbuf[2] << 8 | tbuf[3];
|
||||
*lendata = get_unaligned_be32(tbuf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -113,7 +119,7 @@ static int readmagic_bitstream(char *bitdata, int *offset)
|
||||
/*
|
||||
* NOTE: supports only bitstream format
|
||||
*/
|
||||
static enum fmt_image get_imageformat(struct fpgaimage *fimage)
|
||||
static enum fmt_image get_imageformat(void)
|
||||
{
|
||||
return f_bit;
|
||||
}
|
||||
@ -127,34 +133,54 @@ static void gs_print_header(struct fpgaimage *fimage)
|
||||
pr_info("lendata: %d\n", fimage->lendata);
|
||||
}
|
||||
|
||||
static void gs_read_bitstream(struct fpgaimage *fimage)
|
||||
static int gs_read_bitstream(struct fpgaimage *fimage)
|
||||
{
|
||||
char *bitdata;
|
||||
int offset;
|
||||
int err;
|
||||
|
||||
offset = 0;
|
||||
bitdata = (char *)fimage->fw_entry->data;
|
||||
|
||||
readmagic_bitstream(bitdata, &offset);
|
||||
readinfo_bitstream(bitdata, fimage->filename, &offset);
|
||||
readinfo_bitstream(bitdata, fimage->part, &offset);
|
||||
readinfo_bitstream(bitdata, fimage->date, &offset);
|
||||
readinfo_bitstream(bitdata, fimage->time, &offset);
|
||||
readlength_bitstream(bitdata, &fimage->lendata, &offset);
|
||||
err = readmagic_bitstream(bitdata, &offset);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = readinfo_bitstream(bitdata, fimage->filename, MAX_STR, &offset);
|
||||
if (err)
|
||||
return err;
|
||||
err = readinfo_bitstream(bitdata, fimage->part, MAX_STR, &offset);
|
||||
if (err)
|
||||
return err;
|
||||
err = readinfo_bitstream(bitdata, fimage->date, MAX_STR, &offset);
|
||||
if (err)
|
||||
return err;
|
||||
err = readinfo_bitstream(bitdata, fimage->time, MAX_STR, &offset);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = readlength_bitstream(bitdata, &fimage->lendata, &offset);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
fimage->fpgadata = bitdata + offset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gs_read_image(struct fpgaimage *fimage)
|
||||
{
|
||||
int img_fmt;
|
||||
int err;
|
||||
|
||||
img_fmt = get_imageformat(fimage);
|
||||
img_fmt = get_imageformat();
|
||||
|
||||
switch (img_fmt) {
|
||||
case f_bit:
|
||||
pr_info("image is bitstream format\n");
|
||||
gs_read_bitstream(fimage);
|
||||
err = gs_read_bitstream(fimage);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
default:
|
||||
pr_err("unsupported fpga image format\n");
|
||||
|
Loading…
Reference in New Issue
Block a user