⬢ DragonFlyBSD Kernel Audit
DF-4289 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/amd/amdgpu/atom.h
+++ b/sys/dev/drm/amd/amdgpu/atom.h
@@ -126,6 +126,7 @@ struct atom_context {
 	struct lock mutex;
 	void *bios;
+	uint32_t bios_size;	/* ROM image length in bytes */
 	uint32_t cmd_table, data_table;
 	uint16_t *iio;
@@ -146,7 +147,7 @@ struct atom_context {
 
-struct atom_context *amdgpu_atom_parse(struct card_info *, void *);
+struct atom_context *amdgpu_atom_parse(struct card_info *, void *, uint32_t);
--- a/sys/dev/drm/amd/amdgpu/atom.c
+++ b/sys/dev/drm/amd/amdgpu/atom.c
@@ -1296,10 +1296,11 @@
-struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios)
+struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios,
+    uint32_t bios_size)
 {
 	int base;
 	struct atom_context *ctx =
 	    kzalloc(sizeof(struct atom_context), GFP_KERNEL);
@@ -1308,6 +1309,7 @@
 
 	ctx->card = card;
 	ctx->bios = bios;
+	ctx->bios_size = bios_size;
@@ -1384,9 +1386,19 @@ bool amdgpu_atom_parse_data_header(struct atom_context *ctx, int index,
 	int offset = index * 2 + 4;
 	int idx = CU16(ctx->data_table + offset);
 	u16 *mdt = (u16 *)(ctx->bios + ctx->data_table + 4);
+	uint16_t tsize;
 
 	if (!mdt[index])
 		return false;
 
+	/*
+	 * Security: idx and the table's own size field are VBIOS-controlled.
+	 * Reject any data table whose declared extent runs past the end of
+	 * the ROM image so downstream walkers (e.g. the fixed-stride
+	 * ATOM_ASIC_SS_ASSIGNMENT walk in powerplay's
+	 * asic_internal_ss_get_ss_asignment) cannot be steered out of the
+	 * bios buffer by a crafted usStructureSize.
+	 */
+	tsize = CU16(idx);
+	if ((uint32_t)idx + tsize > ctx->bios_size)
+		return false;
+
 	if (size)
 		*size = CU16(idx);
--- a/sys/dev/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/sys/dev/drm/amd/amdgpu/amdgpu_atombios.c
@@ -2034,7 +2034,8 @@
 	atom_card_info->pll_write = cail_pll_write;
 
-	adev->mode_info.atom_context = amdgpu_atom_parse(atom_card_info, adev->bios);
+	adev->mode_info.atom_context = amdgpu_atom_parse(atom_card_info,
+	    adev->bios, adev->bios_size);