Skip to contentSkip to conversation

staging: rtl8723bs: validate monitor transmit frame lengths

PATCH Superseded Mariano Baragiola 3 participants 7 messages Jul 15 – Jul 27 Staging

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 staging: rtl8723bs: validate monitor transmit frame lengths

rtw_cfg80211_monitor_if_xmit_entry() removes the radiotap header and then reads the 802.11 frame control field without checking that a base 802.11 header remains.

The data path also pulls the calculated 802.11, QoS and SNAP header span before confirming that the skb contains it. A truncated frame can therefore cause out-of-bounds reads or leave insufficient data for the Ethernet address writes.

Reject frames that do not contain the base 802.11 header and data frames that do not contain their complete calculated header span.

---
 drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 4 ++++
 1 file changed, 4 insertions(+)
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +4 -0
index 6a97afd89dc7..bed8192ab44f 100644
@@ -2033,6 +2033,8 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc
 
 	/* Skip the ratio tap header */
 	skb_pull(skb, rtap_len);
+	if (unlikely(skb->len < dot11_hdr_len))
+		goto fail;
 
 	dot11_hdr = (struct ieee80211_hdr *)skb->data;
 	frame_control = le16_to_cpu(dot11_hdr->frame_control);
@@ -2045,6 +2047,8 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc
 			qos_len = 2;
 		if ((frame_control & 0x0300) == 0x0300)
 			dot11_hdr_len += 6;
+		if (unlikely(skb->len < dot11_hdr_len + qos_len + snap_len))
+			goto fail;
 
 		memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
 		memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
Signature · 1 line
2.55.0
#1 lore raw
Quoted 9 lines · Mariano Baragiola

rtw_cfg80211_monitor_if_xmit_entry() removes the radiotap header and then reads the 802.11 frame control field without checking that a base 802.11 header remains.

The data path also pulls the calculated 802.11, QoS and SNAP header span before confirming that the skb contains it. A truncated frame can therefore cause out-of-bounds reads or leave insufficient data for the Ethernet address writes.

Quoted 5 lines

Reject frames that do not contain the base 802.11 header and data frames that do not contain their complete calculated header span.

---

Looks reasonable. Please add a Fixes tag.

regards,
dan carpenter

#2 lore raw

PATCH v2 1/1 staging: rtl8723bs: validate monitor transmit frame lengths

In reply to Mariano Baragiola

rtw_cfg80211_monitor_if_xmit_entry() removes the radiotap header and then reads the 802.11 frame control field without checking that a base 802.11 header remains.

The data path also pulls the calculated 802.11, QoS and SNAP header span before confirming that the skb contains it. A truncated frame can therefore cause out-of-bounds reads or leave insufficient data for the Ethernet address writes.

Reject frames that do not contain the base 802.11 header and data frames that do not contain their complete calculated header span.

Fixes 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver")
---
 drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 4 ++++
 1 file changed, 4 insertions(+)
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +4 -0
index 6a97afd89dc7..bed8192ab44f 100644
@@ -2033,6 +2033,8 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc
 
 	/* Skip the ratio tap header */
 	skb_pull(skb, rtap_len);
+	if (unlikely(skb->len < dot11_hdr_len))
+		goto fail;
 
 	dot11_hdr = (struct ieee80211_hdr *)skb->data;
 	frame_control = le16_to_cpu(dot11_hdr->frame_control);
@@ -2045,6 +2047,8 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc
 			qos_len = 2;
 		if ((frame_control & 0x0300) == 0x0300)
 			dot11_hdr_len += 6;
+		if (unlikely(skb->len < dot11_hdr_len + qos_len + snap_len))
+			goto fail;
 
 		memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
 		memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
Signature · 1 line
2.55.0
#3 lore raw
Quoted 44 lines · Mariano Baragiola

rtw_cfg80211_monitor_if_xmit_entry() removes the radiotap header and then reads the 802.11 frame control field without checking that a base 802.11 header remains.

The data path also pulls the calculated 802.11, QoS and SNAP header span before confirming that the skb contains it. A truncated frame can therefore cause out-of-bounds reads or leave insufficient data for the Ethernet address writes.

Reject frames that do not contain the base 802.11 header and data frames that do not contain their complete calculated header span.

Fixes 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver")
---
 drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 4 ++++
 1 file changed, 4 insertions(+)
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +4 -0
index 6a97afd89dc7..bed8192ab44f 100644
@@ -2033,6 +2033,8 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc
 
 	/* Skip the ratio tap header */
 	skb_pull(skb, rtap_len);
+	if (unlikely(skb->len < dot11_hdr_len))
+		goto fail;
 
 	dot11_hdr = (struct ieee80211_hdr *)skb->data;
 	frame_control = le16_to_cpu(dot11_hdr->frame_control);
@@ -2045,6 +2047,8 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc
 			qos_len = 2;
 		if ((frame_control & 0x0300) == 0x0300)
 			dot11_hdr_len += 6;
+		if (unlikely(skb->len < dot11_hdr_len + qos_len + snap_len))
+			goto fail;
 
 		memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
 		memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
Signature · 1 line
2.55.0

Hi,

This is the friendly patch-bot of Greg Kroah-Hartman. You have sent him a patch that has triggered this response. He used to manually respond to these common problems, but in order to save his sanity (he kept writing the same thing over and over, yet to different people), I was created. Hopefully you will not take offence and will fix the problem in your patch and resubmit it so that it can be accepted into the Linux kernel tree.

You are receiving this message because of the following common error(s) as indicated below:

