@@ -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;
}
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> --- drivers/net/wireless/realtek/rtw89/fw.c | 35 +++++++++++++++++++++++++ 1 file changed, 35 insertions(+)