DF-1130 / fix.diff
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | diff --git a/sys/dev/drm/radeon/si.c b/sys/dev/drm/radeon/si.c --- a/sys/dev/drm/radeon/si.c +++ b/sys/dev/drm/radeon/si.c @@ -1574,14 +1574,20 @@ if (rdev->new_fw) { const struct mc_firmware_header_v1_0 *hdr = (const struct mc_firmware_header_v1_0 *)rdev->mc_fw->data; + u32 io_off = le32_to_cpu(hdr->io_debug_array_offset_bytes); + u32 io_size = le32_to_cpu(hdr->io_debug_size_bytes); + u32 uc_off = le32_to_cpu(hdr->header.ucode_array_offset_bytes); + u32 uc_size = le32_to_cpu(hdr->header.ucode_size_bytes); + u32 ds = rdev->mc_fw->datasize; radeon_ucode_print_mc_hdr(&hdr->header); - regs_size = le32_to_cpu(hdr->io_debug_size_bytes) / (4 * 2); - new_io_mc_regs = (const __le32 *) - (rdev->mc_fw->data + le32_to_cpu(hdr->io_debug_array_offset_bytes)); - ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4; - new_fw_data = (const __le32 *) - (rdev->mc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); + if (io_off > ds || io_size > ds - io_off || + uc_off > ds || uc_size > ds - uc_off) + return -EINVAL; + regs_size = io_size / (4 * 2); + new_io_mc_regs = (const __le32 *)(rdev->mc_fw->data + io_off); + ucode_size = uc_size / 4; + new_fw_data = (const __le32 *)(rdev->mc_fw->data + uc_off); } else { ucode_size = rdev->mc_fw->datasize / 4; @@ -3481,33 +3487,46 @@ (const struct gfx_firmware_header_v1_0 *)rdev->me_fw->data; const __le32 *fw_data; u32 fw_size; + u32 ds_pfp = rdev->pfp_fw->datasize; + u32 ds_ce = rdev->ce_fw->datasize; + u32 ds_me = rdev->me_fw->datasize; + u32 off, size; radeon_ucode_print_gfx_hdr(&pfp_hdr->header); radeon_ucode_print_gfx_hdr(&ce_hdr->header); radeon_ucode_print_gfx_hdr(&me_hdr->header); /* PFP */ - fw_data = (const __le32 *) - (rdev->pfp_fw->data + le32_to_cpu(pfp_hdr->header.ucode_array_offset_bytes)); - fw_size = le32_to_cpu(pfp_hdr->header.ucode_size_bytes) / 4; + off = le32_to_cpu(pfp_hdr->header.ucode_array_offset_bytes); + size = le32_to_cpu(pfp_hdr->header.ucode_size_bytes); + if (off > ds_pfp || size > ds_pfp - off) + return -EINVAL; + fw_data = (const __le32 *)(rdev->pfp_fw->data + off); + fw_size = size / 4; WREG32(CP_PFP_UCODE_ADDR, 0); for (i = 0; i < fw_size; i++) WREG32(CP_PFP_UCODE_DATA, le32_to_cpup(fw_data++)); WREG32(CP_PFP_UCODE_ADDR, 0); /* CE */ - fw_data = (const __le32 *) - (rdev->ce_fw->data + le32_to_cpu(ce_hdr->header.ucode_array_offset_bytes)); - fw_size = le32_to_cpu(ce_hdr->header.ucode_size_bytes) / 4; + off = le32_to_cpu(ce_hdr->header.ucode_array_offset_bytes); + size = le32_to_cpu(ce_hdr->header.ucode_size_bytes); + if (off > ds_ce || size > ds_ce - off) + return -EINVAL; + fw_data = (const __le32 *)(rdev->ce_fw->data + off); + fw_size = size / 4; WREG32(CP_CE_UCODE_ADDR, 0); for (i = 0; i < fw_size; i++) WREG32(CP_CE_UCODE_DATA, le32_to_cpup(fw_data++)); WREG32(CP_CE_UCODE_ADDR, 0); /* ME */ - fw_data = (const __be32 *) - (rdev->me_fw->data + le32_to_cpu(me_hdr->header.ucode_array_offset_bytes)); - fw_size = le32_to_cpu(me_hdr->header.ucode_size_bytes) / 4; + off = le32_to_cpu(me_hdr->header.ucode_array_offset_bytes); + size = le32_to_cpu(me_hdr->header.ucode_size_bytes); + if (off > ds_me || size > ds_me - off) + return -EINVAL; + fw_data = (const __le32 *)(rdev->me_fw->data + off); + fw_size = size / 4; WREG32(CP_ME_RAM_WADDR, 0); for (i = 0; i < fw_size; i++) WREG32(CP_ME_RAM_DATA, le32_to_cpup(fw_data++)); @@ -5876,11 +5895,17 @@ if (rdev->new_fw) { const struct rlc_firmware_header_v1_0 *hdr = (const struct rlc_firmware_header_v1_0 *)rdev->rlc_fw->data; - u32 fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4; - const __le32 *fw_data = (const __le32 *) - (rdev->rlc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); + u32 uc_off = le32_to_cpu(hdr->header.ucode_array_offset_bytes); + u32 uc_size = le32_to_cpu(hdr->header.ucode_size_bytes); + u32 ds = rdev->rlc_fw->datasize; + u32 fw_size; + const __le32 *fw_data; radeon_ucode_print_rlc_hdr(&hdr->header); + if (uc_off > ds || uc_size > ds - uc_off) + return -EINVAL; + fw_size = uc_size / 4; + fw_data = (const __le32 *)(rdev->rlc_fw->data + uc_off); for (i = 0; i < fw_size; i++) { WREG32(RLC_UCODE_ADDR, i); |