Commit 8b0f0bb2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull udf, ext2, isofs fixes and cleanups from Jan Kara:

 - A few UDF cleanups and fixes for handling corrupted filesystems

 - ext2 fix for handling of corrupted filesystem

 - isofs module description

 - jbd2 module description

* tag 'fs_for_v6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  ext2: Verify bitmap and itable block numbers before using them
  udf: prevent integer overflow in udf_bitmap_free_blocks()
  udf: Avoid excessive partition lengths
  udf: Drop load_block_bitmap() wrapper
  udf: Avoid using corrupted block bitmap buffer
  udf: Fix bogus checksum computation in udf_rename()
  udf: Fix lock ordering in udf_evict_inode()
  udf: Drop pointless IS_IMMUTABLE and IS_APPEND check
  isofs: add missing MODULE_DESCRIPTION()
  jbd2: add missing MODULE_DESCRIPTION()
parents d6018321 322a6aff
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -77,26 +77,33 @@ static int ext2_valid_block_bitmap(struct super_block *sb,
	ext2_grpblk_t next_zero_bit;
	ext2_fsblk_t bitmap_blk;
	ext2_fsblk_t group_first_block;
	ext2_grpblk_t max_bit;

	group_first_block = ext2_group_first_block_no(sb, block_group);
	max_bit = ext2_group_last_block_no(sb, block_group) - group_first_block;

	/* check whether block bitmap block number is set */
	bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
	offset = bitmap_blk - group_first_block;
	if (!ext2_test_bit(offset, bh->b_data))
	if (offset < 0 || offset > max_bit ||
	    !ext2_test_bit(offset, bh->b_data))
		/* bad block bitmap */
		goto err_out;

	/* check whether the inode bitmap block number is set */
	bitmap_blk = le32_to_cpu(desc->bg_inode_bitmap);
	offset = bitmap_blk - group_first_block;
	if (!ext2_test_bit(offset, bh->b_data))
	if (offset < 0 || offset > max_bit ||
	    !ext2_test_bit(offset, bh->b_data))
		/* bad block bitmap */
		goto err_out;

	/* check whether the inode table block number is set */
	bitmap_blk = le32_to_cpu(desc->bg_inode_table);
	offset = bitmap_blk - group_first_block;
	if (offset < 0 || offset > max_bit ||
	    offset + EXT2_SB(sb)->s_itb_per_group - 1 > max_bit)
		goto err_out;
	next_zero_bit = ext2_find_next_zero_bit(bh->b_data,
				offset + EXT2_SB(sb)->s_itb_per_group,
				offset);
+1 −0
Original line number Diff line number Diff line
@@ -1617,4 +1617,5 @@ static void __exit exit_iso9660_fs(void)

module_init(init_iso9660_fs)
module_exit(exit_iso9660_fs)
MODULE_DESCRIPTION("ISO 9660 CDROM file system support");
MODULE_LICENSE("GPL");
+1 −0
Original line number Diff line number Diff line
@@ -3181,6 +3181,7 @@ static void __exit journal_exit(void)
	jbd2_journal_destroy_caches();
}

MODULE_DESCRIPTION("Generic filesystem journal-writing module");
MODULE_LICENSE("GPL");
module_init(journal_init);
module_exit(journal_exit);
+29 −45
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include "udfdecl.h"

#include <linux/bitops.h>
#include <linux/overflow.h>

#include "udf_i.h"
#include "udf_sb.h"
@@ -64,12 +65,16 @@ static int read_block_bitmap(struct super_block *sb,
	}

	for (i = 0; i < count; i++)
		if (udf_test_bit(i + off, bh->b_data))
		if (udf_test_bit(i + off, bh->b_data)) {
			bitmap->s_block_bitmap[bitmap_nr] =
							ERR_PTR(-EFSCORRUPTED);
			brelse(bh);
			return -EFSCORRUPTED;
		}
	return 0;
}

