mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
nilfs2: verify metadata sizes read from disk
Add code to check sizes of on-disk data of metadata files such as inode size, segment usage size, DAT entry size, and checkpoint size. Although these sizes are read from disk, the current implementation doesn't check them. If these sizes are not sane on disk, it can cause out-of-range access to metadata or memory access overrun on metadata block buffers due to overflow in sundry calculations. Both lower limit and upper limit of metadata sizes are verified to prevent these issues. Signed-off-by: Ryusuke Konishi <[email protected]> Cc: Andreas Rohner <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
f9f32c44e7
commit
0ec060d188
5 changed files with 54 additions and 0 deletions
|
|
@ -942,6 +942,18 @@ int nilfs_cpfile_read(struct super_block *sb, size_t cpsize,
|
|||
struct inode *cpfile;
|
||||
int err;
|
||||
|
||||
if (cpsize > sb->s_blocksize) {
|
||||
printk(KERN_ERR
|
||||
"NILFS: too large checkpoint size: %zu bytes.\n",
|
||||
cpsize);
|
||||
return -EINVAL;
|
||||
} else if (cpsize < NILFS_MIN_CHECKPOINT_SIZE) {
|
||||
printk(KERN_ERR
|
||||
"NILFS: too small checkpoint size: %zu bytes.\n",
|
||||
cpsize);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cpfile = nilfs_iget_locked(sb, NULL, NILFS_CPFILE_INO);
|
||||
if (unlikely(!cpfile))
|
||||
return -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -484,6 +484,18 @@ int nilfs_dat_read(struct super_block *sb, size_t entry_size,
|
|||
struct nilfs_dat_info *di;
|
||||
int err;
|
||||
|
||||
if (entry_size > sb->s_blocksize) {
|
||||
printk(KERN_ERR
|
||||
"NILFS: too large DAT entry size: %zu bytes.\n",
|
||||
entry_size);
|
||||
return -EINVAL;
|
||||
} else if (entry_size < NILFS_MIN_DAT_ENTRY_SIZE) {
|
||||
printk(KERN_ERR
|
||||
"NILFS: too small DAT entry size: %zu bytes.\n",
|
||||
entry_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dat = nilfs_iget_locked(sb, NULL, NILFS_DAT_INO);
|
||||
if (unlikely(!dat))
|
||||
return -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -1169,6 +1169,18 @@ int nilfs_sufile_read(struct super_block *sb, size_t susize,
|
|||
void *kaddr;
|
||||
int err;
|
||||
|
||||
if (susize > sb->s_blocksize) {
|
||||
printk(KERN_ERR
|
||||
"NILFS: too large segment usage size: %zu bytes.\n",
|
||||
susize);
|
||||
return -EINVAL;
|
||||
} else if (susize < NILFS_MIN_SEGMENT_USAGE_SIZE) {
|
||||
printk(KERN_ERR
|
||||
"NILFS: too small segment usage size: %zu bytes.\n",
|
||||
susize);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sufile = nilfs_iget_locked(sb, NULL, NILFS_SUFILE_INO);
|
||||
if (unlikely(!sufile))
|
||||
return -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -399,6 +399,16 @@ static int nilfs_store_disk_layout(struct the_nilfs *nilfs,
|
|||
return -EINVAL;
|
||||
|
||||
nilfs->ns_inode_size = le16_to_cpu(sbp->s_inode_size);
|
||||
if (nilfs->ns_inode_size > nilfs->ns_blocksize) {
|
||||
printk(KERN_ERR "NILFS: too large inode size: %d bytes.\n",
|
||||
nilfs->ns_inode_size);
|
||||
return -EINVAL;
|
||||
} else if (nilfs->ns_inode_size < NILFS_MIN_INODE_SIZE) {
|
||||
printk(KERN_ERR "NILFS: too small inode size: %d bytes.\n",
|
||||
nilfs->ns_inode_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nilfs->ns_first_ino = le32_to_cpu(sbp->s_first_ino);
|
||||
|
||||
nilfs->ns_blocks_per_segment = le32_to_cpu(sbp->s_blocks_per_segment);
|
||||
|
|
|
|||
Loading…
Reference in a new issue