[patch 17/50] Bluetooth: Add packet size checks for CAPI messages (CVE-2006-6106)

2007-01-05 Thread Chris Wright
-stable review patch.  If anyone has any objections, please let us know.
--

From: Marcel Holtmann <[EMAIL PROTECTED]>

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 <[EMAIL PROTECTED]>
Signed-off-by: Chris Wright <[EMAIL PROTECTED]>
---

 net/bluetooth/cmtp/capi.c |   39 +--
 1 file changed, 33 insertions(+), 6 deletions(-)

--- linux-2.6.19.1.orig/net/bluetooth/cmtp/capi.c
+++ linux-2.6.19.1/net/bluetooth/cmtp/capi.c
@@ -196,6 +196,9 @@ static void cmtp_recv_interopmsg(struct 
 
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);
 
@@ -226,6 +229,9 @@ static void cmtp_recv_interopmsg(struct 
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);
 
@@ -246,17 +252,26 @@ static void cmtp_recv_interopmsg(struct 
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) {
@@ -269,13 +284,18 @@ static void cmtp_recv_interopmsg(struct 
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;
@@ -284,14 +304,18 @@ static void cmtp_recv_interopmsg(struct 
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;
@@ -309,6 +333,9 @@ void cmtp_recv_capimsg(struct cmtp_sessi
 
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;

--
-
To unsubscribe from this list: 

[patch 17/50] Bluetooth: Add packet size checks for CAPI messages (CVE-2006-6106)

2007-01-05 Thread Chris Wright
-stable review patch.  If anyone has any objections, please let us know.
--

From: Marcel Holtmann [EMAIL PROTECTED]

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 [EMAIL PROTECTED]
Signed-off-by: Chris Wright [EMAIL PROTECTED]
---

 net/bluetooth/cmtp/capi.c |   39 +--
 1 file changed, 33 insertions(+), 6 deletions(-)

--- linux-2.6.19.1.orig/net/bluetooth/cmtp/capi.c
+++ linux-2.6.19.1/net/bluetooth/cmtp/capi.c
@@ -196,6 +196,9 @@ static void cmtp_recv_interopmsg(struct 
 
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);
 
@@ -226,6 +229,9 @@ static void cmtp_recv_interopmsg(struct 
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);
 
@@ -246,17 +252,26 @@ static void cmtp_recv_interopmsg(struct 
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) {
@@ -269,13 +284,18 @@ static void cmtp_recv_interopmsg(struct 
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;
@@ -284,14 +304,18 @@ static void cmtp_recv_interopmsg(struct 
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;
@@ -309,6 +333,9 @@ void cmtp_recv_capimsg(struct cmtp_sessi
 
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;

--
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a