linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Fix corrupted SDP response for sequence size > 256
@ 2012-11-19 19:04 Bart Westgeest
  2012-11-19 19:04 ` [PATCH 1/3] sdp: Inlined single use of function sdp_set_data_type Bart Westgeest
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Bart Westgeest @ 2012-11-19 19:04 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bart Westgeest

This patchset includes minor refactoring and a bug fix. The bug
is exposed when a data sequence grows beyond 256 bytes, in this case the
complete sequence data is written, but the size is truncated to one
byte, resulting in a corrupted SDP response.

RE: Feedback on potential fix for issue while advertising Feature List

Bart Westgeest (3):
  sdp: Inlined single use of function sdp_set_data_type
  sdp: Limit side effects of sdp_get_data_type and sdp_get_data_size
  sdp: Upgrade datatype SEQ8 to SEQ16 when data size is greater than
    256

 lib/sdp.c |   56 +++++++++++++++++++++++---------------------------------
 1 file changed, 23 insertions(+), 33 deletions(-)

-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/3] sdp: Inlined single use of function sdp_set_data_type
  2012-11-19 19:04 [PATCH 0/3] Fix corrupted SDP response for sequence size > 256 Bart Westgeest
@ 2012-11-19 19:04 ` Bart Westgeest
  2012-11-19 19:04 ` [PATCH 2/3] sdp: Limit side effects of sdp_get_data_type and sdp_get_data_size Bart Westgeest
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Bart Westgeest @ 2012-11-19 19:04 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bart Westgeest

Inlining single use of sdp_set_data_type to improve code readability,
since the function was doing more than just setting the data type.
---
 lib/sdp.c |   18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/lib/sdp.c b/lib/sdp.c
index 1a5bf01..dba3f59 100644
--- a/lib/sdp.c
+++ b/lib/sdp.c
@@ -666,18 +666,6 @@ static int sdp_get_data_type(sdp_buf_t *buf, uint8_t dtd)
 	return data_type;
 }
 
-static int sdp_set_data_type(sdp_buf_t *buf, uint8_t dtd)
-{
-	int data_type = 0;
-	uint8_t *p = buf->data + buf->data_size;
-
-	*p = dtd;
-	data_type = sdp_get_data_type(buf, dtd);
-	buf->data_size += data_type;
-
-	return data_type;
-}
-
 void sdp_set_attrid(sdp_buf_t *buf, uint16_t attr)
 {
 	uint8_t *p = buf->data;
@@ -815,9 +803,13 @@ int sdp_gen_pdu(sdp_buf_t *buf, sdp_data_t *d)
 	uint128_t u128;
 	uint8_t *seqp = buf->data + buf->data_size;
 
-	pdu_size = sdp_set_data_type(buf, dtd);
+	pdu_size = sdp_get_data_type(buf, dtd);
+	buf->data_size += pdu_size;
+
 	data_size = sdp_get_data_size(buf, d);
 
+	*seqp = dtd;
+
 	switch (dtd) {
 	case SDP_DATA_NIL:
 		break;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/3] sdp: Limit side effects of sdp_get_data_type and sdp_get_data_size
  2012-11-19 19:04 [PATCH 0/3] Fix corrupted SDP response for sequence size > 256 Bart Westgeest
  2012-11-19 19:04 ` [PATCH 1/3] sdp: Inlined single use of function sdp_set_data_type Bart Westgeest
@ 2012-11-19 19:04 ` Bart Westgeest
  2012-11-19 20:24   ` Anderson Lizardo
  2012-11-19 19:04 ` [PATCH 3/3] sdp: Upgrade datatype SEQ8 to SEQ16 when data size is greater than 256 Bart Westgeest
  2012-11-20 12:57 ` [PATCH 0/3] Fix corrupted SDP response for sequence size > 256 Johan Hedberg
  3 siblings, 1 reply; 9+ messages in thread
From: Bart Westgeest @ 2012-11-19 19:04 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bart Westgeest

Remove modification of buf->buf_size in 'get' functions. Data is
still indirectly modified due to recursive nature of code.

Renamed sdp_get_data_type to sdp_get_data_type_size.
---
 lib/sdp.c |   26 +++++++++-----------------
 1 file changed, 9 insertions(+), 17 deletions(-)

