All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH -next 0/6] Fix two issue about ext4 extended attribute
@ 2022-12-06  1:58 Ye Bin
  2022-12-06  1:58 ` [PATCH -next 1/6] ext4: fix WARNING in ext4_expand_extra_isize_ea Ye Bin
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Ye Bin @ 2022-12-06  1:58 UTC (permalink / raw)
  To: tytso, adilger.kernel, linux-ext4; +Cc: linux-kernel, jack, Ye Bin

From: Ye Bin <yebin10@huawei.com>

This patchset fix two issues:
1. Patch [1]-[4] fix WARNING in ext4_expand_extra_isize_ea.
2. Patch [6] fix inode leak in 'ext4_xattr_inode_create()'.
3. Patch [5] is cleanup.

Ye Bin (6):
  ext4: fix WARNING in ext4_expand_extra_isize_ea
  ext4: add primary check extended attribute inode in
    ext4_xattr_check_entries()
  ext4: remove unnessary size check in ext4_xattr_inode_get()
  ext4: allocate extended attribute value in vmalloc area
  ext4: rename xattr_find_entry() and __xattr_check_inode()
  ext4: fix inode leak in 'ext4_xattr_inode_create()'

 fs/ext4/xattr.c | 82 ++++++++++++++++++++++++++++++++-----------------
 fs/ext4/xattr.h | 11 ++-----
 2 files changed, 57 insertions(+), 36 deletions(-)

-- 
2.31.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH -next 1/6] ext4: fix WARNING in ext4_expand_extra_isize_ea
  2022-12-06  1:58 [PATCH -next 0/6] Fix two issue about ext4 extended attribute Ye Bin
@ 2022-12-06  1:58 ` Ye Bin
  2022-12-06 12:04   ` Jan Kara
  2022-12-06  1:58 ` [PATCH -next 2/6] ext4: add primary check extended attribute inode in ext4_xattr_check_entries() Ye Bin
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Ye Bin @ 2022-12-06  1:58 UTC (permalink / raw)
  To: tytso, adilger.kernel, linux-ext4
  Cc: linux-kernel, jack, Ye Bin, syzbot+4d99a966fd74bdeeec36

From: Ye Bin <yebin10@huawei.com>

Syzbot found the following issue:
------------[ cut here ]------------
WARNING: CPU: 1 PID: 3631 at mm/page_alloc.c:5534 __alloc_pages+0x30a/0x560 mm/page_alloc.c:5534
Modules linked in:
CPU: 1 PID: 3631 Comm: syz-executor261 Not tainted 6.1.0-rc6-syzkaller-00308-g644e9524388a #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022
RIP: 0010:__alloc_pages+0x30a/0x560 mm/page_alloc.c:5534
RSP: 0018:ffffc90003ccf080 EFLAGS: 00010246
RAX: ffffc90003ccf0e0 RBX: 000000000000000c RCX: 0000000000000000
RDX: 0000000000000028 RSI: 0000000000000000 RDI: ffffc90003ccf108
RBP: ffffc90003ccf198 R08: dffffc0000000000 R09: ffffc90003ccf0e0
R10: fffff52000799e21 R11: 1ffff92000799e1c R12: 0000000000040c40
R13: 1ffff92000799e18 R14: dffffc0000000000 R15: 1ffff92000799e14
FS:  0000555555c10300(0000) GS:ffff8880b9900000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007ffc36f70000 CR3: 00000000744ad000 CR4: 00000000003506e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
 <TASK>
 __alloc_pages_node include/linux/gfp.h:223 [inline]
 alloc_pages_node include/linux/gfp.h:246 [inline]
 __kmalloc_large_node+0x8a/0x1a0 mm/slab_common.c:1096
 __do_kmalloc_node mm/slab_common.c:943 [inline]
 __kmalloc+0xfe/0x1a0 mm/slab_common.c:968
 kmalloc include/linux/slab.h:558 [inline]
 ext4_xattr_move_to_block fs/ext4/xattr.c:2558 [inline]
 ext4_xattr_make_inode_space fs/ext4/xattr.c:2673 [inline]
 ext4_expand_extra_isize_ea+0xe3f/0x1cd0 fs/ext4/xattr.c:2765
 __ext4_expand_extra_isize+0x2b8/0x3f0 fs/ext4/inode.c:5857
 ext4_try_to_expand_extra_isize fs/ext4/inode.c:5900 [inline]
 __ext4_mark_inode_dirty+0x51a/0x670 fs/ext4/inode.c:5978
 ext4_inline_data_truncate+0x548/0xd00 fs/ext4/inline.c:2021
 ext4_truncate+0x341/0xeb0 fs/ext4/inode.c:4221
 ext4_process_orphan+0x1aa/0x2d0 fs/ext4/orphan.c:339
 ext4_orphan_cleanup+0xb60/0x1340 fs/ext4/orphan.c:474
 __ext4_fill_super fs/ext4/super.c:5515 [inline]
 ext4_fill_super+0x80ed/0x8610 fs/ext4/super.c:5643
 get_tree_bdev+0x400/0x620 fs/super.c:1324
 vfs_get_tree+0x88/0x270 fs/super.c:1531
 do_new_mount+0x289/0xad0 fs/namespace.c:3040
 do_mount fs/namespace.c:3383 [inline]
 __do_sys_mount fs/namespace.c:3591 [inline]
 __se_sys_mount+0x2d3/0x3c0 fs/namespace.c:3568
 do_syscall_x64 arch/x86/entry/common.c:50 [inline]
 do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
 entry_SYSCALL_64_after_hwframe+0x63/0xcd
 </TASK>