static int __load_block_bitmap(struct super_block *sb,
static int load_block_bitmap(struct super_block *sb,
			     struct udf_bitmap *bitmap,
			     unsigned int block_group)
{
@@ -81,8 +86,15 @@ static int __load_block_bitmap(struct super_block *sb,
			  block_group, nr_groups);
	}

	if (bitmap->s_block_bitmap[block_group])
	if (bitmap->s_block_bitmap[block_group]) {
		/*
		 * The bitmap failed verification in the past. No point in
		 * trying again.
		 */
		if (IS_ERR(bitmap->s_block_bitmap[block_group]))
			return PTR_ERR(bitmap->s_block_bitmap[block_group]);
		return block_group;
	}

	retval = read_block_bitmap(sb, bitmap, block_group, block_group);
	if (retval < 0)
@@ -91,23 +103,6 @@ static int __load_block_bitmap(struct super_block *sb,
	return block_group;
}

static inline int load_block_bitmap(struct super_block *sb,
				    struct udf_bitmap *bitmap,
				    unsigned int block_group)
{
	int slot;

	slot = __load_block_bitmap(sb, bitmap, block_group);

	if (slot < 0)
		return slot;

	if (!bitmap->s_block_bitmap[slot])
		return -EIO;

	return slot;
}

static void udf_add_free_space(struct super_block *sb, u16 partition, u32 cnt)
{
	struct udf_sb_info *sbi = UDF_SB(sb);
@@ -129,7 +124,6 @@ static void udf_bitmap_free_blocks(struct super_block *sb,
{
	struct udf_sb_info *sbi = UDF_SB(sb);
	struct buffer_head *bh = NULL;
	struct udf_part_map *partmap;
	unsigned long block;
	unsigned long block_group;
	unsigned long bit;
@@ -138,19 +132,9 @@ static void udf_bitmap_free_blocks(struct super_block *sb,
	unsigned long overflow;

	mutex_lock(&sbi->s_alloc_mutex);
	partmap = &sbi->s_partmaps[bloc->partitionReferenceNum];
	if (bloc->logicalBlockNum + count < count ||
	    (bloc->logicalBlockNum + count) > partmap->s_partition_len) {
		udf_debug("%u < %d || %u + %u > %u\n",
			  bloc->logicalBlockNum, 0,
			  bloc->logicalBlockNum, count,
			  partmap->s_partition_len);
		goto error_return;
	}

	/* We make sure this cannot overflow when mounting the filesystem */
	block = bloc->logicalBlockNum + offset +
		(sizeof(struct spaceBitmapDesc) << 3);

	do {
		overflow = 0;
		block_group = block >> (sb->s_blocksize_bits + 3);
@@ -380,7 +364,6 @@ static void udf_table_free_blocks(struct super_block *sb,
				  uint32_t count)
{
	struct udf_sb_info *sbi = UDF_SB(sb);
	struct udf_part_map *partmap;
	uint32_t start, end;
	uint32_t elen;
	struct kernel_lb_addr eloc;
@@ -389,16 +372,6 @@ static void udf_table_free_blocks(struct super_block *sb,
	struct udf_inode_info *iinfo;

	mutex_lock(&sbi->s_alloc_mutex);
	partmap = &sbi->s_partmaps[bloc->partitionReferenceNum];
	if (bloc->logicalBlockNum + count < count ||
	    (bloc->logicalBlockNum + count) > partmap->s_partition_len) {
		udf_debug("%u < %d || %u + %u > %u\n",
			  bloc->logicalBlockNum, 0,
			  bloc->logicalBlockNum, count,
			  partmap->s_partition_len);
		goto error_return;
	}

	iinfo = UDF_I(table);
	udf_add_free_space(sb, sbi->s_partition, count);

@@ -673,6 +646,17 @@ void udf_free_blocks(struct super_block *sb, struct inode *inode,
{
	uint16_t partition = bloc->partitionReferenceNum;
	struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
	uint32_t blk;

	if (check_add_overflow(bloc->logicalBlockNum, offset, &blk) ||
	    check_add_overflow(blk, count, &blk) ||
	    bloc->logicalBlockNum + count > map->s_partition_len) {
		udf_debug("Invalid request to free blocks: (%d, %u), off %u, "
			  "len %u, partition len %u\n",
			  partition, bloc->logicalBlockNum, offset, count,
			  map->s_partition_len);
		return;
	}

	if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) {
		udf_bitmap_free_blocks(sb, map->s_uspace.s_bitmap,
+2 −0
Original line number Diff line number Diff line
@@ -232,7 +232,9 @@ static int udf_setattr(struct mnt_idmap *idmap, struct dentry *dentry,

	if ((attr->ia_valid & ATTR_SIZE) &&
	    attr->ia_size != i_size_read(inode)) {
		filemap_invalidate_lock(inode->i_mapping);
		error = udf_setsize(inode, attr->ia_size);
		filemap_invalidate_unlock(inode->i_mapping);
		if (error)
			return error;
	}
Loading