From f39c79a261bf19109234df386959fc855d84d202 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 24 Jun 2008 00:26:47 +0000 Subject: Use safe functions for the server PDU extraction --- sdpd/request.c | 26 ++++++++++++++++++++++++-- sdpd/service.c | 32 +++++++++++++++++++++++++++----- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/sdpd/request.c b/sdpd/request.c index 44b65f69..9020dd38 100644 --- a/sdpd/request.c +++ b/sdpd/request.c @@ -67,8 +67,9 @@ static int extract_des(uint8_t *buf, int len, sdp_list_t **svcReqSeq, uint8_t *p uint8_t dataType; int status = 0; const uint8_t *p; + int bufsize; - scanned = sdp_extract_seqtype(buf, &seqType, &data_size); + scanned = sdp_extract_seqtype_safe(buf, len, &seqType, &data_size); debug("Seq type : %d", seqType); if (!scanned || (seqType != SDP_SEQ8 && seqType != SDP_SEQ16)) { @@ -76,6 +77,7 @@ static int extract_des(uint8_t *buf, int len, sdp_list_t **svcReqSeq, uint8_t *p return -1; } p = buf + scanned; + bufsize = len - scanned; debug("Data size : %d", data_size); @@ -83,6 +85,11 @@ static int extract_des(uint8_t *buf, int len, sdp_list_t **svcReqSeq, uint8_t *p char *pElem = NULL; int localSeqLength = 0; + if (bufsize < sizeof(uint8_t)) { + debug("->Unexpected end of buffer"); + return -1; + } + dataType = *(uint8_t *)p; debug("Data type: 0x%02x", dataType); @@ -100,27 +107,42 @@ static int extract_des(uint8_t *buf, int len, sdp_list_t **svcReqSeq, uint8_t *p case SDP_UINT16: p += sizeof(uint8_t); seqlen += sizeof(uint8_t); + bufsize -= sizeof(uint8_t); + if (bufsize < sizeof(uint16_t)) { + debug("->Unexpected end of buffer"); + return -1; + } + pElem = malloc(sizeof(uint16_t)); bt_put_unaligned(ntohs(bt_get_unaligned((uint16_t *)p)), (uint16_t *)pElem); p += sizeof(uint16_t); seqlen += sizeof(uint16_t); + bufsize -= sizeof(uint16_t); break; case SDP_UINT32: p += sizeof(uint8_t); seqlen += sizeof(uint8_t); + bufsize -= sizeof(uint8_t); + if (bufsize < (int)sizeof(uint32_t)) { + debug("->Unexpected end of buffer"); + return -1; + } + pElem = malloc(sizeof(uint32_t)); bt_put_unaligned(ntohl(bt_get_unaligned((uint32_t *)p)), (uint32_t *)pElem); p += sizeof(uint32_t); seqlen += sizeof(uint32_t); + bufsize -= sizeof(uint32_t); break; case SDP_UUID16: case SDP_UUID32: case SDP_UUID128: pElem = malloc(sizeof(uuid_t)); - status = sdp_uuid_extract(p, (uuid_t *)pElem, &localSeqLength); + status = sdp_uuid_extract_safe(p, bufsize, (uuid_t *) pElem, &localSeqLength); if (status == 0) { seqlen += localSeqLength; p += localSeqLength; + bufsize -= localSeqLength; } break; default: diff --git a/sdpd/service.c b/sdpd/service.c index 57a272db..a1072cd6 100644 --- a/sdpd/service.c +++ b/sdpd/service.c @@ -412,7 +412,7 @@ int remove_record_from_server(uint32_t handle) } // FIXME: refactor for server-side -static sdp_record_t *extract_pdu_server(bdaddr_t *device, uint8_t *p, uint32_t handleExpected, int *scanned) +static sdp_record_t *extract_pdu_server(bdaddr_t *device, uint8_t *p, int bufsize, uint32_t handleExpected, int *scanned) { int extractStatus = -1, localExtractedLength = 0; uint8_t dtd; @@ -422,13 +422,24 @@ static sdp_record_t *extract_pdu_server(bdaddr_t *device, uint8_t *p, uint32_t h sdp_data_t *pAttr = NULL; uint32_t handle = 0xffffffff; - *scanned = sdp_extract_seqtype(p, &dtd, &seqlen); + *scanned = sdp_extract_seqtype_safe(p, bufsize, &dtd, &seqlen); p += *scanned; + bufsize -= *scanned; + + if (bufsize < sizeof(uint8_t) + sizeof(uint8_t)) { + debug("Unexpected end of packet"); + return NULL; + } + lookAheadAttrId = ntohs(bt_get_unaligned((uint16_t *) (p + sizeof(uint8_t)))); debug("Look ahead attr id : %d", lookAheadAttrId); if (lookAheadAttrId == SDP_ATTR_RECORD_HANDLE) { + if (bufsize < (sizeof(uint8_t) * 2) + sizeof(uint16_t) + sizeof(uint32_t)) { + debug("Unexpected end of packet"); + return NULL; + } handle = ntohl(bt_get_unaligned((uint32_t *) (p + sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint8_t)))); @@ -456,6 +467,11 @@ static sdp_record_t *extract_pdu_server(bdaddr_t *device, uint8_t *p, uint32_t h int attrSize = sizeof(uint8_t); int attrValueLength = 0; + if (bufsize < attrSize + sizeof(uint16_t)) { + debug("Unexpected end of packet: Terminating extraction of attributes"); + break; + } + debug("Extract PDU, sequenceLength: %d localExtractedLength: %d", seqlen, localExtractedLength); dtd = *(uint8_t *) p; @@ -464,7 +480,8 @@ static sdp_record_t *extract_pdu_server(bdaddr_t *device, uint8_t *p, uint32_t h debug("DTD of attrId : %d Attr id : 0x%x", dtd, attrId); - pAttr = sdp_extract_attr(p + attrSize, &attrValueLength, rec); + pAttr = sdp_extract_attr_safe(p + attrSize, bufsize - attrSize, + &attrValueLength, rec); debug("Attr id : 0x%x attrValueLength : %d", attrId, attrValueLength); @@ -475,6 +492,7 @@ static sdp_record_t *extract_pdu_server(bdaddr_t *device, uint8_t *p, uint32_t h } localExtractedLength += attrSize; p += attrSize; + bufsize -= attrSize; sdp_attr_replace(rec, attrId, pAttr); extractStatus = 0; debug("Extract PDU, seqLength: %d localExtractedLength: %d", @@ -499,16 +517,18 @@ int service_register_req(sdp_req_t *req, sdp_buf_t *rsp) int scanned = 0; sdp_data_t *handle; uint8_t *p = req->buf + sizeof(sdp_pdu_hdr_t); + int bufsize = req->len - sizeof(sdp_pdu_hdr_t); sdp_record_t *rec; req->flags = *p++; if (req->flags & SDP_DEVICE_RECORD) { bacpy(&req->device, (bdaddr_t *) p); p += sizeof(bdaddr_t); + bufsize -= sizeof(bdaddr_t); } // save image of PDU: we need it when clients request this attribute - rec = extract_pdu_server(&req->device, p, 0xffffffff, &scanned); + rec = extract_pdu_server(&req->device, p, bufsize, 0xffffffff, &scanned); if (!rec) goto invalid; @@ -566,18 +586,20 @@ int service_update_req(sdp_req_t *req, sdp_buf_t *rsp) sdp_record_t *orec; int status = 0, scanned = 0; uint8_t *p = req->buf + sizeof(sdp_pdu_hdr_t); + int bufsize = req->len - sizeof(sdp_pdu_hdr_t); uint32_t handle = ntohl(bt_get_unaligned((uint32_t *) p)); debug("Svc Rec Handle: 0x%x", handle); p += sizeof(uint32_t); + bufsize -= sizeof(uint32_t); orec = sdp_record_find(handle); debug("SvcRecOld: %p", orec); if (orec) { - sdp_record_t *nrec = extract_pdu_server(BDADDR_ANY, p, handle, &scanned); + sdp_record_t *nrec = extract_pdu_server(BDADDR_ANY, p, bufsize, handle, &scanned); if (nrec && handle == nrec->handle) { update_db_timestamp(); update_svclass_list(); -- cgit