Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2018-10-12 12:16:04 +0200
committerTakashi Iwai <tiwai@suse.de>2018-10-12 12:16:04 +0200
commit0c4a66339af6ecfcdb37ee7511b88dddaca48e0e (patch)
treef8f37f8c77d929d4f66d82406459c89f43c00cc8
parent9bfac39b2032a59287f94eab461bd4a9df2595ca (diff)
Squashfs: Compute expected length from inode size rather than
block length (bsc#1051510).
-rw-r--r--patches.fixes/Squashfs-Compute-expected-length-from-inode-size-rat.patch192
-rw-r--r--series.conf1
2 files changed, 193 insertions, 0 deletions
diff --git a/patches.fixes/Squashfs-Compute-expected-length-from-inode-size-rat.patch b/patches.fixes/Squashfs-Compute-expected-length-from-inode-size-rat.patch
new file mode 100644
index 0000000000..ceafa3a12e
--- /dev/null
+++ b/patches.fixes/Squashfs-Compute-expected-length-from-inode-size-rat.patch
@@ -0,0 +1,192 @@
+From a3f94cb99a854fa381fe7fadd97c4f61633717a5 Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@squashfs.org.uk>
+Date: Thu, 2 Aug 2018 16:45:15 +0100
+Subject: [PATCH] Squashfs: Compute expected length from inode size rather than block length
+Mime-version: 1.0
+Content-type: text/plain; charset=UTF-8
+Content-transfer-encoding: 8bit
+Git-commit: a3f94cb99a854fa381fe7fadd97c4f61633717a5
+Patch-mainline: v4.18-rc8
+References: bsc#1051510
+
+Previously in squashfs_readpage() when copying data into the page
+cache, it used the length of the datablock read from the filesystem
+(after decompression). However, if the filesystem has been corrupted
+this data block may be short, which will leave pages unfilled.
+
+The fix for this is to compute the expected number of bytes to copy
+from the inode size, and use this to detect if the block is short.
+
+Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
+Tested-by: Willy Tarreau <w@1wt.eu>
+Cc: Анатолий Тросиненко <anatoly.trosinenko@gmail.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Acked-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ fs/squashfs/file.c | 25 ++++++++++---------------
+ fs/squashfs/file_cache.c | 4 ++--
+ fs/squashfs/file_direct.c | 16 +++++++++++-----
+ fs/squashfs/squashfs.h | 2 +-
+ 4 files changed, 24 insertions(+), 23 deletions(-)
+
+diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c
+index cce3060650ae..f1c1430ae721 100644
+--- a/fs/squashfs/file.c
++++ b/fs/squashfs/file.c
+@@ -431,10 +431,9 @@ void squashfs_copy_cache(struct page *page, struct squashfs_cache_entry *buffer,
+ }
+
+ /* Read datablock stored packed inside a fragment (tail-end packed block) */
+-static int squashfs_readpage_fragment(struct page *page)
++static int squashfs_readpage_fragment(struct page *page, int expected)
+ {
+ struct inode *inode = page->mapping->host;
+- struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
+ struct squashfs_cache_entry *buffer = squashfs_get_fragment(inode->i_sb,
+ squashfs_i(inode)->fragment_block,
+ squashfs_i(inode)->fragment_size);
+@@ -445,23 +444,16 @@ static int squashfs_readpage_fragment(struct page *page)
+ squashfs_i(inode)->fragment_block,
+ squashfs_i(inode)->fragment_size);
+ else
+- squashfs_copy_cache(page, buffer, i_size_read(inode) &
+- (msblk->block_size - 1),
++ squashfs_copy_cache(page, buffer, expected,
+ squashfs_i(inode)->fragment_offset);
+
+ squashfs_cache_put(buffer);
+ return res;
+ }
+
+-static int squashfs_readpage_sparse(struct page *page, int index, int file_end)
++static int squashfs_readpage_sparse(struct page *page, int expected)
+ {
+- struct inode *inode = page->mapping->host;
+- struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
+- int bytes = index == file_end ?
+- (i_size_read(inode) & (msblk->block_size - 1)) :
+- msblk->block_size;
+-
+- squashfs_copy_cache(page, NULL, bytes, 0);
++ squashfs_copy_cache(page, NULL, expected, 0);
+ return 0;
+ }
+
+@@ -471,6 +463,9 @@ static int squashfs_readpage(struct file *file, struct page *page)
+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
+ int index = page->index >> (msblk->block_log - PAGE_SHIFT);
+ int file_end = i_size_read(inode) >> msblk->block_log;
++ int expected = index == file_end ?
++ (i_size_read(inode) & (msblk->block_size - 1)) :
++ msblk->block_size;
+ int res;
+ void *pageaddr;
+
+@@ -489,11 +484,11 @@ static int squashfs_readpage(struct file *file, struct page *page)
+ goto error_out;
+
+ if (bsize == 0)
+- res = squashfs_readpage_sparse(page, index, file_end);
++ res = squashfs_readpage_sparse(page, expected);
+ else
+- res = squashfs_readpage_block(page, block, bsize);
++ res = squashfs_readpage_block(page, block, bsize, expected);
+ } else
+- res = squashfs_readpage_fragment(page);
++ res = squashfs_readpage_fragment(page, expected);
+
+ if (!res)
+ return 0;
+diff --git a/fs/squashfs/file_cache.c b/fs/squashfs/file_cache.c
+index f2310d2a2019..a9ba8d96776a 100644
+--- a/fs/squashfs/file_cache.c
++++ b/fs/squashfs/file_cache.c
+@@ -20,7 +20,7 @@
+ #include "squashfs.h"
+
+ /* Read separately compressed datablock and memcopy into page cache */
+-int squashfs_readpage_block(struct page *page, u64 block, int bsize)
++int squashfs_readpage_block(struct page *page, u64 block, int bsize, int expected)
+ {
+ struct inode *i = page->mapping->host;
+ struct squashfs_cache_entry *buffer = squashfs_get_datablock(i->i_sb,
+@@ -31,7 +31,7 @@ int squashfs_readpage_block(struct page *page, u64 block, int bsize)
+ ERROR("Unable to read page, block %llx, size %x\n", block,
+ bsize);
+ else
+- squashfs_copy_cache(page, buffer, buffer->length, 0);
++ squashfs_copy_cache(page, buffer, expected, 0);
+
+ squashfs_cache_put(buffer);
+ return res;
+diff --git a/fs/squashfs/file_direct.c b/fs/squashfs/file_direct.c
+index 096990254a2e..80db1b86a27c 100644
+--- a/fs/squashfs/file_direct.c
++++ b/fs/squashfs/file_direct.c
+@@ -21,10 +21,11 @@
+ #include "page_actor.h"
+
+ static int squashfs_read_cache(struct page *target_page, u64 block, int bsize,
+- int pages, struct page **page);
++ int pages, struct page **page, int bytes);
+
+ /* Read separately compressed datablock directly into page cache */
+-int squashfs_readpage_block(struct page *target_page, u64 block, int bsize)
++int squashfs_readpage_block(struct page *target_page, u64 block, int bsize,
++ int expected)
+
+ {
+ struct inode *inode = target_page->mapping->host;
+@@ -83,7 +84,7 @@ int squashfs_readpage_block(struct page *target_page, u64 block, int bsize)
+ * using an intermediate buffer.
+ */
+ res = squashfs_read_cache(target_page, block, bsize, pages,
+- page);
++ page, expected);
+ if (res < 0)
+ goto mark_errored;
+
+@@ -95,6 +96,11 @@ int squashfs_readpage_block(struct page *target_page, u64 block, int bsize)
+ if (res < 0)
+ goto mark_errored;
+
++ if (res != expected) {
++ res = -EIO;
++ goto mark_errored;
++ }
++
+ /* Last page may have trailing bytes not filled */
+ bytes = res % PAGE_SIZE;
+ if (bytes) {
+@@ -138,12 +144,12 @@ int squashfs_readpage_block(struct page *target_page, u64 block, int bsize)
+
+
+ static int squashfs_read_cache(struct page *target_page, u64 block, int bsize,
+- int pages, struct page **page)
++ int pages, struct page **page, int bytes)
+ {
+ struct inode *i = target_page->mapping->host;
+ struct squashfs_cache_entry *buffer = squashfs_get_datablock(i->i_sb,
+ block, bsize);
+- int bytes = buffer->length, res = buffer->error, n, offset = 0;
++ int res = buffer->error, n, offset = 0;
+
+ if (res) {
+ ERROR("Unable to read page, block %llx, size %x\n", block,
+diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
+index d8d43724cf2a..f89f8a74c6ce 100644
+--- a/fs/squashfs/squashfs.h
++++ b/fs/squashfs/squashfs.h
+@@ -72,7 +72,7 @@ void squashfs_copy_cache(struct page *, struct squashfs_cache_entry *, int,
+ int);
+
+ /* file_xxx.c */
+-extern int squashfs_readpage_block(struct page *, u64, int);
++extern int squashfs_readpage_block(struct page *, u64, int, int);
+
+ /* id.c */
+ extern int squashfs_get_id(struct super_block *, unsigned int, unsigned int *);
+--
+2.19.0
+
diff --git a/series.conf b/series.conf
index 87beae6acb..61020c011e 100644
--- a/series.conf
+++ b/series.conf
@@ -16999,6 +16999,7 @@
patches.suse/cpufreq-intel_pstate-Limit-the-scope-of-HWP-dynamic-.patch
patches.fixes/tools-power-turbostat-fix-S-on-UP-systems.patch
patches.fixes/tools-power-turbostat-Read-extended-processor-family.patch
+ patches.fixes/Squashfs-Compute-expected-length-from-inode-size-rat.patch
patches.drivers/iwlwifi-add-more-card-IDs-for-9000-series
patches.fixes/inet-frag-enforce-memory-limits-earlier.patch
patches.fixes/ipv4-frags-handle-possible-skb-truesize-change.patch