diff --git a/lib/sdp.c b/lib/sdp.c
index dba3f59..026163e 100644
--- a/lib/sdp.c
+++ b/lib/sdp.c
@@ -633,37 +633,32 @@ void sdp_set_seq_len(uint8_t *ptr, uint32_t length)
 	}
 }
 
-static int sdp_get_data_type(sdp_buf_t *buf, uint8_t dtd)
+static int sdp_get_data_type_size(uint8_t dtd)
 {
-	int data_type = 0;
-
-	data_type += sizeof(uint8_t);
+	int size = sizeof(uint8_t);
 
 	switch (dtd) {
 	case SDP_SEQ8:
 	case SDP_TEXT_STR8:
 	case SDP_URL_STR8:
 	case SDP_ALT8:
-		data_type += sizeof(uint8_t);
+		size += sizeof(uint8_t);
 		break;
 	case SDP_SEQ16:
 	case SDP_TEXT_STR16:
 	case SDP_URL_STR16:
 	case SDP_ALT16:
-		data_type += sizeof(uint16_t);
+		size += sizeof(uint16_t);
 		break;
 	case SDP_SEQ32:
 	case SDP_TEXT_STR32:
 	case SDP_URL_STR32:
 	case SDP_ALT32:
-		data_type += sizeof(uint32_t);
+		size += sizeof(uint32_t);
 		break;
 	}
 
-	if (!buf->data)
-		buf->buf_size += data_type;
-
-	return data_type;
+	return size;
 }
 
 void sdp_set_attrid(sdp_buf_t *buf, uint16_t attr)
@@ -762,9 +757,6 @@ static int sdp_get_data_size(sdp_buf_t *buf, sdp_data_t *d)
 		break;
 	}
 
-	if (!buf->data)
-		buf->buf_size += data_size;
-
 	return data_size;
 }
 
@@ -783,8 +775,8 @@ static int sdp_gen_buffer(sdp_buf_t *buf, sdp_data_t *d)
 	/* attribute length */
 	buf->buf_size += sizeof(uint8_t) + sizeof(uint16_t);
 
-	sdp_get_data_type(buf, d->dtd);
-	sdp_get_data_size(buf, d);
+	buf->buf_size += sdp_get_data_type_size(d->dtd);
+	buf->buf_size += sdp_get_data_size(buf, d);
 
 	if (buf->buf_size > UCHAR_MAX && d->dtd == SDP_SEQ8)
 		buf->buf_size += sizeof(uint8_t);
@@ -803,7 +795,7 @@ int sdp_gen_pdu(sdp_buf_t *buf, sdp_data_t *d)
 	uint128_t u128;
 	uint8_t *seqp = buf->data + buf->data_size;
 
-	pdu_size = sdp_get_data_type(buf, dtd);
+	pdu_size = sdp_get_data_type_size(dtd);
 	buf->data_size += pdu_size;
 
 	data_size = sdp_get_data_size(buf, d);
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/3] sdp: Upgrade datatype SEQ8 to SEQ16 when data size is greater than 256
  2012-11-19 19:04 [PATCH 0/3] Fix corrupted SDP response for sequence size > 256 Bart Westgeest
  2012-11-19 19:04 ` [PATCH 1/3] sdp: Inlined single use of function sdp_set_data_type Bart Westgeest
  2012-11-19 19:04 ` [PATCH 2/3] sdp: Limit side effects of sdp_get_data_type and sdp_get_data_size Bart Westgeest
