Commit 1dca7c28 authored by Marcel Holtmann's avatar Marcel Holtmann Committed by Chris Wright

[PATCH] Bluetooth: Add packet size checks for CAPI messages (CVE-2006-6106)

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: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarChris Wright <chrisw@sous-sol.org>
parent 8dc0b54b
...@@ -196,6 +196,9 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s ...@@ -196,6 +196,9 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
switch (CAPIMSG_SUBCOMMAND(skb->data)) { switch (CAPIMSG_SUBCOMMAND(skb->data)) {
case CAPI_CONF: case CAPI_CONF:
if (skb->len < CAPI_MSG_BASELEN + 10)
break;
func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5); func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8); info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
...@@ -226,6 +229,9 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s ...@@ -226,6 +229,9 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break; break;
case CAPI_FUNCTION_GET_PROFILE: 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); controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
msgnum = CAPIMSG_MSGID(skb->data); msgnum = CAPIMSG_MSGID(skb->data);
...@@ -246,17 +252,26 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s ...@@ -246,17 +252,26 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break; break;
case CAPI_FUNCTION_GET_MANUFACTURER: case CAPI_FUNCTION_GET_MANUFACTURER:
if (skb->len < CAPI_MSG_BASELEN + 15)
break;
controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10); controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
if (!info && ctrl) { if (!info && ctrl) {
strncpy(ctrl->manu, int len = min_t(uint, CAPI_MANUFACTURER_LEN,
skb->data + CAPI_MSG_BASELEN + 15,
skb->data[CAPI_MSG_BASELEN + 14]); skb->data[CAPI_MSG_BASELEN + 14]);
memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
strncpy(ctrl->manu,
skb->data + CAPI_MSG_BASELEN + 15, len);
} }
break; break;
case CAPI_FUNCTION_GET_VERSION: case CAPI_FUNCTION_GET_VERSION:
if (skb->len < CAPI_MSG_BASELEN + 32)
break;
controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12); controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
if (!info && ctrl) { if (!info && ctrl) {
...@@ -269,13 +284,18 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s ...@@ -269,13 +284,18 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break; break;
case CAPI_FUNCTION_GET_SERIAL_NUMBER: case CAPI_FUNCTION_GET_SERIAL_NUMBER:
if (skb->len < CAPI_MSG_BASELEN + 17)
break;
controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12); controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
if (!info && ctrl) { if (!info && ctrl) {
int len = min_t(uint, CAPI_SERIAL_LEN,
skb->data[CAPI_MSG_BASELEN + 16]);
memset(ctrl->serial, 0, CAPI_SERIAL_LEN); memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
strncpy(ctrl->serial, strncpy(ctrl->serial,
skb->data + CAPI_MSG_BASELEN + 17, skb->data + CAPI_MSG_BASELEN + 17, len);
skb->data[CAPI_MSG_BASELEN + 16]);
} }
break; break;
...@@ -284,14 +304,18 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s ...@@ -284,14 +304,18 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break; break;
case CAPI_IND: case CAPI_IND:
if (skb->len < CAPI_MSG_BASELEN + 6)
break;
func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3); func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
if (func == CAPI_FUNCTION_LOOPBACK) { 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); appl = CAPIMSG_APPID(skb->data);
msgnum = CAPIMSG_MSGID(skb->data); msgnum = CAPIMSG_MSGID(skb->data);
cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func, cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
skb->data + CAPI_MSG_BASELEN + 6, skb->data + CAPI_MSG_BASELEN + 6, len);
skb->data[CAPI_MSG_BASELEN + 5]);
} }
break; break;
...@@ -309,6 +333,9 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb) ...@@ -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); 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) { if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
cmtp_recv_interopmsg(session, skb); cmtp_recv_interopmsg(session, skb);
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment