Bluetooth: bnep: fix out-of-bounds reads on short RX/TX frames and control fallthrough

Fix multiple out-of-bounds reads in Bluetooth BNEP frame processing:

1. In bnep_rx_frame() and bnep_ctrl_frame() (net/bluetooth/bnep/core.c),
   use pskb_may_pull() to verify the BNEP header, control type byte,
   filter count, and extension headers exist before reading them, and
   return 0 after handling BNEP_CONTROL instead of falling through to
   Ethernet frame submission when no extension headers follow.
2. In bnep_net_xmit() (net/bluetooth/bnep/netdev.c), verify skb->len >=
   ETH_HLEN with pskb_may_pull() before reading the 14-byte Ethernet
   header to prevent an out-of-bounds heap read and infoleak on short
   AF_PACKET TX frames.

Fixes: 1da177e4c3 ("Linux-2.6.12-rc2")
Assisted-by: LLM
Signed-off-by: Hui Peng <benquike@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Hui Peng 2026-09-19 22:17:38 +00:00 committed by Luiz Augusto von Dentz
parent b5dbb41b21
commit f0ca020cbb
2 changed files with 23 additions and 2 deletions

View File

@ -270,9 +270,14 @@ static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
BT_DBG("type 0x%x len %u", h->type, h->len);
if (skb->len < h->len) {
err = -EILSEQ;
break;
}
switch (h->type & BNEP_TYPE_MASK) {
case BNEP_EXT_CONTROL:
bnep_rx_control(s, skb->data, skb->len);
bnep_rx_control(s, skb->data, h->len);
break;
default:
@ -373,6 +378,11 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
goto badframe;
}
if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
kfree_skb(skb);
return 0;
}
/* Strip 802.1p header */
if (ntohs(s->eh.h_proto) == ETH_P_8021Q) {
if (!skb_pull(skb, 4))
@ -451,6 +461,11 @@ static int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb)
goto send;
}
if (skb->len < ETH_HLEN) {
kfree_skb(skb);
return 0;
}
iv[il++] = (struct kvec) { &type, 1 };
len++;

View File

@ -166,6 +166,12 @@ static netdev_tx_t bnep_net_xmit(struct sk_buff *skb,
BT_DBG("skb %p, dev %p", skb, dev);
if (!pskb_may_pull(skb, ETH_HLEN)) {
dev->stats.tx_dropped++;
kfree_skb(skb);
return NETDEV_TX_OK;
}
#ifdef CONFIG_BT_BNEP_MC_FILTER
if (bnep_net_mc_filter(skb, s)) {
kfree_skb(skb);
@ -218,7 +224,7 @@ void bnep_net_setup(struct net_device *dev)
dev->addr_len = ETH_ALEN;
ether_setup(dev);
dev->min_mtu = 0;
dev->min_mtu = ETH_MIN_MTU;
dev->max_mtu = ETH_MAX_MTU;
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
dev->netdev_ops = &bnep_netdev_ops;