@ 2012-11-19 19:04 ` Bart Westgeest
  2012-11-19 20:38   ` Anderson Lizardo
  2012-11-20 12:57 ` [PATCH 0/3] Fix corrupted SDP response for sequence size > 256 Johan Hedberg
  3 siblings, 1 reply; 9+ messages in thread
From: Bart Westgeest @ 2012-11-19 19:04 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bart Westgeest

Fixes a bug where the complete sequence data is written, but the size
is truncated to one byte.
---
 lib/sdp.c |   18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/lib/sdp.c b/lib/sdp.c
index 026163e..ceb1192 100644
--- a/lib/sdp.c
+++ b/lib/sdp.c
@@ -786,23 +786,29 @@ static int sdp_gen_buffer(sdp_buf_t *buf, sdp_data_t *d)
 
 int sdp_gen_pdu(sdp_buf_t *buf, sdp_data_t *d)
 {
-	uint32_t pdu_size = 0, data_size = 0;
+	uint32_t pdu_size, data_size;
 	unsigned char *src = NULL, is_seq = 0, is_alt = 0;
-	uint8_t dtd = d->dtd;
 	uint16_t u16;
 	uint32_t u32;
 	uint64_t u64;
 	uint128_t u128;
 	uint8_t *seqp = buf->data + buf->data_size;
+	uint32_t orig_data_size = buf->data_size;
 
-	pdu_size = sdp_get_data_type_size(dtd);
+recalculate:
+	pdu_size = sdp_get_data_type_size(d->dtd);
 	buf->data_size += pdu_size;
 
 	data_size = sdp_get_data_size(buf, d);
+	if (data_size > UCHAR_MAX && d->dtd == SDP_SEQ8) {
+		buf->data_size = orig_data_size;
+		d->dtd = SDP_SEQ16;
+		goto recalculate;
+	}
 
-	*seqp = dtd;
+	*seqp = d->dtd;
 
-	switch (dtd) {
+	switch (d->dtd) {
 	case SDP_DATA_NIL:
 		break;
 	case SDP_UINT8:
@@ -884,7 +890,7 @@ int sdp_gen_pdu(sdp_buf_t *buf, sdp_data_t *d)
 		if (src && buf->buf_size >= buf->data_size + data_size) {
 			memcpy(buf->data + buf->data_size, src, data_size);
 			buf->data_size += data_size;
-		} else if (dtd != SDP_DATA_NIL) {
+		} else if (d->dtd != SDP_DATA_NIL) {
 			SDPDBG("Gen PDU : Can't copy from invalid source or dest\n");
 		}
 	}
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] sdp: Limit side effects of sdp_get_data_type and sdp_get_data_size
  2012-11-19 19:04 ` [PATCH 2/3] sdp: Limit side effects of sdp_get_data_type and sdp_get_data_size Bart Westgeest
@ 2012-11-19 20:24   ` Anderson Lizardo
  2012-11-19 21:06     ` Bart Westgeest
  0 siblings, 1 reply; 9+ messages in thread
From: Anderson Lizardo @ 2012-11-19 20:24 UTC (permalink / raw)
  To: Bart Westgeest; +Cc: linux-bluetooth

Hi Bart,

On Mon, Nov 19, 2012 at 3:04 PM, Bart Westgeest <bart@elbrys.com> wrote:
> @@ -762,9 +757,6 @@ static int sdp_get_data_size(sdp_buf_t *buf, sdp_data_t *d)
>                 break;
>         }
>
> -       if (!buf->data)
> -               buf->buf_size += data_size;
> -
>         return data_size;
>  }
>
> @@ -783,8 +775,8 @@ static int sdp_gen_buffer(sdp_buf_t *buf, sdp_data_t *d)
>         /* attribute length */
>         buf->buf_size += sizeof(uint8_t) + sizeof(uint16_t);
>
> -       sdp_get_data_type(buf, d->dtd);
> -       sdp_get_data_size(buf, d);
> +       buf->buf_size += sdp_get_data_type_size(d->dtd);
> +       buf->buf_size += sdp_get_data_size(buf, d);

No need to check for "if (!buf->data)" like in the original code?

>
>         if (buf->buf_size > UCHAR_MAX && d->dtd == SDP_SEQ8)
>                 buf->buf_size += sizeof(uint8_t);
> @@ -803,7 +795,7 @@ int sdp_gen_pdu(sdp_buf_t *buf, sdp_data_t *d)
>         uint128_t u128;
>         uint8_t *seqp = buf->data + buf->data_size;
>
> -       pdu_size = sdp_get_data_type(buf, dtd);
> +       pdu_size = sdp_get_data_type_size(dtd);

Same here. Additionally, buf->buf_size is not being updated.

