Whamcloud - gitweb
libext2fs: strengthen i_extra_isize checks when reading/writing xattrs
authorDarrick J. Wong <darrick.wong@oracle.com>
Tue, 27 Jan 2015 18:10:08 +0000 (13:10 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 27 Jan 2015 18:10:21 +0000 (13:10 -0500)
Strengthen the i_extra_isize checks to look for obviously too-small
values before trying to operate on inode EAs.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
lib/ext2fs/ext_attr.c
tests/f_write_ea_toobig_extra_isize/expect.1 [new file with mode: 0644]
tests/f_write_ea_toobig_extra_isize/expect.2 [new file with mode: 0644]
tests/f_write_ea_toobig_extra_isize/image.gz [new file with mode: 0644]
tests/f_write_ea_toobig_extra_isize/name [new file with mode: 0644]
tests/f_write_ea_toosmall_extra_isize/expect.1 [new file with mode: 0644]
tests/f_write_ea_toosmall_extra_isize/expect.2 [new file with mode: 0644]
tests/f_write_ea_toosmall_extra_isize/image.gz [new file with mode: 0644]
tests/f_write_ea_toosmall_extra_isize/name [new file with mode: 0644]

index e8544dc..df512d8 100644 (file)
@@ -536,8 +536,9 @@ errcode_t ext2fs_xattrs_write(struct ext2_xattr_handle *handle)
        x = handle->attrs;
        qsort(x, handle->length, sizeof(struct ext2_xattr), attr_compare);
 
-       /* Does the inode have size for EA? */
-       if (EXT2_INODE_SIZE(handle->fs->super) <= EXT2_GOOD_OLD_INODE_SIZE +
+       /* Does the inode have space for EA? */
+       if (inode->i_extra_isize < sizeof(inode->i_extra_isize) ||
+           EXT2_INODE_SIZE(handle->fs->super) <= EXT2_GOOD_OLD_INODE_SIZE +
                                                  inode->i_extra_isize +
                                                  sizeof(__u32))
                goto write_ea_block;
@@ -773,8 +774,9 @@ errcode_t ext2fs_xattrs_read(struct ext2_xattr_handle *handle)
 
        xattrs_free_keys(handle);
 
-       /* Does the inode have size for EA? */
-       if (EXT2_INODE_SIZE(handle->fs->super) <= EXT2_GOOD_OLD_INODE_SIZE +
+       /* Does the inode have space for EA? */
+       if (inode->i_extra_isize < sizeof(inode->i_extra_isize) ||
+           EXT2_INODE_SIZE(handle->fs->super) <= EXT2_GOOD_OLD_INODE_SIZE +
                                                  inode->i_extra_isize +
                                                  sizeof(__u32))
                goto read_ea_block;
diff --git a/tests/f_write_ea_toobig_extra_isize/expect.1 b/tests/f_write_ea_toobig_extra_isize/expect.1
new file mode 100644 (file)
index 0000000..b7e7438
--- /dev/null
@@ -0,0 +1,12 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Directory inode 12, block #0, offset 4: directory corrupted
+Salvage? yes
+
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 12/128 files (0.0% non-contiguous), 17/512 blocks
+Exit status is 1
diff --git a/tests/f_write_ea_toobig_extra_isize/expect.2 b/tests/f_write_ea_toobig_extra_isize/expect.2
new file mode 100644 (file)
index 0000000..3b6073e
--- /dev/null
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 12/128 files (0.0% non-contiguous), 17/512 blocks
+Exit status is 0
diff --git a/tests/f_write_ea_toobig_extra_isize/image.gz b/tests/f_write_ea_toobig_extra_isize/image.gz
new file mode 100644 (file)
index 0000000..291924b
Binary files /dev/null and b/tests/f_write_ea_toobig_extra_isize/image.gz differ
diff --git a/tests/f_write_ea_toobig_extra_isize/name b/tests/f_write_ea_toobig_extra_isize/name
new file mode 100644 (file)
index 0000000..a5ed718
--- /dev/null
@@ -0,0 +1 @@
+write EA when i_extra_size is too big for EA
diff --git a/tests/f_write_ea_toosmall_extra_isize/expect.1 b/tests/f_write_ea_toosmall_extra_isize/expect.1
new file mode 100644 (file)
index 0000000..eecfc9d
--- /dev/null
@@ -0,0 +1,15 @@
+Pass 1: Checking inodes, blocks, and sizes
+Inode 12 has a extra size (1) which is invalid
+Fix? yes
+
+Pass 2: Checking directory structure
+Directory inode 12, block #0, offset 4: directory corrupted
+Salvage? yes
+
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 12/128 files (0.0% non-contiguous), 17/512 blocks
+Exit status is 1
diff --git a/tests/f_write_ea_toosmall_extra_isize/expect.2 b/tests/f_write_ea_toosmall_extra_isize/expect.2
new file mode 100644 (file)
index 0000000..3b6073e
--- /dev/null
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 12/128 files (0.0% non-contiguous), 17/512 blocks
+Exit status is 0
diff --git a/tests/f_write_ea_toosmall_extra_isize/image.gz b/tests/f_write_ea_toosmall_extra_isize/image.gz
new file mode 100644 (file)
index 0000000..78a0149
Binary files /dev/null and b/tests/f_write_ea_toosmall_extra_isize/image.gz differ
diff --git a/tests/f_write_ea_toosmall_extra_isize/name b/tests/f_write_ea_toosmall_extra_isize/name
new file mode 100644 (file)
index 0000000..718c12c
--- /dev/null
@@ -0,0 +1 @@
+write EA when i_extra_size is too small to make sense