aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMat Martineau <mathewm@codeaurora.org>2012-05-02 12:41:59 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-05-16 15:13:37 -0400
commit35c84d76ee52f49fe2635d8cd686b5b658e8d892 (patch)
tree79704b24e59038ddd3730afefe15791890802e5b /net
parent85d59726c5c66016a507f1f4a60db8e374dd284d (diff)
Bluetooth: Fix a redundant and problematic incoming MTU check
The L2CAP MTU for incoming data is verified differently depending on the L2CAP mode, so the check is best performed in a mode-specific context. Checking the incoming MTU before HCI fragment reassembly is a layer violation and assumes all bytes after the standard L2CAP header are L2CAP data. This approach causes issues with unsegmented ERTM or streaming mode frames, where there are additional enhanced or extended headers before the data payload and possible FCS bytes after the data payload. A valid frame could be as many as 10 bytes larger than the MTU. Removing this code is the best fix, because the MTU is checked later on for all L2CAP data frames (connectionless, basic, ERTM, and streaming). This also gets rid of outdated locking (socket instead of l2cap_chan) and an extra lookup of the channel ID. Signed-off-by: Mat Martineau <mathewm@codeaurora.org> Reviewed-by: Ulisses Furquim <ulisses@profusion.mobi> Signed-off-by: Gustavo Padovan <gustavo@padovan.org>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/l2cap_core.c20
1 files changed, 0 insertions, 20 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 1e12d6d58e84..aea54f55c41d 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5000,8 +5000,6 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
5000 5000
5001 if (!(flags & ACL_CONT)) { 5001 if (!(flags & ACL_CONT)) {
5002 struct l2cap_hdr *hdr; 5002 struct l2cap_hdr *hdr;
5003 struct l2cap_chan *chan;
5004 u16 cid;
5005 int len; 5003 int len;
5006 5004
5007 if (conn->rx_len) { 5005 if (conn->rx_len) {
@@ -5021,7 +5019,6 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
5021 5019
5022 hdr = (struct l2cap_hdr *) skb->data; 5020 hdr = (struct l2cap_hdr *) skb->data;
5023 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; 5021 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
5024 cid = __le16_to_cpu(hdr->cid);
5025 5022
5026 if (len == skb->len) { 5023 if (len == skb->len) {
5027 /* Complete frame received */ 5024 /* Complete frame received */
@@ -5038,23 +5035,6 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
5038 goto drop; 5035 goto drop;
5039 } 5036 }
5040 5037
5041 chan = l2cap_get_chan_by_scid(conn, cid);
5042
5043 if (chan && chan->sk) {
5044 struct sock *sk = chan->sk;
5045 lock_sock(sk);
5046
5047 if (chan->imtu < len - L2CAP_HDR_SIZE) {
5048 BT_ERR("Frame exceeding recv MTU (len %d, "
5049 "MTU %d)", len,
5050 chan->imtu);
5051 release_sock(sk);
5052 l2cap_conn_unreliable(conn, ECOMM);
5053 goto drop;
5054 }
5055 release_sock(sk);
5056 }
5057
5058 /* Allocate skb for the complete frame (with header) */ 5038 /* Allocate skb for the complete frame (with header) */
5059 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); 5039 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
5060 if (!conn->rx_skb) 5040 if (!conn->rx_skb)