>         buf->data_size += pdu_size;
>
>         data_size = sdp_get_data_size(buf, d);

Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/3] sdp: Upgrade datatype SEQ8 to SEQ16 when data size is greater than 256
  2012-11-19 19:04 ` [PATCH 3/3] sdp: Upgrade datatype SEQ8 to SEQ16 when data size is greater than 256 Bart Westgeest
@ 2012-11-19 20:38   ` Anderson Lizardo
  2012-11-19 21:33     ` Bart Westgeest
  0 siblings, 1 reply; 9+ messages in thread
From: Anderson Lizardo @ 2012-11-19 20:38 UTC (permalink / raw)
  To: Bart Westgeest; +Cc: linux-bluetooth

Hi Bart,

On Mon, Nov 19, 2012 at 3:04 PM, Bart Westgeest <bart@elbrys.com> wrote:
> Fixes a bug where the complete sequence data is written, but the size
> is truncated to one byte.
> ---
>  lib/sdp.c |   18 ++++++++++++------
>  1 file changed, 12 insertions(+), 6 deletions(-)
>
> diff --git a/lib/sdp.c b/lib/sdp.c
> index 026163e..ceb1192 100644
> --- a/lib/sdp.c
> +++ b/lib/sdp.c
> @@ -786,23 +786,29 @@ static int sdp_gen_buffer(sdp_buf_t *buf, sdp_data_t *d)
>
>  int sdp_gen_pdu(sdp_buf_t *buf, sdp_data_t *d)
>  {
> -       uint32_t pdu_size = 0, data_size = 0;
> +       uint32_t pdu_size, data_size;
>         unsigned char *src = NULL, is_seq = 0, is_alt = 0;
> -       uint8_t dtd = d->dtd;
>         uint16_t u16;
>         uint32_t u32;
>         uint64_t u64;
>         uint128_t u128;
>         uint8_t *seqp = buf->data + buf->data_size;
> +       uint32_t orig_data_size = buf->data_size;
>
> -       pdu_size = sdp_get_data_type_size(dtd);
> +recalculate:
> +       pdu_size = sdp_get_data_type_size(d->dtd);
>         buf->data_size += pdu_size;
>
>         data_size = sdp_get_data_size(buf, d);
> +       if (data_size > UCHAR_MAX && d->dtd == SDP_SEQ8) {
> +               buf->data_size = orig_data_size;
> +               d->dtd = SDP_SEQ16;
> +               goto recalculate;

IMHO, using "goto" here is too complicated for 3 lines of code that
will just be run at most twice. So I would simply duplicate them
inside the if(). But others may have different opinion on this regard.

> +       }
>
> -       *seqp = dtd;
> +       *seqp = d->dtd;
>
> -       switch (dtd) {
> +       switch (d->dtd) {
>         case SDP_DATA_NIL:
>                 break;
>         case SDP_UINT8:

Best Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] sdp: Limit side effects of sdp_get_data_type and sdp_get_data_size
  2012-11-19 20:24   ` Anderson Lizardo
@ 2012-11-19 21:06     ` Bart Westgeest
  0 siblings, 0 replies; 9+ messages in thread
From: Bart Westgeest @ 2012-11-19 21:06 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: linux-bluetooth

Hi Anderson,

>> -       sdp_get_data_type(buf, d->dtd);
>> -       sdp_get_data_size(buf, d);
>> +       buf->buf_size += sdp_get_data_type_size(d->dtd);
>> +       buf->buf_size += sdp_get_data_size(buf, d);
>
> No need to check for "if (!buf->data)" like in the original code?

I do not think there's a need for it, this modification is in 
sdp_gen_buffer. sdp_gen_buffer is called three times from the following 
functions: (1) sdp_attr_size, (2) sdp_append_to_pdu, and (3) 
gen_dataseq_pdu.

For (2) & (3), buf is memset to 0 prior to calling sdp_gen_buffer, thus 
buf->data is always NULL.

For (1), buf is also memset to 0 for the first call to sdp_attr_size, 
which is called repetitively in a foreach statement. Repetitive calls to 
sdp_gen_buffer on the same buffer will not (ever) result in an 
allocation of buf->data as far as I can tell.

>> -       pdu_size = sdp_get_data_type(buf, dtd);
>> +       pdu_size = sdp_get_data_type_size(dtd);
>
> Same here. Additionally, buf->buf_size is not being updated.

This modification is in sdp_gen_pdu. sdp_gen_pdu is never called with 
buf->data == NULL. If it would, then the initialization of seqp in 
sdp_gen_pdu is erroneous, since it uses buf->data without verifying it.

In addition, in the current code, sdp_gen_pdu is only called from three 
locations: (1) get_data_size, (2) sdp_append_to_pdu, (3) 
gen_dataseq_pdu. In all cases the buf->data is either allocated prior to 
calling (2 & 3), or (1) there's an if statement preventing sdp_gen_pdu 
from being called when buf->data == NULL.

Bart

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/3] sdp: Upgrade datatype SEQ8 to SEQ16 when data size is greater than 256
  2012-11-19 20:38   ` Anderson Lizardo
