summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLijo Lazar <lijo.lazar@amd.com>2026-06-16 10:14:58 +0530
committerAlex Deucher <alexander.deucher@amd.com>2026-07-01 11:14:50 -0400
commitbe88697602238c3dcb47bbc2db1eef923f63e78b (patch)
treed428d8b98e12147992ed169c4f37e508ffaf90e8 /drivers
parent230753e46a4a9d04dad6a9b5dbaeb7fd52add7d0 (diff)
downloadlinux-next-be88697602238c3dcb47bbc2db1eef923f63e78b.tar.gz
linux-next-be88697602238c3dcb47bbc2db1eef923f63e78b.zip
drm/amdgpu: bounds check ATOM IIO table parsing
atom_index_iio() parsed the IIO bytecode without bounds checks, allowing out-of-bounds reads on a malformed VBIOS. Pass the BIOS size into amdgpu_atom_parse() and bound the parse loops by it. Signed-off-by: Lijo Lazar <lijo.lazar@amd.com> Assisted-by: Claude Code Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Asad Kamal <asad.kamal@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atom.c25
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atom.h3
3 files changed, 23 insertions, 7 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
index acd22bff1882..27c0dc8f6137 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -1923,7 +1923,7 @@ int amdgpu_atombios_init(struct amdgpu_device *adev)
atom_card_info->pll_read = cail_pll_read;
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);
if (!adev->mode_info.atom_context) {
amdgpu_atombios_fini(adev);
return -ENOMEM;
diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c
index ca5d091549e1..c3824934ac7d 100644
--- a/drivers/gpu/drm/amd/amdgpu/atom.c
+++ b/drivers/gpu/drm/amd/amdgpu/atom.c
@@ -1327,11 +1327,25 @@ static void atom_index_iio(struct atom_context *ctx, int base)
ctx->iio = kzalloc(2 * 256, GFP_KERNEL);
if (!ctx->iio)
return;
- while (CU8(base) == ATOM_IIO_START) {
- ctx->iio[CU8(base + 1)] = base + 2;
+ while (base + 1 < ctx->bios_size && CU8(base) == ATOM_IIO_START) {
+ uint8_t index = CU8(base + 1);
+ int start = base + 2;
base += 2;
- while (CU8(base) != ATOM_IIO_END)
- base += atom_iio_len[CU8(base)];
+ while (base < ctx->bios_size && CU8(base) != ATOM_IIO_END) {
+ uint8_t op = CU8(base);
+
+ /*
+ * Unknown opcode: its length is unknown so the byte
+ * stream cannot be resynced reliably.
+ */
+ if (op >= ARRAY_SIZE(atom_iio_len))
+ return;
+ base += atom_iio_len[op];
+ }
+ if (base >= ctx->bios_size)
+ return;
+ /* Only index well-formed methods, others stay 0 */
+ ctx->iio[index] = start;
base += 3;
}
}
@@ -1553,7 +1567,7 @@ static inline void atom_print_vbios_info(struct atom_context *ctx)
drm_info(ctx->card->dev, "ATOM BIOS: %s\n", vbios_info);
}
-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 =
@@ -1567,6 +1581,7 @@ struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios)
ctx->card = card;
ctx->bios = bios;
+ ctx->bios_size = bios_size;
if (CU16(0) != ATOM_BIOS_MAGIC) {
pr_info("Invalid BIOS magic\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/atom.h b/drivers/gpu/drm/amd/amdgpu/atom.h
index bb3d9eb7eb6b..4687c019cbe3 100644
--- a/drivers/gpu/drm/amd/amdgpu/atom.h
+++ b/drivers/gpu/drm/amd/amdgpu/atom.h
@@ -133,6 +133,7 @@ struct atom_context {
struct card_info *card;
struct mutex mutex;
void *bios;
+ uint32_t bios_size;
uint32_t cmd_table, data_table;
uint16_t *iio;
@@ -160,7 +161,7 @@ struct atom_context {
extern int amdgpu_atom_debug;
-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 amdgpu_atom_execute_table(struct atom_context *ctx, int index, uint32_t *params, int params_size);
int amdgpu_atom_asic_init(struct atom_context *ctx);
void amdgpu_atom_destroy(struct atom_context *ctx);