Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=f4777569204cb59f2f04fbe9ef4e9a6918209104
Commit:     f4777569204cb59f2f04fbe9ef4e9a6918209104
Parent:     d2e7543c41755f4ec75385536b109d5f084fe734
Author:     Marcel Holtmann <[EMAIL PROTECTED]>
AuthorDate: Mon Jan 8 02:16:23 2007 +0100
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Tue Jan 9 00:29:53 2007 -0800

    [Bluetooth] Add packet size checks for CAPI messages
    
    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]>
---
 net/bluetooth/cmtp/capi.c |   39 +++++++++++++++++++++++++++++++++------
 1 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c
index be04e9f..ab166b4 100644
--- a/net/bluetooth/cmtp/capi.c
+++ b/net/bluetooth/cmtp/capi.c
@@ -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);
 
@@ -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);
 
@@ -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) {
@@ -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;
@@ -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;
@@ -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;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to