diff options
Diffstat (limited to 'fs/udf/super.c')
-rw-r--r-- | fs/udf/super.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c index 2217f7ed7a49..3460ecc826d1 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -336,7 +336,8 @@ static void udf_sb_free_bitmap(struct udf_bitmap *bitmap) int nr_groups = bitmap->s_nr_groups; for (i = 0; i < nr_groups; i++) - brelse(bitmap->s_block_bitmap[i]); + if (!IS_ERR_OR_NULL(bitmap->s_block_bitmap[i])) + brelse(bitmap->s_block_bitmap[i]); kvfree(bitmap); } @@ -630,7 +631,7 @@ static int udf_parse_param(struct fs_context *fc, struct fs_parameter *param) if (!uopt->nls_map) { errorf(fc, "iocharset %s not found", param->string); - return -EINVAL;; + return -EINVAL; } } break; @@ -895,7 +896,7 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block) int ret; struct timestamp *ts; - outstr = kmalloc(128, GFP_KERNEL); + outstr = kzalloc(128, GFP_KERNEL); if (!outstr) return -ENOMEM; @@ -921,11 +922,11 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block) ret = udf_dstrCS0toChar(sb, outstr, 31, pvoldesc->volIdent, 32); if (ret < 0) { - strcpy(UDF_SB(sb)->s_volume_ident, "InvalidName"); + strscpy_pad(UDF_SB(sb)->s_volume_ident, "InvalidName"); pr_warn("incorrect volume identification, setting to " "'InvalidName'\n"); } else { - strncpy(UDF_SB(sb)->s_volume_ident, outstr, ret); + strscpy_pad(UDF_SB(sb)->s_volume_ident, outstr); } udf_debug("volIdent[] = '%s'\n", UDF_SB(sb)->s_volume_ident); @@ -1110,12 +1111,19 @@ static int udf_fill_partdesc_info(struct super_block *sb, struct udf_part_map *map; struct udf_sb_info *sbi = UDF_SB(sb); struct partitionHeaderDesc *phd; + u32 sum; int err; map = &sbi->s_partmaps[p_index]; map->s_partition_len = le32_to_cpu(p->partitionLength); /* blocks */ map->s_partition_root = le32_to_cpu(p->partitionStartingLocation); + if (check_add_overflow(map->s_partition_root, map->s_partition_len, + &sum)) { + udf_err(sb, "Partition %d has invalid location %u + %u\n", + p_index, map->s_partition_root, map->s_partition_len); + return -EFSCORRUPTED; + } if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY)) map->s_partition_flags |= UDF_PART_FLAG_READ_ONLY; @@ -1171,6 +1179,14 @@ static int udf_fill_partdesc_info(struct super_block *sb, bitmap->s_extPosition = le32_to_cpu( phd->unallocSpaceBitmap.extPosition); map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP; + /* Check whether math over bitmap won't overflow. */ + if (check_add_overflow(map->s_partition_len, + sizeof(struct spaceBitmapDesc) << 3, + &sum)) { + udf_err(sb, "Partition %d is too long (%u)\n", p_index, + map->s_partition_len); + return -EFSCORRUPTED; + } udf_debug("unallocSpaceBitmap (part %d) @ %u\n", p_index, bitmap->s_extPosition); } |