aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2018-03-02 16:59:15 -0800
committerTheodore Ts'o <tytso@mit.edu>2018-03-03 15:26:36 -0500
commit198a2d0a77d1c33790855c7827da6f1520db103e (patch)
tree8784d40f72309be6c119fbb25c4e307dd4849755
parentc88970f2258459e84f3fbed3b80653b3e8746dfb (diff)
downloade2fsprogs-198a2d0a77d1c33790855c7827da6f1520db103e.tar.gz
libext2fs: make sure the system.data xattr gets created
Both the kernel and e2fsck expect that if an inode has inline data, then it contains a "system.data" xattr -- even if i_size <= 60 so the data fits entirely in i_block. But if a symlink of exactly 60 bytes (not counting a NUL terminator) was created using ext2fs_symlink() and the inline data feature was enabled, then the symlink inode ended up with inline data but without a system.data xattr. This is possible because "fast" symlinks store a NUL terminator but inline data symlinks do not. So 60 bytes is too long for a real fast symlink, but still short enough to fit the entire target in i_block as a "slow" symlink using inline data. Some places use ext2fs_inline_data_init() to ensure the system.data xattr is created, but the symlink path does not. Fix this by making ext2fs_inline_data_set() set system.data to an empty string when i_size <= 60. Fixes: 54e880b870f7 ("libext2fs: handle inline data in read/write function") Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--lib/ext2fs/inline_data.c50
-rw-r--r--tests/f_create_symlinks/expect20
-rw-r--r--tests/f_create_symlinks/script4
3 files changed, 43 insertions, 31 deletions
diff --git a/lib/ext2fs/inline_data.c b/lib/ext2fs/inline_data.c
index e3ae2e84e..21e82027d 100644
--- a/lib/ext2fs/inline_data.c
+++ b/lib/ext2fs/inline_data.c
@@ -545,7 +545,10 @@ errcode_t ext2fs_inline_data_set(ext2_filsys fs, ext2_ino_t ino,
void *buf, size_t size)
{
struct ext2_inode inode_buf;
- struct ext2_inline_data data;
+ struct ext2_inline_data data = {
+ .fs = fs,
+ .ino = ino,
+ };
errcode_t retval;
size_t free_ea_size, existing_size, free_inode_size;
@@ -558,37 +561,34 @@ errcode_t ext2fs_inline_data_set(ext2_filsys fs, ext2_ino_t ino,
if (size <= EXT4_MIN_INLINE_DATA_SIZE) {
memcpy((void *)inode->i_block, buf, size);
- return ext2fs_write_inode(fs, ino, inode);
- }
-
- retval = ext2fs_xattr_inode_max_size(fs, ino, &free_ea_size);
- if (retval)
- return retval;
+ } else {
+ retval = ext2fs_xattr_inode_max_size(fs, ino, &free_ea_size);
+ if (retval)
+ return retval;
- retval = ext2fs_inline_data_size(fs, ino, &existing_size);
- if (retval)
- return retval;
+ retval = ext2fs_inline_data_size(fs, ino, &existing_size);
+ if (retval)
+ return retval;
- if (existing_size < EXT4_MIN_INLINE_DATA_SIZE)
- free_inode_size = EXT4_MIN_INLINE_DATA_SIZE - existing_size;
- else
- free_inode_size = 0;
+ if (existing_size < EXT4_MIN_INLINE_DATA_SIZE) {
+ free_inode_size = EXT4_MIN_INLINE_DATA_SIZE -
+ existing_size;
+ } else {
+ free_inode_size = 0;
+ }
- if (size != existing_size &&
- size > existing_size + free_ea_size + free_inode_size)
- return EXT2_ET_INLINE_DATA_NO_SPACE;
+ if (size != existing_size &&
+ size > existing_size + free_ea_size + free_inode_size)
+ return EXT2_ET_INLINE_DATA_NO_SPACE;
- memcpy((void *)inode->i_block, buf, EXT4_MIN_INLINE_DATA_SIZE);
+ memcpy((void *)inode->i_block, buf, EXT4_MIN_INLINE_DATA_SIZE);
+ if (size > EXT4_MIN_INLINE_DATA_SIZE)
+ data.ea_size = size - EXT4_MIN_INLINE_DATA_SIZE;
+ data.ea_data = (char *) buf + EXT4_MIN_INLINE_DATA_SIZE;
+ }
retval = ext2fs_write_inode(fs, ino, inode);
if (retval)
return retval;
- data.fs = fs;
- data.ino = ino;
- if (size > EXT4_MIN_INLINE_DATA_SIZE)
- data.ea_size = size - EXT4_MIN_INLINE_DATA_SIZE;
- else
- data.ea_size = 0;
- data.ea_data = (char *) buf + EXT4_MIN_INLINE_DATA_SIZE;
return ext2fs_inline_data_ea_set(&data);
}
diff --git a/tests/f_create_symlinks/expect b/tests/f_create_symlinks/expect
index c21729a80..71f0c6299 100644
--- a/tests/f_create_symlinks/expect
+++ b/tests/f_create_symlinks/expect
@@ -7,6 +7,7 @@ Pass 5: Checking group summary information
test_filesys: 11/128 files (0.0% non-contiguous), 441/1024 blocks
Exit status is 0
debugfs -R "symlink /l_30 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" test.img
+debugfs -R "symlink /l_60 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" test.img
debugfs -R "symlink /l_70 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" test.img
debugfs -R "symlink /l_500 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" test.img
debugfs -R "symlink /l_1023 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" test.img
@@ -25,9 +26,20 @@ Links: 1 Blockcount: 0
Fragment: Address: 0 Number: 0 Size: 0
Size of extra inode fields: 32
Fast link dest: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
-debugfs -R "stat /l_70" test.img
+debugfs -R "stat /l_60" test.img
Inode: 13 Type: symlink Mode: 0777 Flags: 0x10000000
Generation: 0 Version: 0x00000000:00000000
+User: 0 Group: 0 Project: 0 Size: 60
+File ACL: 0 Directory ACL: 0
+Links: 1 Blockcount: 0
+Fragment: Address: 0 Number: 0 Size: 0
+Size of extra inode fields: 32
+Extended attributes:
+ system.data (0)
+Fast link dest: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+debugfs -R "stat /l_70" test.img
+Inode: 14 Type: symlink Mode: 0777 Flags: 0x10000000
+Generation: 0 Version: 0x00000000:00000000
User: 0 Group: 0 Project: 0 Size: 70
File ACL: 0 Directory ACL: 0
Links: 1 Blockcount: 0
@@ -37,7 +49,7 @@ Extended attributes:
system.data (10)
Fast link dest: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
debugfs -R "stat /l_500" test.img
-Inode: 14 Type: symlink Mode: 0777 Flags: 0x80000
+Inode: 15 Type: symlink Mode: 0777 Flags: 0x80000
Generation: 0 Version: 0x00000000:00000000
User: 0 Group: 0 Project: 0 Size: 500
File ACL: 0 Directory ACL: 0
@@ -47,7 +59,7 @@ Size of extra inode fields: 32
EXTENTS:
(0):153
debugfs -R "stat /l_1023" test.img
-Inode: 15 Type: symlink Mode: 0777 Flags: 0x80000
+Inode: 16 Type: symlink Mode: 0777 Flags: 0x80000
Generation: 0 Version: 0x00000000:00000000
User: 0 Group: 0 Project: 0 Size: 1023
File ACL: 0 Directory ACL: 0
@@ -65,5 +77,5 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-test_filesys: 15/128 files (0.0% non-contiguous), 443/1024 blocks
+test_filesys: 16/128 files (0.0% non-contiguous), 443/1024 blocks
Exit status is 0
diff --git a/tests/f_create_symlinks/script b/tests/f_create_symlinks/script
index 73f95a6e8..1a97216aa 100644
--- a/tests/f_create_symlinks/script
+++ b/tests/f_create_symlinks/script
@@ -23,13 +23,13 @@ echo Exit status is $status >> $OUT.new
sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
rm -f $OUT.new
-for i in 30 70 500 1023 1024 1500; do
+for i in 30 60 70 500 1023 1024 1500; do
echo "debugfs -R \"symlink /l_$i $(perl -e "print 'x' x $i;")\" test.img" >> $OUT
$DEBUGFS -w -R "symlink /l_$i $(perl -e "print 'x' x $i;")" $TMPFILE \
2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
done
-for i in 30 70 500 1023 1024 1500; do
+for i in 30 60 70 500 1023 1024 1500; do
echo "debugfs -R \"stat /l_$i\" test.img" >> $OUT
$DEBUGFS -R "stat /l_$i" $TMPFILE 2>&1 | \
sed -f $cmd_dir/filter.sed | grep -v "time: " >> $OUT