- This looks like a new version of a previously submitted patch, but you did not list below the --- line any changes from the previous version. Please read the section entitled "The canonical patch format" in the kernel file, Documentation/process/submitting-patches.rst for what needs to be done here to properly describe this.

If you wish to discuss this problem further, or you have questions about how to resolve this issue, please feel free to respond to this email and Greg will reply once he has dug out from the pending patches received from other developers.

thanks,

greg k-h's patch email bot

#4 lore raw

PATCH v3 1/1 staging: rtl8723bs: validate monitor transmit frame lengths

In reply to Mariano Baragiola

rtw_cfg80211_monitor_if_xmit_entry() removes the radiotap header and then reads the 802.11 frame control field without checking that a base 802.11 header remains.

The data path also pulls the calculated 802.11, QoS and SNAP header span before confirming that the skb contains it. A truncated frame can therefore cause out-of-bounds reads or leave insufficient data for the Ethernet address writes.

Reject frames that do not contain the base 802.11 header and data frames that do not contain their complete calculated header span.

Fixes 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver")

---
Changes in v3:
- Add the below-separator changelog as requested by Greg K-H patch-bot.

Changes in v2:
- Add the Fixes tag as requested by Dan Carpenter.

 drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 4 ++++
 1 file changed, 4 insertions(+)
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +4 -0
index 6a97afd89dc7..bed8192ab44f 100644
@@ -2033,6 +2033,8 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc
 
 	/* Skip the ratio tap header */
 	skb_pull(skb, rtap_len);
+	if (unlikely(skb->len < dot11_hdr_len))
+		goto fail;
 
 	dot11_hdr = (struct ieee80211_hdr *)skb->data;
 	frame_control = le16_to_cpu(dot11_hdr->frame_control);
@@ -2045,6 +2047,8 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc
 			qos_len = 2;
 		if ((frame_control & 0x0300) == 0x0300)
 			dot11_hdr_len += 6;
+		if (unlikely(skb->len < dot11_hdr_len + qos_len + snap_len))
+			goto fail;
 
 		memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
 		memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
Signature · 1 line
2.55.0
#5 lore raw
Quoted 29 lines · Mariano Baragiola

rtw_cfg80211_monitor_if_xmit_entry() removes the radiotap header and then reads the 802.11 frame control field without checking that a base 802.11 header remains.

The data path also pulls the calculated 802.11, QoS and SNAP header span before confirming that the skb contains it. A truncated frame can therefore cause out-of-bounds reads or leave insufficient data for the Ethernet address writes.

Reject frames that do not contain the base 802.11 header and data frames that do not contain their complete calculated header span.

Fixes 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver")

---
Changes in v3:
- Add the below-separator changelog as requested by Greg K-H patch-bot.

Changes in v2:
- Add the Fixes tag as requested by Dan Carpenter.

 drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 4 ++++
 1 file changed, 4 insertions(+)
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +0 -0
index 6a97afd89dc7..bed8192ab44f 100644

drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc · line 2037

Quoted 5 lines
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +2 -0
@@ -2033,6 +2033,8 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc
 
 	/* Skip the ratio tap header */
 	skb_pull(skb, rtap_len);
+	if (unlikely(skb->len < dot11_hdr_len))
+		goto fail;

Only ever use likely/unlikely if you can measure the difference of it not being there. Otherwise the cpu will almost always get it right instead.

Is that the case here?

drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc · line 2051

Quoted 9 lines
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +2 -0
 	dot11_hdr = (struct ieee80211_hdr *)skb->data;
 	frame_control = le16_to_cpu(dot11_hdr->frame_control);
@@ -2045,6 +2047,8 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc
 			qos_len = 2;
 		if ((frame_control & 0x0300) == 0x0300)
 			dot11_hdr_len += 6;
+		if (unlikely(skb->len < dot11_hdr_len + qos_len + snap_len))
+			goto fail;

Same here, is this actually measurable?

thanks,

greg k-h

#6 lore raw

PATCH v4 1/1 staging: rtl8723bs: validate monitor transmit frame lengths

In reply to Mariano Baragiola

rtw_cfg80211_monitor_if_xmit_entry() removes the radiotap header and then reads the 802.11 frame control field without checking that a base 802.11 header remains.

The data path also pulls the calculated 802.11, QoS and SNAP header span before confirming that the skb contains it. A truncated frame can therefore cause out-of-bounds reads or leave insufficient data for the Ethernet address writes.

Reject frames that do not contain the base 802.11 header and data frames that do not contain their complete calculated header span.

Fixes 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver")

---
Changes in v4:
- Remove unlikely() from both new length checks in response to Greg Kroah-Hartman's review; no measurements exist to justify the annotations.

Changes in v3:
- Add the revision history below the separator.

Changes in v2:
- Add the Fixes tag as requested by Dan Carpenter.

 drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 4 ++++
 1 file changed, 4 insertions(+)
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +4 -0
index 6a97afd89dc7..6404044d2185 100644
@@ -2033,6 +2033,8 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc
 
 	/* Skip the ratio tap header */
 	skb_pull(skb, rtap_len);
+	if (skb->len < dot11_hdr_len)
+		goto fail;
 
 	dot11_hdr = (struct ieee80211_hdr *)skb->data;
 	frame_control = le16_to_cpu(dot11_hdr->frame_control);
@@ -2045,6 +2047,8 @@ static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struc
 			qos_len = 2;
 		if ((frame_control & 0x0300) == 0x0300)
 			dot11_hdr_len += 6;
+		if (skb->len < dot11_hdr_len + qos_len + snap_len)
+			goto fail;
 
 		memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
 		memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
Signature · 1 line
2.55.0