[Patch] fix buffer truncation when client receives multiple messages

Paulius Zaleckas paulius.zaleckas at teltonika.lt
Mon Apr 7 11:33:21 CEST 2008


lgsm_handle doesn't have members you are using...

P.S. Is your tree available to the outside world?

Paulius Zaleckas

andrzej zaborowski wrote:
> Hi,
> 
> On 04/04/2008, Paulius Zaleckas <paulius.zaleckas at teltonika.lt> wrote:
>> I found this bug by running two instances of libgsm-tool -m shell and
>> issuing sl=4 command to read more than 10 messages.
>>  Cause is that response is bigger than buffer supplied to socket read
>> command. When lgsm_handle_packet parses data it finds incomplete data packet
>> at the end of this buffer. We receive missing part in next socket read
>> command.
> 
> Ugh, I'm quite sure I submitted a patch to fix this mid last year.
> 
>>  My solution is to copy incomplete part to the beginning of the buffer and
>> start filling it from the point where incomplete packet ends.
> 
> I used the same idea.  lgsm_handle_packet in my tree looks like this:
> 
> int lgsm_handle_packet(struct lgsm_handle *lh, const char *buf, int len)
> {
>         struct gsmd_msg_hdr *gmh;
>         lgsm_msg_handler *handler;
>         int rc = 0;
> 
>         if (lh->usock_len + len > sizeof(lh->usock_fifo))
>                 return -ENOMEM;
> 
>         memcpy(lh->usock_fifo + lh->usock_len, buf, len);
>         lh->usock_len += len;
>         gmh = (struct gsmd_msg_hdr *) lh->usock_fifo;
>         while (lh->usock_len >= sizeof(*gmh) &&
>                         lh->usock_len >= sizeof(*gmh) + gmh->len) {
>                 if (gmh->msg_type < __NUM_GSMD_MSGS &&
>                         (handler = lh->handler[gmh->msg_type]))
>                         rc |= handler(lh, gmh);
>                 else {
>                         fprintf(stderr, "unable to handle packet "
>                                         "type=%u id=%u\n",
>                                         gmh->msg_type, gmh->id);
>                         rc |= EINVAL;
>                 }
> 
>                 lh->usock_len -= gmh->len + sizeof(*gmh);
>                 memmove(lh->usock_fifo,
>                                 lh->usock_fifo + gmh->len + sizeof(*gmh),
>                                 lh->usock_len);
>         }
> 
>         return -rc;
> }
> 
> The usock_* fields are allocated per usock handle (I think this is
> cleaner) and the buffer is still limited.
> 
>>  This solution is backward compatible.
>>
>>  I have two more ideas how to solve this:
>>  1. Use circular buffer in libgsmd, but this adds more memory usage...
>>  2. Do the socket reading inside libgsmd and do smart processing. For
>> example read only the size of header check what is the length of the packed
>> and dynamically allocate space for it and so on... This would reduce user
>> code, improve message handling and reduce memory usage. But in this case we
>> will have to change API.
> 
> Yup this would be even better, except slightly slower because of all
> the malloc()s that would be needed.  This would be the only acceptable
> solution for GNU/Hurd for example :)
> 
> Cheers




More information about the gsmd-devel mailing list