summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhillip Lougher <phillip@squashfs.org.uk>2012-01-03 02:58:13 +0000
committerPhillip Lougher <phillip@squashfs.org.uk>2012-01-03 04:00:43 +0000
commit3d4a1c80c4eb97187b3a61b3bfa8c804327f7a45 (patch)
treef845494ae3eaa257256095e009b55885517de0c5
parentcc37f75a9ffbbfcb1c3297534f293c8284e3c5a6 (diff)
downloadlinux-stable-3d4a1c80c4eb97187b3a61b3bfa8c804327f7a45.tar.gz
linux-stable-3d4a1c80c4eb97187b3a61b3bfa8c804327f7a45.tar.bz2
linux-stable-3d4a1c80c4eb97187b3a61b3bfa8c804327f7a45.zip
Squashfs: fix i_blocks calculation with extended regular files
The le64_to_cpu() forces the calculation to be unsigned, with the effect that it can underflow leading to an incorrect large value. This bug only triggers in rare(ish) circumstances, an empty file encoded as an extended regular file or a completely sparse file. Normally empty files are encoded as a regular file rather than as an extended regular file (and the regular file i_blocks calculation doesn't have this bug). To save space regular file inodes are optimised to encode the most commonly occurring files. Less common regular files are encoded using extended regular file inodes which contain extra information. Empty files with nlinks greater than 1, and or empty files with extended attributes are encoded using extended regular file inodes and they will hit this bug. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
-rw-r--r--fs/squashfs/inode.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
index fd7b3b3bda13..81afbccfa843 100644
--- a/fs/squashfs/inode.c
+++ b/fs/squashfs/inode.c
@@ -208,8 +208,8 @@ int squashfs_read_inode(struct inode *inode, long long ino)
inode->i_op = &squashfs_inode_ops;
inode->i_fop = &generic_ro_fops;
inode->i_mode |= S_IFREG;
- inode->i_blocks = ((inode->i_size -
- le64_to_cpu(sqsh_ino->sparse) - 1) >> 9) + 1;
+ inode->i_blocks = (inode->i_size -
+ le64_to_cpu(sqsh_ino->sparse) + 511) >> 9;
squashfs_i(inode)->fragment_block = frag_blk;
squashfs_i(inode)->fragment_size = frag_size;