[patch 17/50] Bluetooth: Add packet size checks for CAPI messages (CVE-2006-6106)
-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)
-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