mirror of
https://github.com/torvalds/linux.git
synced 2026-05-13 00:28:54 +02:00
gpu: nova-core: use checked arithmetic in FWSEC firmware parsing
Use checked_add() and checked_mul() when computing offsets from firmware-provided values in new_fwsec(). Without checked arithmetic, corrupt firmware could cause integer overflow. The danger is not just wrapping to a huge value, but potentially wrapping to a small plausible offset that passes validation yet accesses entirely wrong data, causing silent corruption or security issues. Reviewed-by: Zhi Wang <zhiw@nvidia.com> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260126202305.2526618-2-joelagnelf@nvidia.com [acourbot@nvidia.com: rewrap commit message to make checkpatch happy.] [acourbot@nvidia.com: add missing empty lines after new code blocks.] [acourbot@nvidia.com: move SAFETY comments to the unsafe statement they describe.] [acourbot@nvidia.com: remove obvious computation comments and use `CALC:` for the remaining ones.] Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
This commit is contained in:
parent
6ad005ce69
commit
0568b376a0
|
|
@ -45,10 +45,7 @@
|
|||
Signed,
|
||||
Unsigned, //
|
||||
},
|
||||
num::{
|
||||
FromSafeCast,
|
||||
IntoSafeCast, //
|
||||
},
|
||||
num::FromSafeCast,
|
||||
vbios::Vbios,
|
||||
};
|
||||
|
||||
|
|
@ -266,7 +263,12 @@ fn new_fwsec(dev: &Device<device::Bound>, bios: &Vbios, cmd: FwsecCommand) -> Re
|
|||
let ucode = bios.fwsec_image().ucode(&desc)?;
|
||||
let mut dma_object = DmaObject::from_data(dev, ucode)?;
|
||||
|
||||
let hdr_offset = usize::from_safe_cast(desc.imem_load_size() + desc.interface_offset());
|
||||
let hdr_offset = desc
|
||||
.imem_load_size()
|
||||
.checked_add(desc.interface_offset())
|
||||
.map(usize::from_safe_cast)
|
||||
.ok_or(EINVAL)?;
|
||||
|
||||
// SAFETY: we have exclusive access to `dma_object`.
|
||||
let hdr: &FalconAppifHdrV1 = unsafe { transmute(&dma_object, hdr_offset) }?;
|
||||
|
||||
|
|
@ -276,26 +278,29 @@ fn new_fwsec(dev: &Device<device::Bound>, bios: &Vbios, cmd: FwsecCommand) -> Re
|
|||
|
||||
// Find the DMEM mapper section in the firmware.
|
||||
for i in 0..usize::from(hdr.entry_count) {
|
||||
// CALC: hdr_offset + header_size + i * entry_size.
|
||||
let entry_offset = hdr_offset
|
||||
.checked_add(usize::from(hdr.header_size))
|
||||
.and_then(|o| o.checked_add(i.checked_mul(usize::from(hdr.entry_size))?))
|
||||
.ok_or(EINVAL)?;
|
||||
|
||||
// SAFETY: we have exclusive access to `dma_object`.
|
||||
let app: &FalconAppifV1 = unsafe {
|
||||
transmute(
|
||||
&dma_object,
|
||||
hdr_offset + usize::from(hdr.header_size) + i * usize::from(hdr.entry_size),
|
||||
)
|
||||
}?;
|
||||
let app: &FalconAppifV1 = unsafe { transmute(&dma_object, entry_offset) }?;
|
||||
|
||||
if app.id != NVFW_FALCON_APPIF_ID_DMEMMAPPER {
|
||||
continue;
|
||||
}
|
||||
let dmem_base = app.dmem_base;
|
||||
|
||||
// SAFETY: we have exclusive access to `dma_object`.
|
||||
let dmem_mapper: &mut FalconAppifDmemmapperV3 = unsafe {
|
||||
transmute_mut(
|
||||
&mut dma_object,
|
||||
(desc.imem_load_size() + dmem_base).into_safe_cast(),
|
||||
)
|
||||
}?;
|
||||
let dmem_mapper_offset = desc
|
||||
.imem_load_size()
|
||||
.checked_add(dmem_base)
|
||||
.map(usize::from_safe_cast)
|
||||
.ok_or(EINVAL)?;
|
||||
|
||||
let dmem_mapper: &mut FalconAppifDmemmapperV3 =
|
||||
// SAFETY: we have exclusive access to `dma_object`.
|
||||
unsafe { transmute_mut(&mut dma_object, dmem_mapper_offset) }?;
|
||||
|
||||
dmem_mapper.init_cmd = match cmd {
|
||||
FwsecCommand::Frts { .. } => NVFW_FALCON_APPIF_DMEMMAPPER_CMD_FRTS,
|
||||
|
|
@ -303,13 +308,15 @@ fn new_fwsec(dev: &Device<device::Bound>, bios: &Vbios, cmd: FwsecCommand) -> Re
|
|||
};
|
||||
let cmd_in_buffer_offset = dmem_mapper.cmd_in_buffer_offset;
|
||||
|
||||
// SAFETY: we have exclusive access to `dma_object`.
|
||||
let frts_cmd: &mut FrtsCmd = unsafe {
|
||||
transmute_mut(
|
||||
&mut dma_object,
|
||||
(desc.imem_load_size() + cmd_in_buffer_offset).into_safe_cast(),
|
||||
)
|
||||
}?;
|
||||
let frts_cmd_offset = desc
|
||||
.imem_load_size()
|
||||
.checked_add(cmd_in_buffer_offset)
|
||||
.map(usize::from_safe_cast)
|
||||
.ok_or(EINVAL)?;
|
||||
|
||||
let frts_cmd: &mut FrtsCmd =
|
||||
// SAFETY: we have exclusive access to `dma_object`.
|
||||
unsafe { transmute_mut(&mut dma_object, frts_cmd_offset) }?;
|
||||
|
||||
frts_cmd.read_vbios = ReadVbios {
|
||||
ver: 1,
|
||||
|
|
@ -355,8 +362,11 @@ pub(crate) fn new(
|
|||
// Patch signature if needed.
|
||||
let desc = bios.fwsec_image().header()?;
|
||||
let ucode_signed = if desc.signature_count() != 0 {
|
||||
let sig_base_img =
|
||||
usize::from_safe_cast(desc.imem_load_size() + desc.pkc_data_offset());
|
||||
let sig_base_img = desc
|
||||
.imem_load_size()
|
||||
.checked_add(desc.pkc_data_offset())
|
||||
.map(usize::from_safe_cast)
|
||||
.ok_or(EINVAL)?;
|
||||
let desc_sig_versions = u32::from(desc.signature_versions());
|
||||
let reg_fuse_version =
|
||||
falcon.signature_reg_fuse_version(bar, desc.engine_id_mask(), desc.ucode_id())?;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user