diff options
| author | Eliot Courtney <ecourtney@nvidia.com> | 2026-05-25 16:57:21 +0300 |
|---|---|---|
| committer | Danilo Krummrich <dakr@kernel.org> | 2026-05-25 17:30:34 +0300 |
| commit | 33f1402bcfa6cfd85fa265ce6fa5c6bb7d981c6d (patch) | |
| tree | 769efd4344242e20fc89cb8f8d9b67e62c195de7 | |
| parent | 7a1d09e477b6496f13f92b84ed9b2eab191b3366 (diff) | |
| download | linux-33f1402bcfa6cfd85fa265ce6fa5c6bb7d981c6d.tar.xz | |
gpu: nova-core: vbios: avoid reading too far in read_more_at_offset
Fix bug where `read_more_at_offset` would unnecessarily read more data.
This happens when the window to read has some part cached and some part
not. It would read `len` bytes instead of just the uncached portion,
which could read past `BIOS_MAX_SCAN_LEN`.
Fixes: 6fda04e7f0cd ("gpu: nova-core: vbios: Add base support for VBIOS construction and iteration")
Reviewed-by: John Hubbard <jhubbard@nvidia.com>
Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>
Link: https://patch.msgid.link/20260525-fix-vbios-v5-3-e5e455251537@nvidia.com
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
| -rw-r--r-- | drivers/gpu/nova-core/vbios.rs | 25 |
1 files changed, 11 insertions, 14 deletions
diff --git a/drivers/gpu/nova-core/vbios.rs b/drivers/gpu/nova-core/vbios.rs index 180928433766..79eb01dabc6f 100644 --- a/drivers/gpu/nova-core/vbios.rs +++ b/drivers/gpu/nova-core/vbios.rs @@ -185,8 +185,13 @@ impl<'a> VbiosIterator<'a> { /// Read bytes from the ROM at the current end of the data vector. fn read_more(&mut self, len: usize) -> Result { - let current_len = self.data.len(); - let start = ROM_OFFSET + current_len; + let start = self.data.len(); + let end = start + len; + + if end > BIOS_MAX_SCAN_LEN { + dev_err!(self.dev, "Error: exceeded BIOS scan limit.\n"); + return Err(EINVAL); + } // Ensure length is a multiple of 4 for 32-bit reads if len % core::mem::size_of::<u32>() != 0 { @@ -200,9 +205,9 @@ impl<'a> VbiosIterator<'a> { self.data.reserve(len, GFP_KERNEL)?; // Read ROM data bytes and push directly to `data`. - for addr in (start..start + len).step_by(core::mem::size_of::<u32>()) { + for addr in (start..end).step_by(core::mem::size_of::<u32>()) { // Read 32-bit word from the VBIOS ROM - let word = self.bar0.try_read32(addr)?; + let word = self.bar0.try_read32(ROM_OFFSET + addr)?; // Convert the `u32` to a 4 byte array and push each byte. word.to_ne_bytes() @@ -215,17 +220,9 @@ impl<'a> VbiosIterator<'a> { /// Read bytes at a specific offset, filling any gap. fn read_more_at_offset(&mut self, offset: usize, len: usize) -> Result { - if offset > BIOS_MAX_SCAN_LEN { - dev_err!(self.dev, "Error: exceeded BIOS scan limit.\n"); - return Err(EINVAL); - } - - // If `offset` is beyond current data size, fill the gap first. - let current_len = self.data.len(); - let gap_bytes = offset.saturating_sub(current_len); + let end = offset.checked_add(len).ok_or(EINVAL)?; - // Now read the requested bytes at the offset. - self.read_more(gap_bytes + len) + self.read_more(end.saturating_sub(self.data.len())) } /// Read a BIOS image at a specific offset and create a [`BiosImage`] from it. |
