From 3ab9e173c7381a3149f350039f6e1c09f2681a1d Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 21 Jun 2017 22:12:39 -0400 Subject: [PATCH] add patch fix-ext4_xattr_move-to-block --- fix-ext4_xattr_move-to-block | 71 ++++++++++++++++++++++++++++++++++++++++++++ series | 1 + timestamps | 5 ++-- 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 fix-ext4_xattr_move-to-block diff --git a/fix-ext4_xattr_move-to-block b/fix-ext4_xattr_move-to-block new file mode 100644 index 00000000..f03adadb --- /dev/null +++ b/fix-ext4_xattr_move-to-block @@ -0,0 +1,71 @@ +ext4: fix ext4_xattr_move_to_block() + +From: Tahsin Erdogan + +When moving xattr entries from inline area to a xattr block, entries +that refer to external xattr inodes need special handling because +value data is not available in the inline area but rather should be +read from its external inode. + +Signed-off-by: Tahsin Erdogan +Signed-off-by: Theodore Ts'o +--- + fs/ext4/xattr.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index 6a6bee246873..9c243b3510b7 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -1658,18 +1658,16 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode, + struct ext4_xattr_ibody_find *is = NULL; + struct ext4_xattr_block_find *bs = NULL; + char *buffer = NULL, *b_entry_name = NULL; +- size_t value_offs, value_size; ++ size_t value_size = le32_to_cpu(entry->e_value_size); + struct ext4_xattr_info i = { + .value = NULL, + .value_len = 0, + .name_index = entry->e_name_index, ++ .in_inode = !!entry->e_value_inum, + }; + struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode); + int error; + +- value_offs = le16_to_cpu(entry->e_value_offs); +- value_size = le32_to_cpu(entry->e_value_size); +- + is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS); + bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS); + buffer = kmalloc(value_size, GFP_NOFS); +@@ -1685,7 +1683,17 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode, + bs->bh = NULL; + + /* Save the entry name and the entry value */ +- memcpy(buffer, (void *)IFIRST(header) + value_offs, value_size); ++ if (entry->e_value_inum) { ++ error = ext4_xattr_inode_get(inode, ++ le32_to_cpu(entry->e_value_inum), ++ buffer, value_size); ++ if (error) ++ goto out; ++ } else { ++ size_t value_offs = le16_to_cpu(entry->e_value_offs); ++ memcpy(buffer, (void *)IFIRST(header) + value_offs, value_size); ++ } ++ + memcpy(b_entry_name, entry->e_name, entry->e_name_len); + b_entry_name[entry->e_name_len] = '\0'; + i.name = b_entry_name; +@@ -1703,7 +1711,6 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode, + if (error) + goto out; + +- i.name = b_entry_name; + i.value = buffer; + i.value_len = value_size; + error = ext4_xattr_block_find(inode, &i, bs); +-- +2.13.1.611.g7e3b11ae1-goog + + diff --git a/series b/series index 6762a9c5..3d867d1c 100644 --- a/series +++ b/series @@ -16,6 +16,7 @@ clean-up-ext4_xattr_inode_get add-missing-le32-conversions ext4_xattr_value_same-should-return-false-for-external-data fix-ext4_xattr_make_inode_space-value-size-calculation +fix-ext4_xattr_move-to-block #################################################### # unstable patches diff --git a/timestamps b/timestamps index 1bdf2de8..ee4ceaf0 100755 --- a/timestamps +++ b/timestamps @@ -48,6 +48,7 @@ touch -d @1498096656 clean-up-ext4_xattr_inode_get touch -d @1498096770 add-missing-le32-conversions touch -d @1498096926 ext4_xattr_value_same-should-return-false-for-external-data touch -d @1498097144 fix-ext4_xattr_make_inode_space-value-size-calculation -touch -d @1498097333 series -touch -d @1498097337 status touch -d @1498097342 timestamps +touch -d @1498097514 fix-ext4_xattr_move-to-block +touch -d @1498097543 series +touch -d @1498097547 status -- 2.11.4.GIT