diff options
| author | Marcel Holtmann <marcel@holtmann.org> | 2008-06-24 00:26:47 +0000 | 
|---|---|---|
| committer | Marcel Holtmann <marcel@holtmann.org> | 2008-06-24 00:26:47 +0000 | 
| commit | f39c79a261bf19109234df386959fc855d84d202 (patch) | |
| tree | 6ebb46b7ba25bb62523d1bb568ad4a56dfc621cf | |
| parent | bf39ef3c93da52c445a181b840cbd45601979481 (diff) | |
Use safe functions for the server PDU extraction
| -rw-r--r-- | sdpd/request.c | 26 | ||||
| -rw-r--r-- | 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(); | 
