* [PATCH] Fix a squashfs crash when reading large directories
@ 2020-11-22 21:02 Campbell Suter
2020-11-22 21:18 ` João Marcos Costa
0 siblings, 1 reply; 2+ messages in thread
From: Campbell Suter @ 2020-11-22 21:02 UTC (permalink / raw)
To: u-boot
SquashFS encodes directories with more than 256 entries, with xattrs or
a few other things with a different type of inode than most directories.
This type of directory entry has an indexing feature to increase the
performance of filename lookups. When U-Boot's squashfs driver
calculates the length of such an inode, it incorrectly adds one to the
number of indexes which causes the length to be miscalculated, causing a
synchronous abort when reading the next inode.
This occurs for directories that satisfy all the following conditions:
* They have at least 257 entries, the size of their inodes add to >8K,
or they have extended attributes.
* They are not the root directory (as there is no subsequent inode to
read), and are not the last child of the root directory.
* The length of the names of all the child files sum to a sufficent
value (I think this is the point where the child entries span multiple
metadata blocks, but I haven't confirmed it)
The following script generates a squashfs that was crashing when listed:
mkdir -p files/{a,b,c}
pad=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
for i in {1..257}; do touch files/b/file-$(printf '%03d' $i)-$pad done
mksquashfs files result.squashfs
Signed-off-by: Campbell Suter <campbell@snapit.group>
---
fs/squashfs/sqfs_inode.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/squashfs/sqfs_inode.c b/fs/squashfs/sqfs_inode.c
index 14d70cf678..e76ec7cbdf 100644
--- a/fs/squashfs/sqfs_inode.c
+++ b/fs/squashfs/sqfs_inode.c
@@ -49,7 +49,7 @@ int sqfs_inode_size(struct squashfs_base_inode *inode, u32 blk_size)
return sizeof(*ldir);
di = ldir->index;
- while (l < i_count + 1) {
+ while (l < i_count) {
sz = get_unaligned_le32(&di->size) + 1;
index_list_size += sz;
di = (void *)di + sizeof(*di) + sz;
@@ -57,7 +57,7 @@ int sqfs_inode_size(struct squashfs_base_inode *inode, u32 blk_size)
}
return sizeof(*ldir) + index_list_size +
- (i_count + 1) * SQFS_DIR_INDEX_BASE_LENGTH;
+ i_count * SQFS_DIR_INDEX_BASE_LENGTH;
}
case SQFS_LREG_TYPE: {
--
2.28.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [PATCH] Fix a squashfs crash when reading large directories
2020-11-22 21:02 [PATCH] Fix a squashfs crash when reading large directories Campbell Suter
@ 2020-11-22 21:18 ` João Marcos Costa
0 siblings, 0 replies; 2+ messages in thread
From: João Marcos Costa @ 2020-11-22 21:18 UTC (permalink / raw)
To: u-boot
Em dom, 22 de nov de 2020 18:02, Campbell Suter <campbell@snapit.group>
escreveu:
> SquashFS encodes directories with more than 256 entries, with xattrs or
> a few other things with a different type of inode than most directories.
>
> This type of directory entry has an indexing feature to increase the
> performance of filename lookups. When U-Boot's squashfs driver
> calculates the length of such an inode, it incorrectly adds one to the
> number of indexes which causes the length to be miscalculated, causing a
> synchronous abort when reading the next inode.
>
> This occurs for directories that satisfy all the following conditions:
>
> * They have at least 257 entries, the size of their inodes add to >8K,
> or they have extended attributes.
> * They are not the root directory (as there is no subsequent inode to
> read), and are not the last child of the root directory.
> * The length of the names of all the child files sum to a sufficent
> value (I think this is the point where the child entries span multiple
> metadata blocks, but I haven't confirmed it)
>
> The following script generates a squashfs that was crashing when listed:
>
> mkdir -p files/{a,b,c}
> pad=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> for i in {1..257}; do touch files/b/file-$(printf '%03d' $i)-$pad done
> mksquashfs files result.squashfs
>
> Signed-off-by: Campbell Suter <campbell@snapit.group>
> ---
>
> fs/squashfs/sqfs_inode.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/fs/squashfs/sqfs_inode.c b/fs/squashfs/sqfs_inode.c
> index 14d70cf678..e76ec7cbdf 100644
> --- a/fs/squashfs/sqfs_inode.c
> +++ b/fs/squashfs/sqfs_inode.c
> @@ -49,7 +49,7 @@ int sqfs_inode_size(struct squashfs_base_inode *inode,
> u32 blk_size)
> return sizeof(*ldir);
>
> di = ldir->index;
> - while (l < i_count + 1) {
> + while (l < i_count) {
> sz = get_unaligned_le32(&di->size) + 1;
> index_list_size += sz;
> di = (void *)di + sizeof(*di) + sz;
> @@ -57,7 +57,7 @@ int sqfs_inode_size(struct squashfs_base_inode *inode,
> u32 blk_size)
> }
>
> return sizeof(*ldir) + index_list_size +
> - (i_count + 1) * SQFS_DIR_INDEX_BASE_LENGTH;
> + i_count * SQFS_DIR_INDEX_BASE_LENGTH;
> }
>
> case SQFS_LREG_TYPE: {
> --
> 2.28.0
>
Hello,
First of all, thanks for this contribution, but someone has recently sent a
similar patch fixing this very same issue. It was already tested and
reviewed, but not yet merged to u-boot/master.
Best regards,
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-11-22 21:18 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-22 21:02 [PATCH] Fix a squashfs crash when reading large directories Campbell Suter
2020-11-22 21:18 ` João Marcos Costa
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.