|
@@ -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;
|