From 0008d8086649d3bb3afd0c4697f5b73ccf6f293d Mon Sep 17 00:00:00 2001 From: Joao Marcos Costa Date: Mon, 17 May 2021 18:20:38 -0300 Subject: fs/squashfs: fix reading of fragmented files The fragmented files were not correctly read because of two issues: - The squashfs_file_info struct has a field named 'comp', which tells if the file's fragment is compressed or not. This field was always set to 'true' in sqfs_get_regfile_info and sqfs_get_lregfile_info. It should actually take sqfs_frag_lookup's return value. This patch addresses these two assignments. - In sqfs_read, the fragments (compressed or not) were copied to the output buffer through a for loop which was reading data at the wrong offset. Replace these loops by equivalent calls to memcpy, with the right parameters. I tested this patch by comparing the MD5 checksum of a few fragmented files with the respective md5sum output in sandbox, considering both compressed and uncompressed fragments. Signed-off-by: Joao Marcos Costa Tested-by: Richard Genoud Reviewed-by: Miquel Raynal --- fs/squashfs/sqfs.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c index 997be2dcf4..92ab8ac631 100644 --- a/fs/squashfs/sqfs.c +++ b/fs/squashfs/sqfs.c @@ -1253,7 +1253,7 @@ static int sqfs_get_regfile_info(struct squashfs_reg_inode *reg, fentry); if (ret < 0) return -EINVAL; - finfo->comp = true; + finfo->comp = ret; if (fentry->size < 1 || fentry->start == 0x7FFFFFFF) return -EINVAL; } else { @@ -1291,7 +1291,7 @@ static int sqfs_get_lregfile_info(struct squashfs_lreg_inode *lreg, fentry); if (ret < 0) return -EINVAL; - finfo->comp = true; + finfo->comp = ret; if (fentry->size < 1 || fentry->start == 0x7FFFFFFF) return -EINVAL; } else { @@ -1547,20 +1547,16 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len, goto out; } - for (j = *actread; j < finfo.size; j++) { - memcpy(buf + j, &fragment_block[finfo.offset + j], 1); - (*actread)++; - } + memcpy(buf + *actread, &fragment_block[finfo.offset], finfo.size - *actread); + *actread = finfo.size; free(fragment_block); } else if (finfo.frag && !finfo.comp) { fragment_block = (void *)fragment + table_offset; - for (j = *actread; j < finfo.size; j++) { - memcpy(buf + j, &fragment_block[finfo.offset + j], 1); - (*actread)++; - } + memcpy(buf + *actread, &fragment_block[finfo.offset], finfo.size - *actread); + *actread = finfo.size; } out: -- cgit