Skip to contentSkip to conversation

wifi: rtw89: fw: add firmware blacklist to avoid obsolete secure firmware

PATCH In review Ping-Ke Shih 1 participant 7 messages Feb 17, 2025 – Feb 21, 2025 Realtek wireless driver (rtw89)

lore
Share & tools
lore

Ping-Ke Shih

author maintainer
#0 lore raw

cover wifi: rtw89: fw: add firmware blacklist to avoid obsolete secure firmware

Considering weak or flaw firmware is not safe. Refuse using obsolete firmware on secure chips. Add and update a blacklist in driver, when a firmware is considered not secure.

The remaining four patches are to refine firmware codes by the way.

Ping-Ke Shih (5):
wifi: rtw89: fw: add blacklist to avoid obsolete secure firmware
wifi: rtw89: fw: get sb_sel_ver via get_unaligned_le32()
wifi: rtw89: fw: propagate error code from rtw89_h2c_tx()
wifi: rtw89: fw: add debug message for unexpected secure firmware
wifi: rtw89: fw: safely cast mfw_hdr pointer from firmware->data

 drivers/net/wireless/realtek/rtw89/core.h     |  2 +
 drivers/net/wireless/realtek/rtw89/fw.c       | 91 ++++++++++++++++---
 drivers/net/wireless/realtek/rtw89/fw.h       | 12 +++
 drivers/net/wireless/realtek/rtw89/rtw8851b.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852a.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852b.c |  1 +
 .../net/wireless/realtek/rtw89/rtw8852bt.c    |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852c.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8922a.c |  1 +
 9 files changed, 100 insertions(+), 11 deletions(-)
Signature · 1 line
2.25.1
author maintainer
#1 lore raw

PATCH 1/5 wifi: rtw89: fw: add blacklist to avoid obsolete secure firmware

To ensure secure chip only runs expected secure firmware, stop using obsolete firmware in blacklist which weakness or flaw was found.

---
 drivers/net/wireless/realtek/rtw89/core.h     |  2 +
 drivers/net/wireless/realtek/rtw89/fw.c       | 52 ++++++++++++++++++-
 drivers/net/wireless/realtek/rtw89/fw.h       | 12 +++++
 drivers/net/wireless/realtek/rtw89/rtw8851b.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852a.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852b.c |  1 +
 .../net/wireless/realtek/rtw89/rtw8852bt.c    |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852c.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8922a.c |  1 +
 9 files changed, 71 insertions(+), 1 deletion(-)
drivers/net/wireless/realtek/rtw89/core.h +2 -0
index b3fdd8eded21..5044d78435b8 100644
@@ -17,6 +17,7 @@ struct rtw89_dev;
 struct rtw89_pci_info;
 struct rtw89_mac_gen_def;
 struct rtw89_phy_gen_def;
+struct rtw89_fw_blacklist;
 struct rtw89_efuse_block_cfg;
 struct rtw89_h2c_rf_tssi;
 struct rtw89_fw_txpwr_track_cfg;
