validate_inode() compares inode->i_size with c->max_inode_sz only. The size is read from the on-flash inode node as a 64-bit value and stored in the signed loff_t, so a value with the top bit set becomes negative and passes the check. The read paths then do size arithmetic with that negative value, for example (i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT in do_readpage() and (i_size - 1) >> PAGE_SHIFT in populate_page(). Reject such inodes like the other invalid on-flash fields. Fixes: 1e51764a3c2a ("UBIFS: add new flash file system") Cc: stable@vger.kernel.org Signed-off-by: Shao Mingyin --- v2: no change since v1. diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 38972786817e..602f0cd9713f 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -71,9 +71,9 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode) int err; const struct ubifs_inode *ui = ubifs_inode(inode); - if (inode->i_size > c->max_inode_sz) { - ubifs_err(c, "inode is too large (%lld)", - (long long)inode->i_size); + if (inode->i_size < 0 || inode->i_size > c->max_inode_sz) { + ubifs_err(c, "inode size %lld is out of range (max. is %lld)", + (long long)inode->i_size, c->max_inode_sz); return 1; }