From patchwork Thu Sep 5 01:13:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 13791581 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0B7728F58 for ; Thu, 5 Sep 2024 01:13:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725498832; cv=none; b=omlGIB+JAmAC9J95eLCLZZ8yQPa16RJsmQi+ruKbzCo9d3i9mwiQKafDDSNnLNN4ISKOOlbAH/y9zepX8qqLGx8wrfMO99jbHWuN1fOgOLgI2ipYW7lps4mFwEls1/8WYCNR3UrrtP9NG7BhAZkW3r5CfGjknxLMTXK+n5ezlD0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725498832; c=relaxed/simple; bh=ElKbY9BBrRfTrH4YsO7q/xU8KmVMxUAbGg4Kq/aR+6w=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QfJyw75VIjXAUJbOxz3yuOcoi28g/shq3WUFKsNI4V/h47Okx3s5owRINjPBiB1J6DgHaraRPqIrvmz3UQYVSvjX4QqQye0ZHD1DFSnfK5+fvoA65EdjBHTBVKS2TT2Xqvctej+l2fwL9xRxN2hmFYVGMSOiCq2ZsGJ4dPMinyI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=GCTeRKCD; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=GCTeRKCD; arc=none smtp.client-ip=195.135.223.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="GCTeRKCD"; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="GCTeRKCD" Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 214211F7F8 for ; Thu, 5 Sep 2024 01:13:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1725498828; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VQpFMKAuJPHv1EFSTqkizFNtAyzB3FQx+WFDWvfF3X8=; b=GCTeRKCD7vrpIzuC4FKQHEPxUblQHfmASk/K0W9ptA4ewRcDd/3sMYgdgX1ILZLpfb128V SznCz5nLADSEvd7mRNRWNVJPt6E+quRW/5PaVESqYVZIi7dfTHzdVyy/iPfT6mEn08uWlJ 6cPRAoRslMs5+zkqvg3pQnhthiavyx8= Authentication-Results: smtp-out2.suse.de; dkim=pass header.d=suse.com header.s=susede1 header.b=GCTeRKCD DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1725498828; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VQpFMKAuJPHv1EFSTqkizFNtAyzB3FQx+WFDWvfF3X8=; b=GCTeRKCD7vrpIzuC4FKQHEPxUblQHfmASk/K0W9ptA4ewRcDd/3sMYgdgX1ILZLpfb128V SznCz5nLADSEvd7mRNRWNVJPt6E+quRW/5PaVESqYVZIi7dfTHzdVyy/iPfT6mEn08uWlJ 6cPRAoRslMs5+zkqvg3pQnhthiavyx8= Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 6305F13508 for ; Thu, 5 Sep 2024 01:13:47 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id ONz/CcsF2WbMKQAAD6G6ig (envelope-from ) for ; Thu, 05 Sep 2024 01:13:47 +0000 From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 1/4] btrfs-progs: convert: fix inline extent size for symbol link Date: Thu, 5 Sep 2024 10:43:21 +0930 Message-ID: <4e9620084674f98620c4508d482de383b653ea9f.1725498618.git.wqu@suse.com> X-Mailer: git-send-email 2.46.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Rspamd-Queue-Id: 214211F7F8 X-Spam-Score: -3.01 X-Rspamd-Action: no action X-Spamd-Result: default: False [-3.01 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; R_DKIM_ALLOW(-0.20)[suse.com:s=susede1]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; MX_GOOD(-0.01)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; ARC_NA(0.00)[]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_ONE(0.00)[1]; PREVIOUSLY_DELIVERED(0.00)[linux-btrfs@vger.kernel.org]; RCVD_TLS_ALL(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; FUZZY_BLOCKED(0.00)[rspamd.com]; TO_DN_NONE(0.00)[]; DWL_DNSWL_BLOCKED(0.00)[suse.com:dkim]; MIME_TRACE(0.00)[0:+]; DKIM_TRACE(0.00)[suse.com:+] X-Rspamd-Server: rspamd1.dmz-prg2.suse.org X-Spam-Flag: NO X-Spam-Level: [BUG] Sometimes test case btrfs/012 fails randomly, with the failure to read a softlink: QA output created by 012 Checking converted btrfs against the original one: -OK +readlink: Structure needs cleaning Checking saved ext2 image against the original one: OK Furthermore, this will trigger a kernel error message: BTRFS critical (device dm-2): regular/prealloc extent found for non-regular inode 133081 [CAUSE] For that specific inode 133081, the tree dump looks like this: item 127 key (133081 INODE_ITEM 0) itemoff 40984 itemsize 160 generation 1 transid 1 size 4095 nbytes 4096 block group 0 mode 120777 links 1 uid 0 gid 0 rdev 0 sequence 0 flags 0x0(none) item 128 key (133081 INODE_REF 133080) itemoff 40972 itemsize 12 index 2 namelen 2 name: l3 item 129 key (133081 EXTENT_DATA 0) itemoff 40919 itemsize 53 generation 4 type 1 (regular) extent data disk byte 2147483648 nr 38080512 extent data offset 37974016 nr 4096 ram 38080512 extent compression 0 (none) Note that, the soft link inode size is 4095 at the max size (PATH_MAX, removing the terminating NUL). But the nbytes is 4096, exactly matching the sector size of the btrfs. Thus it results the creation of a regular extent, but for btrfs we do not accept a soft link with a regular/preallocated extent, thus kernel rejects such read and failed the readlink call. The root cause is in the convert code, where for soft links we always create a data extent with its size + 1, causing the above problem. I guess the original code is to handle the terminating NUL, but in btrfs we never need to store the terminating NUL for inline extents nor file names. Thus this pitfall in btrfs-convert leads to the above invalid data extent and fail the test case. [FIX] - Fix the ext2 and reiserfs symbolic link creation code To remove the terminating NUL. - Add extra checks for the size of a symbolic link Btrfs has extra limits on the size of a symbolic link, as btrfs must store symbolic link targets as inlined extents. This means for 4K node sized btrfs, the size limit is smaller than the usual PATH_MAX - 1 (only around 4000 bytes instead of 4095). So for certain nodesize, some filesystems can not be converted to btrfs. (this should be rare, because the default nodesize is 16K already) - Split the symbolic link and inline data extent size checks For symbolic links the real limit is PATH_MAX - 1 (removing the terminating NUL), but for inline data extents the limit is sectorsize - 1, which can be different from 4096 - 1 (e.g. 64K sector size). Signed-off-by: Qu Wenruo --- convert/source-ext2.c | 29 +++++++++++++++++++++++------ convert/source-reiserfs.c | 10 ++++++++-- kernel-shared/file-item.c | 6 ++++++ kernel-shared/file-item.h | 18 ++++++++++++++++++ 4 files changed, 55 insertions(+), 8 deletions(-) diff --git a/convert/source-ext2.c b/convert/source-ext2.c index acba5db7ee81..d06f90a98e9b 100644 --- a/convert/source-ext2.c +++ b/convert/source-ext2.c @@ -390,6 +390,7 @@ static int ext2_create_file_extents(struct btrfs_trans_handle *trans, ext2_filsys ext2_fs, ext2_ino_t ext2_ino, u32 convert_flags) { + struct btrfs_fs_info *fs_info = trans->fs_info; int ret; char *buffer = NULL; errcode_t err; @@ -397,8 +398,20 @@ static int ext2_create_file_extents(struct btrfs_trans_handle *trans, u32 last_block; u32 sectorsize = root->fs_info->sectorsize; u64 inode_size = btrfs_stack_inode_size(btrfs_inode); + bool meet_inline_size_limit; struct blk_iterate_data data; + if (S_ISLNK(btrfs_stack_inode_mode(btrfs_inode))) { + meet_inline_size_limit = inode_size <= btrfs_symlink_max_size(fs_info); + if (!meet_inline_size_limit) { + error("symlink too large for ext2 inode %u, has %llu max %u", + ext2_ino, inode_size, btrfs_symlink_max_size(fs_info)); + return -ENAMETOOLONG; + } + } else { + meet_inline_size_limit = inode_size <= btrfs_data_inline_max_size(fs_info); + } + init_blk_iterate_data(&data, trans, root, btrfs_inode, objectid, convert_flags & CONVERT_FLAG_DATACSUM); @@ -430,8 +443,7 @@ static int ext2_create_file_extents(struct btrfs_trans_handle *trans, if (ret) goto fail; if ((convert_flags & CONVERT_FLAG_INLINE_DATA) && data.first_block == 0 - && data.num_blocks > 0 && inode_size < sectorsize - && inode_size <= BTRFS_MAX_INLINE_DATA_SIZE(root->fs_info)) { + && data.num_blocks > 0 && meet_inline_size_limit) { u64 num_bytes = data.num_blocks * sectorsize; u64 disk_bytenr = data.disk_block * sectorsize; u64 nbytes; @@ -476,21 +488,26 @@ static int ext2_create_symlink(struct btrfs_trans_handle *trans, int ret; char *pathname; u64 inode_size = btrfs_stack_inode_size(btrfs_inode); + if (ext2fs_inode_data_blocks2(ext2_fs, ext2_inode)) { - btrfs_set_stack_inode_size(btrfs_inode, inode_size + 1); + if (inode_size > btrfs_symlink_max_size(trans->fs_info)) { + error("symlink too large for ext2 inode %u, has %llu max %u", + ext2_ino, inode_size, + btrfs_symlink_max_size(trans->fs_info)); + return -ENAMETOOLONG; + } ret = ext2_create_file_extents(trans, root, objectid, btrfs_inode, ext2_fs, ext2_ino, CONVERT_FLAG_DATACSUM | CONVERT_FLAG_INLINE_DATA); - btrfs_set_stack_inode_size(btrfs_inode, inode_size); return ret; } pathname = (char *)&(ext2_inode->i_block[0]); BUG_ON(pathname[inode_size] != 0); ret = btrfs_insert_inline_extent(trans, root, objectid, 0, - pathname, inode_size + 1); - btrfs_set_stack_inode_nbytes(btrfs_inode, inode_size + 1); + pathname, inode_size); + btrfs_set_stack_inode_nbytes(btrfs_inode, inode_size); return ret; } diff --git a/convert/source-reiserfs.c b/convert/source-reiserfs.c index 3edc72ed08a5..3475b15277dc 100644 --- a/convert/source-reiserfs.c +++ b/convert/source-reiserfs.c @@ -537,9 +537,15 @@ static int reiserfs_copy_symlink(struct btrfs_trans_handle *trans, symlink = tp_item_body(&path); len = get_ih_item_len(tp_item_head(&path)); + if (len > btrfs_symlink_max_size(trans->fs_info)) { + error("symlink too large, has %u max %u", + len, btrfs_symlink_max_size(trans->fs_info)); + ret = -ENAMETOOLONG; + goto fail; + } ret = btrfs_insert_inline_extent(trans, root, objectid, 0, - symlink, len + 1); - btrfs_set_stack_inode_nbytes(btrfs_inode, len + 1); + symlink, len); + btrfs_set_stack_inode_nbytes(btrfs_inode, len); fail: pathrelse(&path); return ret; diff --git a/kernel-shared/file-item.c b/kernel-shared/file-item.c index d2da56e1f523..eb9024022d9f 100644 --- a/kernel-shared/file-item.c +++ b/kernel-shared/file-item.c @@ -26,6 +26,7 @@ #include "kernel-shared/extent_io.h" #include "kernel-shared/uapi/btrfs.h" #include "common/internal.h" +#include "common/messages.h" #define MAX_CSUM_ITEMS(r, size) ((((BTRFS_LEAF_DATA_SIZE(r->fs_info) - \ sizeof(struct btrfs_item) * 2) / \ @@ -88,6 +89,7 @@ int btrfs_insert_inline_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid, u64 offset, const char *buffer, size_t size) { + struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_key key; struct btrfs_path *path; struct extent_buffer *leaf; @@ -97,6 +99,10 @@ int btrfs_insert_inline_extent(struct btrfs_trans_handle *trans, int err = 0; int ret; + if (size > max(btrfs_symlink_max_size(fs_info), + btrfs_data_inline_max_size(fs_info))) + return -EUCLEAN; + path = btrfs_alloc_path(); if (!path) return -ENOMEM; diff --git a/kernel-shared/file-item.h b/kernel-shared/file-item.h index 0df8f4dfea72..2c1e17c990dc 100644 --- a/kernel-shared/file-item.h +++ b/kernel-shared/file-item.h @@ -92,5 +92,23 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, u64 logical, int btrfs_insert_inline_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid, u64 offset, const char *buffer, size_t size); +/* + * For symlink we allow up to PATH_MAX - 1 (PATH_MAX includes the terminating NUL, + * but fs doesn't store that terminating NUL). + * + * But for inlined data extents, the up limit is sectorsize - 1 (inclusive), or a + * regular extent should be created instead. + */ +static inline u32 btrfs_symlink_max_size(struct btrfs_fs_info *fs_info) +{ + return min_t(u32, BTRFS_MAX_INLINE_DATA_SIZE(fs_info), + PATH_MAX - 1); +} + +static inline u32 btrfs_data_inline_max_size(struct btrfs_fs_info *fs_info) +{ + return min_t(u32, BTRFS_MAX_INLINE_DATA_SIZE(fs_info), + fs_info->sectorsize - 1); +} #endif From patchwork Thu Sep 5 01:13:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 13791583 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 262338F6E for ; Thu, 5 Sep 2024 01:13:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725498834; cv=none; b=lPUxwAKlMU9hvRcRUxhbIZ4/cX9XbSPq2Isgakmzfi7tGc80zS+WzqzTYjcr4zHJqxNX79RFLcgGzmtWr6QMacrNprtQXvjcQayukREl1GG/UhZPAk/30tLOhLkou35q97aWPBIrNN94o2+jkJWQ2UinSW+CYju3wsQEUGtNDlI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725498834; c=relaxed/simple; bh=qtJ/u922NqpONB/LtGvgwSV7sEQiNKZVax6VGDIymOg=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lHJkM2sqgs44J3dU5btVpW/ygZp9EL2pZB+owDVSensVGQ/wc6HhJmxOCVkWPl5u43M2x/kMuwnPiWeezylxfO5gMLdcn702E9pUlMJUOciuTC2x0cPk+MO2RD/tE32aL4m9lIoZReiybYmcNlRbHciXTACy3BYJM+YvUCJB1T8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=HOMDPfrG; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=HOMDPfrG; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="HOMDPfrG"; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="HOMDPfrG" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 5964D219C9 for ; Thu, 5 Sep 2024 01:13:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1725498829; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=R2rTnlrTr/V+hvZrCoacc6TtHjuHlRjKvliG4WqKZ+s=; b=HOMDPfrGjDHeanlr8NLISr5h8p8Vfo0fXFTBZs9jKmVY045TqTz7ESTS8SRDIexdxP97G3 e8esl23rdSNkFYIAuKRBsEZpX+9s6mm5nw8R1mYKxRY+tEd7ZJyJrs5YVZ3B5PksL59WV2 XhEMu5A3G6BgpbOqml+kjDt3o1nMb+M= Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1725498829; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=R2rTnlrTr/V+hvZrCoacc6TtHjuHlRjKvliG4WqKZ+s=; b=HOMDPfrGjDHeanlr8NLISr5h8p8Vfo0fXFTBZs9jKmVY045TqTz7ESTS8SRDIexdxP97G3 e8esl23rdSNkFYIAuKRBsEZpX+9s6mm5nw8R1mYKxRY+tEd7ZJyJrs5YVZ3B5PksL59WV2 XhEMu5A3G6BgpbOqml+kjDt3o1nMb+M= Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 9035E13508 for ; Thu, 5 Sep 2024 01:13:48 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id UPEhFcwF2WbMKQAAD6G6ig (envelope-from ) for ; Thu, 05 Sep 2024 01:13:48 +0000 From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 2/4] btrfs-progs: check/original: detect invalid file extent items for symbolic links Date: Thu, 5 Sep 2024 10:43:22 +0930 Message-ID: <88fb398f778e76297ca27817eb44697392279b53.1725498618.git.wqu@suse.com> X-Mailer: git-send-email 2.46.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Level: X-Spamd-Result: default: False [-2.80 / 50.00]; BAYES_HAM(-3.00)[99.99%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; ARC_NA(0.00)[]; RCPT_COUNT_ONE(0.00)[1]; RCVD_VIA_SMTP_AUTH(0.00)[]; MIME_TRACE(0.00)[0:+]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; PREVIOUSLY_DELIVERED(0.00)[linux-btrfs@vger.kernel.org]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; FUZZY_BLOCKED(0.00)[rspamd.com]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; TO_DN_NONE(0.00)[]; RCVD_TLS_ALL(0.00)[] X-Spam-Score: -2.80 X-Spam-Flag: NO [BUG] There is a recent bug that btrfs/012 fails and kernel rejects to read a symbolic link which is backed by a regular extent. Furthremore in that case, "btrfs check" doesn't detect such problem at all. [CAUSE] For symbolic links, we only allow inline file extents, and this means we should only have a symbolic link target which is smaller than 4K. But btrfs check doesn't handle symbolic link inodes any differently, thus it doesn't check if the file extents are inlined or not, nor reporting this problem as an error. [FIX] When processing data extents, if we find the owning inode is a symbolic link, and the file extent is regular/preallocated, mark the inode with I_ERR_FILE_EXTENT_TOO_LARGE error. Signed-off-by: Qu Wenruo --- check/main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/check/main.c b/check/main.c index 599f22ec36ee..d4108b7315e0 100644 --- a/check/main.c +++ b/check/main.c @@ -1745,6 +1745,13 @@ static int process_file_extent(struct btrfs_root *root, rec->errors |= I_ERR_BAD_FILE_EXTENT; if (disk_bytenr > 0) rec->found_size += num_bytes; + /* + * Symbolic links should only have inlined extents. + * A regular extent means it's already too large to + * be inlined. + */ + if (S_ISLNK(rec->imode)) + rec->errors |= I_ERR_FILE_EXTENT_TOO_LARGE; } else { rec->errors |= I_ERR_BAD_FILE_EXTENT; } From patchwork Thu Sep 5 01:13:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 13791584 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 36F8979DC for ; Thu, 5 Sep 2024 01:13:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725498834; cv=none; b=Swsoo2PuQOmBIh9rjzscEbGfGTvbkh+7z6sKt4J+wBpx/zMjxgamZFSFCyzEtcRXwFVHwYllUXc5VAQp5Xqzra5v7UVst2so71Q65A5k6L5yUSSYLJ4gd6x7QfG/vmNc7Rs0YQDIh5oKxkmfjvbW0CqH49b9S06ihS6cITIhgK0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725498834; c=relaxed/simple; bh=3SemLpMbxOjY3l4ZgvUZiMNUAuW62W8y7VM2Ruo9c6Q=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cQ3ifAlt8OQCmtqQXFfY8ty5Fk0qnLWSqkjao6MaJNhO6yngn8Z4+KRvQf3957/eYZ9HmMv0LBkvimPn2KsaEiJE6tYvVVDlmZfuXjs5uMRvsazJ0Ep08WW6pVLXsS930LWuLAGZj8MQg6OYibBk+vkHKeydy/XNs4151RiVnMk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=Bb9DlFrN; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=Bb9DlFrN; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="Bb9DlFrN"; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="Bb9DlFrN" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 7BE5E21A00 for ; Thu, 5 Sep 2024 01:13:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1725498830; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/1e0TrzUsYMos6YwtndrYPh2pr7jNyVnN6mKPOdHCNw=; b=Bb9DlFrNmVW+PwhNKzwMILktqxcyxunGJAtooQYLsGa2upoFS/Zk74gESZWb2nlxmH91gi uxjMzv+rnihm1rEdLi/zYke0QULFeaB0rg5qQjlNoHxm491fXfskb916GnaoieQOnLKVry BhuSIJGIlK/r3mtt9+zn3nRsnOufqr4= Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1725498830; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/1e0TrzUsYMos6YwtndrYPh2pr7jNyVnN6mKPOdHCNw=; b=Bb9DlFrNmVW+PwhNKzwMILktqxcyxunGJAtooQYLsGa2upoFS/Zk74gESZWb2nlxmH91gi uxjMzv+rnihm1rEdLi/zYke0QULFeaB0rg5qQjlNoHxm491fXfskb916GnaoieQOnLKVry BhuSIJGIlK/r3mtt9+zn3nRsnOufqr4= Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id BDDA213508 for ; Thu, 5 Sep 2024 01:13:49 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id mMM4IM0F2WbMKQAAD6G6ig (envelope-from ) for ; Thu, 05 Sep 2024 01:13:49 +0000 From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 3/4] btrfs-progs: check/lowmem: detect invalid file extents for symbolic links Date: Thu, 5 Sep 2024 10:43:23 +0930 Message-ID: X-Mailer: git-send-email 2.46.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Score: -2.80 X-Spamd-Result: default: False [-2.80 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; ARC_NA(0.00)[]; RCPT_COUNT_ONE(0.00)[1]; RCVD_VIA_SMTP_AUTH(0.00)[]; MIME_TRACE(0.00)[0:+]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; PREVIOUSLY_DELIVERED(0.00)[linux-btrfs@vger.kernel.org]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; FUZZY_BLOCKED(0.00)[rspamd.com]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; TO_DN_NONE(0.00)[]; RCVD_TLS_ALL(0.00)[] X-Spam-Flag: NO X-Spam-Level: [BUG] There is a recent bug that btrfs/012 fails and kernel rejects to read a symbolic link which is backed by a regular extent. Furthremore in that case, "btrfs check --mode=lowmem" doesn't detect such problem at all. [CAUSE] For symbolic links, we only allow inline extents, and this means we should only have a symbolic link target which is smaller than 4K. But lowmem mode btrfs check doesn't handle symbolic link inodes any differently, thus it doesn't check if the file extents are inlined or not, nor reporting this problem as an error. [FIX] When processing data extents, if we find the owning inode is a symbolic link, and the file extent is regular/preallocated, report an error for the bad file extent item. Signed-off-by: Qu Wenruo --- check/mode-lowmem.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index a9908eaf629d..4b6faccacbbc 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -3351,6 +3351,31 @@ out_no_release: return err; } +static int read_inode_item(struct btrfs_root *root, + u64 ino, struct btrfs_inode_item *ret_ii) +{ + struct btrfs_path path = { 0 }; + struct btrfs_key key = { + .objectid = ino, + .type = BTRFS_INODE_ITEM_KEY, + .offset = 0 + }; + int ret; + + ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); + if (ret > 0) + ret = -ENOENT; + if (ret < 0) + goto out; + + read_extent_buffer(path.nodes[0], ret_ii, + btrfs_item_ptr_offset(path.nodes[0], path.slots[0]), + sizeof(*ret_ii)); +out: + btrfs_release_path(&path); + return ret; +} + /* * Check EXTENT_DATA item, mainly for its dbackref in extent tree * @@ -3371,6 +3396,7 @@ static int check_extent_data_item(struct btrfs_root *root, struct btrfs_extent_item *ei; struct btrfs_extent_inline_ref *iref; struct btrfs_extent_data_ref *dref; + struct btrfs_inode_item inode_item; u64 owner; u64 disk_bytenr; u64 disk_num_bytes; @@ -3400,6 +3426,24 @@ static int check_extent_data_item(struct btrfs_root *root, extent_num_bytes = btrfs_file_extent_num_bytes(eb, fi); offset = btrfs_file_extent_offset(eb, fi); + /* + * There is a regular/preallocated data extent. Make sure the owning + * inode is not a symbolic link. + * As symbolic links can only have inline data extents. + */ + ret = read_inode_item(root, fi_key.objectid, &inode_item); + if (ret < 0) { + errno = -ret; + error("failed to grab the inode item for inode %llu: %m", + fi_key.objectid); + err |= INODE_ITEM_MISSING; + } + if (S_ISLNK(inode_item.mode)) { + error("symbolic link at root %lld ino %llu has regular/preallocated extents", + root->root_key.objectid, fi_key.objectid); + err |= FILE_EXTENT_ERROR; + } + /* Check unaligned disk_bytenr, disk_num_bytes and num_bytes */ if (!IS_ALIGNED(disk_bytenr, gfs_info->sectorsize)) { error( From patchwork Thu Sep 5 01:13:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 13791585 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 73B64B661 for ; Thu, 5 Sep 2024 01:13:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725498835; cv=none; b=TS9Tm9m0lHRjKVwQVStjO9MgLWtDOpWw3meIMf7txRmQHUYyFDNUVyN6Erf6ForGv58YHM26UlUKyKgR6RDE+v4ifKGLe97Tb2rwZxdP2HiLGXoiQHLjlIXTqAk8XvNURUxMxoRzw1SENy99WkJoBnRFUpcZ+0CDYOu8QS7aZjM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725498835; c=relaxed/simple; bh=A2y2NfacRgME26rDfUnQO6jPW2+8P+bn93wZB/iu+3Q=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PMx/xsDInkLStZmD/xLWJtZWheZd0GldWbGV1M/DnfuSuKaUJ2mJkWHxD15MemtR1cp6ZRWVtgPq09jFusokjipXHsoGGrgNyuBwAfgH8sYjlUbBfmeB1m5C9JsOoT7h8tPjT3L9JdG0jNkQ5X5YC5jnGFDQzR+FuYh1WCIZpTs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=d9vsPiOI; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=d9vsPiOI; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="d9vsPiOI"; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="d9vsPiOI" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id B63A421A2D for ; Thu, 5 Sep 2024 01:13:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1725498831; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Y+5cNJcxMFT8UIb9ApKpwfgkE7LT1Kso3brVsZAiFNM=; b=d9vsPiOILbklMyKGSqiPKc59IZPBHV5cVHOILyLYgSddpeeGsBlgiOt1+NYrDoJXaH12Wp P6QjXiciO3yC99JTUKALQ2/Qw+cJdSV9GG4MvT6ELdZzNILmwJjlrH1mXi2H8EcdArGrpV qhqwcWjeySKdeLVZEsOhLykr8PZrnOc= Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1725498831; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Y+5cNJcxMFT8UIb9ApKpwfgkE7LT1Kso3brVsZAiFNM=; b=d9vsPiOILbklMyKGSqiPKc59IZPBHV5cVHOILyLYgSddpeeGsBlgiOt1+NYrDoJXaH12Wp P6QjXiciO3yC99JTUKALQ2/Qw+cJdSV9GG4MvT6ELdZzNILmwJjlrH1mXi2H8EcdArGrpV qhqwcWjeySKdeLVZEsOhLykr8PZrnOc= Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id EB65113508 for ; Thu, 5 Sep 2024 01:13:50 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id iOVSK84F2WbMKQAAD6G6ig (envelope-from ) for ; Thu, 05 Sep 2024 01:13:50 +0000 From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 4/4] btrfs-progs: convert-tests: add a test case to verify large symbolic link handling Date: Thu, 5 Sep 2024 10:43:24 +0930 Message-ID: <1ef57f7fa8c482700016251c2a63fd254c3960ea.1725498618.git.wqu@suse.com> X-Mailer: git-send-email 2.46.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Score: -2.80 X-Spamd-Result: default: False [-2.80 / 50.00]; BAYES_HAM(-3.00)[99.99%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; ARC_NA(0.00)[]; RCPT_COUNT_ONE(0.00)[1]; RCVD_VIA_SMTP_AUTH(0.00)[]; MIME_TRACE(0.00)[0:+]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; PREVIOUSLY_DELIVERED(0.00)[linux-btrfs@vger.kernel.org]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; FUZZY_BLOCKED(0.00)[rspamd.com]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; TO_DN_NONE(0.00)[]; RCVD_TLS_ALL(0.00)[] X-Spam-Flag: NO X-Spam-Level: The new test case will: - Create a symbolic which contains a 4095 bytes sized target on ext4 - Convert the ext4 to btrfs - Make sure we can still read the symbolic link For unpatched btrfs-convert, the resulted symbolic link will be rejected by kernel and fail. Signed-off-by: Qu Wenruo --- .../027-large-symbol-link/test.sh | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100755 tests/convert-tests/027-large-symbol-link/test.sh diff --git a/tests/convert-tests/027-large-symbol-link/test.sh b/tests/convert-tests/027-large-symbol-link/test.sh new file mode 100755 index 000000000000..2a001424df83 --- /dev/null +++ b/tests/convert-tests/027-large-symbol-link/test.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Make sure btrfs-convert can handle a symbol link which is 4095 bytes large + +source "$TEST_TOP/common" || exit +source "$TEST_TOP/common.convert" || exit + +setup_root_helper +prepare_test_dev 1G +check_global_prereq mkfs.ext4 + +# This is at the symbolic link size limit (PATH_MAX includes the terminating NUL). +link_target=$(printf "%0.sb" {1..4095}) + +convert_test_prep_fs ext4 mke2fs -t ext4 -b 4096 +run_check $SUDO_HELPER ln -s "$link_target" "$TEST_MNT/symbol_link" +run_check_umount_test_dev + +# For unpatched btrfs-convert, it will always append one byte to the +# link target, causing above 4095 target to be 4096, exactly one sector, +# resulting a regular file extent. +convert_test_do_convert + +run_check_mount_test_dev +# If the unpatched btrfs-convert created a regular extent, and the kernel is +# newer enough, such readlink will be rejected by kernel. +run_check $SUDO_HELPER readlink "$TEST_MNT/symbol_link" +run_check_umount_test_dev