mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 12:35:52 +02:00
wifi: rtw89: fw: validate multi-firmware header before accessing
A firmeware file contains multi-firmware with a header to represent
contents. The mfw_hdr->fw_nr is to define number of firmware in file.
+-----+-------+------+---------+--------------+
| sig | fw_nr | rsvd | version | reserved |
+---------------------------------------------+ --
fw 0 | cv | type | mp | rsvd | shift | size | rsvd | \
+---------------------------------------------+ |
fw 1 | cv | type | mp | rsvd | shift | size | rsvd | | mfw_hdr->fw_nr
+---------------------------------------------+ |
fw N-1 | ... | /
+=============================================+ --
| fw 0 content |
| (pointed by fw0 shift/size) |
+=============================================+
To avoid Coverity warning, validate header is in range of firmware size,
and also validate the range of actual firmware content is in range.
Addresses-Coverity-ID: 1494046 ("Untrusted loop bound")
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20250203072911.47313-4-pkshih@realtek.com
This commit is contained in:
parent
5dde1a569c
commit
1f0efffd59
|
|
@ -489,6 +489,30 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev,
|
|||
}
|
||||
}
|
||||
|
||||
static int rtw89_mfw_validate_hdr(struct rtw89_dev *rtwdev,
|
||||
const struct firmware *firmware,
|
||||
const struct rtw89_mfw_hdr *mfw_hdr)
|
||||
{
|
||||
const void *mfw = firmware->data;
|
||||
u32 mfw_len = firmware->size;
|
||||
u8 fw_nr = mfw_hdr->fw_nr;
|
||||
const void *ptr;
|
||||
|
||||
if (fw_nr == 0) {
|
||||
rtw89_err(rtwdev, "mfw header has no fw entry\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ptr = &mfw_hdr->info[fw_nr];
|
||||
|
||||
if (ptr > mfw + mfw_len) {
|
||||
rtw89_err(rtwdev, "mfw header out of address\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
|
||||
struct rtw89_fw_suit *fw_suit, bool nowarn)
|
||||
|
|
@ -499,6 +523,7 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
|
|||
u32 mfw_len = firmware->size;
|
||||
const struct rtw89_mfw_hdr *mfw_hdr = (const struct rtw89_mfw_hdr *)mfw;
|
||||
const struct rtw89_mfw_info *mfw_info = NULL, *tmp;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (mfw_hdr->sig != RTW89_MFW_SIG) {
|
||||
|
|
@ -511,6 +536,10 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
|
|||
return 0;
|
||||
}
|
||||
|
||||
ret = rtw89_mfw_validate_hdr(rtwdev, firmware, mfw_hdr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < mfw_hdr->fw_nr; i++) {
|
||||
tmp = &mfw_hdr->info[i];
|
||||
if (tmp->type != type)
|
||||
|
|
@ -540,6 +569,12 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
|
|||
found:
|
||||
fw_suit->data = mfw + le32_to_cpu(mfw_info->shift);
|
||||
fw_suit->size = le32_to_cpu(mfw_info->size);
|
||||
|
||||
if (fw_suit->data + fw_suit->size > mfw + mfw_len) {
|
||||
rtw89_err(rtwdev, "fw_suit %d out of address\n", type);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user