@ 2012-11-19 21:33     ` Bart Westgeest
  0 siblings, 0 replies; 9+ messages in thread
From: Bart Westgeest @ 2012-11-19 21:33 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: linux-bluetooth

Hi Anderson,

>> +recalculate:
>> +       pdu_size = sdp_get_data_type_size(d->dtd);
>>          buf->data_size += pdu_size;
>>
>>          data_size = sdp_get_data_size(buf, d);
>> +       if (data_size > UCHAR_MAX && d->dtd == SDP_SEQ8) {
>> +               buf->data_size = orig_data_size;
>> +               d->dtd = SDP_SEQ16;
>> +               goto recalculate;
>
> IMHO, using "goto" here is too complicated for 3 lines of code that
> will just be run at most twice. So I would simply duplicate them
> inside the if(). But others may have different opinion on this regard.

I don't have strong feelings about this. I can change it.

One could argue that the way I did it shows that the *same* code needs 
to be executed again. (It the same code can also be moved into a 
do-while) - this, as well what I have currently, would allow for a data 
upgrade to SDP_SEQ16 -> SDP_SEQ32, and SDP_ALT8 -> SDP_ALT16-> SDP_ALT32 
as well, which theoretically are also needed as far as I can tell.

For the record, in any regard, I think the fix is rather ugly, goto 
statement or not. This problem is now 'fixed' in two places (the other 
one in sdp_append_to_buf, with the corresponding data length increase in 
sdp_gen_buffer). IMHO, the code requires a bigger cleanup. I actually 
made an attempt at it, but the fix got too big, and I opted for what I 
submitted instead.

To get back on topic, let me know if you or others want me to re-submit.

Bart

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/3] Fix corrupted SDP response for sequence size > 256
  2012-11-19 19:04 [PATCH 0/3] Fix corrupted SDP response for sequence size > 256 Bart Westgeest
                   ` (2 preceding siblings ...)
  2012-11-19 19:04 ` [PATCH 3/3] sdp: Upgrade datatype SEQ8 to SEQ16 when data size is greater than 256 Bart Westgeest
@ 2012-11-20 12:57 ` Johan Hedberg
  3 siblings, 0 replies; 9+ messages in thread
From: Johan Hedberg @ 2012-11-20 12:57 UTC (permalink / raw)
  To: Bart Westgeest; +Cc: linux-bluetooth

Hi Bart,

On Mon, Nov 19, 2012, Bart Westgeest wrote:
> This patchset includes minor refactoring and a bug fix. The bug
> is exposed when a data sequence grows beyond 256 bytes, in this case the
> complete sequence data is written, but the size is truncated to one
> byte, resulting in a corrupted SDP response.
> 
> RE: Feedback on potential fix for issue while advertising Feature List
> 
> Bart Westgeest (3):
>   sdp: Inlined single use of function sdp_set_data_type
>   sdp: Limit side effects of sdp_get_data_type and sdp_get_data_size
>   sdp: Upgrade datatype SEQ8 to SEQ16 when data size is greater than
>     256
> 
>  lib/sdp.c |   56 +++++++++++++++++++++++---------------------------------
>  1 file changed, 23 insertions(+), 33 deletions(-)

I'm happy with these as well as your responses to the feedback you got,
so the patches are now pushed upstream.

Regarding the SDP code needing cleanups/fixing/rewriting in general, we
know :) This is one of the oldest pieces of code in the stack which
could definitely use a rewrite. However, no one has come along with the
time to do it yet.

Johan

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2012-11-20 12:57 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-19 19:04 [PATCH 0/3] Fix corrupted SDP response for sequence size > 256 Bart Westgeest
2012-11-19 19:04 ` [PATCH 1/3] sdp: Inlined single use of function sdp_set_data_type Bart Westgeest
2012-11-19 19:04 ` [PATCH 2/3] sdp: Limit side effects of sdp_get_data_type and sdp_get_data_size Bart Westgeest
2012-11-19 20:24   ` Anderson Lizardo
2012-11-19 21:06     ` Bart Westgeest
2012-11-19 19:04 ` [PATCH 3/3] sdp: Upgrade datatype SEQ8 to SEQ16 when data size is greater than 256 Bart Westgeest
2012-11-19 20:38   ` Anderson Lizardo
2012-11-19 21:33     ` Bart Westgeest
2012-11-20 12:57 ` [PATCH 0/3] Fix corrupted SDP response for sequence size > 256 Johan Hedberg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).