Reason is allocate 16M memory by kmalloc, but MAX_ORDER is 11, kmalloc
can allocate maxium size memory is 4M.
XATTR_SIZE_MAX is currently 64k, but EXT4_XATTR_SIZE_MAX is '(1 << 24)',
so 'ext4_xattr_check_entries()' regards this length as legal. Then trigger
warning in 'ext4_xattr_move_to_block()'.
To solve above issue, according to Jan Kara's suggestion use kvmalloc()
to allocate memory in ext4_xattr_move_to_block().

Reported-by: syzbot+4d99a966fd74bdeeec36@syzkaller.appspotmail.com
Fixes: 54dd0e0a1b25 ("ext4: add extra checks to ext4_xattr_block_get()")
Signed-off-by: Ye Bin <yebin10@huawei.com>
---
 fs/ext4/xattr.h | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
index 824faf0b15a8..444ee46838c3 100644
--- a/fs/ext4/xattr.h
+++ b/fs/ext4/xattr.h
@@ -71,15 +71,10 @@ struct ext4_xattr_entry {
 #define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1))
 
 /*
- * XATTR_SIZE_MAX is currently 64k, but for the purposes of checking
- * for file system consistency errors, we use a somewhat bigger value.
- * This allows XATTR_SIZE_MAX to grow in the future, but by using this
- * instead of INT_MAX for certain consistency checks, we don't need to
- * worry about arithmetic overflows.  (Actually XATTR_SIZE_MAX is
- * defined in include/uapi/linux/limits.h, so changing it is going
- * not going to be trivial....)
+ * Use XATTR_SIZE_MAX to checking for file system consistency errors. Extended
+ * attribute length exceed XATTR_SIZE_MAX is ilegal.
  */
-#define EXT4_XATTR_SIZE_MAX (1 << 24)
+#define EXT4_XATTR_SIZE_MAX XATTR_SIZE_MAX
 
 /*
  * The minimum size of EA value when you start storing it in an external inode
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH -next 2/6] ext4: add primary check extended attribute inode in ext4_xattr_check_entries()
  2022-12-06  1:58 [PATCH -next 0/6] Fix two issue about ext4 extended attribute Ye Bin
  2022-12-06  1:58 ` [PATCH -next 1/6] ext4: fix WARNING in ext4_expand_extra_isize_ea Ye Bin
@ 2022-12-06  1:58 ` Ye Bin
  2022-12-06  1:58 ` [PATCH -next 3/6] ext4: remove unnessary size check in ext4_xattr_inode_get() Ye Bin
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Ye Bin @ 2022-12-06  1:58 UTC (permalink / raw)
  To: tytso, adilger.kernel, linux-ext4; +Cc: linux-kernel, jack, Ye Bin

From: Ye Bin <yebin10@huawei.com>

Add primary check for extended attribute inode, only do hash check when read
ea_inode's data in ext4_xattr_inode_get().

Signed-off-by: Ye Bin <yebin10@huawei.com>
---
 fs/ext4/xattr.c | 41 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 36 insertions(+), 5 deletions(-)

diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 718ef3987f94..eed001eee3ec 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -83,6 +83,9 @@ static __le32 ext4_xattr_hash_entry(char *name, size_t name_len, __le32 *value,
 				    size_t value_count);
 static void ext4_xattr_rehash(struct ext4_xattr_header *);
 
+static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
+				 u32 ea_inode_hash, struct inode **ea_inode);
+
 static const struct xattr_handler * const ext4_xattr_handler_map[] = {
 	[EXT4_XATTR_INDEX_USER]		     = &ext4_xattr_user_handler,
 #ifdef CONFIG_EXT4_FS_POSIX_ACL
@@ -181,9 +184,32 @@ ext4_xattr_handler(int name_index)
 	return handler;
 }
 
+static inline int ext4_xattr_check_extra_inode(struct inode *inode,
+					       struct ext4_xattr_entry *entry)
+{
+	int err;
+	struct inode *ea_inode;
+
+	err = ext4_xattr_inode_iget(inode, le32_to_cpu(entry->e_value_inum),
+				    le32_to_cpu(entry->e_hash), &ea_inode);
+	if (err)
+		return err;
+
+	if (i_size_read(ea_inode) != le32_to_cpu(entry->e_value_size)) {
+		ext4_warning_inode(ea_inode,
+                           "ea_inode file size=%llu entry size=%u",
+                           i_size_read(ea_inode),
+			   le32_to_cpu(entry->e_value_size));
+		err = -EFSCORRUPTED;
+	}
+	iput(ea_inode);
+
+	return err;
+}
+
 static int
-ext4_xattr_check_entries(struct ext4_xattr_entry *entry, void *end,
-			 void *value_start)
+ext4_xattr_check_entries(struct inode *inode, struct ext4_xattr_entry *entry,
+			 void *end, void *value_start)
 {
 	struct ext4_xattr_entry *e = entry;
 
@@ -221,6 +247,10 @@ ext4_xattr_check_entries(struct ext4_xattr_entry *entry, void *end,
 			    size > end - value ||
 			    EXT4_XATTR_SIZE(size) > end - value)
 				return -EFSCORRUPTED;
+		} else if (entry->e_value_inum) {
+			int err = ext4_xattr_check_extra_inode(inode, entry);
+			if (err)
+				return err;
 		}
 		entry = EXT4_XATTR_NEXT(entry);
 	}
@@ -243,8 +273,8 @@ __ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh,
 	error = -EFSBADCRC;
 	if (!ext4_xattr_block_csum_verify(inode, bh))
 		goto errout;
-	error = ext4_xattr_check_entries(BFIRST(bh), bh->b_data + bh->b_size,
-					 bh->b_data);
+	error = ext4_xattr_check_entries(inode, BFIRST(bh),
+					 bh->b_data + bh->b_size, bh->b_data);
 errout:
 	if (error)
 		__ext4_error_inode(inode, function, line, 0, -error,
@@ -268,7 +298,8 @@ __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
 	if (end - (void *)header < sizeof(*header) + sizeof(u32) ||
 	    (header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)))
 		goto errout;
-	error = ext4_xattr_check_entries(IFIRST(header), end, IFIRST(header));
+	error = ext4_xattr_check_entries(inode, IFIRST(header), end,
+					 IFIRST(header));
 errout:
 	if (error)
 		__ext4_error_inode(inode, function, line, 0, -error,
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH -next 3/6] ext4: remove unnessary size check in ext4_xattr_inode_get()
  2022-12-06  1:58 [PATCH -next 0/6] Fix two issue about ext4 extended attribute Ye Bin
  2022-12-06  1:58 ` [PATCH -next 1/6] ext4: fix WARNING in ext4_expand_extra_isize_ea Ye Bin
  2022-12-06  1:58 ` [PATCH -next 2/6] ext4: add primary check extended attribute inode in ext4_xattr_check_entries() Ye Bin
@ 2022-12-06  1:58 ` Ye Bin
  2022-12-06  1:58 ` [PATCH -next 4/6] ext4: allocate extended attribute value in vmalloc area Ye Bin
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Ye Bin @ 2022-12-06  1:58 UTC (permalink / raw)
  To: tytso, adilger.kernel, linux-ext4; +Cc: linux-kernel, jack, Ye Bin

From: Ye Bin <yebin10@huawei.com>

As previous patch add check in ext4_xattr_check_entries(), before call
ext4_xattr_inode_get() will already do xattr entries check.

Signed-off-by: Ye Bin <yebin10@huawei.com>
---
 fs/ext4/xattr.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index eed001eee3ec..75287422c36c 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -525,14 +525,6 @@ ext4_xattr_inode_get(struct inode *inode, struct ext4_xattr_entry *entry,
 		goto out;
 	}
 
-	if (i_size_read(ea_inode) != size) {
-		ext4_warning_inode(ea_inode,
-				   "ea_inode file size=%llu entry size=%zu",
-				   i_size_read(ea_inode), size);
-		err = -EFSCORRUPTED;
-		goto out;
-	}
-
 	err = ext4_xattr_inode_read(ea_inode, buffer, size);
 	if (err)
 		goto out;
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH -next 4/6] ext4: allocate extended attribute value in vmalloc area
  2022-12-06  1:58 [PATCH -next 0/6] Fix two issue about ext4 extended attribute Ye Bin
                   ` (2 preceding siblings ...)
  2022-12-06  1:58 ` [PATCH -next 3/6] ext4: remove unnessary size check in ext4_xattr_inode_get() Ye Bin
@ 2022-12-06  1:58 ` Ye Bin
  2022-12-06  1:58 ` [PATCH -next 5/6] ext4: rename xattr_find_entry() and __xattr_check_inode() Ye Bin
  2022-12-06  1:58 ` [PATCH -next 6/6] ext4: fix inode leak in 'ext4_xattr_inode_create()' Ye Bin
  5 siblings, 0 replies; 11+ messages in thread
From: Ye Bin @ 2022-12-06  1:58 UTC (permalink / raw)
  To: tytso, adilger.kernel, linux-ext4; +Cc: linux-kernel, jack, Ye Bin

From: Ye Bin <yebin10@huawei.com>

Now, extended attribute value maxium length is 64K. The memory requested here
does not need continuous physical addresses, so it is appropriate to use
kvmalloc to request memory. At the same time, it can also cope with the
situation that the extension attribute will become longer in the future.

Signed-off-by: Ye Bin <yebin10@huawei.com>
---
 fs/ext4/xattr.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 75287422c36c..efa623658c12 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -2579,7 +2579,7 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
 
 	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);
+	buffer = kvmalloc(value_size, GFP_NOFS);
 	b_entry_name = kmalloc(entry->e_name_len + 1, GFP_NOFS);
 	if (!is || !bs || !buffer || !b_entry_name) {
 		error = -ENOMEM;
@@ -2631,7 +2631,7 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
 	error = 0;
 out:
 	kfree(b_entry_name);
-	kfree(buffer);
+	kvfree(buffer);
 	if (is)
 		brelse(is->iloc.bh);
 	if (bs)
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH -next 5/6] ext4: rename xattr_find_entry() and __xattr_check_inode()
  2022-12-06  1:58 [PATCH -next 0/6] Fix two issue about ext4 extended attribute Ye Bin
                   ` (3 preceding siblings ...)
  2022-12-06  1:58 ` [PATCH -next 4/6] ext4: allocate extended attribute value in vmalloc area Ye Bin
@ 2022-12-06  1:58 ` Ye Bin
  2022-12-06 12:07   ` Jan Kara
  2022-12-06  1:58 ` [PATCH -next 6/6] ext4: fix inode leak in 'ext4_xattr_inode_create()' Ye Bin
  5 siblings, 1 reply; 11+ messages in thread
From: Ye Bin @ 2022-12-06  1:58 UTC (permalink / raw)
  To: tytso, adilger.kernel, linux-ext4; +Cc: linux-kernel, jack, Ye Bin

From: Ye Bin <yebin10@huawei.com>

xattr_find_entry() and __xattr_check_inode() is in EXT4 xattr module. so
add 'ext4' prefix to unify name style.

Signed-off-by: Ye Bin <yebin10@huawei.com>
---
 fs/ext4/xattr.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index efa623658c12..003fe1f2d6a8 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -290,7 +290,7 @@ __ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh,
 
 
 static int
-__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
+__ext4_xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
 			 void *end, const char *function, unsigned int line)
 {
 	int error = -EFSCORRUPTED;
@@ -307,11 +307,11 @@ __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
 	return error;
 }
 
-#define xattr_check_inode(inode, header, end) \
-	__xattr_check_inode((inode), (header), (end), __func__, __LINE__)
+#define ext4_xattr_check_inode(inode, header, end) \
+	__ext4_xattr_check_inode((inode), (header), (end), __func__, __LINE__)
 
 static int
-xattr_find_entry(struct inode *inode, struct ext4_xattr_entry **pentry,
+ext4_xattr_find_entry(struct inode *inode, struct ext4_xattr_entry **pentry,
 		 void *end, int name_index, const char *name, int sorted)
 {
 	struct ext4_xattr_entry *entry, *next;
@@ -577,7 +577,7 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
 	ext4_xattr_block_cache_insert(ea_block_cache, bh);
 	entry = BFIRST(bh);
 	end = bh->b_data + bh->b_size;
-	error = xattr_find_entry(inode, &entry, end, name_index, name, 1);
+	error = ext4_xattr_find_entry(inode, &entry, end, name_index, name, 1);
 	if (error)
 		goto cleanup;
 	size = le32_to_cpu(entry->e_value_size);
@@ -628,11 +628,11 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
 	raw_inode = ext4_raw_inode(&iloc);
 	header = IHDR(inode, raw_inode);
 	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
-	error = xattr_check_inode(inode, header, end);
+	error = ext4_xattr_check_inode(inode, header, end);
 	if (error)
 		goto cleanup;
 	entry = IFIRST(header);
-	error = xattr_find_entry(inode, &entry, end, name_index, name, 0);
+	error = ext4_xattr_find_entry(inode, &entry, end, name_index, name, 0);
 	if (error)
 		goto cleanup;
 	size = le32_to_cpu(entry->e_value_size);
@@ -773,7 +773,7 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 	raw_inode = ext4_raw_inode(&iloc);
 	header = IHDR(inode, raw_inode);
 	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
-	error = xattr_check_inode(inode, header, end);
+	error = ext4_xattr_check_inode(inode, header, end);
 	if (error)
 		goto cleanup;
 	error = ext4_xattr_list_entries(dentry, IFIRST(header),
@@ -859,7 +859,7 @@ int ext4_get_inode_usage(struct inode *inode, qsize_t *usage)
 		raw_inode = ext4_raw_inode(&iloc);
 		header = IHDR(inode, raw_inode);
 		end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
-		ret = xattr_check_inode(inode, header, end);
+		ret = ext4_xattr_check_inode(inode, header, end);
 		if (ret)
 			goto out;
 
@@ -1862,7 +1862,7 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
 		bs->s.first = BFIRST(bs->bh);
 		bs->s.end = bs->bh->b_data + bs->bh->b_size;
 		bs->s.here = bs->s.first;
-		error = xattr_find_entry(inode, &bs->s.here, bs->s.end,
+		error = ext4_xattr_find_entry(inode, &bs->s.here, bs->s.end,
 					 i->name_index, i->name, 1);
 		if (error && error != -ENODATA)
 			return error;
@@ -2222,11 +2222,11 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
 	is->s.here = is->s.first;
 	is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
 	if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
-		error = xattr_check_inode(inode, header, is->s.end);
+		error = ext4_xattr_check_inode(inode, header, is->s.end);
 		if (error)
 			return error;
 		/* Find the named attribute. */
-		error = xattr_find_entry(inode, &is->s.here, is->s.end,
+		error = ext4_xattr_find_entry(inode, &is->s.here, is->s.end,
 					 i->name_index, i->name, 0);
 		if (error && error != -ENODATA)
 			return error;
@@ -2742,7 +2742,7 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
 	min_offs = end - base;
 	total_ino = sizeof(struct ext4_xattr_ibody_header) + sizeof(u32);
 
-	error = xattr_check_inode(inode, header, end);
+	error = ext4_xattr_check_inode(inode, header, end);
 	if (error)
 		goto cleanup;
 
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH -next 6/6] ext4: fix inode leak in 'ext4_xattr_inode_create()'
  2022-12-06  1:58 [PATCH -next 0/6] Fix two issue about ext4 extended attribute Ye Bin
                   ` (4 preceding siblings ...)
  2022-12-06  1:58 ` [PATCH -next 5/6] ext4: rename xattr_find_entry() and __xattr_check_inode() Ye Bin
@ 2022-12-06  1:58 ` Ye Bin
  2022-12-06 12:10   ` Jan Kara
  5 siblings, 1 reply; 11+ messages in thread
From: Ye Bin @ 2022-12-06  1:58 UTC (permalink / raw)
  To: tytso, adilger.kernel, linux-ext4; +Cc: linux-kernel, jack, Ye Bin

From: Ye Bin <yebin10@huawei.com>

There is issue as follows when do setxattr with inject fault:
[localhost]#fsck.ext4  -fn  /dev/sda
e2fsck 1.46.6-rc1 (12-Sep-2022)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Unattached zero-length inode 15.  Clear? no

Unattached inode 15
Connect to /lost+found? no

Pass 5: Checking group summary information

/dev/sda: ********** WARNING: Filesystem still has errors **********

/dev/sda: 15/655360 files (0.0% non-contiguous), 66755/2621440 blocks

Above issue occur in 'ext4_xattr_inode_create()', if 'ext4_mark_inode_dirty()'
failed need to drop inode's i_nlink. Or will lead to inode leak.

Signed-off-by: Ye Bin <yebin10@huawei.com>
---
 fs/ext4/xattr.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 003fe1f2d6a8..734f787ae7ed 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -1464,6 +1464,9 @@ static struct inode *ext4_xattr_inode_create(handle_t *handle,
 		if (!err)
 			err = ext4_inode_attach_jinode(ea_inode);
 		if (err) {
+			if (ext4_xattr_inode_dec_ref(handle, ea_inode))
+				ext4_warning_inode(ea_inode,
+					"cleanup dec ref error %d", err);
 			iput(ea_inode);
 			return ERR_PTR(err);
 		}
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH -next 1/6] ext4: fix WARNING in ext4_expand_extra_isize_ea
  2022-12-06  1:58 ` [PATCH -next 1/6] ext4: fix WARNING in ext4_expand_extra_isize_ea Ye Bin
@ 2022-12-06 12:04   ` Jan Kara
  2022-12-06 13:44     ` yebin (H)
  0 siblings, 1 reply; 11+ messages in thread
From: Jan Kara @ 2022-12-06 12:04 UTC (permalink / raw)
  To: Ye Bin
  Cc: tytso, adilger.kernel, linux-ext4, linux-kernel, jack, Ye Bin,
	syzbot+4d99a966fd74bdeeec36

On Tue 06-12-22 09:58:01, Ye Bin wrote:
> From: Ye Bin <yebin10@huawei.com>
> 
> Syzbot found the following issue:
> ------------[ cut here ]------------
> WARNING: CPU: 1 PID: 3631 at mm/page_alloc.c:5534 __alloc_pages+0x30a/0x560 mm/page_alloc.c:5534
> Modules linked in:
> CPU: 1 PID: 3631 Comm: syz-executor261 Not tainted 6.1.0-rc6-syzkaller-00308-g644e9524388a #0
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022
> RIP: 0010:__alloc_pages+0x30a/0x560 mm/page_alloc.c:5534
> RSP: 0018:ffffc90003ccf080 EFLAGS: 00010246
> RAX: ffffc90003ccf0e0 RBX: 000000000000000c RCX: 0000000000000000
> RDX: 0000000000000028 RSI: 0000000000000000 RDI: ffffc90003ccf108
> RBP: ffffc90003ccf198 R08: dffffc0000000000 R09: ffffc90003ccf0e0
> R10: fffff52000799e21 R11: 1ffff92000799e1c R12: 0000000000040c40
> R13: 1ffff92000799e18 R14: dffffc0000000000 R15: 1ffff92000799e14
> FS:  0000555555c10300(0000) GS:ffff8880b9900000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00007ffc36f70000 CR3: 00000000744ad000 CR4: 00000000003506e0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> Call Trace:
>  <TASK>
>  __alloc_pages_node include/linux/gfp.h:223 [inline]
>  alloc_pages_node include/linux/gfp.h:246 [inline]
>  __kmalloc_large_node+0x8a/0x1a0 mm/slab_common.c:1096
>  __do_kmalloc_node mm/slab_common.c:943 [inline]
>  __kmalloc+0xfe/0x1a0 mm/slab_common.c:968
>  kmalloc include/linux/slab.h:558 [inline]
>  ext4_xattr_move_to_block fs/ext4/xattr.c:2558 [inline]
>  ext4_xattr_make_inode_space fs/ext4/xattr.c:2673 [inline]
>  ext4_expand_extra_isize_ea+0xe3f/0x1cd0 fs/ext4/xattr.c:2765
>  __ext4_expand_extra_isize+0x2b8/0x3f0 fs/ext4/inode.c:5857
>  ext4_try_to_expand_extra_isize fs/ext4/inode.c:5900 [inline]
>  __ext4_mark_inode_dirty+0x51a/0x670 fs/ext4/inode.c:5978
>  ext4_inline_data_truncate+0x548/0xd00 fs/ext4/inline.c:2021
>  ext4_truncate+0x341/0xeb0 fs/ext4/inode.c:4221
>  ext4_process_orphan+0x1aa/0x2d0 fs/ext4/orphan.c:339
>  ext4_orphan_cleanup+0xb60/0x1340 fs/ext4/orphan.c:474
>  __ext4_fill_super fs/ext4/super.c:5515 [inline]
>  ext4_fill_super+0x80ed/0x8610 fs/ext4/super.c:5643
>  get_tree_bdev+0x400/0x620 fs/super.c:1324
>  vfs_get_tree+0x88/0x270 fs/super.c:1531
>  do_new_mount+0x289/0xad0 fs/namespace.c:3040
>  do_mount fs/namespace.c:3383 [inline]
>  __do_sys_mount fs/namespace.c:3591 [inline]
>  __se_sys_mount+0x2d3/0x3c0 fs/namespace.c:3568
>  do_syscall_x64 arch/x86/entry/common.c:50 [inline]
>  do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
>  entry_SYSCALL_64_after_hwframe+0x63/0xcd
>  </TASK>
> 
> Reason is allocate 16M memory by kmalloc, but MAX_ORDER is 11, kmalloc
> can allocate maxium size memory is 4M.
> XATTR_SIZE_MAX is currently 64k, but EXT4_XATTR_SIZE_MAX is '(1 << 24)',
> so 'ext4_xattr_check_entries()' regards this length as legal. Then trigger
> warning in 'ext4_xattr_move_to_block()'.
> To solve above issue, according to Jan Kara's suggestion use kvmalloc()
> to allocate memory in ext4_xattr_move_to_block().
> 
> Reported-by: syzbot+4d99a966fd74bdeeec36@syzkaller.appspotmail.com
> Fixes: 54dd0e0a1b25 ("ext4: add extra checks to ext4_xattr_block_get()")
> Signed-off-by: Ye Bin <yebin10@huawei.com>

The changelog speak about kvmalloc() while your patch changes
EXT4_XATTR_SIZE_MAX. This needs to be fixed. If Ted is find with this
change, I have no problem with it either but I remember there were some
discussions about what EXT4_XATTR_SIZE_MAX should be when ea_inode feature
has been developed. Ted might remember.

Also the change from kmalloc() to kvmalloc() is a desirable one anyway. It
is not always easy to find physically contiguous 64k of memory so
kvmalloc() makes the allocation much more likely to succeed.

								Honza

-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH -next 5/6] ext4: rename xattr_find_entry() and __xattr_check_inode()
  2022-12-06  1:58 ` [PATCH -next 5/6] ext4: rename xattr_find_entry() and __xattr_check_inode() Ye Bin
@ 2022-12-06 12:07   ` Jan Kara
  0 siblings, 0 replies; 11+ messages in thread
From: Jan Kara @ 2022-12-06 12:07 UTC (permalink / raw)
  To: Ye Bin; +Cc: tytso, adilger.kernel, linux-ext4, linux-kernel, jack, Ye Bin

On Tue 06-12-22 09:58:05, Ye Bin wrote:
> From: Ye Bin <yebin10@huawei.com>
> 
> xattr_find_entry() and __xattr_check_inode() is in EXT4 xattr module. so
> add 'ext4' prefix to unify name style.
> 
> Signed-off-by: Ye Bin <yebin10@huawei.com>

Looks nice. Just one nit below:

> @@ -1862,7 +1862,7 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
>  		bs->s.first = BFIRST(bs->bh);
>  		bs->s.end = bs->bh->b_data + bs->bh->b_size;
>  		bs->s.here = bs->s.first;
> -		error = xattr_find_entry(inode, &bs->s.here, bs->s.end,
> +		error = ext4_xattr_find_entry(inode, &bs->s.here, bs->s.end,
>  					 i->name_index, i->name, 1);
>  		if (error && error != -ENODATA)
>  			return error;
> @@ -2222,11 +2222,11 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
>  	is->s.here = is->s.first;
>  	is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
>  	if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
> -		error = xattr_check_inode(inode, header, is->s.end);
> +		error = ext4_xattr_check_inode(inode, header, is->s.end);
>  		if (error)
>  			return error;
>  		/* Find the named attribute. */
> -		error = xattr_find_entry(inode, &is->s.here, is->s.end,
> +		error = ext4_xattr_find_entry(inode, &is->s.here, is->s.end,
>  					 i->name_index, i->name, 0);
>  		if (error && error != -ENODATA)
>  			return error;

The indentation of arguments in the above should be updated as well to look
like:

		error = ext4_xattr_find_entry(inode, &is->s.here, is->s.end,
					      i->name_index, i->name, 0);

								Honza
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH -next 6/6] ext4: fix inode leak in 'ext4_xattr_inode_create()'
  2022-12-06  1:58 ` [PATCH -next 6/6] ext4: fix inode leak in 'ext4_xattr_inode_create()' Ye Bin
@ 2022-12-06 12:10   ` Jan Kara
  0 siblings, 0 replies; 11+ messages in thread
From: Jan Kara @ 2022-12-06 12:10 UTC (permalink / raw)
  To: Ye Bin; +Cc: tytso, adilger.kernel, linux-ext4, linux-kernel, jack, Ye Bin

On Tue 06-12-22 09:58:06, Ye Bin wrote:
> From: Ye Bin <yebin10@huawei.com>
> 
> There is issue as follows when do setxattr with inject fault:
> [localhost]#fsck.ext4  -fn  /dev/sda
> e2fsck 1.46.6-rc1 (12-Sep-2022)
> Pass 1: Checking inodes, blocks, and sizes
> Pass 2: Checking directory structure
> Pass 3: Checking directory connectivity
> Pass 4: Checking reference counts
> Unattached zero-length inode 15.  Clear? no
> 
> Unattached inode 15
> Connect to /lost+found? no
> 
> Pass 5: Checking group summary information
> 
> /dev/sda: ********** WARNING: Filesystem still has errors **********
> 
> /dev/sda: 15/655360 files (0.0% non-contiguous), 66755/2621440 blocks
> 
> Above issue occur in 'ext4_xattr_inode_create()', if 'ext4_mark_inode_dirty()'
> failed need to drop inode's i_nlink. Or will lead to inode leak.
> 
> Signed-off-by: Ye Bin <yebin10@huawei.com>

The change looks good. Feel free to add:

Reviewed-by: Jan Kara <jack@suse.cz>

I'm just slightly wondering if there is ever a situation when
ext4_mark_inode_dirty() fails but the following cleanup would succeed...

								Honza 

> ---
>  fs/ext4/xattr.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
> index 003fe1f2d6a8..734f787ae7ed 100644
> --- a/fs/ext4/xattr.c
> +++ b/fs/ext4/xattr.c
> @@ -1464,6 +1464,9 @@ static struct inode *ext4_xattr_inode_create(handle_t *handle,
>  		if (!err)
>  			err = ext4_inode_attach_jinode(ea_inode);
>  		if (err) {
> +			if (ext4_xattr_inode_dec_ref(handle, ea_inode))
> +				ext4_warning_inode(ea_inode,
> +					"cleanup dec ref error %d", err);
>  			iput(ea_inode);
>  			return ERR_PTR(err);
>  		}
> -- 
> 2.31.1
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH -next 1/6] ext4: fix WARNING in ext4_expand_extra_isize_ea
  2022-12-06 12:04   ` Jan Kara
@ 2022-12-06 13:44     ` yebin (H)
  0 siblings, 0 replies; 11+ messages in thread
From: yebin (H) @ 2022-12-06 13:44 UTC (permalink / raw)
  To: Jan Kara, Ye Bin
  Cc: tytso, adilger.kernel, linux-ext4, linux-kernel,
	syzbot+4d99a966fd74bdeeec36



On 2022/12/6 20:04, Jan Kara wrote:
> On Tue 06-12-22 09:58:01, Ye Bin wrote:
>> From: Ye Bin <yebin10@huawei.com>
>>
>> Syzbot found the following issue:
>> ------------[ cut here ]------------
>> WARNING: CPU: 1 PID: 3631 at mm/page_alloc.c:5534 __alloc_pages+0x30a/0x560 mm/page_alloc.c:5534
>> Modules linked in:
>> CPU: 1 PID: 3631 Comm: syz-executor261 Not tainted 6.1.0-rc6-syzkaller-00308-g644e9524388a #0
>> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022
>> RIP: 0010:__alloc_pages+0x30a/0x560 mm/page_alloc.c:5534
>> RSP: 0018:ffffc90003ccf080 EFLAGS: 00010246
>> RAX: ffffc90003ccf0e0 RBX: 000000000000000c RCX: 0000000000000000
>> RDX: 0000000000000028 RSI: 0000000000000000 RDI: ffffc90003ccf108
>> RBP: ffffc90003ccf198 R08: dffffc0000000000 R09: ffffc90003ccf0e0
>> R10: fffff52000799e21 R11: 1ffff92000799e1c R12: 0000000000040c40
>> R13: 1ffff92000799e18 R14: dffffc0000000000 R15: 1ffff92000799e14
>> FS:  0000555555c10300(0000) GS:ffff8880b9900000(0000) knlGS:0000000000000000
>> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>> CR2: 00007ffc36f70000 CR3: 00000000744ad000 CR4: 00000000003506e0
>> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
>> DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
>> Call Trace:
>>   <TASK>
>>   __alloc_pages_node include/linux/gfp.h:223 [inline]
>>   alloc_pages_node include/linux/gfp.h:246 [inline]
>>   __kmalloc_large_node+0x8a/0x1a0 mm/slab_common.c:1096
>>   __do_kmalloc_node mm/slab_common.c:943 [inline]
>>   __kmalloc+0xfe/0x1a0 mm/slab_common.c:968
>>   kmalloc include/linux/slab.h:558 [inline]
>>   ext4_xattr_move_to_block fs/ext4/xattr.c:2558 [inline]
>>   ext4_xattr_make_inode_space fs/ext4/xattr.c:2673 [inline]
>>   ext4_expand_extra_isize_ea+0xe3f/0x1cd0 fs/ext4/xattr.c:2765
>>   __ext4_expand_extra_isize+0x2b8/0x3f0 fs/ext4/inode.c:5857
>>   ext4_try_to_expand_extra_isize fs/ext4/inode.c:5900 [inline]
>>   __ext4_mark_inode_dirty+0x51a/0x670 fs/ext4/inode.c:5978
>>   ext4_inline_data_truncate+0x548/0xd00 fs/ext4/inline.c:2021
>>   ext4_truncate+0x341/0xeb0 fs/ext4/inode.c:4221
>>   ext4_process_orphan+0x1aa/0x2d0 fs/ext4/orphan.c:339
>>   ext4_orphan_cleanup+0xb60/0x1340 fs/ext4/orphan.c:474
>>   __ext4_fill_super fs/ext4/super.c:5515 [inline]
>>   ext4_fill_super+0x80ed/0x8610 fs/ext4/super.c:5643
>>   get_tree_bdev+0x400/0x620 fs/super.c:1324
>>   vfs_get_tree+0x88/0x270 fs/super.c:1531
>>   do_new_mount+0x289/0xad0 fs/namespace.c:3040
>>   do_mount fs/namespace.c:3383 [inline]
>>   __do_sys_mount fs/namespace.c:3591 [inline]
>>   __se_sys_mount+0x2d3/0x3c0 fs/namespace.c:3568
>>   do_syscall_x64 arch/x86/entry/common.c:50 [inline]
>>   do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
>>   entry_SYSCALL_64_after_hwframe+0x63/0xcd
>>   </TASK>
>>
>> Reason is allocate 16M memory by kmalloc, but MAX_ORDER is 11, kmalloc
>> can allocate maxium size memory is 4M.
>> XATTR_SIZE_MAX is currently 64k, but EXT4_XATTR_SIZE_MAX is '(1 << 24)',
>> so 'ext4_xattr_check_entries()' regards this length as legal. Then trigger
>> warning in 'ext4_xattr_move_to_block()'.
>> To solve above issue, according to Jan Kara's suggestion use kvmalloc()
>> to allocate memory in ext4_xattr_move_to_block().
>>
>> Reported-by: syzbot+4d99a966fd74bdeeec36@syzkaller.appspotmail.com
>> Fixes: 54dd0e0a1b25 ("ext4: add extra checks to ext4_xattr_block_get()")
>> Signed-off-by: Ye Bin <yebin10@huawei.com>
> The changelog speak about kvmalloc() while your patch changes
> EXT4_XATTR_SIZE_MAX. This needs to be fixed. If Ted is find with this
> change, I have no problem with it either but I remember there were some
> discussions about what EXT4_XATTR_SIZE_MAX should be when ea_inode feature
> has been developed. Ted might remember.

I'm sorry I forgot to modify the commit message, I will modify the 
changelog again.

> Also the change from kmalloc() to kvmalloc() is a desirable one anyway. It
> is not always easy to find physically contiguous 64k of memory so
> kvmalloc() makes the allocation much more likely to succeed.
>
> 								Honza

A later patch use kvmalloc to allocate  extended attribute value memory.



^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2022-12-06 13:44 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-06  1:58 [PATCH -next 0/6] Fix two issue about ext4 extended attribute Ye Bin
2022-12-06  1:58 ` [PATCH -next 1/6] ext4: fix WARNING in ext4_expand_extra_isize_ea Ye Bin
2022-12-06 12:04   ` Jan Kara
2022-12-06 13:44     ` yebin (H)
2022-12-06  1:58 ` [PATCH -next 2/6] ext4: add primary check extended attribute inode in ext4_xattr_check_entries() Ye Bin
2022-12-06  1:58 ` [PATCH -next 3/6] ext4: remove unnessary size check in ext4_xattr_inode_get() Ye Bin
2022-12-06  1:58 ` [PATCH -next 4/6] ext4: allocate extended attribute value in vmalloc area Ye Bin
2022-12-06  1:58 ` [PATCH -next 5/6] ext4: rename xattr_find_entry() and __xattr_check_inode() Ye Bin
2022-12-06 12:07   ` Jan Kara
2022-12-06  1:58 ` [PATCH -next 6/6] ext4: fix inode leak in 'ext4_xattr_inode_create()' Ye Bin
2022-12-06 12:10   ` Jan Kara

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.