mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2026-01-27 21:27:18 +01:00
tools/squashfs4: fix rare data corruption issue
There is a chance that the squashfs4 tool may create a broken image
under certain conditions. Backport the fix from upstream to address
this issue.
Report: https://forum.openwrt.org/t/bug-squashfs4-tools-4-7-4-create-corrupted-image/244894
Fixes: 64432358e0 ("tools/squashfs4: update to 4.7.3")
Reported-by: Oleg S <remittor@gmail.com>
Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/21458
Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
parent
a9254a593b
commit
d93429888c
2 changed files with 102 additions and 1 deletions
|
|
@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
|||
PKG_NAME:=squashfs4
|
||||
PKG_CPE_ID:=cpe:/a:phillip_lougher:squashfs
|
||||
PKG_VERSION:=4.7.4
|
||||
PKG_RELEASE=1
|
||||
PKG_RELEASE=2
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/plougher/squashfs-tools
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
From 767d44ceff8fc8e1e7a47a0bcafdcc40eaeb6503 Mon Sep 17 00:00:00 2001
|
||||
From: Phillip Lougher <phillip@squashfs.org.uk>
|
||||
Date: Thu, 8 Jan 2026 01:20:40 +0000
|
||||
Subject: [PATCH] mksquashfs: don't create duplicate virtual -> real disk
|
||||
mappings
|
||||
|
||||
This bug is caused by commit 472588dc40292fa3d047369f1e758016a6b26e70,
|
||||
but it is exposed by commit 078529915caab11e85299aac1304671151d507a3.
|
||||
|
||||
The first commit adds a virtual -> real disk mapping in cases where a
|
||||
multi-block file contains all sparse blocks. In this case no data
|
||||
block has been written for this file, and it may mean no virtual -> real
|
||||
disk mapping will exist otherwise.
|
||||
|
||||
However, a side effect of this is two duplicate virtual -> real disk
|
||||
mappings may be created, with different values.
|
||||
|
||||
Now previously before commit 078529915caab11e85299aac1304671151d507a3,
|
||||
Mksquashfs waited for all outstanding data blocks to be processed by the
|
||||
orderer thread before creating the metadata. At this point all the
|
||||
duplicate virtual -> real disk mappings will exist, and the lookup
|
||||
routine will return the last one created - which happens to be the
|
||||
correct one.
|
||||
|
||||
After commit 078529915caab11e85299aac1304671151d507a3, Mksquashfs no
|
||||
longer waits for all outstanding data blocks to be processed by the
|
||||
orderer thread, which means when the lookup takes place in metadata
|
||||
creation, there may exist only the first wrong duplicate, which will be
|
||||
returned. Obviously there may exist both duplicate values in which case
|
||||
the correct one will be returned. In other words this is a race
|
||||
condition, and it is highly dependent on hardware and input data
|
||||
whether it triggers.
|
||||
|
||||
The fix is to increment the virtual disk position after creating a
|
||||
mapping when a multi-block file contains all sparse blocks. This
|
||||
obviously prevents duplicate mappings from being created.
|
||||
|
||||
Fixes https://github.com/plougher/squashfs-tools/issues/339
|
||||
|
||||
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
|
||||
---
|
||||
squashfs-tools/mksquashfs.c | 12 +++++++++---
|
||||
squashfs-tools/virt_disk_pos.h | 9 +++++++++
|
||||
2 files changed, 18 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/squashfs-tools/mksquashfs.c
|
||||
+++ b/squashfs-tools/mksquashfs.c
|
||||
@@ -2923,8 +2923,10 @@ static struct file_info *write_file_proc
|
||||
fragment_buffer ? fragment_buffer->checksum : 0, FALSE,
|
||||
TRUE);
|
||||
|
||||
- if(!is_vpos_marked())
|
||||
+ if(!is_vpos_marked()) {
|
||||
send_orderer_create_map(get_marked_vpos());
|
||||
+ inc_vpos();
|
||||
+ }
|
||||
|
||||
gen_cache_block_put(fragment_buffer);
|
||||
file_count ++;
|
||||
@@ -3027,8 +3029,10 @@ static struct file_info *write_file_bloc
|
||||
if(buffer_list[block])
|
||||
put_write_buffer_hash(buffer_list[block]);
|
||||
|
||||
- if(!is_vpos_marked())
|
||||
+ if(!is_vpos_marked()) {
|
||||
send_orderer_create_map(get_marked_vpos());
|
||||
+ inc_vpos();
|
||||
+ }
|
||||
} else {
|
||||
for(block = thresh; block < blocks; block ++)
|
||||
gen_cache_block_put(buffer_list[block]);
|
||||
@@ -3140,8 +3144,10 @@ static struct file_info *write_file_bloc
|
||||
block_list, get_marked_vpos(), fragment, 0, fragment_buffer ?
|
||||
fragment_buffer->checksum : 0, FALSE, TRUE);
|
||||
|
||||
- if(!is_vpos_marked())
|
||||
+ if(!is_vpos_marked()) {
|
||||
send_orderer_create_map(get_marked_vpos());
|
||||
+ inc_vpos();
|
||||
+ }
|
||||
|
||||
gen_cache_block_put(fragment_buffer);
|
||||
file_count ++;
|
||||
--- a/squashfs-tools/virt_disk_pos.h
|
||||
+++ b/squashfs-tools/virt_disk_pos.h
|
||||
@@ -96,6 +96,15 @@ static inline long long get_and_inc_vpos
|
||||
}
|
||||
|
||||
|
||||
+static inline void inc_vpos()
|
||||
+{
|
||||
+ if(marked_vpos == 0)
|
||||
+ BAD_ERROR("BUG: Saved write position is empty!\n");
|
||||
+
|
||||
+ vpos ++;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static inline int reset_vpos(void)
|
||||
{
|
||||
if(marked_vpos == 0)
|
||||
Loading…
Add table
Reference in a new issue