Skip to content

Commit

Permalink
[Bluetooth] Add packet size checks for CAPI messages
Browse files Browse the repository at this point in the history
With malformed packets it might be possible to overwrite internal
CMTP and CAPI data structures. This patch adds additional length
checks to prevent these kinds of remote attacks.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
  • Loading branch information
Marcel Holtmann authored and David S. Miller committed Jan 9, 2007
1 parent d2e7543 commit f477756
Showing 1 changed file with 33 additions and 6 deletions.
39 changes: 33 additions & 6 deletions net/bluetooth/cmtp/capi.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s

switch (CAPIMSG_SUBCOMMAND(skb->data)) {
case CAPI_CONF:
if (skb->len < CAPI_MSG_BASELEN + 10)
break;

func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);

Expand Down Expand Up @@ -226,6 +229,9 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break;

case CAPI_FUNCTION_GET_PROFILE:
if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile))
break;

controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
msgnum = CAPIMSG_MSGID(skb->data);

Expand All @@ -246,17 +252,26 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break;

case CAPI_FUNCTION_GET_MANUFACTURER:
if (skb->len < CAPI_MSG_BASELEN + 15)
break;

controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);

if (!info && ctrl) {
int len = min_t(uint, CAPI_MANUFACTURER_LEN,
skb->data[CAPI_MSG_BASELEN + 14]);

memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
strncpy(ctrl->manu,
skb->data + CAPI_MSG_BASELEN + 15,
skb->data[CAPI_MSG_BASELEN + 14]);
skb->data + CAPI_MSG_BASELEN + 15, len);
}

break;

case CAPI_FUNCTION_GET_VERSION:
if (skb->len < CAPI_MSG_BASELEN + 32)
break;

controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);

if (!info && ctrl) {
Expand All @@ -269,13 +284,18 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break;

case CAPI_FUNCTION_GET_SERIAL_NUMBER:
if (skb->len < CAPI_MSG_BASELEN + 17)
break;

controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);

if (!info && ctrl) {
int len = min_t(uint, CAPI_SERIAL_LEN,
skb->data[CAPI_MSG_BASELEN + 16]);

memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
strncpy(ctrl->serial,
skb->data + CAPI_MSG_BASELEN + 17,
skb->data[CAPI_MSG_BASELEN + 16]);
skb->data + CAPI_MSG_BASELEN + 17, len);
}

break;
Expand All @@ -284,14 +304,18 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break;

case CAPI_IND:
if (skb->len < CAPI_MSG_BASELEN + 6)
break;

func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);

if (func == CAPI_FUNCTION_LOOPBACK) {
int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
skb->data[CAPI_MSG_BASELEN + 5]);
appl = CAPIMSG_APPID(skb->data);
msgnum = CAPIMSG_MSGID(skb->data);
cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
skb->data + CAPI_MSG_BASELEN + 6,
skb->data[CAPI_MSG_BASELEN + 5]);
skb->data + CAPI_MSG_BASELEN + 6, len);
}

break;
Expand All @@ -309,6 +333,9 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)

BT_DBG("session %p skb %p len %d", session, skb, skb->len);

if (skb->len < CAPI_MSG_BASELEN)
return;

if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
cmtp_recv_interopmsg(session, skb);
return;
Expand Down

0 comments on commit f477756

Please sign in to comment.