Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 310163 Details for
Bug 452715
CVE-2008-2374 bluez-libs: SDP payload processing vulnerability
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Fixes for SDP vulnerability in bluez-libs
patch-sdp-vuln-bluez-libs-3.33-to-3.34 (text/plain), 29.37 KB, created by
Marcel Holtmann
on 2008-06-24 16:37:29 UTC
(
hide
)
Description:
Fixes for SDP vulnerability in bluez-libs
Filename:
MIME Type:
Creator:
Marcel Holtmann
Created:
2008-06-24 16:37:29 UTC
Size:
29.37 KB
patch
obsolete
>diff --git a/include/sdp_lib.h b/include/sdp_lib.h >index eac2fe6..143056f 100644 >--- a/include/sdp_lib.h >+++ b/include/sdp_lib.h >@@ -479,6 +479,7 @@ void sdp_uuid32_to_uuid128(uuid_t *uuid128, uuid_t *uuid32); > int sdp_uuid128_to_uuid(uuid_t *uuid); > int sdp_uuid_to_proto(uuid_t *uuid); > int sdp_uuid_extract(const uint8_t *buffer, uuid_t *uuid, int *scanned); >+int sdp_uuid_extract_safe(const uint8_t *buffer, int bufsize, uuid_t *uuid, int *scanned); > void sdp_uuid_print(const uuid_t *uuid); > > #define MAX_LEN_UUID_STR 37 >@@ -585,7 +586,7 @@ static inline int sdp_get_icon_url(const sdp_record_t *rec, char *str, int len) > } > > sdp_record_t *sdp_extract_pdu(const uint8_t *pdata, int *scanned); >-sdp_data_t *sdp_extract_string(uint8_t *, int *); >+sdp_record_t *sdp_extract_pdu_safe(const uint8_t *pdata, int bufsize, int *scanned); > > void sdp_data_print(sdp_data_t *data); > void sdp_print_service_attr(sdp_list_t *alist); >@@ -601,8 +602,10 @@ int sdp_gen_pdu(sdp_buf_t *pdu, sdp_data_t *data); > int sdp_gen_record_pdu(const sdp_record_t *rec, sdp_buf_t *pdu); > > int sdp_extract_seqtype(const uint8_t *buf, uint8_t *dtdp, int *seqlen); >+int sdp_extract_seqtype_safe(const uint8_t *buf, int bufsize, uint8_t *dtdp, int *size); > > sdp_data_t *sdp_extract_attr(const uint8_t *pdata, int *extractedLength, sdp_record_t *rec); >+sdp_data_t *sdp_extract_attr_safe(const uint8_t *pdata, int bufsize, int *extractedLength, sdp_record_t *rec); > > void sdp_pattern_add_uuid(sdp_record_t *rec, uuid_t *uuid); > void sdp_pattern_add_uuidseq(sdp_record_t *rec, sdp_list_t *seq); >diff --git a/src/sdp.c b/src/sdp.c >index 3ec877a..f8953c4 100644 >--- a/src/sdp.c >+++ b/src/sdp.c >@@ -904,15 +904,76 @@ void sdp_data_free(sdp_data_t *d) > free(d); > } > >-static sdp_data_t *extract_int(const void *p, int *len) >+int sdp_uuid_extract_safe(const uint8_t *p, int bufsize, uuid_t *uuid, int *scanned) > { >- sdp_data_t *d = malloc(sizeof(sdp_data_t)); >+ uint8_t type; >+ >+ if (bufsize < sizeof(uint8_t)) { >+ SDPERR("Unexpected end of packet"); >+ return -1; >+ } >+ >+ type = *(const uint8_t *) p; >+ >+ if (!SDP_IS_UUID(type)) { >+ SDPERR("Unknown data type : %d expecting a svc UUID\n", type); >+ return -1; >+ } >+ p += sizeof(uint8_t); >+ *scanned += sizeof(uint8_t); >+ bufsize -= sizeof(uint8_t); >+ if (type == SDP_UUID16) { >+ if (bufsize < sizeof(uint16_t)) { >+ SDPERR("Not enough room for 16-bit UUID"); >+ return -1; >+ } >+ sdp_uuid16_create(uuid, ntohs(bt_get_unaligned((uint16_t *) p))); >+ *scanned += sizeof(uint16_t); >+ p += sizeof(uint16_t); >+ } else if (type == SDP_UUID32) { >+ if (bufsize < sizeof(uint32_t)) { >+ SDPERR("Not enough room for 32-bit UUID"); >+ return -1; >+ } >+ sdp_uuid32_create(uuid, ntohl(bt_get_unaligned((uint32_t *) p))); >+ *scanned += sizeof(uint32_t); >+ p += sizeof(uint32_t); >+ } else { >+ if (bufsize < sizeof(uint128_t)) { >+ SDPERR("Not enough room for 128-bit UUID"); >+ return -1; >+ } >+ sdp_uuid128_create(uuid, p); >+ *scanned += sizeof(uint128_t); >+ p += sizeof(uint128_t); >+ } >+ return 0; >+} >+ >+int sdp_uuid_extract(const uint8_t *p, uuid_t *uuid, int *scanned) >+{ >+ /* Assume p points to a buffer of size at least SDP_MAX_ATTR_LEN, >+ because we don't have any better information */ >+ return sdp_uuid_extract_safe(p, SDP_MAX_ATTR_LEN, uuid, scanned); >+} >+ >+static sdp_data_t *extract_int(const void *p, int bufsize, int *len) >+{ >+ sdp_data_t *d; >+ >+ if (bufsize < sizeof(uint8_t)) { >+ SDPERR("Unexpected end of packet"); >+ return NULL; >+ } >+ >+ d = malloc(sizeof(sdp_data_t)); > > SDPDBG("Extracting integer\n"); > memset(d, 0, sizeof(sdp_data_t)); > d->dtd = *(uint8_t *) p; > p += sizeof(uint8_t); > *len += sizeof(uint8_t); >+ bufsize -= sizeof(uint8_t); > > switch (d->dtd) { > case SDP_DATA_NIL: >@@ -920,26 +981,51 @@ static sdp_data_t *extract_int(const void *p, int *len) > case SDP_BOOL: > case SDP_INT8: > case SDP_UINT8: >+ if (bufsize < sizeof(uint8_t)) { >+ SDPERR("Unexpected end of packet"); >+ free(d); >+ return NULL; >+ } > *len += sizeof(uint8_t); > d->val.uint8 = *(uint8_t *) p; > break; > case SDP_INT16: > case SDP_UINT16: >+ if (bufsize < sizeof(uint16_t)) { >+ SDPERR("Unexpected end of packet"); >+ free(d); >+ return NULL; >+ } > *len += sizeof(uint16_t); > d->val.uint16 = ntohs(bt_get_unaligned((uint16_t *) p)); > break; > case SDP_INT32: > case SDP_UINT32: >+ if (bufsize < sizeof(uint32_t)) { >+ SDPERR("Unexpected end of packet"); >+ free(d); >+ return NULL; >+ } > *len += sizeof(uint32_t); > d->val.uint32 = ntohl(bt_get_unaligned((uint32_t *) p)); > break; > case SDP_INT64: > case SDP_UINT64: >+ if (bufsize < sizeof(uint64_t)) { >+ SDPERR("Unexpected end of packet"); >+ free(d); >+ return NULL; >+ } > *len += sizeof(uint64_t); > d->val.uint64 = ntoh64(bt_get_unaligned((uint64_t *) p)); > break; > case SDP_INT128: > case SDP_UINT128: >+ if (bufsize < sizeof(uint128_t)) { >+ SDPERR("Unexpected end of packet"); >+ free(d); >+ return NULL; >+ } > *len += sizeof(uint128_t); > ntoh128((uint128_t *) p, &d->val.uint128); > break; >@@ -950,13 +1036,13 @@ static sdp_data_t *extract_int(const void *p, int *len) > return d; > } > >-static sdp_data_t *extract_uuid(const uint8_t *p, int *len, sdp_record_t *rec) >+static sdp_data_t *extract_uuid(const uint8_t *p, int bufsize, int *len, sdp_record_t *rec) > { > sdp_data_t *d = malloc(sizeof(sdp_data_t)); > > SDPDBG("Extracting UUID"); > memset(d, 0, sizeof(sdp_data_t)); >- if (sdp_uuid_extract(p, &d->val.uuid, len) < 0) { >+ if (sdp_uuid_extract_safe(p, bufsize, &d->val.uuid, len) < 0) { > free(d); > return NULL; > } >@@ -969,29 +1055,49 @@ static sdp_data_t *extract_uuid(const uint8_t *p, int *len, sdp_record_t *rec) > /* > * Extract strings from the PDU (could be service description and similar info) > */ >-static sdp_data_t *extract_str(const void *p, int *len) >+static sdp_data_t *extract_str(const void *p, int bufsize, int *len) > { > char *s; > int n; >- sdp_data_t *d = malloc(sizeof(sdp_data_t)); >+ sdp_data_t *d; >+ >+ if (bufsize < sizeof(uint8_t)) { >+ SDPERR("Unexpected end of packet"); >+ return NULL; >+ } >+ >+ d = malloc(sizeof(sdp_data_t)); > > memset(d, 0, sizeof(sdp_data_t)); > d->dtd = *(uint8_t *) p; > p += sizeof(uint8_t); > *len += sizeof(uint8_t); >+ bufsize -= sizeof(uint8_t); > > switch (d->dtd) { > case SDP_TEXT_STR8: > case SDP_URL_STR8: >+ if (bufsize < sizeof(uint8_t)) { >+ SDPERR("Unexpected end of packet"); >+ free(d); >+ return NULL; >+ } > n = *(uint8_t *) p; > p += sizeof(uint8_t); >- *len += sizeof(uint8_t) + n; >+ *len += sizeof(uint8_t); >+ bufsize -= sizeof(uint8_t); > break; > case SDP_TEXT_STR16: > case SDP_URL_STR16: >+ if (bufsize < sizeof(uint16_t)) { >+ SDPERR("Unexpected end of packet"); >+ free(d); >+ return NULL; >+ } > n = ntohs(bt_get_unaligned((uint16_t *) p)); > p += sizeof(uint16_t); > *len += sizeof(uint16_t) + n; >+ bufsize -= sizeof(uint16_t); > break; > default: > SDPERR("Sizeof text string > UINT16_MAX\n"); >@@ -999,10 +1105,23 @@ static sdp_data_t *extract_str(const void *p, int *len) > return 0; > } > >+ if (bufsize < n) { >+ SDPERR("String too long to fit in packet"); >+ free(d); >+ return NULL; >+ } >+ > s = malloc(n + 1); >+ if (!s) { >+ SDPERR("Not enough memory for incoming string"); >+ free(d); >+ return NULL; >+ } > memset(s, 0, n + 1); > memcpy(s, p, n); > >+ *len += n; >+ > SDPDBG("Len : %d\n", n); > SDPDBG("Str : %s\n", s); > >@@ -1011,7 +1130,67 @@ static sdp_data_t *extract_str(const void *p, int *len) > return d; > } > >-static sdp_data_t *extract_seq(const void *p, int *len, sdp_record_t *rec) >+/* >+ * Extract the sequence type and its length, and return offset into buf >+ * or 0 on failure. >+ */ >+int sdp_extract_seqtype_safe(const uint8_t *buf, int bufsize, uint8_t *dtdp, int *size) >+{ >+ uint8_t dtd; >+ int scanned = sizeof(uint8_t); >+ >+ if (bufsize < sizeof(uint8_t)) { >+ SDPERR("Unexpected end of packet"); >+ return 0; >+ } >+ >+ dtd = *(uint8_t *) buf; >+ buf += sizeof(uint8_t); >+ bufsize -= sizeof(uint8_t); >+ *dtdp = dtd; >+ switch (dtd) { >+ case SDP_SEQ8: >+ case SDP_ALT8: >+ if (bufsize < sizeof(uint8_t)) { >+ SDPERR("Unexpected end of packet"); >+ return 0; >+ } >+ *size = *(uint8_t *) buf; >+ scanned += sizeof(uint8_t); >+ break; >+ case SDP_SEQ16: >+ case SDP_ALT16: >+ if (bufsize < sizeof(uint16_t)) { >+ SDPERR("Unexpected end of packet"); >+ return 0; >+ } >+ *size = ntohs(bt_get_unaligned((uint16_t *) buf)); >+ scanned += sizeof(uint16_t); >+ break; >+ case SDP_SEQ32: >+ case SDP_ALT32: >+ if (bufsize < sizeof(uint32_t)) { >+ SDPERR("Unexpected end of packet"); >+ return 0; >+ } >+ *size = ntohl(bt_get_unaligned((uint32_t *) buf)); >+ scanned += sizeof(uint32_t); >+ break; >+ default: >+ SDPERR("Unknown sequence type, aborting\n"); >+ return 0; >+ } >+ return scanned; >+} >+ >+int sdp_extract_seqtype(const uint8_t *buf, uint8_t *dtdp, int *size) >+{ >+ /* Assume buf points to a buffer of size at least SDP_MAX_ATTR_LEN, >+ because we don't have any better information */ >+ return sdp_extract_seqtype_safe(buf, SDP_MAX_ATTR_LEN, dtdp, size); >+} >+ >+static sdp_data_t *extract_seq(const void *p, int bufsize, int *len, sdp_record_t *rec) > { > int seqlen, n = 0; > sdp_data_t *curr, *prev; >@@ -1019,17 +1198,24 @@ static sdp_data_t *extract_seq(const void *p, int *len, sdp_record_t *rec) > > SDPDBG("Extracting SEQ"); > memset(d, 0, sizeof(sdp_data_t)); >- *len = sdp_extract_seqtype(p, &d->dtd, &seqlen); >+ *len = sdp_extract_seqtype_safe(p, bufsize, &d->dtd, &seqlen); > SDPDBG("Sequence Type : 0x%x length : 0x%x\n", d->dtd, seqlen); > > if (*len == 0) > return d; > >+ if (*len > bufsize) { >+ SDPERR("Packet not big enough to hold sequence."); >+ free(d); >+ return NULL; >+ } >+ > p += *len; >+ bufsize -= *len; > curr = prev = NULL; > while (n < seqlen) { > int attrlen = 0; >- curr = sdp_extract_attr(p, &attrlen, rec); >+ curr = sdp_extract_attr_safe(p, bufsize, &attrlen, rec); > if (curr == NULL) > break; > >@@ -1040,6 +1226,7 @@ static sdp_data_t *extract_seq(const void *p, int *len, sdp_record_t *rec) > prev = curr; > p += attrlen; > n += attrlen; >+ bufsize -= attrlen; > > SDPDBG("Extracted: %d SequenceLength: %d", n, seqlen); > } >@@ -1048,11 +1235,18 @@ static sdp_data_t *extract_seq(const void *p, int *len, sdp_record_t *rec) > return d; > } > >-sdp_data_t *sdp_extract_attr(const uint8_t *p, int *size, sdp_record_t *rec) >+sdp_data_t *sdp_extract_attr_safe(const uint8_t *p, int bufsize, int *size, sdp_record_t *rec) > { > sdp_data_t *elem; > int n = 0; >- uint8_t dtd = *(const uint8_t *)p; >+ uint8_t dtd; >+ >+ if (bufsize < sizeof(uint8_t)) { >+ SDPERR("Unexpected end of packet"); >+ return NULL; >+ } >+ >+ dtd = *(const uint8_t *)p; > > SDPDBG("extract_attr: dtd=0x%x", dtd); > switch (dtd) { >@@ -1068,12 +1262,12 @@ sdp_data_t *sdp_extract_attr(const uint8_t *p, int *size, sdp_record_t *rec) > case SDP_INT32: > case SDP_INT64: > case SDP_INT128: >- elem = extract_int(p, &n); >+ elem = extract_int(p, bufsize, &n); > break; > case SDP_UUID16: > case SDP_UUID32: > case SDP_UUID128: >- elem = extract_uuid(p, &n, rec); >+ elem = extract_uuid(p, bufsize, &n, rec); > break; > case SDP_TEXT_STR8: > case SDP_TEXT_STR16: >@@ -1081,7 +1275,7 @@ sdp_data_t *sdp_extract_attr(const uint8_t *p, int *size, sdp_record_t *rec) > case SDP_URL_STR8: > case SDP_URL_STR16: > case SDP_URL_STR32: >- elem = extract_str(p, &n); >+ elem = extract_str(p, bufsize, &n); > break; > case SDP_SEQ8: > case SDP_SEQ16: >@@ -1089,7 +1283,7 @@ sdp_data_t *sdp_extract_attr(const uint8_t *p, int *size, sdp_record_t *rec) > case SDP_ALT8: > case SDP_ALT16: > case SDP_ALT32: >- elem = extract_seq(p, &n, rec); >+ elem = extract_seq(p, bufsize, &n, rec); > break; > default: > SDPERR("Unknown data descriptor : 0x%x terminating\n", dtd); >@@ -1099,6 +1293,13 @@ sdp_data_t *sdp_extract_attr(const uint8_t *p, int *size, sdp_record_t *rec) > return elem; > } > >+sdp_data_t *sdp_extract_attr(const uint8_t *p, int *size, sdp_record_t *rec) >+{ >+ /* Assume p points to a buffer of size at least SDP_MAX_ATTR_LEN, >+ because we don't have any better information */ >+ return sdp_extract_attr_safe(p, SDP_MAX_ATTR_LEN, size, rec); >+} >+ > #ifdef SDP_DEBUG > static void attr_print_func(void *value, void *userData) > { >@@ -1122,7 +1323,7 @@ void sdp_print_service_attr(sdp_list_t *svcAttrList) > } > #endif > >-sdp_record_t *sdp_extract_pdu(const uint8_t *buf, int *scanned) >+sdp_record_t *sdp_extract_pdu_safe(const uint8_t *buf, int bufsize, int *scanned) > { > int extracted = 0, seqlen = 0; > uint8_t dtd; >@@ -1130,21 +1331,30 @@ sdp_record_t *sdp_extract_pdu(const uint8_t *buf, int *scanned) > sdp_record_t *rec = sdp_record_alloc(); > const uint8_t *p = buf; > >- *scanned = sdp_extract_seqtype(buf, &dtd, &seqlen); >+ *scanned = sdp_extract_seqtype_safe(buf, bufsize, &dtd, &seqlen); > p += *scanned; >+ bufsize -= *scanned; > rec->attrlist = NULL; >- while (extracted < seqlen) { >+ >+ while (extracted < seqlen && bufsize > 0) { > int n = sizeof(uint8_t), attrlen = 0; > sdp_data_t *data = NULL; > >- SDPDBG("Extract PDU, sequenceLength: %d localExtractedLength: %d", seqlen, extracted); >+ SDPDBG("Extract PDU, sequenceLength: %d localExtractedLength: %d", >+ seqlen, extracted); >+ >+ if (bufsize < n + sizeof(uint16_t)) { >+ SDPERR("Unexpected end of packet"); >+ break; >+ } >+ > dtd = *(uint8_t *) p; > attr = ntohs(bt_get_unaligned((uint16_t *) (p + n))); > n += sizeof(uint16_t); > > SDPDBG("DTD of attrId : %d Attr id : 0x%x \n", dtd, attr); > >- data = sdp_extract_attr(p + n, &attrlen, rec); >+ data = sdp_extract_attr_safe(p + n, bufsize - n, &attrlen, rec); > > SDPDBG("Attr id : 0x%x attrValueLength : %d\n", attr, attrlen); > >@@ -1162,9 +1372,11 @@ sdp_record_t *sdp_extract_pdu(const uint8_t *buf, int *scanned) > > extracted += n; > p += n; >+ bufsize -= n; > sdp_attr_replace(rec, attr, data); >+ > SDPDBG("Extract PDU, seqLength: %d localExtractedLength: %d", >- seqlen, extracted); >+ seqlen, extracted); > } > #ifdef SDP_DEBUG > SDPDBG("Successful extracting of Svc Rec attributes\n"); >@@ -1174,6 +1386,13 @@ sdp_record_t *sdp_extract_pdu(const uint8_t *buf, int *scanned) > return rec; > } > >+sdp_record_t *sdp_extract_pdu(const uint8_t *buf, int *scanned) >+{ >+ /* Assume buf points to a buffer of size at least SDP_MAX_ATTR_LEN, >+ because we don't have any better information */ >+ return sdp_extract_pdu_safe(buf, SDP_MAX_ATTR_LEN, scanned); >+} >+ > #ifdef SDP_DEBUG > static void print_dataseq(sdp_data_t *p) > { >@@ -1262,40 +1481,6 @@ sdp_data_t *sdp_data_get(const sdp_record_t *rec, uint16_t attrId) > return NULL; > } > >-/* >- * Extract the sequence type and its length, and return offset into buf >- * or 0 on failure. >- */ >-int sdp_extract_seqtype(const uint8_t *buf, uint8_t *dtdp, int *size) >-{ >- uint8_t dtd = *(uint8_t *) buf; >- int scanned = sizeof(uint8_t); >- >- buf += sizeof(uint8_t); >- *dtdp = dtd; >- switch (dtd) { >- case SDP_SEQ8: >- case SDP_ALT8: >- *size = *(uint8_t *) buf; >- scanned += sizeof(uint8_t); >- break; >- case SDP_SEQ16: >- case SDP_ALT16: >- *size = ntohs(bt_get_unaligned((uint16_t *) buf)); >- scanned += sizeof(uint16_t); >- break; >- case SDP_SEQ32: >- case SDP_ALT32: >- *size = ntohl(bt_get_unaligned((uint32_t *) buf)); >- scanned += sizeof(uint32_t); >- break; >- default: >- SDPERR("Unknown sequence type, aborting\n"); >- return 0; >- } >- return scanned; >-} >- > int sdp_send_req(sdp_session_t *session, uint8_t *buf, uint32_t size) > { > uint32_t sent = 0; >@@ -2329,32 +2514,6 @@ int sdp_uuid_to_proto(uuid_t *uuid) > return 0; > } > >-int sdp_uuid_extract(const uint8_t *p, uuid_t *uuid, int *scanned) >-{ >- uint8_t type = *(const uint8_t *) p; >- >- if (!SDP_IS_UUID(type)) { >- SDPERR("Unknown data type : %d expecting a svc UUID\n", type); >- return -1; >- } >- p += sizeof(uint8_t); >- *scanned += sizeof(uint8_t); >- if (type == SDP_UUID16) { >- sdp_uuid16_create(uuid, ntohs(bt_get_unaligned((uint16_t *) p))); >- *scanned += sizeof(uint16_t); >- p += sizeof(uint16_t); >- } else if (type == SDP_UUID32) { >- sdp_uuid32_create(uuid, ntohl(bt_get_unaligned((uint32_t *) p))); >- *scanned += sizeof(uint32_t); >- p += sizeof(uint32_t); >- } else { >- sdp_uuid128_create(uuid, p); >- *scanned += sizeof(uint128_t); >- p += sizeof(uint128_t); >- } >- return 0; >-} >- > /* > * This function appends data to the PDU buffer "dst" from source "src". > * The data length is also computed and set. >@@ -2484,6 +2643,13 @@ int sdp_device_record_register_binary(sdp_session_t *session, bdaddr_t *device, > if (status < 0) > goto end; > >+ if (rspsize < sizeof(sdp_pdu_hdr_t)) { >+ SDPERR("Unexpected end of packet"); >+ errno = EPROTO; >+ status = -1; >+ goto end; >+ } >+ > rsphdr = (sdp_pdu_hdr_t *) rsp; > p = rsp + sizeof(sdp_pdu_hdr_t); > >@@ -2495,6 +2661,12 @@ int sdp_device_record_register_binary(sdp_session_t *session, bdaddr_t *device, > errno = EPROTO; > status = -1; > } else { >+ if (rspsize < sizeof(sdp_pdu_hdr_t) + sizeof(uint32_t)) { >+ SDPERR("Unexpected end of packet"); >+ errno = EPROTO; >+ status = -1; >+ goto end; >+ } > if (handle) > *handle = ntohl(bt_get_unaligned((uint32_t *) p)); > } >@@ -2590,6 +2762,13 @@ int sdp_device_record_unregister_binary(sdp_session_t *session, bdaddr_t *device > if (status < 0) > goto end; > >+ if (rspsize < sizeof(sdp_pdu_hdr_t) + sizeof(uint16_t)) { >+ SDPERR("Unexpected end of packet"); >+ errno = EPROTO; >+ status = -1; >+ goto end; >+ } >+ > rsphdr = (sdp_pdu_hdr_t *) rspbuf; > p = rspbuf + sizeof(sdp_pdu_hdr_t); > status = bt_get_unaligned((uint16_t *) p); >@@ -2689,6 +2868,13 @@ int sdp_device_record_update(sdp_session_t *session, bdaddr_t *device, const sdp > if (status < 0) > goto end; > >+ if (rspsize < sizeof(sdp_pdu_hdr_t) + sizeof(uint16_t)) { >+ SDPERR("Unexpected end of packet"); >+ errno = EPROTO; >+ status = -1; >+ goto end; >+ } >+ > SDPDBG("Send req status : %d\n", status); > > rsphdr = (sdp_pdu_hdr_t *) rspbuf; >@@ -2764,18 +2950,23 @@ void sdp_pattern_add_uuidseq(sdp_record_t *rec, sdp_list_t *seq) > * handles are not in "data element sequence" form, but just like > * an array of service handles > */ >-static void extract_record_handle_seq(uint8_t *pdu, sdp_list_t **seq, int count, int *scanned) >+static void extract_record_handle_seq(uint8_t *pdu, int bufsize, sdp_list_t **seq, int count, int *scanned) > { > sdp_list_t *pSeq = *seq; > uint8_t *pdata = pdu; > int n; > > for (n = 0; n < count; n++) { >+ if (bufsize < sizeof(uint32_t)) { >+ SDPERR("Unexpected end of packet"); >+ break; >+ } > uint32_t *pSvcRec = malloc(sizeof(uint32_t)); > *pSvcRec = ntohl(bt_get_unaligned((uint32_t *) pdata)); > pSeq = sdp_list_append(pSeq, pSvcRec); > pdata += sizeof(uint32_t); > *scanned += sizeof(uint32_t); >+ bufsize -= sizeof(uint32_t); > } > *seq = pSeq; > } >@@ -2792,7 +2983,7 @@ static int gen_dataseq_pdu(uint8_t *dst, const sdp_list_t *seq, uint8_t dtd) > > // Fill up the value and the dtd arrays > SDPDBG(""); >- >+ > memset(&buf, 0, sizeof(sdp_buf_t)); > buf.data = malloc(256); > buf.buf_size = 256; >@@ -2843,12 +3034,17 @@ typedef struct { > unsigned char data[16]; > } __attribute__ ((packed)) sdp_cstate_t; > >-static int copy_cstate(uint8_t *pdata, const sdp_cstate_t *cstate) >+static int copy_cstate(uint8_t *pdata, int pdata_len, const sdp_cstate_t *cstate) > { > if (cstate) { >- *pdata++ = cstate->length; >- memcpy(pdata, cstate->data, cstate->length); >- return cstate->length + 1; >+ uint8_t len = cstate->length; >+ if (len >= pdata_len) { >+ SDPERR("Continuation state size exceeds internal buffer"); >+ len = pdata_len - 1; >+ } >+ *pdata++ = len; >+ memcpy(pdata, cstate->data, len); >+ return len + 1; > } > *pdata = 0; > return 1; >@@ -2890,7 +3086,7 @@ int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search, > uint32_t reqsize = 0, _reqsize; > uint32_t rspsize = 0, rsplen; > int seqlen = 0; >- int scanned, total_rec_count, rec_count; >+ int scanned, total_rec_count, rec_count, pdata_len; > uint8_t *pdata, *_pdata; > uint8_t *reqbuf, *rspbuf; > sdp_pdu_hdr_t *reqhdr, *rsphdr; >@@ -2928,7 +3124,8 @@ int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search, > > do { > // Add continuation state or NULL (first time) >- reqsize = _reqsize + copy_cstate(_pdata, cstate); >+ reqsize = _reqsize + copy_cstate(_pdata, >+ SDP_REQ_BUFFER_SIZE - _reqsize, cstate); > > // Set the request header's param length > reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); >@@ -2942,7 +3139,12 @@ int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search, > if (status < 0) > goto end; > >- rsplen = 0; >+ if (rspsize < sizeof(sdp_pdu_hdr_t)) { >+ SDPERR("Unexpected end of packet"); >+ status = -1; >+ goto end; >+ } >+ > rsphdr = (sdp_pdu_hdr_t *) rspbuf; > rsplen = ntohs(rsphdr->plen); > >@@ -2953,14 +3155,23 @@ int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search, > } > scanned = 0; > pdata = rspbuf + sizeof(sdp_pdu_hdr_t); >+ pdata_len = rspsize - sizeof(sdp_pdu_hdr_t); >+ >+ if (pdata_len < sizeof(uint16_t) + sizeof(uint16_t)) { >+ SDPERR("Unexpected end of packet"); >+ status = -1; >+ goto end; >+ } > > // net service record match count > total_rec_count = ntohs(bt_get_unaligned((uint16_t *) pdata)); > pdata += sizeof(uint16_t); > scanned += sizeof(uint16_t); >+ pdata_len -= sizeof(uint16_t); > rec_count = ntohs(bt_get_unaligned((uint16_t *) pdata)); > pdata += sizeof(uint16_t); > scanned += sizeof(uint16_t); >+ pdata_len -= sizeof(uint16_t); > > SDPDBG("Total svc count: %d\n", total_rec_count); > SDPDBG("Current svc count: %d\n", rec_count); >@@ -2970,12 +3181,18 @@ int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search, > status = -1; > goto end; > } >- extract_record_handle_seq(pdata, rsp, rec_count, &scanned); >+ extract_record_handle_seq(pdata, pdata_len, rsp, rec_count, &scanned); > SDPDBG("BytesScanned : %d\n", scanned); > > if (rsplen > scanned) { > uint8_t cstate_len; > >+ if (rspsize < sizeof(sdp_pdu_hdr_t) + scanned + sizeof(uint8_t)) { >+ SDPERR("Unexpected end of packet: continuation state data missing"); >+ status = -1; >+ goto end; >+ } >+ > pdata = rspbuf + sizeof(sdp_pdu_hdr_t) + scanned; > cstate_len = *(uint8_t *) pdata; > if (cstate_len > 0) { >@@ -2986,7 +3203,7 @@ int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search, > } > } while (cstate); > >- end: >+end: > if (reqbuf) > free(reqbuf); > if (rspbuf) >@@ -3034,7 +3251,7 @@ sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle, > uint32_t reqsize = 0, _reqsize; > uint32_t rspsize = 0, rsp_count; > int attr_list_len = 0; >- int seqlen = 0; >+ int seqlen = 0, pdata_len; > uint8_t *pdata, *_pdata; > uint8_t *reqbuf, *rspbuf; > sdp_pdu_hdr_t *reqhdr, *rsphdr; >@@ -3090,7 +3307,8 @@ sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle, > > do { > // add NULL continuation state >- reqsize = _reqsize + copy_cstate(_pdata, cstate); >+ reqsize = _reqsize + copy_cstate(_pdata, >+ SDP_REQ_BUFFER_SIZE - _reqsize, cstate); > > // set the request header's param length > reqhdr->tid = htons(sdp_gen_tid(session)); >@@ -3099,6 +3317,13 @@ sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle, > status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize); > if (status < 0) > goto end; >+ >+ if (rspsize < sizeof(sdp_pdu_hdr_t)) { >+ SDPERR("Unexpected end of packet"); >+ status = -1; >+ goto end; >+ } >+ > rsp_count = 0; > rsphdr = (sdp_pdu_hdr_t *) rspbuf; > if (rsphdr->pdu_id == SDP_ERROR_RSP) { >@@ -3107,11 +3332,25 @@ sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle, > goto end; > } > pdata = rspbuf + sizeof(sdp_pdu_hdr_t); >+ pdata_len = rspsize - sizeof(sdp_pdu_hdr_t); >+ >+ if (pdata_len < sizeof(uint16_t)) { >+ SDPERR("Unexpected end of packet"); >+ status = -1; >+ goto end; >+ } >+ > rsp_count = ntohs(bt_get_unaligned((uint16_t *) pdata)); > attr_list_len += rsp_count; > pdata += sizeof(uint16_t); >+ pdata_len -= sizeof(uint16_t); > > // if continuation state set need to re-issue request before parsing >+ if (pdata_len < rsp_count + sizeof(uint8_t)) { >+ SDPERR("Unexpected end of packet: continuation state data missing"); >+ status = -1; >+ goto end; >+ } > cstate_len = *(uint8_t *) (pdata + rsp_count); > > SDPDBG("Response id : %d\n", rsphdr->pdu_id); >@@ -3138,15 +3377,17 @@ sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle, > > if (attr_list_len > 0) { > int scanned = 0; >- if (rsp_concat_buf.data_size != 0) >+ if (rsp_concat_buf.data_size != 0) { > pdata = rsp_concat_buf.data; >- rec = sdp_extract_pdu(pdata, &scanned); >+ pdata_len = rsp_concat_buf.data_size; >+ } >+ rec = sdp_extract_pdu_safe(pdata, pdata_len, &scanned); > > if (!rec) > status = -1; > } > >- end: >+end: > if (reqbuf) > free(reqbuf); > if (rsp_concat_buf.data) >@@ -3311,7 +3552,7 @@ int sdp_service_search_async(sdp_session_t *session, const sdp_list_t *search, u > pdata += sizeof(uint16_t); > > // set the request header's param length >- cstate_len = copy_cstate(pdata, NULL); >+ cstate_len = copy_cstate(pdata, SDP_REQ_BUFFER_SIZE - t->reqsize, NULL); > reqhdr->plen = htons((t->reqsize + cstate_len) - sizeof(sdp_pdu_hdr_t)); > > if (sdp_send_req(session, t->reqbuf, t->reqsize + cstate_len) < 0) { >@@ -3425,7 +3666,7 @@ int sdp_service_attr_async(sdp_session_t *session, uint32_t handle, sdp_attrreq_ > SDPDBG("Attr list length : %d\n", seqlen); > > // set the request header's param length >- cstate_len = copy_cstate(pdata, NULL); >+ cstate_len = copy_cstate(pdata, SDP_REQ_BUFFER_SIZE - t->reqsize, NULL); > reqhdr->plen = htons((t->reqsize + cstate_len) - sizeof(sdp_pdu_hdr_t)); > > if (sdp_send_req(session, t->reqbuf, t->reqsize + cstate_len) < 0) { >@@ -3544,7 +3785,7 @@ int sdp_service_search_attr_async(sdp_session_t *session, const sdp_list_t *sear > t->reqsize += seqlen; > > // set the request header's param length >- cstate_len = copy_cstate(pdata, NULL); >+ cstate_len = copy_cstate(pdata, SDP_REQ_BUFFER_SIZE - t->reqsize, NULL); > reqhdr->plen = htons((t->reqsize + cstate_len) - sizeof(sdp_pdu_hdr_t)); > > if (sdp_send_req(session, t->reqbuf, t->reqsize + cstate_len) < 0) { >@@ -3757,7 +3998,8 @@ int sdp_process(sdp_session_t *session) > reqhdr->tid = htons(sdp_gen_tid(session)); > > // add continuation state >- cstate_len = copy_cstate(t->reqbuf + t->reqsize, pcstate); >+ cstate_len = copy_cstate(t->reqbuf + t->reqsize, >+ SDP_REQ_BUFFER_SIZE - t->reqsize, pcstate); > > reqsize = t->reqsize + cstate_len; > >@@ -3836,7 +4078,7 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search > uint32_t reqsize = 0, _reqsize; > uint32_t rspsize = 0; > int seqlen = 0, attr_list_len = 0; >- int rsp_count = 0, cstate_len = 0; >+ int rsp_count = 0, cstate_len = 0, pdata_len; > uint8_t *pdata, *_pdata; > uint8_t *reqbuf, *rspbuf; > sdp_pdu_hdr_t *reqhdr, *rsphdr; >@@ -3900,12 +4142,19 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search > reqhdr->tid = htons(sdp_gen_tid(session)); > > // add continuation state (can be null) >- reqsize = _reqsize + copy_cstate(_pdata, cstate); >+ reqsize = _reqsize + copy_cstate(_pdata, >+ SDP_REQ_BUFFER_SIZE - _reqsize, cstate); > > // set the request header's param length > reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); > rsphdr = (sdp_pdu_hdr_t *) rspbuf; > status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize); >+ if (rspsize < sizeof(sdp_pdu_hdr_t)) { >+ SDPERR("Unexpected end of packet"); >+ status = -1; >+ goto end; >+ } >+ > if (status < 0) { > SDPDBG("Status : 0x%x\n", rsphdr->pdu_id); > goto end; >@@ -3917,9 +4166,25 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search > } > > pdata = rspbuf + sizeof(sdp_pdu_hdr_t); >+ pdata_len = rspsize - sizeof(sdp_pdu_hdr_t); >+ >+ if (pdata_len < sizeof(uint16_t)) { >+ SDPERR("Unexpected end of packet"); >+ status = -1; >+ goto end; >+ } >+ > rsp_count = ntohs(bt_get_unaligned((uint16_t *) pdata)); > attr_list_len += rsp_count; > pdata += sizeof(uint16_t); // pdata points to attribute list >+ pdata_len -= sizeof(uint16_t); >+ >+ if (pdata_len < rsp_count + sizeof(uint8_t)) { >+ SDPERR("Unexpected end of packet: continuation state data missing"); >+ status = -1; >+ goto end; >+ } >+ > cstate_len = *(uint8_t *) (pdata + rsp_count); > > SDPDBG("Attrlist byte count : %d\n", attr_list_len); >@@ -3946,24 +4211,27 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search > if (attr_list_len > 0) { > int scanned = 0; > >- if (rsp_concat_buf.data_size != 0) >+ if (rsp_concat_buf.data_size != 0) { > pdata = rsp_concat_buf.data; >+ pdata_len = rsp_concat_buf.data_size; >+ } > > /* > * Response is a sequence of sequence(s) for one or > * more data element sequence(s) representing services > * for which attributes are returned > */ >- scanned = sdp_extract_seqtype(pdata, &dataType, &seqlen); >+ scanned = sdp_extract_seqtype_safe(pdata, pdata_len, &dataType, &seqlen); > > SDPDBG("Bytes scanned : %d\n", scanned); > SDPDBG("Seq length : %d\n", seqlen); > > if (scanned && seqlen) { > pdata += scanned; >+ pdata_len -= scanned; > do { > int recsize = 0; >- sdp_record_t *rec = sdp_extract_pdu(pdata, &recsize); >+ sdp_record_t *rec = sdp_extract_pdu_safe(pdata, pdata_len, &recsize); > if (rec == NULL) { > SDPERR("SVC REC is null\n"); > status = -1; >@@ -3975,13 +4243,14 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search > } > scanned += recsize; > pdata += recsize; >+ pdata_len -= recsize; > > SDPDBG("Loc seq length : %d\n", recsize); > SDPDBG("Svc Rec Handle : 0x%x\n", rec->handle); > SDPDBG("Bytes scanned : %d\n", scanned); > SDPDBG("Attrlist byte count : %d\n", attr_list_len); > rec_list = sdp_list_append(rec_list, rec); >- } while (scanned < attr_list_len); >+ } while (scanned < attr_list_len && pdata_len > 0); > > SDPDBG("Successful scan of service attr lists\n"); > *rsp = rec_list;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 452715
: 310163 |
310164
|
310247
|
310250
|
310333
|
310417