Whamcloud - gitweb
libext2fs: initialize i_extra_isize when writing EAs
authorDarrick J. Wong <darrick.wong@oracle.com>
Tue, 27 Jan 2015 15:59:19 +0000 (10:59 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 27 Jan 2015 15:59:19 +0000 (10:59 -0500)
If i_extra_isize is zero when we try to write extended attributes,
we'll end up writing the EA magic into the i_extra_isize field, which
causes a subsequent crash on big endian systems (when we try to write
0xEA02 bytes past the inode!).  Therefore when the field is zero, set
i_extra_isize to the desired extra_isize size, zero those bytes, and
write the EAs after the end of the extended inode.

v2: Don't bother if we have 128b inodes, and ensure that the value
is 32b-aligned so that the EA magic starts on a 32b boundary.

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_no_extra_isize/expect.1 [new file with mode: 0644]
tests/f_write_ea_no_extra_isize/expect.2 [new file with mode: 0644]
tests/f_write_ea_no_extra_isize/image.gz [new file with mode: 0644]
tests/f_write_ea_no_extra_isize/name [new file with mode: 0644]

index 70bc3f9..c6fcf54 100644 (file)
@@ -519,6 +519,18 @@ errcode_t ext2fs_xattrs_write(struct ext2_xattr_handle *handle)
        if (err)
                goto out;
 
+       /* If extra_isize isn't set, we need to set it now */
+       if (inode->i_extra_isize == 0 &&
+           EXT2_INODE_SIZE(handle->fs->super) > EXT2_GOOD_OLD_INODE_SIZE) {
+               char *p = (char *)inode;
+               size_t extra = handle->fs->super->s_want_extra_isize;
+
+               if (extra == 0)
+                       extra = sizeof(__u32);
+               memset(p + EXT2_GOOD_OLD_INODE_SIZE, 0, extra);
+               inode->i_extra_isize = extra;
+       }
+
        move_inline_data_to_front(handle);
 
        x = handle->attrs;
diff --git a/tests/f_write_ea_no_extra_isize/expect.1 b/tests/f_write_ea_no_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_no_extra_isize/expect.2 b/tests/f_write_ea_no_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_no_extra_isize/image.gz b/tests/f_write_ea_no_extra_isize/image.gz
new file mode 100644 (file)
index 0000000..928daff
Binary files /dev/null and b/tests/f_write_ea_no_extra_isize/image.gz differ
diff --git a/tests/f_write_ea_no_extra_isize/name b/tests/f_write_ea_no_extra_isize/name
new file mode 100644 (file)
index 0000000..200e365
--- /dev/null
@@ -0,0 +1 @@
+write EA when i_extra_size is zero