Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 486efbbc authored by Theodore Ts'o's avatar Theodore Ts'o Committed by Greg Kroah-Hartman
Browse files

ext4: add bounds checking in get_max_inline_xattr_value_size()



commit 2220eaf90992c11d888fe771055d4de330385f01 upstream.

Normally the extended attributes in the inode body would have been
checked when the inode is first opened, but if someone is writing to
the block device while the file system is mounted, it's possible for
the inode table to get corrupted.  Add bounds checking to avoid
reading beyond the end of allocated memory if this happens.

Reported-by: default avatar <syzbot+1966db24521e5f6e23f7@syzkaller.appspotmail.com>
Link: https://syzkaller.appspot.com/bug?extid=1966db24521e5f6e23f7


Cc: stable@kernel.org
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b4fa4768
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ static int get_max_inline_xattr_value_size(struct inode *inode,
	struct ext4_xattr_ibody_header *header;
	struct ext4_xattr_entry *entry;
	struct ext4_inode *raw_inode;
	void *end;
	int free, min_offs;

	if (!EXT4_INODE_HAS_XATTR_SPACE(inode))
@@ -55,14 +56,23 @@ static int get_max_inline_xattr_value_size(struct inode *inode,
	raw_inode = ext4_raw_inode(iloc);
	header = IHDR(inode, raw_inode);
	entry = IFIRST(header);
	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;

	/* Compute min_offs. */
	for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
	while (!IS_LAST_ENTRY(entry)) {
		void *next = EXT4_XATTR_NEXT(entry);

		if (next >= end) {
			EXT4_ERROR_INODE(inode,
					 "corrupt xattr in inline inode");
			return 0;
		}
		if (!entry->e_value_inum && entry->e_value_size) {
			size_t offs = le16_to_cpu(entry->e_value_offs);
			if (offs < min_offs)
				min_offs = offs;
		}
		entry = next;
	}
	free = min_offs -
		((void *)entry - (void *)IFIRST(header)) - sizeof(__u32);