Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Bluetooth: L2CAP: Fix calling sk_filter on non-socket based channel

Only sockets will have the chan->data set to an actual sk, channels
like A2MP would have its own data which would likely cause a crash when
calling sk_filter, in order to fix this a new callback has been
introduced so channels can implement their own filtering if necessary.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

authored by

Luiz Augusto von Dentz and committed by
Marcel Holtmann
f1942564 eddb7732

+20 -3
+2
include/net/bluetooth/l2cap.h
··· 665 665 struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, 666 666 unsigned long hdr_len, 667 667 unsigned long len, int nb); 668 + int (*filter) (struct l2cap_chan * chan, 669 + struct sk_buff *skb); 668 670 }; 669 671 670 672 struct l2cap_conn {
+4 -3
net/bluetooth/l2cap_core.c
··· 7301 7301 goto drop; 7302 7302 } 7303 7303 7304 - if ((chan->mode == L2CAP_MODE_ERTM || 7305 - chan->mode == L2CAP_MODE_STREAMING) && sk_filter(chan->data, skb)) 7306 - goto drop; 7304 + if (chan->ops->filter) { 7305 + if (chan->ops->filter(chan, skb)) 7306 + goto drop; 7307 + } 7307 7308 7308 7309 if (!control->sframe) { 7309 7310 int err;
+14
net/bluetooth/l2cap_sock.c
··· 1664 1664 sk->sk_state_change(sk); 1665 1665 } 1666 1666 1667 + static int l2cap_sock_filter(struct l2cap_chan *chan, struct sk_buff *skb) 1668 + { 1669 + struct sock *sk = chan->data; 1670 + 1671 + switch (chan->mode) { 1672 + case L2CAP_MODE_ERTM: 1673 + case L2CAP_MODE_STREAMING: 1674 + return sk_filter(sk, skb); 1675 + } 1676 + 1677 + return 0; 1678 + } 1679 + 1667 1680 static const struct l2cap_ops l2cap_chan_ops = { 1668 1681 .name = "L2CAP Socket Interface", 1669 1682 .new_connection = l2cap_sock_new_connection_cb, ··· 1692 1679 .get_sndtimeo = l2cap_sock_get_sndtimeo_cb, 1693 1680 .get_peer_pid = l2cap_sock_get_peer_pid_cb, 1694 1681 .alloc_skb = l2cap_sock_alloc_skb_cb, 1682 + .filter = l2cap_sock_filter, 1695 1683 }; 1696 1684 1697 1685 static void l2cap_sock_destruct(struct sock *sk)