aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>2014-03-01 18:23:14 +0900
committerDaniel Phillips <daniel@tux3.org>2014-03-01 18:23:14 +0900
commitddeafc38ef0734f5a7f4bf0892eaf7013f6a5e36 (patch)
tree020faa2bd88147c6daca164cebfeebfb187922d7
parentfdba06fdccab595f23190d2927da90cc95e05053 (diff)
downloadlinux-tux3-ddeafc38ef0734f5a7f4bf0892eaf7013f6a5e36.tar.gz
tux3: Fix tux3_truncate_inode_pages_range() overflow handling
At 3.11, truncate_inode_pages_range() was changed to support partial page range. But it doesn't handle corner cases correctly. loff_t is signed, so loff_t >> shift_bits is invalid operation. So, we have to care loff_t doesn't overflow signed. This assumes loff_t >> PAGE_CACHE_SHIFT doesn't overflow pgoff_t (this is true if loff_t < MAX_LFS_FILESIZE). With this assumption, this fix overflow cases by just casting to (u64). Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
-rw-r--r--fs/tux3/filemap_blocklib.c18
-rw-r--r--fs/tux3/inode.c2
2 files changed, 9 insertions, 11 deletions
diff --git a/fs/tux3/filemap_blocklib.c b/fs/tux3/filemap_blocklib.c
index e5a29b516cd27e..e78dafc3a1f43c 100644
--- a/fs/tux3/filemap_blocklib.c
+++ b/fs/tux3/filemap_blocklib.c
@@ -630,6 +630,12 @@ void tux3_truncate_inode_pages_range(struct address_space *mapping,
if (mapping->nrpages == 0)
return;
+ /* FIXME: should use MAX_LFS_FILESIZE, instead of -1 */
+ if (lend == -1 || lend > MAX_LFS_FILESIZE)
+ lend = MAX_LFS_FILESIZE;
+ /* Caller must check maximum size, otherwrite pgoff_t can overflow */
+ BUG_ON(lstart > MAX_LFS_FILESIZE);
+
/* Offsets within partial pages */
partial_start = lstart & (PAGE_CACHE_SIZE - 1);
partial_end = (lend + 1) & (PAGE_CACHE_SIZE - 1);
@@ -640,16 +646,8 @@ void tux3_truncate_inode_pages_range(struct address_space *mapping,
* start of the range and 'partial_end' at the end of the range.
* Note that 'end' is exclusive while 'lend' is inclusive.
*/
- start = (lstart + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
- if (lend == -1)
- /*
- * lend == -1 indicates end-of-file so we have to set 'end'
- * to the highest possible pgoff_t and since the type is
- * unsigned we're using -1.
- */
- end = -1;
- else
- end = (lend + 1) >> PAGE_CACHE_SHIFT;
+ start = ((u64)lstart + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+ end = ((u64)lend + 1) >> PAGE_CACHE_SHIFT;
pagevec_init(&pvec, 0);
index = start;
diff --git a/fs/tux3/inode.c b/fs/tux3/inode.c
index 1e30c2c89fb6b4..70175efbf8a9e9 100644
--- a/fs/tux3/inode.c
+++ b/fs/tux3/inode.c
@@ -601,7 +601,7 @@ static int tux3_truncate(struct inode *inode, loff_t newsize)
/* FIXME: The buffer fork before invalidate. We should merge to
* truncate_pagecache() */
tux3_truncate_inode_pages_range(inode->i_mapping, holebegin,
- LLONG_MAX);
+ MAX_LFS_FILESIZE);
#endif
truncate_pagecache(inode, holebegin);
}