diff options
Diffstat (limited to 'net/bluetooth/cmtp/capi.c')
| -rw-r--r-- | 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 be04e9fb11f6..ab166b48ce8d 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 | |||
| 196 | 196 | ||
| 197 | switch (CAPIMSG_SUBCOMMAND(skb->data)) { | 197 | switch (CAPIMSG_SUBCOMMAND(skb->data)) { |
| 198 | case CAPI_CONF: | 198 | case CAPI_CONF: |
| 199 | if (skb->len < CAPI_MSG_BASELEN + 10) | ||
| 200 | break; | ||
| 201 | |||
| 199 | func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5); | 202 | func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5); |
| 200 | info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8); | 203 | info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8); |
| 201 | 204 | ||
| @@ -226,6 +229,9 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s | |||
| 226 | break; | 229 | break; |
| 227 | 230 | ||
| 228 | case CAPI_FUNCTION_GET_PROFILE: | 231 | case CAPI_FUNCTION_GET_PROFILE: |
| 232 | if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile)) | ||
| 233 | break; | ||
| 234 | |||
| 229 | controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11); | 235 | controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11); |
| 230 | msgnum = CAPIMSG_MSGID(skb->data); | 236 | msgnum = CAPIMSG_MSGID(skb->data); |
| 231 | 237 | ||
| @@ -246,17 +252,26 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s | |||
| 246 | break; | 252 | break; |
| 247 | 253 | ||
| 248 | case CAPI_FUNCTION_GET_MANUFACTURER: | 254 | case CAPI_FUNCTION_GET_MANUFACTURER: |
| 255 | if (skb->len < CAPI_MSG_BASELEN + 15) | ||
| 256 | break; | ||
| 257 | |||
| 249 | controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10); | 258 | controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10); |
| 250 | 259 | ||
| 251 | if (!info && ctrl) { | 260 | if (!info && ctrl) { |
| 261 | int len = min_t(uint, CAPI_MANUFACTURER_LEN, | ||
| 262 | skb->data[CAPI_MSG_BASELEN + 14]); | ||
| 263 | |||
| 264 | memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN); | ||
| 252 | strncpy(ctrl->manu, | 265 | strncpy(ctrl->manu, |
| 253 | skb->data + CAPI_MSG_BASELEN + 15, | 266 | skb->data + CAPI_MSG_BASELEN + 15, len); |
| 254 | skb->data[CAPI_MSG_BASELEN + 14]); | ||
| 255 | } | 267 | } |
| 256 | 268 | ||
| 257 | break; | 269 | break; |
| 258 | 270 | ||
| 259 | case CAPI_FUNCTION_GET_VERSION: | 271 | case CAPI_FUNCTION_GET_VERSION: |
| 272 | if (skb->len < CAPI_MSG_BASELEN + 32) | ||
| 273 | break; | ||
| 274 | |||
| 260 | controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12); | 275 | controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12); |
| 261 | 276 | ||
| 262 | if (!info && ctrl) { | 277 | if (!info && ctrl) { |
| @@ -269,13 +284,18 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s | |||
| 269 | break; | 284 | break; |
| 270 | 285 | ||
| 271 | case CAPI_FUNCTION_GET_SERIAL_NUMBER: | 286 | case CAPI_FUNCTION_GET_SERIAL_NUMBER: |
| 287 | if (skb->len < CAPI_MSG_BASELEN + 17) | ||
| 288 | break; | ||
| 289 | |||
| 272 | controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12); | 290 | controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12); |
| 273 | 291 | ||
| 274 | if (!info && ctrl) { | 292 | if (!info && ctrl) { |
| 293 | int len = min_t(uint, CAPI_SERIAL_LEN, | ||
| 294 | skb->data[CAPI_MSG_BASELEN + 16]); | ||
| 295 | |||
| 275 | memset(ctrl->serial, 0, CAPI_SERIAL_LEN); | 296 | memset(ctrl->serial, 0, CAPI_SERIAL_LEN); |
| 276 | strncpy(ctrl->serial, | 297 | strncpy(ctrl->serial, |
| 277 | skb->data + CAPI_MSG_BASELEN + 17, | 298 | skb->data + CAPI_MSG_BASELEN + 17, len); |
| 278 | skb->data[CAPI_MSG_BASELEN + 16]); | ||
| 279 | } | 299 | } |
| 280 | 300 | ||
| 281 | break; | 301 | break; |
| @@ -284,14 +304,18 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s | |||
| 284 | break; | 304 | break; |
| 285 | 305 | ||
| 286 | case CAPI_IND: | 306 | case CAPI_IND: |
| 307 | if (skb->len < CAPI_MSG_BASELEN + 6) | ||
| 308 | break; | ||
| 309 | |||
| 287 | func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3); | 310 | func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3); |
| 288 | 311 | ||
| 289 | if (func == CAPI_FUNCTION_LOOPBACK) { | 312 | if (func == CAPI_FUNCTION_LOOPBACK) { |
| 313 | int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6, | ||
| 314 | skb->data[CAPI_MSG_BASELEN + 5]); | ||
| 290 | appl = CAPIMSG_APPID(skb->data); | 315 | appl = CAPIMSG_APPID(skb->data); |
| 291 | msgnum = CAPIMSG_MSGID(skb->data); | 316 | msgnum = CAPIMSG_MSGID(skb->data); |
| 292 | cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func, | 317 | cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func, |
| 293 | skb->data + CAPI_MSG_BASELEN + 6, | 318 | skb->data + CAPI_MSG_BASELEN + 6, len); |
| 294 | skb->data[CAPI_MSG_BASELEN + 5]); | ||
| 295 | } | 319 | } |
| 296 | 320 | ||
| 297 | break; | 321 | break; |
| @@ -309,6 +333,9 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb) | |||
| 309 | 333 | ||
| 310 | BT_DBG("session %p skb %p len %d", session, skb, skb->len); | 334 | BT_DBG("session %p skb %p len %d", session, skb, skb->len); |
| 311 | 335 | ||
| 336 | if (skb->len < CAPI_MSG_BASELEN) | ||
| 337 | return; | ||
| 338 | |||
| 312 | if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) { | 339 | if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) { |
| 313 | cmtp_recv_interopmsg(session, skb); | 340 | cmtp_recv_interopmsg(session, skb); |
| 314 | return; | 341 | return; |
