Re: [syzbot] [wireless?] KMSAN: uninit-value in ath9k_hw_init

Fedor Pchelkin
2023-03-13T14:36:33Z

#syz test: https://github.com/google/kmsan.git master

--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -243,7 +243,7 @@ static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)
(u8 *) &reg, sizeof(reg),
(u8 *) &val, sizeof(val),
100);
- if (unlikely(r)) {
+ if (r) {
ath_dbg(common, WMI, "REGISTER READ FAILED: (0x%04x, %d)\n",
reg_offset, r);
return -1;
@@ -259,7 +259,7 @@ static void ath9k_multi_regread(void *hw_priv, u32 *addr,
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
__be32 tmpaddr[8];
- __be32 tmpval[8];
+ __be32 tmpval[8] = {0};
int i, ret;

for (i = 0; i < count; i++) {
@@ -270,7 +270,7 @@ static void ath9k_multi_regread(void *hw_priv, u32 *addr,
(u8 *)tmpaddr , sizeof(u32) * count,
(u8 *)tmpval, sizeof(u32) * count,
100);
- if (unlikely(ret)) {
+ if (ret) {
ath_dbg(common, WMI,
"Multiple REGISTER READ FAILED (count: %d)\n", count);
}
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -204,6 +204,9 @@ static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb)
{
skb_pull(skb, sizeof(struct wmi_cmd_hdr));

+ if (unlikely(skb->len < wmi->cmd_rsp_len))
+ return;
+
if (wmi->cmd_rsp_buf != NULL && wmi->cmd_rsp_len != 0)
memcpy(wmi->cmd_rsp_buf, skb->data, wmi->cmd_rsp_len);

@@ -221,6 +224,9 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
if (unlikely(wmi->stopped))
goto free_skb;

+ if (unlikely(skb->len < sizeof(struct wmi_cmd_hdr)))
+ goto free_skb;
+
hdr = (struct wmi_cmd_hdr *) skb->data;
cmd_id = be16_to_cpu(hdr->command_id);

@@ -308,8 +314,11 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
unsigned long time_left;
int ret = 0;

- if (ah->ah_flags & AH_UNPLUGGED)
- return 0;
+ if (ah->ah_flags & AH_UNPLUGGED) {
+ ath_dbg(common, WMI, "Device unplugged for WMI command: %s\n",
+ wmi_cmd_to_name(cmd_id));
+ return -ENODEV;
+ }

skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC);
if (!skb)
--