diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2014-03-01 18:23:14 +0900 |
---|---|---|
committer | Daniel Phillips <daniel@tux3.org> | 2014-03-01 18:23:14 +0900 |
commit | ddeafc38ef0734f5a7f4bf0892eaf7013f6a5e36 (patch) | |
tree | 020faa2bd88147c6daca164cebfeebfb187922d7 | |
parent | fdba06fdccab595f23190d2927da90cc95e05053 (diff) | |
download | linux-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.c | 18 | ||||
-rw-r--r-- | fs/tux3/inode.c | 2 |
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); } |