@@ -4257,6 +4258,7 @@ struct rtw89_chip_info {
 	bool try_ce_fw;
 	u8 bbmcu_nr;
 	u32 needed_fw_elms;
+	const struct rtw89_fw_blacklist *fw_blacklist;
 	u32 fifo_size;
 	bool small_fifo_size;
 	u32 dle_scc_rsvd_size;
drivers/net/wireless/realtek/rtw89/fw.c +51 -1

70 lines not on this page · raw message

drivers/net/wireless/realtek/rtw89/fw.h +12 -0
index 994d109a9c3c..31d44513b181 100644
@@ -663,6 +663,11 @@ struct rtw89_fw_mss_pool_hdr {
 } __packed;
 
 union rtw89_fw_section_mssc_content {
+	struct {
+		u8 pad[0x20];
+		u8 bit_in_chip_list;
+		u8 ver;
+	} __packed blacklist;
 	struct {
 		u8 pad[58];
 		__le32 v;
@@ -673,6 +678,13 @@ union rtw89_fw_section_mssc_content {
 	} __packed key_sign_len;
 } __packed;
 
+struct rtw89_fw_blacklist {
+	u8 ver;
+	u8 list[32];
+};
+
+extern const struct rtw89_fw_blacklist rtw89_fw_blacklist_default;
+
 static inline void SET_CTRL_INFO_MACID(void *table, u32 val)
 {
 	le32p_replace_bits((__le32 *)(table) + 0, val, GENMASK(6, 0));
drivers/net/wireless/realtek/rtw89/rtw8851b.c +1 -0
index 82289dbad1f4..8fba6413a5cb 100644
@@ -2458,6 +2458,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
 	.try_ce_fw		= true,
 	.bbmcu_nr		= 0,
 	.needed_fw_elms		= 0,
+	.fw_blacklist		= NULL,
 	.fifo_size		= 196608,
 	.small_fifo_size	= true,
 	.dle_scc_rsvd_size	= 98304,
drivers/net/wireless/realtek/rtw89/rtw8852a.c +1 -0
index 2046832d021f..1b958c559aac 100644
@@ -2175,6 +2175,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
 	.try_ce_fw		= false,
 	.bbmcu_nr		= 0,
 	.needed_fw_elms		= 0,
+	.fw_blacklist		= NULL,
 	.fifo_size		= 458752,
 	.small_fifo_size	= false,
 	.dle_scc_rsvd_size	= 0,
drivers/net/wireless/realtek/rtw89/rtw8852b.c +1 -0
index 652914a36245..780fc19d617f 100644
@@ -811,6 +811,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
 	.try_ce_fw		= true,
 	.bbmcu_nr		= 0,
 	.needed_fw_elms		= 0,
+	.fw_blacklist		= &rtw89_fw_blacklist_default,
 	.fifo_size		= 196608,
 	.small_fifo_size	= true,
 	.dle_scc_rsvd_size	= 98304,
drivers/net/wireless/realtek/rtw89/rtw8852bt.c +1 -0
index 6f15245b2f74..1173496a075d 100644
@@ -745,6 +745,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
 	.try_ce_fw		= true,
 	.bbmcu_nr		= 0,
 	.needed_fw_elms		= RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_NO_6GHZ,
+	.fw_blacklist		= &rtw89_fw_blacklist_default,
 	.fifo_size		= 458752,
 	.small_fifo_size	= true,
 	.dle_scc_rsvd_size	= 98304,
drivers/net/wireless/realtek/rtw89/rtw8852c.c +1 -0
index ecc1ff358583..c61e4953bc97 100644
@@ -2967,6 +2967,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
 	.try_ce_fw		= false,
 	.bbmcu_nr		= 0,
 	.needed_fw_elms		= 0,
+	.fw_blacklist		= &rtw89_fw_blacklist_default,
 	.fifo_size		= 458752,
 	.small_fifo_size	= false,
 	.dle_scc_rsvd_size	= 0,
drivers/net/wireless/realtek/rtw89/rtw8922a.c +1 -0
index 898a65a721dc..da26ba22e7e6 100644
@@ -2728,6 +2728,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
 	.try_ce_fw		= false,
 	.bbmcu_nr		= 1,
 	.needed_fw_elms		= RTW89_BE_GEN_DEF_NEEDED_FW_ELEMENTS,
+	.fw_blacklist		= &rtw89_fw_blacklist_default,
 	.fifo_size		= 589824,
 	.small_fifo_size	= false,
 	.dle_scc_rsvd_size	= 0,
Signature · 1 line
2.25.1
author maintainer
#2 lore raw

Re: [PATCH 1/5] wifi: rtw89: fw: add blacklist to avoid obsolete secure firmware

Quoted 4 lines · Ping-Ke Shih

To ensure secure chip only runs expected secure firmware, stop using obsolete firmware in blacklist which weakness or flaw was found.

5 patch(es) applied to rtw-next branch of rtw.git, thanks.

f11d042b3a2e wifi: rtw89: fw: add blacklist to avoid obsolete secure firmware 2f9da853f4d8 wifi: rtw89: fw: get sb_sel_ver via get_unaligned_le32() 56e1acaa0f80 wifi: rtw89: fw: propagate error code from rtw89_h2c_tx() dc2fc1a3419e wifi: rtw89: fw: add debug message for unexpected secure firmware e0722103306f wifi: rtw89: fw: safely cast mfw_hdr pointer from firmware->data

---
https://github.com/pkshih/rtw.git

author maintainer
#3 lore raw

PATCH 2/5 wifi: rtw89: fw: get sb_sel_ver via get_unaligned_le32()

In reply to Ping-Ke Shih

The sb_sel_ver is selection version for secure boot recorded in firmware binary data, and its size is 4 and offset is 58 (not natural alignment). Use get_unaligned_le32() to get this value safely. Find this by reviewing.

---
 drivers/net/wireless/realtek/rtw89/fw.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/realtek/rtw89/fw.c +1 -1
index 17f80f1f23df..abbf420463bd 100644
@@ -324,7 +324,7 @@ static int __parse_formatted_mssc(struct rtw89_dev *rtwdev,
 	if (!sec->secure_boot)
 		goto out;
 
-	sb_sel_ver = le32_to_cpu(section_content->sb_sel_ver.v);
+	sb_sel_ver = get_unaligned_le32(&section_content->sb_sel_ver.v);
 	if (sb_sel_ver && sb_sel_ver != sec->sb_sel_mgn)
 		goto ignore;
 
Signature · 1 line
2.25.1
author maintainer
#4 lore raw

PATCH 3/5 wifi: rtw89: fw: propagate error code from rtw89_h2c_tx()

In reply to Ping-Ke Shih

The error code should be propagated to callers during downloading firmware header and body. Remove unnecessary assignment of -1.

---
 drivers/net/wireless/realtek/rtw89/fw.c | 2 --
 1 file changed, 2 deletions(-)
drivers/net/wireless/realtek/rtw89/fw.c +0 -2
index abbf420463bd..d9efe14fc687 100644
@@ -1510,7 +1510,6 @@ static int __rtw89_fw_download_hdr(struct rtw89_dev *rtwdev,
 	ret = rtw89_h2c_tx(rtwdev, skb, false);
 	if (ret) {
 		rtw89_err(rtwdev, "failed to send h2c\n");
-		ret = -1;
 		goto fail;
 	}
 
@@ -1597,7 +1596,6 @@ static int __rtw89_fw_download_main(struct rtw89_dev *rtwdev,
 		ret = rtw89_h2c_tx(rtwdev, skb, true);
 		if (ret) {
 			rtw89_err(rtwdev, "failed to send h2c\n");
-			ret = -1;
 			goto fail;
 		}
 
Signature · 1 line
2.25.1
author maintainer
#5 lore raw

PATCH 4/5 wifi: rtw89: fw: add debug message for unexpected secure firmware

In reply to Ping-Ke Shih

If failed to load a non-secure firmware with a secure chip, it only throws a unclear message:

rtw89_8922ae 0000:03:00.0: parse fw header fail

To address this case simpler, add a message to point out this.

---
 drivers/net/wireless/realtek/rtw89/fw.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/wireless/realtek/rtw89/fw.c +4 -1
index d9efe14fc687..abbf406a202d 100644
@@ -414,8 +414,11 @@ static int __parse_security_section(struct rtw89_dev *rtwdev,
 			*mssc_len += section_info->mssc * FWDL_SECURITY_CHKSUM_LEN;
 
 		if (sec->secure_boot) {
-			if (sec->mss_idx >= section_info->mssc)
+			if (sec->mss_idx >= section_info->mssc) {
+				rtw89_err(rtwdev, "unexpected MSS %d >= %d\n",
+					  sec->mss_idx, section_info->mssc);
 				return -EFAULT;
+			}
 			section_info->key_addr = content + section_info->len +
 						 sec->mss_idx * FWDL_SECURITY_SIGLEN;
 			section_info->key_len = FWDL_SECURITY_SIGLEN;
Signature · 1 line
2.25.1
author maintainer
#6 lore raw

PATCH 5/5 wifi: rtw89: fw: safely cast mfw_hdr pointer from firmware->data

In reply to Ping-Ke Shih

Check size of struct mfw_hdr within firmware->size before type casting to ensure to validly dereference fields from mfm_hdr pointer. Then, check if signature field is equal to RTW89_MFW_SIG to assert current is multi-firmware.

Addresses-Coverity-ID: 1494046 ("Untrusted loop bound")
Addresses-Coverity-ID: 1544385 ("Untrusted array index read")

---
 drivers/net/wireless/realtek/rtw89/fw.c | 30 ++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 6 deletions(-)
drivers/net/wireless/realtek/rtw89/fw.c +24 -6
index abbf406a202d..7a591ddb910f 100644
@@ -542,6 +542,23 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev,
 	}
 }
 
+static
+const struct rtw89_mfw_hdr *rtw89_mfw_get_hdr_ptr(struct rtw89_dev *rtwdev,
+						  const struct firmware *firmware)
+{
+	const struct rtw89_mfw_hdr *mfw_hdr;
+
+	if (sizeof(*mfw_hdr) > firmware->size)
+		return NULL;
+
+	mfw_hdr = (const struct rtw89_mfw_hdr *)firmware->data;
+
+	if (mfw_hdr->sig != RTW89_MFW_SIG)
+		return NULL;
+
+	return mfw_hdr;
+}
+
 static int rtw89_mfw_validate_hdr(struct rtw89_dev *rtwdev,
 				  const struct firmware *firmware,
 				  const struct rtw89_mfw_hdr *mfw_hdr)
@@ -572,14 +589,15 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
 {
 	struct rtw89_fw_info *fw_info = &rtwdev->fw;
 	const struct firmware *firmware = fw_info->req.firmware;
+	const struct rtw89_mfw_info *mfw_info = NULL, *tmp;
+	const struct rtw89_mfw_hdr *mfw_hdr;
 	const u8 *mfw = firmware->data;
 	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) {
+	mfw_hdr = rtw89_mfw_get_hdr_ptr(rtwdev, firmware);
+	if (!mfw_hdr) {
 		rtw89_debug(rtwdev, RTW89_DBG_FW, "use legacy firmware\n");
 		/* legacy firmware support normal type only */
 		if (type != RTW89_FW_NORMAL)
@@ -635,13 +653,13 @@ static u32 rtw89_mfw_get_size(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_fw_info *fw_info = &rtwdev->fw;
 	const struct firmware *firmware = fw_info->req.firmware;
-	const struct rtw89_mfw_hdr *mfw_hdr =
-		(const struct rtw89_mfw_hdr *)firmware->data;
 	const struct rtw89_mfw_info *mfw_info;
+	const struct rtw89_mfw_hdr *mfw_hdr;
 	u32 size;
 	int ret;
 
-	if (mfw_hdr->sig != RTW89_MFW_SIG) {
+	mfw_hdr = rtw89_mfw_get_hdr_ptr(rtwdev, firmware);
+	if (!mfw_hdr) {
 		rtw89_warn(rtwdev, "not mfw format\n");
 		return 0;
 	}
Signature · 1 line
2.25.1