[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Fri, 2 Mar 2018 16:59:15 -0800
From: Eric Biggers <ebiggers3@...il.com>
To: linux-ext4@...r.kernel.org
Cc: Eric Biggers <ebiggers@...gle.com>
Subject: [PATCH 02/10] libext2fs: make sure the system.data xattr gets created
From: Eric Biggers <ebiggers@...gle.com>
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@...gle.com>
---
lib/ext2fs/inline_data.c | 50 +++++++++++++++++-----------------
tests/f_create_symlinks/expect | 20 +++++++++++---
tests/f_create_symlinks/script | 4 +--
3 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/lib/ext2fs/inline_data.c b/lib/ext2fs/inline_data.c
index 7215c517..0cf80b9a 100644
--- a/lib/ext2fs/inline_data.c
+++ b/lib/ext2fs/inline_data.c
@@ -535,7 +535,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;
@@ -548,37 +551,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 1794e0a7..3033f8aa 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
+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
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
@@ -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
@@ -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 73f95a6e..1a97216a 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
--
2.16.2.395.g2e18187dfd-goog
Powered by blists - more mailing lists