Received: by 2002:a05:6358:c692:b0:131:369:b2a3 with SMTP id fe18csp5848539rwb; Tue, 1 Aug 2023 08:41:25 -0700 (PDT) X-Google-Smtp-Source: APBJJlHi145nxqGL/H2pSO//A2K78ZJBizlnMgEyd53mb3zOmLtRxxrMLKtNoJ1ZsEGZfE5rQCOf X-Received: by 2002:aa7:d1d0:0:b0:522:1d23:a1f8 with SMTP id g16-20020aa7d1d0000000b005221d23a1f8mr2549813edp.26.1690904485036; Tue, 01 Aug 2023 08:41:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1690904485; cv=none; d=google.com; s=arc-20160816; b=OLpvI1PTrG82p3yCxr75+sSo9yuoL0WGfkX77P3eTVTY8N3+I889XC71ku8NcwKlND C69Ml/qys+e9uAuP++uxFLOoQSOiKpS6CoV1G8B97zIJW5vXcbNtQA/ryYKOrzlZFPtN k/IV4tw3lHAegfoiu16y9NCJYVIXcF8dNpSFYZWuc/FogMosOJXdyt8mO9LLIjImZwbj ktONhgj+JG/mrXVYoI+yLdcNQuqpg7YLEi76h43RYn6SsjNlaoqrhSW03nAcIQcSQSnZ WU6pOPzlvpwNEJa1yqLG5tHKOJEsujK8iptPtMMTvr8c5vq7w+ALwVI0bE5fvCujNc82 iVLw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date:dkim-signature; bh=/uc9jfV5mWp9SBXCk2/IiVrmS0qrA3iCP5ySLefQNrE=; fh=e7esVzxLSO8K79ywCOaTTO6Os5rxarD4oBe/5V8xy18=; b=FiX0QU3pC/R8hbEWqOxIv4OLEp1Lr/17V6eIujfga18LkkTpZMvDYpKAbFXAFmdXLh 3wBLlQg9LuTE+YJMGO+jqAVFeXNnBr12ea7Hp2871QiyhU7N5NhnfsV4LJG8saDeq5IE O0FjnN6+44mIyUrZKY3HrbvuDd2+xvSeLskzyv3xuo/JDa28rhX/wwgqOvCj+jjEm44l wlvaBVoeRNeyKEGnyTmD5AsYYoCoCJNAk2OrY7UB1z5Zz20RI3KwxVBjQj73NVdf0MHx 0bankItVCcRddRBogLQRcDkUnDARrVOel/Q67LvH0rokRN38t4j5wLpak/GwKbosfqI6 yJ+Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=R33CuhpM; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id l16-20020aa7d950000000b00522270c5923si8285453eds.528.2023.08.01.08.40.55; Tue, 01 Aug 2023 08:41:25 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-ext4-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=@kernel.org header.s=k20201202 header.b=R33CuhpM; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233110AbjHAPSf (ORCPT + 99 others); Tue, 1 Aug 2023 11:18:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42538 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233839AbjHAPSc (ORCPT ); Tue, 1 Aug 2023 11:18:32 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 082182102; Tue, 1 Aug 2023 08:18:30 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 91A2461531; Tue, 1 Aug 2023 15:18:29 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id ED480C433C8; Tue, 1 Aug 2023 15:18:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1690903109; bh=iR0vxFbHHnoGoKhRMvkLfrUpLYKG6Zy8MO5fgey7/WE=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=R33CuhpMn3/kdUcPqTebZEgIk+MbCkDnO8EGLjqZNH4Ts1Fk4d+Dv8hTjt1nKx0ig NhCfBsGyTlsL7BD/334bYwz70owny1S6yOIVmEijXb5Vu5nDiMUBVMOI7bT3z5CcXt 6Iyr7x5mF29qn00w/iHvY7PP1dSkqDPIAF2rVXg5R83zXqR2gzgLljSqTVdwr6q0eN GHHYfzI4ETWP5zvhtOTcPQriZDPNixmcU/jRui0X58uMMkp4dK6iIVZmascTP5I2VW 2iqvk1SwAAb0apBIA6hMdtbLLYNlOauQBJcQ5M1yPOijaTOXSOBbzJWwI4VoQfLoP4 lH7uP3QNUsaIw== Date: Tue, 1 Aug 2023 08:18:28 -0700 From: "Darrick J. Wong" To: zhangshida Cc: tytso@mit.edu, adilger.kernel@dilger.ca, yi.zhang@huawei.com, linux-ext4@vger.kernel.org, linux-kernel@vger.kernel.org, zhangshida@kylinos.cn, stable@kernel.org, Andreas Dilger Subject: Re: [PATCH v3] ext4: Fix rec_len verify error Message-ID: <20230801151828.GB11332@frogsfrogsfrogs> References: <20230801112337.1856215-1-zhangshida@kylinos.cn> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20230801112337.1856215-1-zhangshida@kylinos.cn> X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, 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-ext4@vger.kernel.org On Tue, Aug 01, 2023 at 07:23:37PM +0800, zhangshida wrote: > 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 introduce 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 > le16_to_cpu(ext4_dir_entry{,_2}.rec_len) accesses 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 > --- > v1->v2: > Use the existing helper to covert the rec_len, as suggested by Andreas. > v2->v3: > 1,Covert all the other rec_len if necessary, as suggested by Darrick. > 2,Rephrase the commit message. > > fs/ext4/namei.c | 16 ++++++++-------- > 1 file changed, 8 insertions(+), 8 deletions(-) > > diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c > index 0caf6c730ce3..8cb377b8ad86 100644 > --- a/fs/ext4/namei.c > +++ b/fs/ext4/namei.c > @@ -346,14 +346,14 @@ static struct ext4_dir_entry_tail *get_dirent_tail(struct inode *inode, > > #ifdef PARANOID > struct ext4_dir_entry *d, *top; > + int blocksize = EXT4_BLOCK_SIZE(inode->i_sb); > > 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; This is sitll missing some pieces; what about this clause at line 367: if (t->det_reserved_zero1 || le16_to_cpu(t->det_rec_len) != sizeof(struct ext4_dir_entry_tail) || t->det_reserved_zero2 || t->det_reserved_ft != EXT4_FT_DIR_CSUM) return NULL; > @@ -445,13 +445,13 @@ 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); > > - if (le16_to_cpu(dirent->rec_len) == EXT4_BLOCK_SIZE(inode->i_sb)) > + if (ext4_rec_len_from_disk(dirent->rec_len, blocksize) == blocksize) > count_offset = 8; > - else if (le16_to_cpu(dirent->rec_len) == 12) { > + else if (ext4_rec_len_from_disk(dirent->rec_len, blocksize) == 12) { Why not lift this ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ to a local variable? @dirent doesn't change, right? > 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 || What about dx_make_map? Here's all the opencoded access I could find: $ git grep le16.*rec_len fs/ext4/ fs/ext4/namei.c:356: le16_to_cpu(d->rec_len)); fs/ext4/namei.c:367: le16_to_cpu(t->det_rec_len) != sizeof(struct ext4_dir_entry_tail) || fs/ext4/namei.c:449: if (le16_to_cpu(dirent->rec_len) == EXT4_BLOCK_SIZE(inode->i_sb)) fs/ext4/namei.c:451: else if (le16_to_cpu(dirent->rec_len) == 12) { fs/ext4/namei.c:453: if (le16_to_cpu(dp->rec_len) != fs/ext4/namei.c:1338: map_tail->size = le16_to_cpu(de->rec_len); --D > -- > 2.27.0 >