Received: by 2002:a05:6358:700f:b0:131:369:b2a3 with SMTP id 15csp1826205rwo; Wed, 2 Aug 2023 23:35:46 -0700 (PDT) X-Google-Smtp-Source: APBJJlE8NgIgc5su/3jIBgrc0F/VyQdEZ+YEYd3OxopKV2A6gFlRZtCH4h3oCfOfQ9I8fHO8eY4v X-Received: by 2002:aa7:c909:0:b0:522:2bc8:cbb8 with SMTP id b9-20020aa7c909000000b005222bc8cbb8mr6391574edt.6.1691044545916; Wed, 02 Aug 2023 23:35:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691044545; cv=none; d=google.com; s=arc-20160816; b=ej/3BsHINlxouRAWUyugscuUFuOJaP2HBrbsOxbpHfBxbhAdES83Ijyvp+PUexC97t YkNYK+gMW6QjLx6GmlAarzN0TyUON+l/Jqpmw0NBcyZTu+Xd65e0JT4BuJaPA1YrOr9O os31LI8IloBAmx/5xxGXnFUzKWnBgG07sh/eNwcSPTB++m3/NM2vlxxAPjjIOYN257DP eTBTN4vy33uLt2Q6W9aZUNTWI6NWSQ4EDP32L/SN0lTjvASTb0++qR26YDZGbwRXmRpI eKcMIHT/QlMmX+qmduURWu0GUHuyx5AfkCisFLxsYdZVFFhUWCrlGKejyQYTJV7WafZq +nyQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=oP3zxtD+0slQxaWy/bQYAlXRzptkEvoefxyTvuaiCok=; fh=h3yk0lElWFjVvKDwquxdow8n2MEs50tUho/hLv/sq2o=; b=AVGJkFssCIBpTlGtoU1HkD82SWc0U6CS5M2yXQQZAJMdU3PqOMuRiEANGVbyBf4jLp GugCn+lc8dMWWcZGex/PqHlMYJHaGItGHM3pcsTe/XTSY5dwKdbzhjEoF0PdcsfEUOnU 4myJPswqVOU+/wFViyIPZSVJenQ/o+C4XF5K8zhegX6BDRlqDcVAvlkcVjzFnbWH+oJC KQirP2h17bzRxYL+ajvrnyYVmxUEwOv6epkA+gZzYwJV8eWRzJItD7rtmmRLATmYygPi CsWrpc60faHgO0HEWkAkdJjtHpNnUhoMVF4vpb/TdyG3sKz7Re17DPJLKq1ZmaIBVGrq OCrg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b=HMNxIJCo; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id b24-20020aa7df98000000b005222c364c66si11202773edy.462.2023.08.02.23.35.20; Wed, 02 Aug 2023 23:35:45 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b=HMNxIJCo; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232735AbjHCGJ4 (ORCPT + 99 others); Thu, 3 Aug 2023 02:09:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37190 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230040AbjHCGJy (ORCPT ); Thu, 3 Aug 2023 02:09:54 -0400 Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9C6D8272C; Wed, 2 Aug 2023 23:09:53 -0700 (PDT) Received: by mail-wr1-x435.google.com with SMTP id ffacd0b85a97d-317b31203c7so525384f8f.2; Wed, 02 Aug 2023 23:09:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1691042992; x=1691647792; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=oP3zxtD+0slQxaWy/bQYAlXRzptkEvoefxyTvuaiCok=; b=HMNxIJCou7SwS+TtE4QnYWHt2S8KQSoYGd1YN/g9jxuYx3P6vtpdEdqfDh8WgE7p17 iwEie3KCbhbNFHJwJV3HUnWzveUyyOXILWsHMpqcTYImxJtI//OLIh8Em7oxBquLij4X CYU5Limw4/qQH6R6rDdZxz72Nc/X9NrROAGqG+f7jEJvJnVdbHLo2A26AEJ5shBATWwj qCmomT/AtqaesLjX+Hlpyac2kdF80nwl3eNu6yYGsL3aY7/S7ucUOE7UUW6+1dRx8Alb FjBscD5qOMnLZ4PjWAkwZHCMxZ67B7QHkPEnU3YE2DRgz0c913VAYix2+aT7w624oObi 40zg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691042992; x=1691647792; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=oP3zxtD+0slQxaWy/bQYAlXRzptkEvoefxyTvuaiCok=; b=Ql7sqYHjGMbHeu4wYXUu34MaeONZMASD0WnIN2rou+1tttyMpv/J8zv46LSWOUQW/f 9X5sOBjHssFBClbnrCorRHcqKu8Z5pF5tAONRrxYLRG9K8v6p+KyZ7jNNSmFfu2VafRp NHW/T+TvJSnv5nWgpjJhXqU+KoyJsUbyNmgsn1FPlMttEUv2TUTHiTSmUAonMQcb7eic x9wTQTJPAp2Yp6UD7c4Bo3gjlvAbGPa8wDV1V37w5x1jgC2EJO6msV4uVnWdr5BZ4cLh YZBCNPdBVpmQRu63OvsG7+uM6qZJ78zodGzVcP2G8G0Fqu48lllLyJDVukU8l598I1SI iLkA== X-Gm-Message-State: ABy/qLYelCPKzeYXFn6GD+4MGoELr9k3P1seh+/FWYTMOFfiX7EPNmfK FxM1iU6CP8IKYrp9KAgTzyz2eDfDtEBJdY4O X-Received: by 2002:adf:d08f:0:b0:317:6310:a616 with SMTP id y15-20020adfd08f000000b003176310a616mr6053018wrh.36.1691042991681; Wed, 02 Aug 2023 23:09:51 -0700 (PDT) Received: from localhost.localdomain ([2a05:f480:1000:b09:5400:4ff:fe6f:7099]) by smtp.gmail.com with ESMTPSA id l10-20020a5d410a000000b00317495f88fasm20696122wrp.112.2023.08.02.23.09.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Aug 2023 23:09:51 -0700 (PDT) From: zhangshida X-Google-Original-From: zhangshida To: tytso@mit.edu, adilger.kernel@dilger.ca, yi.zhang@huawei.com, djwong@kernel.org Cc: linux-ext4@vger.kernel.org, linux-kernel@vger.kernel.org, zhangshida@kylinos.cn, starzhangzsd@gmail.com, stable@kernel.org, Andreas Dilger Subject: [PATCH v4] ext4: Fix rec_len verify error Date: Thu, 3 Aug 2023 14:09:38 +0800 Message-Id: <20230803060938.1929759-1-zhangshida@kylinos.cn> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Shida Zhang With the configuration PAGE_SIZE 64k and filesystem blocksize 64k, a problem occurred when more than 13 million files were directly created under a directory: EXT4-fs error (device xx): ext4_dx_csum_set:492: inode #xxxx: comm xxxxx: dir seems corrupt? Run e2fsck -D. EXT4-fs error (device xx): ext4_dx_csum_verify:463: inode #xxxx: comm xxxxx: dir seems corrupt? Run e2fsck -D. EXT4-fs error (device xx): dx_probe:856: inode #xxxx: block 8188: comm xxxxx: Directory index failed checksum When enough files are created, the fake_dirent->reclen will be 0xffff. it doesn't equal to the blocksize 65536, i.e. 0x10000. But it is not the same condition when blocksize equals to 4k. when enough files are created, the fake_dirent->reclen will be 0x1000. it equals to the blocksize 4k, i.e. 0x1000. The problem seems to be related to the limitation of the 16-bit field when the blocksize is set to 64k. To address this, helpers like ext4_rec_len_{from,to}_disk has already been introduced to complete the conversion between the encoded and the plain form of rec_len. So fix this one by using the helper, and all the other in this file too. Cc: stable@kernel.org Fixes: dbe89444042a ("ext4: Calculate and verify checksums for htree nodes") Suggested-by: Andreas Dilger Suggested-by: Darrick J. Wong Signed-off-by: Shida Zhang --- v3->v4: 1,Convert all the other rec_len, litrerally. 2,Lift a helper output to a local variable. --Suggested by Darrick. v2->v3: 1,Convert all the other rec_len if necessary, as suggested by Darrick. 2,Rephrase the commit message. v1->v2: Use the existing helper to covert the rec_len, as suggested by Andreas. fs/ext4/namei.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 0caf6c730ce3..34fb2d1e66aa 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -343,17 +343,17 @@ static struct ext4_dir_entry_tail *get_dirent_tail(struct inode *inode, struct buffer_head *bh) { struct ext4_dir_entry_tail *t; + int blocksize = EXT4_BLOCK_SIZE(inode->i_sb); #ifdef PARANOID struct ext4_dir_entry *d, *top; d = (struct ext4_dir_entry *)bh->b_data; top = (struct ext4_dir_entry *)(bh->b_data + - (EXT4_BLOCK_SIZE(inode->i_sb) - - sizeof(struct ext4_dir_entry_tail))); - while (d < top && d->rec_len) + (blocksize - sizeof(struct ext4_dir_entry_tail))); + while (d < top && ext4_rec_len_from_disk(d->rec_len, blocksize)) d = (struct ext4_dir_entry *)(((void *)d) + - le16_to_cpu(d->rec_len)); + ext4_rec_len_from_disk(d->rec_len, blocksize)); if (d != top) return NULL; @@ -364,7 +364,8 @@ static struct ext4_dir_entry_tail *get_dirent_tail(struct inode *inode, #endif if (t->det_reserved_zero1 || - le16_to_cpu(t->det_rec_len) != sizeof(struct ext4_dir_entry_tail) || + (ext4_rec_len_from_disk(t->det_rec_len, blocksize) != + sizeof(struct ext4_dir_entry_tail)) || t->det_reserved_zero2 || t->det_reserved_ft != EXT4_FT_DIR_CSUM) return NULL; @@ -445,13 +446,14 @@ static struct dx_countlimit *get_dx_countlimit(struct inode *inode, struct ext4_dir_entry *dp; struct dx_root_info *root; int count_offset; + int blocksize = EXT4_BLOCK_SIZE(inode->i_sb); + unsigned int rlen = ext4_rec_len_from_disk(dirent->rec_len, blocksize); - if (le16_to_cpu(dirent->rec_len) == EXT4_BLOCK_SIZE(inode->i_sb)) + if (rlen == blocksize) count_offset = 8; - else if (le16_to_cpu(dirent->rec_len) == 12) { + else if (rlen == 12) { dp = (struct ext4_dir_entry *)(((void *)dirent) + 12); - if (le16_to_cpu(dp->rec_len) != - EXT4_BLOCK_SIZE(inode->i_sb) - 12) + if (ext4_rec_len_from_disk(dp->rec_len, blocksize) != blocksize - 12) return NULL; root = (struct dx_root_info *)(((void *)dp + 12)); if (root->reserved_zero || @@ -1315,6 +1317,7 @@ static int dx_make_map(struct inode *dir, struct buffer_head *bh, unsigned int buflen = bh->b_size; char *base = bh->b_data; struct dx_hash_info h = *hinfo; + int blocksize = EXT4_BLOCK_SIZE(dir->i_sb); if (ext4_has_metadata_csum(dir->i_sb)) buflen -= sizeof(struct ext4_dir_entry_tail); @@ -1335,11 +1338,12 @@ static int dx_make_map(struct inode *dir, struct buffer_head *bh, map_tail--; map_tail->hash = h.hash; map_tail->offs = ((char *) de - base)>>2; - map_tail->size = le16_to_cpu(de->rec_len); + map_tail->size = ext4_rec_len_from_disk(de->rec_len, + blocksize); count++; cond_resched(); } - de = ext4_next_entry(de, dir->i_sb->s_blocksize); + de = ext4_next_entry(de, blocksize); } return count; } -- 2.27.0