diff mbox series

AW: AW: [swupdate] [PATCH] cpio_utils: fix infinite read when interrupting an update

Message ID cbfd7cc5cc8d4c5fbbb8f14a30745f93@de.bosch.com
State Changes Requested
Headers show
Series AW: AW: [swupdate] [PATCH] cpio_utils: fix infinite read when interrupting an update | expand

Commit Message

mark.jonas Sept. 21, 2018, 10:50 a.m. UTC
> > How do we continue with this issue? Have you been able to reproduce the
> problem using the additional information (compressed image) we gave?
> 
> I have not (yet) tested, but you explanation makes things much more clearer.

I won't be able to further testing today. We will test the proposal and
I plan getting back to you on Tuesday.

Greetings,
Mark

Building Technologies, Panel Software Fire (BT-FIR/ENG1) 
Bosch Sicherheitssysteme GmbH | Postfach 11 11 | 85626 Grasbrunn | GERMANY | www.boschsecurity.com

Sitz: Stuttgart, Registergericht: Amtsgericht Stuttgart HRB 23118 
Aufsichtsratsvorsitzender: Stefan Hartung; Geschäftsführung: Tanja Rückert, Andreas Bartz, Thomas Quante, Bernhard Schuster

Comments

Stefano Babic Sept. 21, 2018, 10:53 a.m. UTC | #1
Hi Mark,

On 21/09/2018 12:50, Jonas Mark (BT-FIR/ENG1) wrote:
> diff --git a/core/cpio_utils.c b/core/cpio_utils.c
> index 40ae474..ef5e30c 100644
> --- a/core/cpio_utils.c
> +++ b/core/cpio_utils.c
> @@ -135,7 +135,10 @@ static int input_step(void *state, void *buffer, size_t size)
>                 size = s->nbytes;
>         }
>         int ret = fill_buffer(s->fdin, buffer, size, s->offs, &s->checksum, s->dgst);
> -       if (ret < 0) {
> +       if (ret <= 0) {
> +               if (ret == 0) {
> +                       s->eof = true;
> +               }
>                 return ret;
>         }
>         s->nbytes -= size;
> 		
> Hi Stefano,
> 
>>>>>> When using the IPC API to do an update from a stream, a new update
>>>>>> cannot be started if the previous one is interrupted.
>>>>>>
>>>>>> The root cause is: when the client closes the socket, the read on the
>>>>>> server side will return 0 and it is treated as a successful read. Thus
>>>>>> it goes into an infinite read loop.
> 
>>>> We think that gunzip_step() has a fatal problem when ret == 0. If
>>>> upstream_step() returns 0, then s->strm.avail_in will be 0, and then
>>>> inflate() has nothing to do. Thus the output buffer will not be used
>>>> and outlen is 0. This will cause that the loop continues because
>>>> nothing was done. But the next call of upstream_step() will return 0
>>>> again because the client does not deliver data any more. This is the
>>>> live lock we are experiencing.
>>
>> Ok, I have not tested, but this is plausible. Anyway, it looks to me
>> strange how you think to fix this. The decompression step, as the other
>> ones, check for an EOF condition:
>>
>>  241                 if (s->eof) {
>>  242                         break;
>>  243                 }
>>
>> This looks to me the natural way for handling the case. The thing is
>> that the input step does not set the eof flag, causing the endless loop
>> you detect - instead of hiding the status in the return code as in
>> patch, we should clearly state that a eof occurs and this should be managed.
>>
>> What about just to set s->eof in input step ?
> 
> Sounds good to me. Is this what you mean?
> 
> diff --git a/core/cpio_utils.c b/core/cpio_utils.c
> index 40ae474..ef5e30c 100644
> --- a/core/cpio_utils.c
> +++ b/core/cpio_utils.c
> @@ -135,7 +135,10 @@ static int input_step(void *state, void *buffer, size_t size)
>                 size = s->nbytes;
>         }
>         int ret = fill_buffer(s->fdin, buffer, size, s->offs, &s->checksum, s->dgst);
> -       if (ret < 0) {
> +       if (ret <= 0) {
> +               if (ret == 0) {
> +                       s->eof = true;
> +               }
>                 return ret;
>         }
>         s->nbytes -= size;
> 

Right, this is what I meant.



>>> How do we continue with this issue? Have you been able to reproduce the
>> problem using the additional information (compressed image) we gave?
>>
>> I have not (yet) tested, but you explanation makes things much more clearer.
> 
> I won't be able to further testing today. We will test the proposal and
> I plan getting back to you on Tuesday.

ok, thanks !

Best regards,
Stefano
diff mbox series

Patch

diff --git a/core/cpio_utils.c b/core/cpio_utils.c
index 40ae474..ef5e30c 100644
--- a/core/cpio_utils.c
+++ b/core/cpio_utils.c
@@ -135,7 +135,10 @@  static int input_step(void *state, void *buffer, size_t size)
                size = s->nbytes;
        }
        int ret = fill_buffer(s->fdin, buffer, size, s->offs, &s->checksum, s->dgst);
-       if (ret < 0) {
+       if (ret <= 0) {
+               if (ret == 0) {
+                       s->eof = true;
+               }
                return ret;
        }
        s->nbytes -= size;
		
Hi Stefano,

> >>>> When using the IPC API to do an update from a stream, a new update
> >>>> cannot be started if the previous one is interrupted.
> >>>>
> >>>> The root cause is: when the client closes the socket, the read on the
> >>>> server side will return 0 and it is treated as a successful read. Thus
> >>>> it goes into an infinite read loop.

> >> We think that gunzip_step() has a fatal problem when ret == 0. If
> >> upstream_step() returns 0, then s->strm.avail_in will be 0, and then
> >> inflate() has nothing to do. Thus the output buffer will not be used
> >> and outlen is 0. This will cause that the loop continues because
> >> nothing was done. But the next call of upstream_step() will return 0
> >> again because the client does not deliver data any more. This is the
> >> live lock we are experiencing.
> 
> Ok, I have not tested, but this is plausible. Anyway, it looks to me
> strange how you think to fix this. The decompression step, as the other
> ones, check for an EOF condition:
> 
>  241                 if (s->eof) {
>  242                         break;
>  243                 }
> 
> This looks to me the natural way for handling the case. The thing is
> that the input step does not set the eof flag, causing the endless loop
> you detect - instead of hiding the status in the return code as in
> patch, we should clearly state that a eof occurs and this should be managed.
> 
> What about just to set s->eof in input step ?

Sounds good to me. Is this what you mean?

diff --git a/core/cpio_utils.c b/core/cpio_utils.c
index 40ae474..ef5e30c 100644
--- a/core/cpio_utils.c
+++ b/core/cpio_utils.c
@@ -135,7 +135,10 @@  static int input_step(void *state, void *buffer, size_t size)
                size = s->nbytes;
        }
        int ret = fill_buffer(s->fdin, buffer, size, s->offs, &s->checksum, s->dgst);
-       if (ret < 0) {
+       if (ret <= 0) {
+               if (ret == 0) {
+                       s->eof = true;
+               }
                return ret;
        }
        s->nbytes -= size;