From patchwork Sun Dec 31 22:32:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507898 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5FEDDC129 for ; Sun, 31 Dec 2023 22:32:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NU9VW3nK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3111CC433C7; Sun, 31 Dec 2023 22:32:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704061952; bh=VHAaFhWqX9pE0nnGEIkk/+HvTQj8Uv9R/U8zruIgtp4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=NU9VW3nKSwaPuczaMJIRyR30fchJL8/HUuDbkCP/afKbKDA3Y4+9gfwnHWniiJc5x jPQ9JVYresEdGrqs0KiML38H+FXRBYzvu/Zt44dzHvz/S7HjEayVySypBl4NHkusOc RD04pEWkzxSuE3oADJryw3MCceHvfH0VK27vyYLSMsv90OdDvioMilg1CXJKoedv6K bzejTyA2HMSUc7Q/+3FhQYl3IeI3fB6o3IEbsWK+oRTO33ZW9oePjf8umNdWMPtQIL fAgjFaAoZRiuboLYMKF3M1rIX1Pky14lpMpRNK0li9sZZicpBNWdBMZzXh4JZbZb6f jbyLgBiH76W7g== Date: Sun, 31 Dec 2023 14:32:31 -0800 Subject: [PATCH 1/9] xfs: add an explicit owner field to xfs_da_args From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404996881.1796662.10277481601586037353.stgit@frogsfrogsfrogs> In-Reply-To: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> References: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Add an explicit owner field to xfs_da_args, which will make it easier for online fsck to set the owner field of the temporary directory and xattr structures that it builds to repair damaged metadata. Note: I hopefully found all the xfs_da_args definitions by looking for automatic stack variable declarations and xfs_da_args.dp assignments: git grep -E '(args.*dp =|struct xfs_da_args[[:space:]]*[a-z0-9][a-z0-9]*)' Signed-off-by: Darrick J. Wong --- db/attrset.c | 2 ++ db/namei.c | 1 + libxfs/xfs_attr_leaf.c | 2 ++ libxfs/xfs_bmap.c | 1 + libxfs/xfs_da_btree.h | 1 + libxfs/xfs_dir2.c | 5 +++++ libxfs/xfs_swapext.c | 2 ++ repair/phase6.c | 3 +++ 8 files changed, 17 insertions(+) diff --git a/db/attrset.c b/db/attrset.c index 0d8d70a8429..2b6cdb5f5c3 100644 --- a/db/attrset.c +++ b/db/attrset.c @@ -161,6 +161,7 @@ attr_set_f( (unsigned long long)iocur_top->ino); goto out; } + args.owner = iocur_top->ino; if (libxfs_attr_set(&args)) { dbprintf(_("failed to set attr %s on inode %llu\n"), @@ -247,6 +248,7 @@ attr_remove_f( (unsigned long long)iocur_top->ino); goto out; } + args.owner = iocur_top->ino; if (libxfs_attr_set(&args)) { dbprintf(_("failed to remove attr %s from inode %llu\n"), diff --git a/db/namei.c b/db/namei.c index 063721ca98f..eb09288b490 100644 --- a/db/namei.c +++ b/db/namei.c @@ -448,6 +448,7 @@ listdir( struct xfs_da_args args = { .dp = dp, .geo = dp->i_mount->m_dir_geo, + .owner = dp->i_ino, }; int error; bool isblock; diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c index aa7aad36864..e3e9c265fab 100644 --- a/libxfs/xfs_attr_leaf.c +++ b/libxfs/xfs_attr_leaf.c @@ -972,6 +972,7 @@ xfs_attr_shortform_to_leaf( nargs.whichfork = XFS_ATTR_FORK; nargs.trans = args->trans; nargs.op_flags = XFS_DA_OP_OKNOENT; + nargs.owner = args->owner; sfe = &sf->list[0]; for (i = 0; i < sf->hdr.count; i++) { @@ -1175,6 +1176,7 @@ xfs_attr3_leaf_to_shortform( nargs.whichfork = XFS_ATTR_FORK; nargs.trans = args->trans; nargs.op_flags = XFS_DA_OP_OKNOENT; + nargs.owner = args->owner; for (i = 0; i < ichdr.count; entry++, i++) { if (entry->flags & XFS_ATTR_INCOMPLETE) diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 54db35bc398..296e7d85f63 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -952,6 +952,7 @@ xfs_bmap_add_attrfork_local( dargs.total = dargs.geo->fsbcount; dargs.whichfork = XFS_DATA_FORK; dargs.trans = tp; + dargs.owner = ip->i_ino; return xfs_dir2_sf_to_block(&dargs); } diff --git a/libxfs/xfs_da_btree.h b/libxfs/xfs_da_btree.h index 706baf36e17..7fb13f26eda 100644 --- a/libxfs/xfs_da_btree.h +++ b/libxfs/xfs_da_btree.h @@ -79,6 +79,7 @@ typedef struct xfs_da_args { int rmtvaluelen2; /* remote attr value length in bytes */ uint32_t op_flags; /* operation flags */ enum xfs_dacmp cmpresult; /* name compare result for lookups */ + xfs_ino_t owner; /* inode that owns the dir/attr data */ } xfs_da_args_t; /* diff --git a/libxfs/xfs_dir2.c b/libxfs/xfs_dir2.c index e503bf8f92f..79b6ec893fd 100644 --- a/libxfs/xfs_dir2.c +++ b/libxfs/xfs_dir2.c @@ -249,6 +249,7 @@ xfs_dir_init( args->geo = dp->i_mount->m_dir_geo; args->dp = dp; args->trans = tp; + args->owner = dp->i_ino; error = xfs_dir2_sf_create(args, pdp->i_ino); kmem_free(args); return error; @@ -294,6 +295,7 @@ xfs_dir_createname( args->whichfork = XFS_DATA_FORK; args->trans = tp; args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; + args->owner = dp->i_ino; if (!inum) args->op_flags |= XFS_DA_OP_JUSTCHECK; @@ -388,6 +390,7 @@ xfs_dir_lookup( args->whichfork = XFS_DATA_FORK; args->trans = tp; args->op_flags = XFS_DA_OP_OKNOENT; + args->owner = dp->i_ino; if (ci_name) args->op_flags |= XFS_DA_OP_CILOOKUP; @@ -461,6 +464,7 @@ xfs_dir_removename( args->total = total; args->whichfork = XFS_DATA_FORK; args->trans = tp; + args->owner = dp->i_ino; if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) { rval = xfs_dir2_sf_removename(args); @@ -522,6 +526,7 @@ xfs_dir_replace( args->total = total; args->whichfork = XFS_DATA_FORK; args->trans = tp; + args->owner = dp->i_ino; if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) { rval = xfs_dir2_sf_replace(args); diff --git a/libxfs/xfs_swapext.c b/libxfs/xfs_swapext.c index 92d2f8fa133..5c96ad8a203 100644 --- a/libxfs/xfs_swapext.c +++ b/libxfs/xfs_swapext.c @@ -524,6 +524,7 @@ xfs_swapext_attr_to_sf( .geo = tp->t_mountp->m_attr_geo, .whichfork = XFS_ATTR_FORK, .trans = tp, + .owner = sxi->sxi_ip2->i_ino, }; struct xfs_buf *bp; int forkoff; @@ -554,6 +555,7 @@ xfs_swapext_dir_to_sf( .geo = tp->t_mountp->m_dir_geo, .whichfork = XFS_DATA_FORK, .trans = tp, + .owner = sxi->sxi_ip2->i_ino, }; struct xfs_dir2_sf_hdr sfh; struct xfs_buf *bp; diff --git a/repair/phase6.c b/repair/phase6.c index c681a69017d..ac037cf80ad 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -1393,6 +1393,7 @@ dir2_kill_block( args.trans = tp; args.whichfork = XFS_DATA_FORK; args.geo = mp->m_dir_geo; + args.owner = ip->i_ino; if (da_bno >= mp->m_dir_geo->leafblk && da_bno < mp->m_dir_geo->freeblk) error = -libxfs_da_shrink_inode(&args, da_bno, bp); else @@ -1496,6 +1497,7 @@ longform_dir2_entry_check_data( struct xfs_da_args da = { .dp = ip, .geo = mp->m_dir_geo, + .owner = ip->i_ino, }; @@ -2284,6 +2286,7 @@ longform_dir2_entry_check( /* is this a block, leaf, or node directory? */ args.dp = ip; args.geo = mp->m_dir_geo; + args.owner = ip->i_ino; libxfs_dir2_isblock(&args, &isblock); libxfs_dir2_isleaf(&args, &isleaf); From patchwork Sun Dec 31 22:32:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507899 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0D7C6C127 for ; Sun, 31 Dec 2023 22:32:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="iPKTeZOR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D2BF1C433C8; Sun, 31 Dec 2023 22:32:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704061967; bh=Ic2LvQPLEwE3jDd135ox5YPj9uv8xMJ2HYxajejTeQg=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=iPKTeZORNXh4IjJt6LTOEfKEwESmHs7t1e/y37Z6zK+gBdYQqWS2Ur0M8YNS8tQFZ 4f1JlFx+tVBlbMHnFFp4GH4l4DAjBZPQNGl1H9dkdr9qxkxBxL5g5jI1sTg684GybN aa8AQj3uTxYso3bKNS0mFvhIBv/hYTKmy/NfgyWtosdK/Tn8BVEofOpmNRs/Amasyw aKAC56oIasn/JlQdShi8gMMp0/P5hG7Kd0ZTZP+rxm5jztHjzNGFjBCeUvv94TRtwt epTKDS46jQB2pI6SYjPoS93/vxydKPbkoagjaoQAyGTS8Z1Seo0Y7oWotqJHQ2o/Qc ifKtfVEZausJw== Date: Sun, 31 Dec 2023 14:32:47 -0800 Subject: [PATCH 2/9] xfs: use the xfs_da_args owner field to set new dir/attr block owner From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404996895.1796662.16921501581836874041.stgit@frogsfrogsfrogs> In-Reply-To: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> References: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong When we're creating leaf, data, freespace, or dabtree blocks for directories and xattrs, use the explicit owner field (instead of the xfs_inode) to set the owner field. This will enable online repair to construct replacement data structures in a temporary file without having to change the owner fields prior to swapping the new and old structures. Signed-off-by: Darrick J. Wong --- libxfs/xfs_attr_leaf.c | 2 +- libxfs/xfs_attr_remote.c | 4 ++-- libxfs/xfs_da_btree.c | 2 +- libxfs/xfs_dir2_block.c | 19 ++++++++++--------- libxfs/xfs_dir2_data.c | 2 +- libxfs/xfs_dir2_leaf.c | 11 +++++------ libxfs/xfs_dir2_node.c | 2 +- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c index e3e9c265fab..1e87c8243f7 100644 --- a/libxfs/xfs_attr_leaf.c +++ b/libxfs/xfs_attr_leaf.c @@ -1308,7 +1308,7 @@ xfs_attr3_leaf_create( ichdr.magic = XFS_ATTR3_LEAF_MAGIC; hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp)); - hdr3->owner = cpu_to_be64(dp->i_ino); + hdr3->owner = cpu_to_be64(args->owner); uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid); ichdr.freemap[0].base = sizeof(struct xfs_attr3_leaf_hdr); diff --git a/libxfs/xfs_attr_remote.c b/libxfs/xfs_attr_remote.c index f1c7cd31459..bc58dc6fa34 100644 --- a/libxfs/xfs_attr_remote.c +++ b/libxfs/xfs_attr_remote.c @@ -521,8 +521,8 @@ xfs_attr_rmtval_set_value( return error; bp->b_ops = &xfs_attr3_rmt_buf_ops; - xfs_attr_rmtval_copyin(mp, bp, args->dp->i_ino, &offset, - &valuelen, &src); + xfs_attr_rmtval_copyin(mp, bp, args->owner, &offset, &valuelen, + &src); error = xfs_bwrite(bp); /* GROT: NOTE: synchronous write */ xfs_buf_relse(bp); diff --git a/libxfs/xfs_da_btree.c b/libxfs/xfs_da_btree.c index 87996c5da4f..672dc8aa433 100644 --- a/libxfs/xfs_da_btree.c +++ b/libxfs/xfs_da_btree.c @@ -481,7 +481,7 @@ xfs_da3_node_create( memset(hdr3, 0, sizeof(struct xfs_da3_node_hdr)); ichdr.magic = XFS_DA3_NODE_MAGIC; hdr3->info.blkno = cpu_to_be64(xfs_buf_daddr(bp)); - hdr3->info.owner = cpu_to_be64(args->dp->i_ino); + hdr3->info.owner = cpu_to_be64(args->owner); uuid_copy(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid); } else { ichdr.magic = XFS_DA_NODE_MAGIC; diff --git a/libxfs/xfs_dir2_block.c b/libxfs/xfs_dir2_block.c index 19fededab5d..1f6a88091e7 100644 --- a/libxfs/xfs_dir2_block.c +++ b/libxfs/xfs_dir2_block.c @@ -160,12 +160,13 @@ xfs_dir3_block_read( static void xfs_dir3_block_init( - struct xfs_mount *mp, - struct xfs_trans *tp, - struct xfs_buf *bp, - struct xfs_inode *dp) + struct xfs_da_args *args, + struct xfs_buf *bp) { - struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; + struct xfs_trans *tp = args->trans; + struct xfs_inode *dp = args->dp; + struct xfs_mount *mp = dp->i_mount; + struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; bp->b_ops = &xfs_dir3_block_buf_ops; xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_BLOCK_BUF); @@ -174,7 +175,7 @@ xfs_dir3_block_init( memset(hdr3, 0, sizeof(*hdr3)); hdr3->magic = cpu_to_be32(XFS_DIR3_BLOCK_MAGIC); hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp)); - hdr3->owner = cpu_to_be64(dp->i_ino); + hdr3->owner = cpu_to_be64(args->owner); uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid); return; @@ -1006,7 +1007,7 @@ xfs_dir2_leaf_to_block( /* * Start converting it to block form. */ - xfs_dir3_block_init(mp, tp, dbp, dp); + xfs_dir3_block_init(args, dbp); needlog = 1; needscan = 0; @@ -1128,7 +1129,7 @@ xfs_dir2_sf_to_block( error = xfs_dir3_data_init(args, blkno, &bp); if (error) goto out_free; - xfs_dir3_block_init(mp, tp, bp, dp); + xfs_dir3_block_init(args, bp); hdr = bp->b_addr; /* @@ -1168,7 +1169,7 @@ xfs_dir2_sf_to_block( * Create entry for . */ dep = bp->b_addr + offset; - dep->inumber = cpu_to_be64(dp->i_ino); + dep->inumber = cpu_to_be64(args->owner); dep->namelen = 1; dep->name[0] = '.'; xfs_dir2_data_put_ftype(mp, dep, XFS_DIR3_FT_DIR); diff --git a/libxfs/xfs_dir2_data.c b/libxfs/xfs_dir2_data.c index aaf3f62af91..6f3ccfeb69f 100644 --- a/libxfs/xfs_dir2_data.c +++ b/libxfs/xfs_dir2_data.c @@ -722,7 +722,7 @@ xfs_dir3_data_init( memset(hdr3, 0, sizeof(*hdr3)); hdr3->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC); hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp)); - hdr3->owner = cpu_to_be64(dp->i_ino); + hdr3->owner = cpu_to_be64(args->owner); uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid); } else diff --git a/libxfs/xfs_dir2_leaf.c b/libxfs/xfs_dir2_leaf.c index 80cea8a275d..8fbda22508d 100644 --- a/libxfs/xfs_dir2_leaf.c +++ b/libxfs/xfs_dir2_leaf.c @@ -302,12 +302,12 @@ xfs_dir3_leafn_read( */ static void xfs_dir3_leaf_init( - struct xfs_mount *mp, - struct xfs_trans *tp, + struct xfs_da_args *args, struct xfs_buf *bp, - xfs_ino_t owner, uint16_t type) { + struct xfs_mount *mp = args->dp->i_mount; + struct xfs_trans *tp = args->trans; struct xfs_dir2_leaf *leaf = bp->b_addr; ASSERT(type == XFS_DIR2_LEAF1_MAGIC || type == XFS_DIR2_LEAFN_MAGIC); @@ -321,7 +321,7 @@ xfs_dir3_leaf_init( ? cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) : cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); leaf3->info.blkno = cpu_to_be64(xfs_buf_daddr(bp)); - leaf3->info.owner = cpu_to_be64(owner); + leaf3->info.owner = cpu_to_be64(args->owner); uuid_copy(&leaf3->info.uuid, &mp->m_sb.sb_meta_uuid); } else { memset(leaf, 0, sizeof(*leaf)); @@ -354,7 +354,6 @@ xfs_dir3_leaf_get_buf( { struct xfs_inode *dp = args->dp; struct xfs_trans *tp = args->trans; - struct xfs_mount *mp = dp->i_mount; struct xfs_buf *bp; int error; @@ -367,7 +366,7 @@ xfs_dir3_leaf_get_buf( if (error) return error; - xfs_dir3_leaf_init(mp, tp, bp, dp->i_ino, magic); + xfs_dir3_leaf_init(args, bp, magic); xfs_dir3_leaf_log_header(args, bp); if (magic == XFS_DIR2_LEAF1_MAGIC) xfs_dir3_leaf_log_tail(args, bp); diff --git a/libxfs/xfs_dir2_node.c b/libxfs/xfs_dir2_node.c index 44c8f3f2b07..b00f783877e 100644 --- a/libxfs/xfs_dir2_node.c +++ b/libxfs/xfs_dir2_node.c @@ -346,7 +346,7 @@ xfs_dir3_free_get_buf( hdr.magic = XFS_DIR3_FREE_MAGIC; hdr3->hdr.blkno = cpu_to_be64(xfs_buf_daddr(bp)); - hdr3->hdr.owner = cpu_to_be64(dp->i_ino); + hdr3->hdr.owner = cpu_to_be64(args->owner); uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_meta_uuid); } else hdr.magic = XFS_DIR2_FREE_MAGIC; From patchwork Sun Dec 31 22:33:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507900 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 148E8C147 for ; Sun, 31 Dec 2023 22:33:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SKe9VmAZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7D53DC433C8; Sun, 31 Dec 2023 22:33:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704061983; bh=nJ8+dOESbWAgfh1l6y7YtGXKdHn/kK0RgtPd+hZrHNg=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=SKe9VmAZL0hEXgXr/cQeSG2yGybokCds8JAKQR2mSmNLxJofPXMKMz8bPTYTX+deh AZ52LxR1Jrzr30UD+r6hR6ECK6zXjpdJc8YsYtQSPRKj9Vb/Q6azSWlux1jOUpmCm4 0/vei2KIjDhQ9RUmk2psF/XkqFByOMU/woJ++E73UozqXfJ3lSL26+qURso7hKGHwH +r7zAgPrliDbFtlxXVxkikVYYhG71HTaHlrAO//dGM7daCcQmtgEWGRn1niXQx7fYX WSJVe57hWTOqVrCdajedSUPdMdyp3u+XN1JSQlX5q6VsUkBiPOviQ95+ylIRDVC6A+ lWL0lPXyAx8Ng== Date: Sun, 31 Dec 2023 14:33:03 -0800 Subject: [PATCH 3/9] xfs: validate attr leaf buffer owners From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404996907.1796662.11234796135079769619.stgit@frogsfrogsfrogs> In-Reply-To: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> References: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Create a leaf block header checking function to validate the owner field of xattr leaf blocks. Signed-off-by: Darrick J. Wong --- libxfs/libxfs_api_defs.h | 3 +++ libxfs/xfs_attr.c | 10 ++++---- libxfs/xfs_attr_leaf.c | 55 ++++++++++++++++++++++++++++++++++++++-------- libxfs/xfs_attr_leaf.h | 4 +++ libxfs/xfs_da_btree.c | 42 +++++++++++++++++++++++++++++++++++ libxfs/xfs_da_btree.h | 1 + libxfs/xfs_swapext.c | 3 ++- 7 files changed, 102 insertions(+), 16 deletions(-) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index a5b3baaa476..eba9a8386d2 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -277,4 +277,7 @@ /* Please keep this list alphabetized. */ +/* XXX remove this */ +#define dump_stack() do { } while(0) + #endif /* __LIBXFS_API_DEFS_H__ */ diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c index cb6c8d081fd..985989b5ade 100644 --- a/libxfs/xfs_attr.c +++ b/libxfs/xfs_attr.c @@ -645,8 +645,8 @@ xfs_attr_leaf_remove_attr( int forkoff; int error; - error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, - &bp); + error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, + args->blkno, &bp); if (error) return error; @@ -677,7 +677,7 @@ xfs_attr_leaf_shrink( if (!xfs_attr_is_leaf(dp)) return 0; - error = xfs_attr3_leaf_read(args->trans, args->dp, 0, &bp); + error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, &bp); if (error) return error; @@ -1158,7 +1158,7 @@ xfs_attr_leaf_try_add( struct xfs_buf *bp; int error; - error = xfs_attr3_leaf_read(args->trans, args->dp, 0, &bp); + error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, &bp); if (error) return error; @@ -1206,7 +1206,7 @@ xfs_attr_leaf_hasname( { int error = 0; - error = xfs_attr3_leaf_read(args->trans, args->dp, 0, bp); + error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, bp); if (error) return error; diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c index 1e87c8243f7..3d798828833 100644 --- a/libxfs/xfs_attr_leaf.c +++ b/libxfs/xfs_attr_leaf.c @@ -385,6 +385,26 @@ xfs_attr3_leaf_verify( return NULL; } +xfs_failaddr_t +xfs_attr3_leaf_header_check( + struct xfs_buf *bp, + xfs_ino_t owner) +{ + struct xfs_mount *mp = bp->b_mount; + + if (xfs_has_crc(mp)) { + struct xfs_attr3_leafblock *hdr3 = bp->b_addr; + + ASSERT(hdr3->hdr.info.hdr.magic == + cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)); + + if (be64_to_cpu(hdr3->hdr.info.owner) != owner) + return __this_address; + } + + return NULL; +} + static void xfs_attr3_leaf_write_verify( struct xfs_buf *bp) @@ -445,16 +465,30 @@ int xfs_attr3_leaf_read( struct xfs_trans *tp, struct xfs_inode *dp, + xfs_ino_t owner, xfs_dablk_t bno, struct xfs_buf **bpp) { + xfs_failaddr_t fa; int err; err = xfs_da_read_buf(tp, dp, bno, 0, bpp, XFS_ATTR_FORK, &xfs_attr3_leaf_buf_ops); - if (!err && tp && *bpp) + if (err || !(*bpp)) + return err; + + fa = xfs_attr3_leaf_header_check(*bpp, owner); + if (fa) { + __xfs_buf_mark_corrupt(*bpp, fa); + xfs_trans_brelse(tp, *bpp); + *bpp = NULL; + xfs_dirattr_mark_sick(dp, XFS_ATTR_FORK); + return -EFSCORRUPTED; + } + + if (tp) xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_ATTR_LEAF_BUF); - return err; + return 0; } /*======================================================================== @@ -1229,7 +1263,7 @@ xfs_attr3_leaf_to_node( error = xfs_da_grow_inode(args, &blkno); if (error) goto out; - error = xfs_attr3_leaf_read(args->trans, dp, 0, &bp1); + error = xfs_attr3_leaf_read(args->trans, dp, args->owner, 0, &bp1); if (error) goto out; @@ -2064,7 +2098,7 @@ xfs_attr3_leaf_toosmall( if (blkno == 0) continue; error = xfs_attr3_leaf_read(state->args->trans, state->args->dp, - blkno, &bp); + state->args->owner, blkno, &bp); if (error) return error; @@ -2785,7 +2819,8 @@ xfs_attr3_leaf_clearflag( /* * Set up the operation. */ - error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, &bp); + error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, + args->blkno, &bp); if (error) return error; @@ -2849,7 +2884,8 @@ xfs_attr3_leaf_setflag( /* * Set up the operation. */ - error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, &bp); + error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, + args->blkno, &bp); if (error) return error; @@ -2908,7 +2944,8 @@ xfs_attr3_leaf_flipflags( /* * Read the block containing the "old" attr */ - error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, &bp1); + error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, + args->blkno, &bp1); if (error) return error; @@ -2916,8 +2953,8 @@ xfs_attr3_leaf_flipflags( * Read the block containing the "new" attr, if it is different */ if (args->blkno2 != args->blkno) { - error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno2, - &bp2); + error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, + args->blkno2, &bp2); if (error) return error; } else { diff --git a/libxfs/xfs_attr_leaf.h b/libxfs/xfs_attr_leaf.h index ce6743463c8..70edddedd1a 100644 --- a/libxfs/xfs_attr_leaf.h +++ b/libxfs/xfs_attr_leaf.h @@ -101,12 +101,14 @@ int xfs_attr_leaf_order(struct xfs_buf *leaf1_bp, struct xfs_buf *leaf2_bp); int xfs_attr_leaf_newentsize(struct xfs_da_args *args, int *local); int xfs_attr3_leaf_read(struct xfs_trans *tp, struct xfs_inode *dp, - xfs_dablk_t bno, struct xfs_buf **bpp); + xfs_ino_t owner, xfs_dablk_t bno, struct xfs_buf **bpp); void xfs_attr3_leaf_hdr_from_disk(struct xfs_da_geometry *geo, struct xfs_attr3_icleaf_hdr *to, struct xfs_attr_leafblock *from); void xfs_attr3_leaf_hdr_to_disk(struct xfs_da_geometry *geo, struct xfs_attr_leafblock *to, struct xfs_attr3_icleaf_hdr *from); +xfs_failaddr_t xfs_attr3_leaf_header_check(struct xfs_buf *bp, + xfs_ino_t owner); #endif /* __XFS_ATTR_LEAF_H__ */ diff --git a/libxfs/xfs_da_btree.c b/libxfs/xfs_da_btree.c index 672dc8aa433..a33c4acbd1d 100644 --- a/libxfs/xfs_da_btree.c +++ b/libxfs/xfs_da_btree.c @@ -247,6 +247,25 @@ xfs_da3_node_verify( return NULL; } +xfs_failaddr_t +xfs_da3_header_check( + struct xfs_buf *bp, + xfs_ino_t owner) +{ + struct xfs_mount *mp = bp->b_mount; + struct xfs_da_blkinfo *hdr = bp->b_addr; + + if (!xfs_has_crc(mp)) + return NULL; + + switch (hdr->magic) { + case cpu_to_be16(XFS_ATTR3_LEAF_MAGIC): + return xfs_attr3_leaf_header_check(bp, owner); + } + + return NULL; +} + static void xfs_da3_node_write_verify( struct xfs_buf *bp) @@ -1586,6 +1605,7 @@ xfs_da3_node_lookup_int( struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr nodehdr; struct xfs_da_args *args; + xfs_failaddr_t fa; xfs_dablk_t blkno; xfs_dahash_t hashval; xfs_dahash_t btreehashval; @@ -1624,6 +1644,12 @@ xfs_da3_node_lookup_int( if (magic == XFS_ATTR_LEAF_MAGIC || magic == XFS_ATTR3_LEAF_MAGIC) { + fa = xfs_attr3_leaf_header_check(blk->bp, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(blk->bp, fa); + xfs_da_mark_sick(args); + return -EFSCORRUPTED; + } blk->magic = XFS_ATTR_LEAF_MAGIC; blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL); break; @@ -1991,6 +2017,7 @@ xfs_da3_path_shift( struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr nodehdr; struct xfs_buf *bp; + xfs_failaddr_t fa; xfs_dablk_t blkno = 0; int level; int error; @@ -2082,6 +2109,12 @@ xfs_da3_path_shift( break; case XFS_ATTR_LEAF_MAGIC: case XFS_ATTR3_LEAF_MAGIC: + fa = xfs_attr3_leaf_header_check(blk->bp, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(blk->bp, fa); + xfs_da_mark_sick(args); + return -EFSCORRUPTED; + } blk->magic = XFS_ATTR_LEAF_MAGIC; ASSERT(level == path->active-1); blk->index = 0; @@ -2284,6 +2317,7 @@ xfs_da3_swap_lastblock( struct xfs_buf *last_buf; struct xfs_buf *sib_buf; struct xfs_buf *par_buf; + xfs_failaddr_t fa; xfs_dahash_t dead_hash; xfs_fileoff_t lastoff; xfs_dablk_t dead_blkno; @@ -2320,6 +2354,14 @@ xfs_da3_swap_lastblock( error = xfs_da3_node_read(tp, dp, last_blkno, &last_buf, w); if (error) return error; + fa = xfs_da3_header_check(last_buf, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(last_buf, fa); + xfs_trans_brelse(tp, last_buf); + xfs_da_mark_sick(args); + return -EFSCORRUPTED; + } + /* * Copy the last block into the dead buffer and log it. */ diff --git a/libxfs/xfs_da_btree.h b/libxfs/xfs_da_btree.h index 7fb13f26eda..99618e0c8a7 100644 --- a/libxfs/xfs_da_btree.h +++ b/libxfs/xfs_da_btree.h @@ -236,6 +236,7 @@ void xfs_da3_node_hdr_from_disk(struct xfs_mount *mp, struct xfs_da3_icnode_hdr *to, struct xfs_da_intnode *from); void xfs_da3_node_hdr_to_disk(struct xfs_mount *mp, struct xfs_da_intnode *to, struct xfs_da3_icnode_hdr *from); +xfs_failaddr_t xfs_da3_header_check(struct xfs_buf *bp, xfs_ino_t owner); extern struct kmem_cache *xfs_da_state_cache; diff --git a/libxfs/xfs_swapext.c b/libxfs/xfs_swapext.c index 5c96ad8a203..eae4f6b7310 100644 --- a/libxfs/xfs_swapext.c +++ b/libxfs/xfs_swapext.c @@ -533,7 +533,8 @@ xfs_swapext_attr_to_sf( if (!xfs_attr_is_leaf(sxi->sxi_ip2)) return 0; - error = xfs_attr3_leaf_read(tp, sxi->sxi_ip2, 0, &bp); + error = xfs_attr3_leaf_read(tp, sxi->sxi_ip2, sxi->sxi_ip2->i_ino, 0, + &bp); if (error) return error; From patchwork Sun Dec 31 22:33:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507901 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 59AB2C13B for ; Sun, 31 Dec 2023 22:33:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VIuRVpSY" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 27426C433C8; Sun, 31 Dec 2023 22:33:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704061999; bh=rhojsQ00PYyMx2awWG/I6XvSzJMnRGgWDzBcRff6T64=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=VIuRVpSYHdR6V0k9PGSaP40JuNB65wIQ2YWXaMu5oKe6m84TDA0D5f8u49ett0/Pn GGx315woH2gmaqt5RTMbbULHi/a69zfHiqV/IBdtv4WU8OA6pfvSx3miUu0rV2DPe7 VtLeJrCGX3sDmPW8wsTk80ahBj/pqMcsUXZHJkCjrOF32lSI1Ckf6HXnZY/jScxqN0 blFB3aercptfgCK73d6Y6jOfDGODGUlsWHiKeolkVaXXC0nBwK7Z4cWaPboaLE4+UF 4wevSGLwq5uALLyY55GeGi0ISpRJ9HfMgViRHSNEpYLeszjNS7Q4rccNFEdo4gA+dN hs02R0+lfAK9Q== Date: Sun, 31 Dec 2023 14:33:18 -0800 Subject: [PATCH 4/9] xfs: validate attr remote value buffer owners From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404996921.1796662.5388176482911414319.stgit@frogsfrogsfrogs> In-Reply-To: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> References: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Check the owner field of xattr remote value blocks. Signed-off-by: Darrick J. Wong --- libxfs/xfs_attr_remote.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libxfs/xfs_attr_remote.c b/libxfs/xfs_attr_remote.c index bc58dc6fa34..f4d71430df4 100644 --- a/libxfs/xfs_attr_remote.c +++ b/libxfs/xfs_attr_remote.c @@ -279,12 +279,12 @@ xfs_attr_rmtval_copyout( struct xfs_mount *mp, struct xfs_buf *bp, struct xfs_inode *dp, + xfs_ino_t owner, int *offset, int *valuelen, uint8_t **dst) { char *src = bp->b_addr; - xfs_ino_t ino = dp->i_ino; xfs_daddr_t bno = xfs_buf_daddr(bp); int len = BBTOB(bp->b_length); int blksize = mp->m_attr_geo->blksize; @@ -298,11 +298,11 @@ xfs_attr_rmtval_copyout( byte_cnt = min(*valuelen, byte_cnt); if (xfs_has_crc(mp)) { - if (xfs_attr3_rmt_hdr_ok(src, ino, *offset, + if (xfs_attr3_rmt_hdr_ok(src, owner, *offset, byte_cnt, bno)) { xfs_alert(mp, "remote attribute header mismatch bno/off/len/owner (0x%llx/0x%x/Ox%x/0x%llx)", - bno, *offset, byte_cnt, ino); + bno, *offset, byte_cnt, owner); xfs_dirattr_mark_sick(dp, XFS_ATTR_FORK); return -EFSCORRUPTED; } @@ -426,8 +426,7 @@ xfs_attr_rmtval_get( return error; error = xfs_attr_rmtval_copyout(mp, bp, args->dp, - &offset, &valuelen, - &dst); + args->owner, &offset, &valuelen, &dst); xfs_buf_relse(bp); if (error) return error; From patchwork Sun Dec 31 22:33:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507902 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 60BD7C127 for ; Sun, 31 Dec 2023 22:33:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="M2dDauJz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D4316C433C8; Sun, 31 Dec 2023 22:33:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704062014; bh=M66T3WE97h+2uo9602Yu00K+GIFcZZ40vOlUhjJnrG8=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=M2dDauJz+SXdb1MlbZBFMj3EnVkUgsQXvDt76KmV/AdHD7rVvDcG0btXZ2E9R6DZW 84IewB6Lp+xU9BLfVMa2QvfxmaWyOW86q6ijsl/4ifC1lImYKrjBkEK7eha697JOR0 ge1XBtcV30vej+mxoMZr3iwn2tRpzitfsgrw0XZcm5mZ+2GN0iizb9+VpDH6PdEMEB pcv3zvQ/L9te7fn5kGqYwz2TAS0PBLYt7kWgzYpoJOL7l+6ctdBjEsQb5B4sWDS+oD nVDr+NPqXWuNr6gGkYcq+m3JijOoHC1GK76yrtJdASBsFnerBGq/pVMkfnVt39qwTs KUUp6xHDWeBOA== Date: Sun, 31 Dec 2023 14:33:34 -0800 Subject: [PATCH 5/9] xfs: validate dabtree node buffer owners From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404996935.1796662.7932669643131262064.stgit@frogsfrogsfrogs> In-Reply-To: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> References: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Check the owner field of dabtree node blocks. Signed-off-by: Darrick J. Wong --- libxfs/xfs_da_btree.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_da_btree.h | 1 2 files changed, 109 insertions(+) diff --git a/libxfs/xfs_da_btree.c b/libxfs/xfs_da_btree.c index a33c4acbd1d..92eae433a5a 100644 --- a/libxfs/xfs_da_btree.c +++ b/libxfs/xfs_da_btree.c @@ -247,6 +247,25 @@ xfs_da3_node_verify( return NULL; } +xfs_failaddr_t +xfs_da3_node_header_check( + struct xfs_buf *bp, + xfs_ino_t owner) +{ + struct xfs_mount *mp = bp->b_mount; + + if (xfs_has_crc(mp)) { + struct xfs_da3_blkinfo *hdr3 = bp->b_addr; + + ASSERT(hdr3->hdr.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)); + + if (be64_to_cpu(hdr3->owner) != owner) + return __this_address; + } + + return NULL; +} + xfs_failaddr_t xfs_da3_header_check( struct xfs_buf *bp, @@ -261,6 +280,8 @@ xfs_da3_header_check( switch (hdr->magic) { case cpu_to_be16(XFS_ATTR3_LEAF_MAGIC): return xfs_attr3_leaf_header_check(bp, owner); + case cpu_to_be16(XFS_DA3_NODE_MAGIC): + return xfs_da3_node_header_check(bp, owner); } return NULL; @@ -1213,6 +1234,7 @@ xfs_da3_root_join( struct xfs_da3_icnode_hdr oldroothdr; int error; struct xfs_inode *dp = state->args->dp; + xfs_failaddr_t fa; trace_xfs_da_root_join(state->args); @@ -1239,6 +1261,13 @@ xfs_da3_root_join( error = xfs_da3_node_read(args->trans, dp, child, &bp, args->whichfork); if (error) return error; + fa = xfs_da3_header_check(bp, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(bp, fa); + xfs_trans_brelse(args->trans, bp); + xfs_da_mark_sick(args); + return -EFSCORRUPTED; + } xfs_da_blkinfo_onlychild_validate(bp->b_addr, oldroothdr.level); /* @@ -1273,6 +1302,7 @@ xfs_da3_node_toosmall( struct xfs_da_blkinfo *info; xfs_dablk_t blkno; struct xfs_buf *bp; + xfs_failaddr_t fa; struct xfs_da3_icnode_hdr nodehdr; int count; int forward; @@ -1347,6 +1377,13 @@ xfs_da3_node_toosmall( state->args->whichfork); if (error) return error; + fa = xfs_da3_node_header_check(bp, state->args->owner); + if (fa) { + __xfs_buf_mark_corrupt(bp, fa); + xfs_trans_brelse(state->args->trans, bp); + xfs_da_mark_sick(state->args); + return -EFSCORRUPTED; + } node = bp->b_addr; xfs_da3_node_hdr_from_disk(dp->i_mount, &thdr, node); @@ -1669,6 +1706,13 @@ xfs_da3_node_lookup_int( return -EFSCORRUPTED; } + fa = xfs_da3_node_header_check(blk->bp, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(blk->bp, fa); + xfs_da_mark_sick(args); + return -EFSCORRUPTED; + } + blk->magic = XFS_DA_NODE_MAGIC; /* @@ -1841,6 +1885,7 @@ xfs_da3_blk_link( struct xfs_da_blkinfo *tmp_info; struct xfs_da_args *args; struct xfs_buf *bp; + xfs_failaddr_t fa; int before = 0; int error; struct xfs_inode *dp = state->args->dp; @@ -1884,6 +1929,13 @@ xfs_da3_blk_link( &bp, args->whichfork); if (error) return error; + fa = xfs_da3_header_check(bp, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(bp, fa); + xfs_trans_brelse(args->trans, bp); + xfs_da_mark_sick(args); + return -EFSCORRUPTED; + } ASSERT(bp != NULL); tmp_info = bp->b_addr; ASSERT(tmp_info->magic == old_info->magic); @@ -1905,6 +1957,13 @@ xfs_da3_blk_link( &bp, args->whichfork); if (error) return error; + fa = xfs_da3_header_check(bp, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(bp, fa); + xfs_trans_brelse(args->trans, bp); + xfs_da_mark_sick(args); + return -EFSCORRUPTED; + } ASSERT(bp != NULL); tmp_info = bp->b_addr; ASSERT(tmp_info->magic == old_info->magic); @@ -1934,6 +1993,7 @@ xfs_da3_blk_unlink( struct xfs_da_blkinfo *tmp_info; struct xfs_da_args *args; struct xfs_buf *bp; + xfs_failaddr_t fa; int error; /* @@ -1964,6 +2024,13 @@ xfs_da3_blk_unlink( &bp, args->whichfork); if (error) return error; + fa = xfs_da3_header_check(bp, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(bp, fa); + xfs_trans_brelse(args->trans, bp); + xfs_da_mark_sick(args); + return -EFSCORRUPTED; + } ASSERT(bp != NULL); tmp_info = bp->b_addr; ASSERT(tmp_info->magic == save_info->magic); @@ -1981,6 +2048,13 @@ xfs_da3_blk_unlink( &bp, args->whichfork); if (error) return error; + fa = xfs_da3_header_check(bp, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(bp, fa); + xfs_trans_brelse(args->trans, bp); + xfs_da_mark_sick(args); + return -EFSCORRUPTED; + } ASSERT(bp != NULL); tmp_info = bp->b_addr; ASSERT(tmp_info->magic == save_info->magic); @@ -2096,6 +2170,12 @@ xfs_da3_path_shift( switch (be16_to_cpu(info->magic)) { case XFS_DA_NODE_MAGIC: case XFS_DA3_NODE_MAGIC: + fa = xfs_da3_node_header_check(blk->bp, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(blk->bp, fa); + xfs_da_mark_sick(args); + return -EFSCORRUPTED; + } blk->magic = XFS_DA_NODE_MAGIC; xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, bp->b_addr); @@ -2400,6 +2480,13 @@ xfs_da3_swap_lastblock( error = xfs_da3_node_read(tp, dp, sib_blkno, &sib_buf, w); if (error) goto done; + fa = xfs_da3_header_check(sib_buf, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(sib_buf, fa); + xfs_da_mark_sick(args); + error = -EFSCORRUPTED; + goto done; + } sib_info = sib_buf->b_addr; if (XFS_IS_CORRUPT(mp, be32_to_cpu(sib_info->forw) != last_blkno || @@ -2421,6 +2508,13 @@ xfs_da3_swap_lastblock( error = xfs_da3_node_read(tp, dp, sib_blkno, &sib_buf, w); if (error) goto done; + fa = xfs_da3_header_check(sib_buf, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(sib_buf, fa); + xfs_da_mark_sick(args); + error = -EFSCORRUPTED; + goto done; + } sib_info = sib_buf->b_addr; if (XFS_IS_CORRUPT(mp, be32_to_cpu(sib_info->back) != last_blkno || @@ -2444,6 +2538,13 @@ xfs_da3_swap_lastblock( error = xfs_da3_node_read(tp, dp, par_blkno, &par_buf, w); if (error) goto done; + fa = xfs_da3_node_header_check(par_buf, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(par_buf, fa); + xfs_da_mark_sick(args); + error = -EFSCORRUPTED; + goto done; + } par_node = par_buf->b_addr; xfs_da3_node_hdr_from_disk(dp->i_mount, &par_hdr, par_node); if (XFS_IS_CORRUPT(mp, @@ -2493,6 +2594,13 @@ xfs_da3_swap_lastblock( error = xfs_da3_node_read(tp, dp, par_blkno, &par_buf, w); if (error) goto done; + fa = xfs_da3_node_header_check(par_buf, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(par_buf, fa); + xfs_da_mark_sick(args); + error = -EFSCORRUPTED; + goto done; + } par_node = par_buf->b_addr; xfs_da3_node_hdr_from_disk(dp->i_mount, &par_hdr, par_node); if (XFS_IS_CORRUPT(mp, par_hdr.level != level)) { diff --git a/libxfs/xfs_da_btree.h b/libxfs/xfs_da_btree.h index 99618e0c8a7..7a004786ee0 100644 --- a/libxfs/xfs_da_btree.h +++ b/libxfs/xfs_da_btree.h @@ -237,6 +237,7 @@ void xfs_da3_node_hdr_from_disk(struct xfs_mount *mp, void xfs_da3_node_hdr_to_disk(struct xfs_mount *mp, struct xfs_da_intnode *to, struct xfs_da3_icnode_hdr *from); xfs_failaddr_t xfs_da3_header_check(struct xfs_buf *bp, xfs_ino_t owner); +xfs_failaddr_t xfs_da3_node_header_check(struct xfs_buf *bp, xfs_ino_t owner); extern struct kmem_cache *xfs_da_state_cache; From patchwork Sun Dec 31 22:33:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507903 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E0C5FC129 for ; Sun, 31 Dec 2023 22:33:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KeLaBbJN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7DFABC433C7; Sun, 31 Dec 2023 22:33:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704062030; bh=HjvFfwu+Ob3NbZYcXgpoBJuB4QKW8NUrYD/8zHpuOQ8=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=KeLaBbJNXK9dFfrmbI2UtCFkTaxlWDXqShG6Jk7sonLY9/iiaJDoo5WvB151FIj/r mdamveQfTlrBk3ycTFFx5/3xcWwRndW4gGJFyr6nIg/bRMGWGHdKYETbaHyDoGdKrv WALdLvp5wLpe4WYyBCcSLwprO/utJoUNd6kio4YWG7Xpx+z/0bLTleDuLMv3CSH56V +lV6zFjNXb/Wz7Rw9DIuICFHHdCqKpZva0JcYWCUP8T+mofdhptPxIgzMoVDL9QMEv WwLAapiuCAlrou3eJacPB9o41ZmyTfeCHJHQf+koOKAHK8A8vYAxa1BXXWIDqyhktn mBUkJyySdFfxw== Date: Sun, 31 Dec 2023 14:33:50 -0800 Subject: [PATCH 6/9] xfs: validate directory leaf buffer owners From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404996948.1796662.18138650154226191110.stgit@frogsfrogsfrogs> In-Reply-To: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> References: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Check the owner field of directory leaf blocks. Signed-off-by: Darrick J. Wong --- libxfs/xfs_da_btree.c | 16 ++++++++++++ libxfs/xfs_dir2.h | 2 ++ libxfs/xfs_dir2_leaf.c | 64 ++++++++++++++++++++++++++++++++++++++++++++---- libxfs/xfs_dir2_node.c | 3 ++ libxfs/xfs_dir2_priv.h | 4 ++- 5 files changed, 80 insertions(+), 9 deletions(-) diff --git a/libxfs/xfs_da_btree.c b/libxfs/xfs_da_btree.c index 92eae433a5a..207fec9e287 100644 --- a/libxfs/xfs_da_btree.c +++ b/libxfs/xfs_da_btree.c @@ -282,8 +282,12 @@ xfs_da3_header_check( return xfs_attr3_leaf_header_check(bp, owner); case cpu_to_be16(XFS_DA3_NODE_MAGIC): return xfs_da3_node_header_check(bp, owner); + case cpu_to_be16(XFS_DIR3_LEAF1_MAGIC): + case cpu_to_be16(XFS_DIR3_LEAFN_MAGIC): + return xfs_dir3_leaf_header_check(bp, owner); } + ASSERT(0); return NULL; } @@ -1694,6 +1698,12 @@ xfs_da3_node_lookup_int( if (magic == XFS_DIR2_LEAFN_MAGIC || magic == XFS_DIR3_LEAFN_MAGIC) { + fa = xfs_dir3_leaf_header_check(blk->bp, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(blk->bp, fa); + xfs_da_mark_sick(args); + return -EFSCORRUPTED; + } blk->magic = XFS_DIR2_LEAFN_MAGIC; blk->hashval = xfs_dir2_leaf_lasthash(args->dp, blk->bp, NULL); @@ -2202,6 +2212,12 @@ xfs_da3_path_shift( break; case XFS_DIR2_LEAFN_MAGIC: case XFS_DIR3_LEAFN_MAGIC: + fa = xfs_dir3_leaf_header_check(blk->bp, args->owner); + if (fa) { + __xfs_buf_mark_corrupt(blk->bp, fa); + xfs_da_mark_sick(args); + return -EFSCORRUPTED; + } blk->magic = XFS_DIR2_LEAFN_MAGIC; ASSERT(level == path->active-1); blk->index = 0; diff --git a/libxfs/xfs_dir2.h b/libxfs/xfs_dir2.h index ac3c264402d..0b01dd6ccf1 100644 --- a/libxfs/xfs_dir2.h +++ b/libxfs/xfs_dir2.h @@ -98,6 +98,8 @@ extern struct xfs_dir2_data_free *xfs_dir2_data_freefind( extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); +xfs_failaddr_t xfs_dir3_leaf_header_check(struct xfs_buf *bp, xfs_ino_t owner); + extern const struct xfs_buf_ops xfs_dir3_block_buf_ops; extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops; extern const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops; diff --git a/libxfs/xfs_dir2_leaf.c b/libxfs/xfs_dir2_leaf.c index 8fbda22508d..14449a23502 100644 --- a/libxfs/xfs_dir2_leaf.c +++ b/libxfs/xfs_dir2_leaf.c @@ -206,6 +206,28 @@ xfs_dir3_leaf_verify( return xfs_dir3_leaf_check_int(mp, &leafhdr, bp->b_addr, true); } +xfs_failaddr_t +xfs_dir3_leaf_header_check( + struct xfs_buf *bp, + xfs_ino_t owner) +{ + struct xfs_mount *mp = bp->b_mount; + + if (xfs_has_crc(mp)) { + struct xfs_dir3_leaf *hdr3 = bp->b_addr; + + ASSERT(hdr3->hdr.info.hdr.magic == + cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || + hdr3->hdr.info.hdr.magic == + cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); + + if (be64_to_cpu(hdr3->hdr.info.owner) != owner) + return __this_address; + } + + return NULL; +} + static void xfs_dir3_leaf_read_verify( struct xfs_buf *bp) @@ -269,32 +291,60 @@ int xfs_dir3_leaf_read( struct xfs_trans *tp, struct xfs_inode *dp, + xfs_ino_t owner, xfs_dablk_t fbno, struct xfs_buf **bpp) { + xfs_failaddr_t fa; int err; err = xfs_da_read_buf(tp, dp, fbno, 0, bpp, XFS_DATA_FORK, &xfs_dir3_leaf1_buf_ops); - if (!err && tp && *bpp) + if (err || !(*bpp)) + return err; + + fa = xfs_dir3_leaf_header_check(*bpp, owner); + if (fa) { + __xfs_buf_mark_corrupt(*bpp, fa); + xfs_trans_brelse(tp, *bpp); + *bpp = NULL; + xfs_dirattr_mark_sick(dp, XFS_DATA_FORK); + return -EFSCORRUPTED; + } + + if (tp) xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_LEAF1_BUF); - return err; + return 0; } int xfs_dir3_leafn_read( struct xfs_trans *tp, struct xfs_inode *dp, + xfs_ino_t owner, xfs_dablk_t fbno, struct xfs_buf **bpp) { + xfs_failaddr_t fa; int err; err = xfs_da_read_buf(tp, dp, fbno, 0, bpp, XFS_DATA_FORK, &xfs_dir3_leafn_buf_ops); - if (!err && tp && *bpp) + if (err || !(*bpp)) + return err; + + fa = xfs_dir3_leaf_header_check(*bpp, owner); + if (fa) { + __xfs_buf_mark_corrupt(*bpp, fa); + xfs_trans_brelse(tp, *bpp); + *bpp = NULL; + xfs_dirattr_mark_sick(dp, XFS_DATA_FORK); + return -EFSCORRUPTED; + } + + if (tp) xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_LEAFN_BUF); - return err; + return 0; } /* @@ -644,7 +694,8 @@ xfs_dir2_leaf_addname( trace_xfs_dir2_leaf_addname(args); - error = xfs_dir3_leaf_read(tp, dp, args->geo->leafblk, &lbp); + error = xfs_dir3_leaf_read(tp, dp, args->owner, args->geo->leafblk, + &lbp); if (error) return error; @@ -1235,7 +1286,8 @@ xfs_dir2_leaf_lookup_int( tp = args->trans; mp = dp->i_mount; - error = xfs_dir3_leaf_read(tp, dp, args->geo->leafblk, &lbp); + error = xfs_dir3_leaf_read(tp, dp, args->owner, args->geo->leafblk, + &lbp); if (error) return error; diff --git a/libxfs/xfs_dir2_node.c b/libxfs/xfs_dir2_node.c index b00f783877e..c0160d725e5 100644 --- a/libxfs/xfs_dir2_node.c +++ b/libxfs/xfs_dir2_node.c @@ -1559,7 +1559,8 @@ xfs_dir2_leafn_toosmall( /* * Read the sibling leaf block. */ - error = xfs_dir3_leafn_read(state->args->trans, dp, blkno, &bp); + error = xfs_dir3_leafn_read(state->args->trans, dp, + state->args->owner, blkno, &bp); if (error) return error; diff --git a/libxfs/xfs_dir2_priv.h b/libxfs/xfs_dir2_priv.h index 1db2e60ba82..2f0e3ad47b3 100644 --- a/libxfs/xfs_dir2_priv.h +++ b/libxfs/xfs_dir2_priv.h @@ -95,9 +95,9 @@ void xfs_dir2_leaf_hdr_from_disk(struct xfs_mount *mp, void xfs_dir2_leaf_hdr_to_disk(struct xfs_mount *mp, struct xfs_dir2_leaf *to, struct xfs_dir3_icleaf_hdr *from); int xfs_dir3_leaf_read(struct xfs_trans *tp, struct xfs_inode *dp, - xfs_dablk_t fbno, struct xfs_buf **bpp); + xfs_ino_t owner, xfs_dablk_t fbno, struct xfs_buf **bpp); int xfs_dir3_leafn_read(struct xfs_trans *tp, struct xfs_inode *dp, - xfs_dablk_t fbno, struct xfs_buf **bpp); + xfs_ino_t owner, xfs_dablk_t fbno, struct xfs_buf **bpp); extern int xfs_dir2_block_to_leaf(struct xfs_da_args *args, struct xfs_buf *dbp); extern int xfs_dir2_leaf_addname(struct xfs_da_args *args); From patchwork Sun Dec 31 22:34:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507904 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 932D1C13B for ; Sun, 31 Dec 2023 22:34:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="W5F02TwX" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1A755C433C7; Sun, 31 Dec 2023 22:34:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704062046; bh=m+RY93tkturq238t9G3jNqjg9FYzvJ/dBJxO1Ew/QLI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=W5F02TwXgD/fFY695xrNRkDvVKjJVCyDXJsuuCRRC/J1DcTFOYAdtjlSIFr8SBa5d 1Ts1/7dpxTp0rTBBZj5db/0kreILnoG4yhiR3yCJCLDiZUHo7i+1SkPUX9/jMnbvY1 ztfQTGxNtRW1TG+/DIfGzaaOQiIbE80fRIZzU812/yxWTVbetfG0nT63hsJYIbosdP 19RC6syeh6OewWM3W4YnaMvBMkYlYdoS5pABn8xxjDVg/zARknGxwRIf80woHRq4b+ eNTSwQx6OPl5as8Z5OWmYXrmnoV+LlcnTD1uFICHlwsPKA/wa2v9xvoY+aZNNp/k6d oxgc8wyIaTIHw== Date: Sun, 31 Dec 2023 14:34:05 -0800 Subject: [PATCH 7/9] xfs: validate explicit directory data buffer owners From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404996961.1796662.16439765852311650250.stgit@frogsfrogsfrogs> In-Reply-To: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> References: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Port the existing directory data header checking function to accept an owner number instead of an xfs_inode, then update the callsites to use xfs_da_args.owner when possible. Signed-off-by: Darrick J. Wong --- db/namei.c | 3 ++- libxfs/xfs_dir2.h | 1 + libxfs/xfs_dir2_block.c | 3 ++- libxfs/xfs_dir2_data.c | 15 +++++++++------ libxfs/xfs_dir2_leaf.c | 21 +++++++++++---------- libxfs/xfs_dir2_node.c | 7 +++---- libxfs/xfs_dir2_priv.h | 3 ++- 7 files changed, 30 insertions(+), 23 deletions(-) diff --git a/db/namei.c b/db/namei.c index eb09288b490..d7bf489cd53 100644 --- a/db/namei.c +++ b/db/namei.c @@ -400,7 +400,8 @@ list_leafdir( libxfs_trim_extent(&map, dabno, geo->leafblk - dabno); /* Read the directory block of that first mapping. */ - error = xfs_dir3_data_read(NULL, dp, map.br_startoff, 0, &bp); + error = xfs_dir3_data_read(NULL, dp, args->owner, + map.br_startoff, 0, &bp); if (error) break; diff --git a/libxfs/xfs_dir2.h b/libxfs/xfs_dir2.h index 0b01dd6ccf1..537596b9de4 100644 --- a/libxfs/xfs_dir2.h +++ b/libxfs/xfs_dir2.h @@ -99,6 +99,7 @@ extern struct xfs_dir2_data_free *xfs_dir2_data_freefind( extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); xfs_failaddr_t xfs_dir3_leaf_header_check(struct xfs_buf *bp, xfs_ino_t owner); +xfs_failaddr_t xfs_dir3_data_header_check(struct xfs_buf *bp, xfs_ino_t owner); extern const struct xfs_buf_ops xfs_dir3_block_buf_ops; extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops; diff --git a/libxfs/xfs_dir2_block.c b/libxfs/xfs_dir2_block.c index 1f6a88091e7..86e49fbc2b7 100644 --- a/libxfs/xfs_dir2_block.c +++ b/libxfs/xfs_dir2_block.c @@ -979,7 +979,8 @@ xfs_dir2_leaf_to_block( * Read the data block if we don't already have it, give up if it fails. */ if (!dbp) { - error = xfs_dir3_data_read(tp, dp, args->geo->datablk, 0, &dbp); + error = xfs_dir3_data_read(tp, dp, args->owner, + args->geo->datablk, 0, &dbp); if (error) return error; } diff --git a/libxfs/xfs_dir2_data.c b/libxfs/xfs_dir2_data.c index 6f3ccfeb69f..9ce0039d6ac 100644 --- a/libxfs/xfs_dir2_data.c +++ b/libxfs/xfs_dir2_data.c @@ -392,17 +392,19 @@ static const struct xfs_buf_ops xfs_dir3_data_reada_buf_ops = { .verify_write = xfs_dir3_data_write_verify, }; -static xfs_failaddr_t +xfs_failaddr_t xfs_dir3_data_header_check( - struct xfs_inode *dp, - struct xfs_buf *bp) + struct xfs_buf *bp, + xfs_ino_t owner) { - struct xfs_mount *mp = dp->i_mount; + struct xfs_mount *mp = bp->b_mount; if (xfs_has_crc(mp)) { struct xfs_dir3_data_hdr *hdr3 = bp->b_addr; - if (be64_to_cpu(hdr3->hdr.owner) != dp->i_ino) + ASSERT(hdr3->hdr.magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)); + + if (be64_to_cpu(hdr3->hdr.owner) != owner) return __this_address; } @@ -413,6 +415,7 @@ int xfs_dir3_data_read( struct xfs_trans *tp, struct xfs_inode *dp, + xfs_ino_t owner, xfs_dablk_t bno, unsigned int flags, struct xfs_buf **bpp) @@ -426,7 +429,7 @@ xfs_dir3_data_read( return err; /* Check things that we can't do in the verifier. */ - fa = xfs_dir3_data_header_check(dp, *bpp); + fa = xfs_dir3_data_header_check(*bpp, owner); if (fa) { __xfs_buf_mark_corrupt(*bpp, fa); xfs_trans_brelse(tp, *bpp); diff --git a/libxfs/xfs_dir2_leaf.c b/libxfs/xfs_dir2_leaf.c index 14449a23502..dd2bb2bc8b6 100644 --- a/libxfs/xfs_dir2_leaf.c +++ b/libxfs/xfs_dir2_leaf.c @@ -882,9 +882,9 @@ xfs_dir2_leaf_addname( * Already had space in some data block. * Just read that one in. */ - error = xfs_dir3_data_read(tp, dp, - xfs_dir2_db_to_da(args->geo, use_block), - 0, &dbp); + error = xfs_dir3_data_read(tp, dp, args->owner, + xfs_dir2_db_to_da(args->geo, use_block), 0, + &dbp); if (error) { xfs_trans_brelse(tp, lbp); return error; @@ -1325,9 +1325,9 @@ xfs_dir2_leaf_lookup_int( if (newdb != curdb) { if (dbp) xfs_trans_brelse(tp, dbp); - error = xfs_dir3_data_read(tp, dp, - xfs_dir2_db_to_da(args->geo, newdb), - 0, &dbp); + error = xfs_dir3_data_read(tp, dp, args->owner, + xfs_dir2_db_to_da(args->geo, newdb), 0, + &dbp); if (error) { xfs_trans_brelse(tp, lbp); return error; @@ -1367,9 +1367,9 @@ xfs_dir2_leaf_lookup_int( ASSERT(cidb != -1); if (cidb != curdb) { xfs_trans_brelse(tp, dbp); - error = xfs_dir3_data_read(tp, dp, - xfs_dir2_db_to_da(args->geo, cidb), - 0, &dbp); + error = xfs_dir3_data_read(tp, dp, args->owner, + xfs_dir2_db_to_da(args->geo, cidb), 0, + &dbp); if (error) { xfs_trans_brelse(tp, lbp); return error; @@ -1663,7 +1663,8 @@ xfs_dir2_leaf_trim_data( /* * Read the offending data block. We need its buffer. */ - error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(geo, db), 0, &dbp); + error = xfs_dir3_data_read(tp, dp, args->owner, + xfs_dir2_db_to_da(geo, db), 0, &dbp); if (error) return error; diff --git a/libxfs/xfs_dir2_node.c b/libxfs/xfs_dir2_node.c index c0160d725e5..69040737418 100644 --- a/libxfs/xfs_dir2_node.c +++ b/libxfs/xfs_dir2_node.c @@ -860,7 +860,7 @@ xfs_dir2_leafn_lookup_for_entry( ASSERT(state->extravalid); curbp = state->extrablk.bp; } else { - error = xfs_dir3_data_read(tp, dp, + error = xfs_dir3_data_read(tp, dp, args->owner, xfs_dir2_db_to_da(args->geo, newdb), 0, &curbp); @@ -1946,9 +1946,8 @@ xfs_dir2_node_addname_int( &freehdr, &findex); } else { /* Read the data block in. */ - error = xfs_dir3_data_read(tp, dp, - xfs_dir2_db_to_da(args->geo, dbno), - 0, &dbp); + error = xfs_dir3_data_read(tp, dp, args->owner, + xfs_dir2_db_to_da(args->geo, dbno), 0, &dbp); } if (error) return error; diff --git a/libxfs/xfs_dir2_priv.h b/libxfs/xfs_dir2_priv.h index 2f0e3ad47b3..879aa2e9fd7 100644 --- a/libxfs/xfs_dir2_priv.h +++ b/libxfs/xfs_dir2_priv.h @@ -78,7 +78,8 @@ extern void xfs_dir3_data_check(struct xfs_inode *dp, struct xfs_buf *bp); extern xfs_failaddr_t __xfs_dir3_data_check(struct xfs_inode *dp, struct xfs_buf *bp); int xfs_dir3_data_read(struct xfs_trans *tp, struct xfs_inode *dp, - xfs_dablk_t bno, unsigned int flags, struct xfs_buf **bpp); + xfs_ino_t owner, xfs_dablk_t bno, unsigned int flags, + struct xfs_buf **bpp); int xfs_dir3_data_readahead(struct xfs_inode *dp, xfs_dablk_t bno, unsigned int flags); From patchwork Sun Dec 31 22:34:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507905 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 577E5C13B for ; Sun, 31 Dec 2023 22:34:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qbkcqaTd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C4735C433C7; Sun, 31 Dec 2023 22:34:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704062061; bh=xTP7xSouAdmiT5Gz27cpxjPjFOtVMPQFJ2tM8BwqcS0=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=qbkcqaTdMKIb1S36PvCRHQm3jZ0jG4TiPnXU7EDq8JpxDoMFj/aWu5kAW5527vSSC PmlmoRVhNKTez5OFmDLSDTFuEnuJ9L3JiPXiKGekrdZH9KLPTnp24G9+hDpfwa/EjT 9dqr5IeSDDYu/EWqeZaIc9x2E/wY2sPXfX84mNLyp+lU5wqfgRCNbrz6uw3JpuXMwk knCBaW1oqn16BNGtkeZ9HrVPzaqdtxU+sOc9cV0A7YFfSuzJP+cINfiOiMbkmllFJF aYsIfGHLbazVl0WVMSB5p4EgMfKlBp8ks6VOLFkgRXcyT+F4xuIGNYa5fN0lsdHKrL lHkgwQv1+I96A== Date: Sun, 31 Dec 2023 14:34:21 -0800 Subject: [PATCH 8/9] xfs: validate explicit directory block buffer owners From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404996975.1796662.7701276307823992202.stgit@frogsfrogsfrogs> In-Reply-To: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> References: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Port the existing directory block header checking function to accept an owner number instead of an xfs_inode, then update the callsites to use xfs_da_args.owner when possible. Signed-off-by: Darrick J. Wong --- db/namei.c | 2 +- libxfs/xfs_dir2.h | 1 + libxfs/xfs_dir2_block.c | 22 ++++++++++++++-------- libxfs/xfs_dir2_priv.h | 2 +- libxfs/xfs_swapext.c | 2 +- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/db/namei.c b/db/namei.c index d7bf489cd53..a8577b97222 100644 --- a/db/namei.c +++ b/db/namei.c @@ -339,7 +339,7 @@ list_blockdir( unsigned int end; int error; - error = xfs_dir3_block_read(NULL, dp, &bp); + error = xfs_dir3_block_read(NULL, dp, args->owner, &bp); if (error) return error; diff --git a/libxfs/xfs_dir2.h b/libxfs/xfs_dir2.h index 537596b9de4..f99788a1f3e 100644 --- a/libxfs/xfs_dir2.h +++ b/libxfs/xfs_dir2.h @@ -100,6 +100,7 @@ extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); xfs_failaddr_t xfs_dir3_leaf_header_check(struct xfs_buf *bp, xfs_ino_t owner); xfs_failaddr_t xfs_dir3_data_header_check(struct xfs_buf *bp, xfs_ino_t owner); +xfs_failaddr_t xfs_dir3_block_header_check(struct xfs_buf *bp, xfs_ino_t owner); extern const struct xfs_buf_ops xfs_dir3_block_buf_ops; extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops; diff --git a/libxfs/xfs_dir2_block.c b/libxfs/xfs_dir2_block.c index 86e49fbc2b7..370f4df0c72 100644 --- a/libxfs/xfs_dir2_block.c +++ b/libxfs/xfs_dir2_block.c @@ -112,18 +112,23 @@ const struct xfs_buf_ops xfs_dir3_block_buf_ops = { .verify_struct = xfs_dir3_block_verify, }; -static xfs_failaddr_t +xfs_failaddr_t xfs_dir3_block_header_check( - struct xfs_inode *dp, - struct xfs_buf *bp) + struct xfs_buf *bp, + xfs_ino_t owner) { - struct xfs_mount *mp = dp->i_mount; + struct xfs_mount *mp = bp->b_mount; if (xfs_has_crc(mp)) { struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; - if (be64_to_cpu(hdr3->owner) != dp->i_ino) + ASSERT(hdr3->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); + + if (be64_to_cpu(hdr3->owner) != owner) { + xfs_err(NULL, "dir block owner 0x%llx doesnt match block 0x%llx", owner, be64_to_cpu(hdr3->owner)); + dump_stack(); return __this_address; + } } return NULL; @@ -133,6 +138,7 @@ int xfs_dir3_block_read( struct xfs_trans *tp, struct xfs_inode *dp, + xfs_ino_t owner, struct xfs_buf **bpp) { struct xfs_mount *mp = dp->i_mount; @@ -145,7 +151,7 @@ xfs_dir3_block_read( return err; /* Check things that we can't do in the verifier. */ - fa = xfs_dir3_block_header_check(dp, *bpp); + fa = xfs_dir3_block_header_check(*bpp, owner); if (fa) { __xfs_buf_mark_corrupt(*bpp, fa); xfs_trans_brelse(tp, *bpp); @@ -380,7 +386,7 @@ xfs_dir2_block_addname( tp = args->trans; /* Read the (one and only) directory block into bp. */ - error = xfs_dir3_block_read(tp, dp, &bp); + error = xfs_dir3_block_read(tp, dp, args->owner, &bp); if (error) return error; @@ -695,7 +701,7 @@ xfs_dir2_block_lookup_int( dp = args->dp; tp = args->trans; - error = xfs_dir3_block_read(tp, dp, &bp); + error = xfs_dir3_block_read(tp, dp, args->owner, &bp); if (error) return error; diff --git a/libxfs/xfs_dir2_priv.h b/libxfs/xfs_dir2_priv.h index 879aa2e9fd7..969e36a03fe 100644 --- a/libxfs/xfs_dir2_priv.h +++ b/libxfs/xfs_dir2_priv.h @@ -51,7 +51,7 @@ extern int xfs_dir_cilookup_result(struct xfs_da_args *args, /* xfs_dir2_block.c */ extern int xfs_dir3_block_read(struct xfs_trans *tp, struct xfs_inode *dp, - struct xfs_buf **bpp); + xfs_ino_t owner, struct xfs_buf **bpp); extern int xfs_dir2_block_addname(struct xfs_da_args *args); extern int xfs_dir2_block_lookup(struct xfs_da_args *args); extern int xfs_dir2_block_removename(struct xfs_da_args *args); diff --git a/libxfs/xfs_swapext.c b/libxfs/xfs_swapext.c index eae4f6b7310..f396593a5c8 100644 --- a/libxfs/xfs_swapext.c +++ b/libxfs/xfs_swapext.c @@ -571,7 +571,7 @@ xfs_swapext_dir_to_sf( if (!isblock) return 0; - error = xfs_dir3_block_read(tp, sxi->sxi_ip2, &bp); + error = xfs_dir3_block_read(tp, sxi->sxi_ip2, sxi->sxi_ip2->i_ino, &bp); if (error) return error; From patchwork Sun Dec 31 22:34:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507906 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 974D3C13B for ; Sun, 31 Dec 2023 22:34:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bEUhKtK3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 68916C433C7; Sun, 31 Dec 2023 22:34:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704062077; bh=AS1sqLpKM2VTlWdZq1KHqXmLnkF8GdmBBpNYp38LEiw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=bEUhKtK3DY6GtGjfxeDVdkJQdE8gcxTy3R3joF5Tw0/wnf//IZJRw7TAXUXIiliCC Wb/vHk89EcXoTqeEoNEb+ovo7acoDNVKurBHAmP8gTWsdrKdagUG0OOW9kQYoKPNys UQ3NveVxHI7rGFcR2p2zM+dbsY5rUCk5jnrD7pP5CUqTd6/jn7ca8jYZhqMHfS5pRx 6Ge5EhOcLOHOZK+hYtG+13/c7CfXd+M0RSKXM78wZn0crbhghvTvTKsQ3iQJm2MFho cy8vQTEWxoYwZySsQffpztbXdZXji1j5VAUo8SmaLCq2GFt3RjN8t9sfJSPJTI8jqe 7YXxdEHGCMUkA== Date: Sun, 31 Dec 2023 14:34:36 -0800 Subject: [PATCH 9/9] xfs: validate explicit directory free block owners From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404996988.1796662.9255833509682611896.stgit@frogsfrogsfrogs> In-Reply-To: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> References: <170404996860.1796662.9605761412685436403.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Port the existing directory freespace block header checking function to accept an owner number instead of an xfs_inode, then update the callsites to use xfs_da_args.owner when possible. Signed-off-by: Darrick J. Wong --- libxfs/xfs_dir2_leaf.c | 3 ++- libxfs/xfs_dir2_node.c | 32 ++++++++++++++++++-------------- libxfs/xfs_dir2_priv.h | 2 +- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/libxfs/xfs_dir2_leaf.c b/libxfs/xfs_dir2_leaf.c index dd2bb2bc8b6..77eca816c66 100644 --- a/libxfs/xfs_dir2_leaf.c +++ b/libxfs/xfs_dir2_leaf.c @@ -1803,7 +1803,8 @@ xfs_dir2_node_to_leaf( /* * Read the freespace block. */ - error = xfs_dir2_free_read(tp, dp, args->geo->freeblk, &fbp); + error = xfs_dir2_free_read(tp, dp, args->owner, args->geo->freeblk, + &fbp); if (error) return error; xfs_dir2_free_hdr_from_disk(mp, &freehdr, fbp->b_addr); diff --git a/libxfs/xfs_dir2_node.c b/libxfs/xfs_dir2_node.c index 69040737418..c94d00eb99c 100644 --- a/libxfs/xfs_dir2_node.c +++ b/libxfs/xfs_dir2_node.c @@ -172,11 +172,11 @@ const struct xfs_buf_ops xfs_dir3_free_buf_ops = { /* Everything ok in the free block header? */ static xfs_failaddr_t xfs_dir3_free_header_check( - struct xfs_inode *dp, - xfs_dablk_t fbno, - struct xfs_buf *bp) + struct xfs_buf *bp, + xfs_ino_t owner, + xfs_dablk_t fbno) { - struct xfs_mount *mp = dp->i_mount; + struct xfs_mount *mp = bp->b_mount; int maxbests = mp->m_dir_geo->free_max_bests; unsigned int firstdb; @@ -192,7 +192,7 @@ xfs_dir3_free_header_check( return __this_address; if (be32_to_cpu(hdr3->nvalid) < be32_to_cpu(hdr3->nused)) return __this_address; - if (be64_to_cpu(hdr3->hdr.owner) != dp->i_ino) + if (be64_to_cpu(hdr3->hdr.owner) != owner) return __this_address; } else { struct xfs_dir2_free_hdr *hdr = bp->b_addr; @@ -211,6 +211,7 @@ static int __xfs_dir3_free_read( struct xfs_trans *tp, struct xfs_inode *dp, + xfs_ino_t owner, xfs_dablk_t fbno, unsigned int flags, struct xfs_buf **bpp) @@ -224,7 +225,7 @@ __xfs_dir3_free_read( return err; /* Check things that we can't do in the verifier. */ - fa = xfs_dir3_free_header_check(dp, fbno, *bpp); + fa = xfs_dir3_free_header_check(*bpp, owner, fbno); if (fa) { __xfs_buf_mark_corrupt(*bpp, fa); xfs_trans_brelse(tp, *bpp); @@ -296,20 +297,23 @@ int xfs_dir2_free_read( struct xfs_trans *tp, struct xfs_inode *dp, + xfs_ino_t owner, xfs_dablk_t fbno, struct xfs_buf **bpp) { - return __xfs_dir3_free_read(tp, dp, fbno, 0, bpp); + return __xfs_dir3_free_read(tp, dp, owner, fbno, 0, bpp); } static int xfs_dir2_free_try_read( struct xfs_trans *tp, struct xfs_inode *dp, + xfs_ino_t owner, xfs_dablk_t fbno, struct xfs_buf **bpp) { - return __xfs_dir3_free_read(tp, dp, fbno, XFS_DABUF_MAP_HOLE_OK, bpp); + return __xfs_dir3_free_read(tp, dp, owner, fbno, XFS_DABUF_MAP_HOLE_OK, + bpp); } static int @@ -714,7 +718,7 @@ xfs_dir2_leafn_lookup_for_addname( if (curbp) xfs_trans_brelse(tp, curbp); - error = xfs_dir2_free_read(tp, dp, + error = xfs_dir2_free_read(tp, dp, args->owner, xfs_dir2_db_to_da(args->geo, newfdb), &curbp); @@ -1353,8 +1357,8 @@ xfs_dir2_leafn_remove( * read in the free block. */ fdb = xfs_dir2_db_to_fdb(geo, db); - error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(geo, fdb), - &fbp); + error = xfs_dir2_free_read(tp, dp, args->owner, + xfs_dir2_db_to_da(geo, fdb), &fbp); if (error) return error; free = fbp->b_addr; @@ -1713,7 +1717,7 @@ xfs_dir2_node_add_datablk( * that was just allocated. */ fbno = xfs_dir2_db_to_fdb(args->geo, *dbno); - error = xfs_dir2_free_try_read(tp, dp, + error = xfs_dir2_free_try_read(tp, dp, args->owner, xfs_dir2_db_to_da(args->geo, fbno), &fbp); if (error) return error; @@ -1860,7 +1864,7 @@ xfs_dir2_node_find_freeblk( * so this might not succeed. This should be really rare, so * there's no reason to avoid it. */ - error = xfs_dir2_free_try_read(tp, dp, + error = xfs_dir2_free_try_read(tp, dp, args->owner, xfs_dir2_db_to_da(args->geo, fbno), &fbp); if (error) @@ -2299,7 +2303,7 @@ xfs_dir2_node_trim_free( /* * Read the freespace block. */ - error = xfs_dir2_free_try_read(tp, dp, fo, &bp); + error = xfs_dir2_free_try_read(tp, dp, args->owner, fo, &bp); if (error) return error; /* diff --git a/libxfs/xfs_dir2_priv.h b/libxfs/xfs_dir2_priv.h index 969e36a03fe..f9bc280e8c2 100644 --- a/libxfs/xfs_dir2_priv.h +++ b/libxfs/xfs_dir2_priv.h @@ -156,7 +156,7 @@ extern int xfs_dir2_node_replace(struct xfs_da_args *args); extern int xfs_dir2_node_trim_free(struct xfs_da_args *args, xfs_fileoff_t fo, int *rvalp); extern int xfs_dir2_free_read(struct xfs_trans *tp, struct xfs_inode *dp, - xfs_dablk_t fbno, struct xfs_buf **bpp); + xfs_ino_t owner, xfs_dablk_t fbno, struct xfs_buf **bpp); /* xfs_dir2_sf.c */ xfs_ino_t xfs_dir2_sf_get_ino(struct xfs_mount *mp, struct xfs_dir2_sf_hdr *hdr,