summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDudu Lu <phx0fer@gmail.com>2026-04-15 12:39:53 +0300
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2026-05-06 23:19:09 +0300
commit72b8deccff17a7644e0367e1aaf1a36cfb014324 (patch)
treec916dcd5d16fe2ac26989d260152bee0d92da32a
parent5ddb8014261137cadaf83ab5617a588d80a22586 (diff)
downloadlinux-72b8deccff17a7644e0367e1aaf1a36cfb014324.tar.xz
Bluetooth: bnep: fix incorrect length parsing in bnep_rx_frame() extension handling
In bnep_rx_frame(), the BNEP_FILTER_NET_TYPE_SET and BNEP_FILTER_MULTI_ADDR_SET extension header parsing has two bugs: 1) The 2-byte length field is read with *(u16 *)(skb->data + 1), which performs a native-endian read. The BNEP protocol specifies this field in big-endian (network byte order), and the same file correctly uses get_unaligned_be16() for the identical fields in bnep_ctrl_set_netfilter() and bnep_ctrl_set_mcfilter(). 2) The length is multiplied by 2, but unlike BNEP_SETUP_CONN_REQ where the length byte counts UUID pairs (requiring * 2 for two UUIDs per entry), the filter extension length field already represents the total data size in bytes. This is confirmed by bnep_ctrl_set_netfilter() which reads the same field as a byte count and divides by 4 to get the number of filter entries. The bogus * 2 means skb_pull advances twice as far as it should, either dropping valid data from the next header or causing the pull to fail entirely when the doubled length exceeds the remaining skb. Fix by splitting the pull into two steps: first use skb_pull_data() to safely pull and validate the 3-byte fixed header (ctrl type + length), then pull the variable-length data using the properly decoded length. Fixes: bf8b9a9cb77b ("Bluetooth: bnep: Add support to extended headers of control frames") Signed-off-by: Dudu Lu <phx0fer@gmail.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
-rw-r--r--net/bluetooth/bnep/core.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index d44987d4515c..853c8d7644b5 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -330,11 +330,18 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
goto badframe;
break;
case BNEP_FILTER_MULTI_ADDR_SET:
- case BNEP_FILTER_NET_TYPE_SET:
- /* Pull: ctrl type (1 b), len (2 b), data (len bytes) */
- if (!skb_pull(skb, 3 + *(u16 *)(skb->data + 1) * 2))
+ case BNEP_FILTER_NET_TYPE_SET: {
+ u8 *hdr;
+
+ /* Pull ctrl type (1 b) + len (2 b) */
+ hdr = skb_pull_data(skb, 3);
+ if (!hdr)
+ goto badframe;
+ /* Pull data (len bytes); length is big-endian */
+ if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
goto badframe;
break;
+ }
default:
kfree_skb(skb);
return 0;