diff mbox series

[v2] cpio_utils: fix infinite read when interrupting an update

Message ID 1537956103-17504-1-git-send-email-mark.jonas@de.bosch.com
State Accepted
Headers show
Series [v2] cpio_utils: fix infinite read when interrupting an update | expand

Commit Message

Jonas Mark (BT-FIR/ENG1-Grb) Sept. 26, 2018, 10:01 a.m. UTC
From: Ben Guan <ben.guan@cn.bosch.com>

When using the IPC API to do an update from a stream using a compressed
image, 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 in
gunzip_step(). Thus, it goes into an infinite read loop.

It is fixed by adhering to the contract that an upstream step return
zero in case of EOF.

It can be reproduced using a compressed image:

1. Start the server via "swupdate -e stable,image2".
2. Trigger an update via "swupdate-client image.swu".
3. Cancel the update via Ctrl + C.
4. Trigger another update via "swupdate-client image.swu".

The following is the sw-description file used for the test:

software =
{
    version = "4.0.0";

    hardware-compatibility: ["4.0"];

    stable = {
        image1: {
            images: (
            {
                filename = "rootfs.ext4.gz";
                device = "/dev/mmcblk2p1";
                compressed = true;
                installed-directly = true;
                sha256 = "@SHA256SUM@";
            }
            );
        };
        image2: {
            images: (
            {
                filename = "rootfs.ext4.gz";
                device = "/dev/mmcblk2p2";
                compressed = true;
                installed-directly = true;
                sha256 = "@SHA256SUM@";
            }
            );
        };
    };
}

Signed-off-by: Ben Guan <ben.guan@cn.bosch.com>
Signed-off-by: Mark Jonas <mark.jonas@de.bosch.com>
---
 core/cpio_utils.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

Comments

Stefano Babic Sept. 30, 2018, 11:06 a.m. UTC | #1
On 26/09/2018 12:01, Mark Jonas wrote:
> From: Ben Guan <ben.guan@cn.bosch.com>
> 
> When using the IPC API to do an update from a stream using a compressed
> image, 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 in
> gunzip_step(). Thus, it goes into an infinite read loop.
> 
> It is fixed by adhering to the contract that an upstream step return
> zero in case of EOF.
> 
> It can be reproduced using a compressed image:
> 
> 1. Start the server via "swupdate -e stable,image2".
> 2. Trigger an update via "swupdate-client image.swu".
> 3. Cancel the update via Ctrl + C.
> 4. Trigger another update via "swupdate-client image.swu".
> 
> The following is the sw-description file used for the test:
> 
> software =
> {
>     version = "4.0.0";
> 
>     hardware-compatibility: ["4.0"];
> 
>     stable = {
>         image1: {
>             images: (
>             {
>                 filename = "rootfs.ext4.gz";
>                 device = "/dev/mmcblk2p1";
>                 compressed = true;
>                 installed-directly = true;
>                 sha256 = "@SHA256SUM@";
>             }
>             );
>         };
>         image2: {
>             images: (
>             {
>                 filename = "rootfs.ext4.gz";
>                 device = "/dev/mmcblk2p2";
>                 compressed = true;
>                 installed-directly = true;
>                 sha256 = "@SHA256SUM@";
>             }
>             );
>         };
>     };
> }
> 
> Signed-off-by: Ben Guan <ben.guan@cn.bosch.com>
> Signed-off-by: Mark Jonas <mark.jonas@de.bosch.com>
> ---
>  core/cpio_utils.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/core/cpio_utils.c b/core/cpio_utils.c
> index 40ae474..0be31e6 100644
> --- a/core/cpio_utils.c
> +++ b/core/cpio_utils.c
> @@ -135,7 +135,7 @@ 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) {
>  		return ret;
>  	}
>  	s->nbytes -= size;
> @@ -173,6 +173,8 @@ static int decrypt_step(void *state, void *buffer, size_t size)
>  	ret = s->upstream_step(s->upstream_state, s->input, sizeof s->input);
>  	if (ret < 0) {
>  		return ret;
> +	} else if (ret == 0) {
> +		s->eof = true;
>  	}
>  
>  	inlen = ret;
> @@ -234,6 +236,8 @@ static int gunzip_step(void *state, void *buffer, size_t size)
>  			ret = s->upstream_step(s->upstream_state, s->input, sizeof s->input);
>  			if (ret < 0) {
>  				return ret;
> +			} else if (ret == 0) {
> +				s->eof = true;
>  			}
>  			s->strm.avail_in = ret;
>  			s->strm.next_in = s->input;
> @@ -317,7 +321,7 @@ int copyfile(int fdin, void *out, unsigned int nbytes, unsigned long *offs, unsi
>  		if (!input_state.dgst)
>  			return -EFAULT;
>  	}
> - 
> +
>  	if (encrypted) {
>  		aes_key = get_aes_key();
>  		ivt = get_aes_ivt();
> 


Acked-by: Stefano Babic <sbabic@denx.de>

Best regards,
Stefano Babic
diff mbox series

Patch

diff --git a/core/cpio_utils.c b/core/cpio_utils.c
index 40ae474..0be31e6 100644
--- a/core/cpio_utils.c
+++ b/core/cpio_utils.c
@@ -135,7 +135,7 @@  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) {
 		return ret;
 	}
 	s->nbytes -= size;
@@ -173,6 +173,8 @@  static int decrypt_step(void *state, void *buffer, size_t size)
 	ret = s->upstream_step(s->upstream_state, s->input, sizeof s->input);
 	if (ret < 0) {
 		return ret;
+	} else if (ret == 0) {
+		s->eof = true;
 	}
 
 	inlen = ret;
@@ -234,6 +236,8 @@  static int gunzip_step(void *state, void *buffer, size_t size)
 			ret = s->upstream_step(s->upstream_state, s->input, sizeof s->input);
 			if (ret < 0) {
 				return ret;
+			} else if (ret == 0) {
+				s->eof = true;
 			}
 			s->strm.avail_in = ret;
 			s->strm.next_in = s->input;
@@ -317,7 +321,7 @@  int copyfile(int fdin, void *out, unsigned int nbytes, unsigned long *offs, unsi
 		if (!input_state.dgst)
 			return -EFAULT;
 	}
- 
+
 	if (encrypted) {
 		aes_key = get_aes_key();
 		ivt = get_aes_ivt();