Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb9951a0 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "SDP: Check p_req_end before reading from p_req"

parents c02d7742 5a8dec98
Loading
Loading
Loading
Loading
+40 −20
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@
 ******************************************************************************/

#include <cutils/log.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -54,7 +53,7 @@
/******************************************************************************/
static void process_service_search(tCONN_CB* p_ccb, uint16_t trans_num,
                                   uint16_t param_len, uint8_t* p_req,
                                   UNUSED_ATTR uint8_t* p_req_end);
                                   uint8_t* p_req_end);

static void process_service_attr_req(tCONN_CB* p_ccb, uint16_t trans_num,
                                     uint16_t param_len, uint8_t* p_req,
@@ -62,7 +61,7 @@ static void process_service_attr_req(tCONN_CB* p_ccb, uint16_t trans_num,

static void process_service_search_attr_req(tCONN_CB* p_ccb, uint16_t trans_num,
                                            uint16_t param_len, uint8_t* p_req,
                                            UNUSED_ATTR uint8_t* p_req_end);
                                            uint8_t* p_req_end);

/******************************************************************************/
/*                E R R O R   T E X T   S T R I N G S                         */
@@ -123,11 +122,25 @@ void sdp_server_handle_client_req(tCONN_CB* p_ccb, BT_HDR* p_msg) {
  alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS,
                     sdp_conn_timer_timeout, p_ccb);

  if (p_req + sizeof(pdu_id) + sizeof(trans_num) > p_req_end) {
    android_errorWriteLog(0x534e4554, "69384124");
    trans_num = 0;
    sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX,
                            SDP_TEXT_BAD_HEADER);
  }

  /* The first byte in the message is the pdu type */
  pdu_id = *p_req++;

  /* Extract the transaction number and parameter length */
  BE_STREAM_TO_UINT16(trans_num, p_req);

  if (p_req + sizeof(param_len) > p_req_end) {
    android_errorWriteLog(0x534e4554, "69384124");
    sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX,
                            SDP_TEXT_BAD_HEADER);
  }

  BE_STREAM_TO_UINT16(param_len, p_req);

  if ((p_req + param_len) != p_req_end) {
@@ -171,7 +184,7 @@ void sdp_server_handle_client_req(tCONN_CB* p_ccb, BT_HDR* p_msg) {
 ******************************************************************************/
static void process_service_search(tCONN_CB* p_ccb, uint16_t trans_num,
                                   uint16_t param_len, uint8_t* p_req,
                                   UNUSED_ATTR uint8_t* p_req_end) {
                                   uint8_t* p_req_end) {
  uint16_t max_replies, cur_handles, rem_handles, cont_offset;
  tSDP_UUID_SEQ uid_seq;
  uint8_t *p_rsp, *p_rsp_start, *p_rsp_param_len;
@@ -189,15 +202,15 @@ static void process_service_search(tCONN_CB* p_ccb, uint16_t trans_num,
  }

  /* Get the max replies we can send. Cap it at our max anyways. */
  BE_STREAM_TO_UINT16(max_replies, p_req);

  if (max_replies > SDP_MAX_RECORDS) max_replies = SDP_MAX_RECORDS;

  if ((!p_req) || (p_req > p_req_end)) {
  if (p_req + sizeof(max_replies) + sizeof(uint8_t) > p_req_end) {
    android_errorWriteLog(0x534e4554, "69384124");
    sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX,
                            SDP_TEXT_BAD_MAX_RECORDS_LIST);
    return;
  }
  BE_STREAM_TO_UINT16(max_replies, p_req);

  if (max_replies > SDP_MAX_RECORDS) max_replies = SDP_MAX_RECORDS;

  /* Get a list of handles that match the UUIDs given to us */
  for (num_rsp_handles = 0; num_rsp_handles < max_replies;) {
@@ -211,7 +224,8 @@ static void process_service_search(tCONN_CB* p_ccb, uint16_t trans_num,

  /* Check if this is a continuation request */
  if (*p_req) {
    if (*p_req++ != SDP_CONTINUATION_LEN || (p_req >= p_req_end)) {
    if (*p_req++ != SDP_CONTINUATION_LEN ||
        (p_req + sizeof(cont_offset) > p_req_end)) {
      sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_CONT_STATE,
                              SDP_TEXT_BAD_CONT_LEN);
      return;
@@ -310,15 +324,16 @@ static void process_service_attr_req(tCONN_CB* p_ccb, uint16_t trans_num,
  bool is_cont = false;
  uint16_t attr_len;

  /* Extract the record handle */
  BE_STREAM_TO_UINT32(rec_handle, p_req);

  if (p_req > p_req_end) {
  if (p_req + sizeof(rec_handle) + sizeof(max_list_len) > p_req_end) {
    android_errorWriteLog(0x534e4554, "69384124");
    sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_SERV_REC_HDL,
                            SDP_TEXT_BAD_HANDLE);
    return;
  }

  /* Extract the record handle */
  BE_STREAM_TO_UINT32(rec_handle, p_req);

  /* Get the max list length we can send. Cap it at MTU size minus overhead */
  BE_STREAM_TO_UINT16(max_list_len, p_req);

@@ -327,7 +342,8 @@ static void process_service_attr_req(tCONN_CB* p_ccb, uint16_t trans_num,

  p_req = sdpu_extract_attr_seq(p_req, param_len, &attr_seq);

  if ((!p_req) || (!attr_seq.num_attr) || (p_req > p_req_end)) {
  if ((!p_req) || (!attr_seq.num_attr) ||
      (p_req + sizeof(uint8_t) > p_req_end)) {
    sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX,
                            SDP_TEXT_BAD_ATTR_LIST);
    return;
@@ -355,7 +371,8 @@ static void process_service_attr_req(tCONN_CB* p_ccb, uint16_t trans_num,

  /* Check if this is a continuation request */
  if (*p_req) {
    if (*p_req++ != SDP_CONTINUATION_LEN) {
    if (*p_req++ != SDP_CONTINUATION_LEN ||
        (p_req + sizeof(cont_offset) > p_req_end)) {
      sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_CONT_STATE,
                              SDP_TEXT_BAD_CONT_LEN);
      return;
@@ -520,7 +537,7 @@ static void process_service_attr_req(tCONN_CB* p_ccb, uint16_t trans_num,
 ******************************************************************************/
static void process_service_search_attr_req(tCONN_CB* p_ccb, uint16_t trans_num,
                                            uint16_t param_len, uint8_t* p_req,
                                            UNUSED_ATTR uint8_t* p_req_end) {
                                            uint8_t* p_req_end) {
  uint16_t max_list_len;
  int16_t rem_len;
  uint16_t len_to_send, cont_offset;
@@ -537,7 +554,8 @@ static void process_service_search_attr_req(tCONN_CB* p_ccb, uint16_t trans_num,
  /* Extract the UUID sequence to search for */
  p_req = sdpu_extract_uid_seq(p_req, param_len, &uid_seq);

  if ((!p_req) || (!uid_seq.num_uids)) {
  if ((!p_req) || (!uid_seq.num_uids) ||
      (p_req + sizeof(uint16_t) > p_req_end)) {
    sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX,
                            SDP_TEXT_BAD_UUID_LIST);
    return;
@@ -551,7 +569,8 @@ static void process_service_search_attr_req(tCONN_CB* p_ccb, uint16_t trans_num,

  p_req = sdpu_extract_attr_seq(p_req, param_len, &attr_seq);

  if ((!p_req) || (!attr_seq.num_attr)) {
  if ((!p_req) || (!attr_seq.num_attr) ||
      (p_req + sizeof(uint8_t) > p_req_end)) {
    sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX,
                            SDP_TEXT_BAD_ATTR_LIST);
    return;
@@ -571,7 +590,8 @@ static void process_service_search_attr_req(tCONN_CB* p_ccb, uint16_t trans_num,

  /* Check if this is a continuation request */
  if (*p_req) {
    if (*p_req++ != SDP_CONTINUATION_LEN) {
    if (*p_req++ != SDP_CONTINUATION_LEN ||
        (p_req + sizeof(uint16_t) > p_req_end)) {
      sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_CONT_STATE,
                              SDP_TEXT_BAD_CONT_LEN);
      return;
+31 −7
Original line number Diff line number Diff line
@@ -333,6 +333,8 @@ uint8_t* sdpu_extract_uid_seq(uint8_t* p, uint16_t param_len,
  p_seq->num_uids = 0;

  /* A UID sequence is composed of a bunch of UIDs. */
  if (sizeof(descr) > param_len) return (NULL);
  param_len -= sizeof(descr);

  BE_STREAM_TO_UINT8(descr, p);
  type = descr >> 3;
@@ -351,19 +353,25 @@ uint8_t* sdpu_extract_uid_seq(uint8_t* p, uint16_t param_len,
      seq_len = 16;
      break;
    case SIZE_IN_NEXT_BYTE:
      if (sizeof(uint8_t) > param_len) return (NULL);
      param_len -= sizeof(uint8_t);
      BE_STREAM_TO_UINT8(seq_len, p);
      break;
    case SIZE_IN_NEXT_WORD:
      if (sizeof(uint16_t) > param_len) return (NULL);
      param_len -= sizeof(uint16_t);
      BE_STREAM_TO_UINT16(seq_len, p);
      break;
    case SIZE_IN_NEXT_LONG:
      if (sizeof(uint32_t) > param_len) return (NULL);
      param_len -= sizeof(uint32_t);
      BE_STREAM_TO_UINT32(seq_len, p);
      break;
    default:
      return (NULL);
  }

  if (seq_len >= param_len) return (NULL);
  if (seq_len > param_len) return (NULL);

  p_seq_end = p + seq_len;

@@ -386,12 +394,15 @@ uint8_t* sdpu_extract_uid_seq(uint8_t* p, uint16_t param_len,
        uuid_len = 16;
        break;
      case SIZE_IN_NEXT_BYTE:
        if (p + sizeof(uint8_t) > p_seq_end) return NULL;
        BE_STREAM_TO_UINT8(uuid_len, p);
        break;
      case SIZE_IN_NEXT_WORD:
        if (p + sizeof(uint16_t) > p_seq_end) return NULL;
        BE_STREAM_TO_UINT16(uuid_len, p);
        break;
      case SIZE_IN_NEXT_LONG:
        if (p + sizeof(uint32_t) > p_seq_end) return NULL;
        BE_STREAM_TO_UINT32(uuid_len, p);
        break;
      default:
@@ -399,7 +410,8 @@ uint8_t* sdpu_extract_uid_seq(uint8_t* p, uint16_t param_len,
    }

    /* If UUID length is valid, copy it across */
    if ((uuid_len == 2) || (uuid_len == 4) || (uuid_len == 16)) {
    if (((uuid_len == 2) || (uuid_len == 4) || (uuid_len == 16)) &&
        (p + uuid_len <= p_seq_end)) {
      p_seq->uuid_entry[p_seq->num_uids].len = (uint16_t)uuid_len;
      BE_STREAM_TO_ARRAY(p, p_seq->uuid_entry[p_seq->num_uids].value,
                         (int)uuid_len);
@@ -436,30 +448,38 @@ uint8_t* sdpu_extract_attr_seq(uint8_t* p, uint16_t param_len,
  p_seq->num_attr = 0;

  /* Get attribute sequence info */
  if (param_len < sizeof(descr)) return NULL;
  param_len -= sizeof(descr);
  BE_STREAM_TO_UINT8(descr, p);
  type = descr >> 3;
  size = descr & 7;

  if (type != DATA_ELE_SEQ_DESC_TYPE) return (p);
  if (type != DATA_ELE_SEQ_DESC_TYPE) return NULL;

  switch (size) {
    case SIZE_IN_NEXT_BYTE:
      if (param_len < sizeof(uint8_t)) return NULL;
      param_len -= sizeof(uint8_t);
      BE_STREAM_TO_UINT8(list_len, p);
      break;

    case SIZE_IN_NEXT_WORD:
      if (param_len < sizeof(uint16_t)) return NULL;
      param_len -= sizeof(uint16_t);
      BE_STREAM_TO_UINT16(list_len, p);
      break;

    case SIZE_IN_NEXT_LONG:
      if (param_len < sizeof(uint32_t)) return NULL;
      param_len -= sizeof(uint32_t);
      BE_STREAM_TO_UINT32(list_len, p);
      break;

    default:
      return (p);
      return NULL;
  }

  if (list_len > param_len) return (p);
  if (list_len > param_len) return NULL;

  p_end_list = p + list_len;

@@ -469,7 +489,7 @@ uint8_t* sdpu_extract_attr_seq(uint8_t* p, uint16_t param_len,
    type = descr >> 3;
    size = descr & 7;

    if (type != UINT_DESC_TYPE) return (p);
    if (type != UINT_DESC_TYPE) return NULL;

    switch (size) {
      case SIZE_TWO_BYTES:
@@ -479,20 +499,24 @@ uint8_t* sdpu_extract_attr_seq(uint8_t* p, uint16_t param_len,
        attr_len = 4;
        break;
      case SIZE_IN_NEXT_BYTE:
        if (p + sizeof(uint8_t) > p_end_list) return NULL;
        BE_STREAM_TO_UINT8(attr_len, p);
        break;
      case SIZE_IN_NEXT_WORD:
        if (p + sizeof(uint16_t) > p_end_list) return NULL;
        BE_STREAM_TO_UINT16(attr_len, p);
        break;
      case SIZE_IN_NEXT_LONG:
        if (p + sizeof(uint32_t) > p_end_list) return NULL;
        BE_STREAM_TO_UINT32(attr_len, p);
        break;
      default:
        return (NULL);
        return NULL;
        break;
    }

    /* Attribute length must be 2-bytes or 4-bytes for a paired entry. */
    if (p + attr_len > p_end_list) return NULL;
    if (attr_len == 2) {
      BE_STREAM_TO_UINT16(p_seq->attr_entry[p_seq->num_attr].start, p);
      p_seq->attr_entry[p_seq->num_attr].end =