[PATCH 10/24] xfs: don't let xfs_bmap_first_unused overflow a xfs_dablk_t

Andrey Albershteyn
2024-12-29T13:40:04Z

From: "Darrick J. Wong" <djwong@kernel.org>

The directory/xattr code uses xfs_bmap_first_unused to find a contiguous
chunk of file range that can hold a particular value. Unfortunately,
file offsets are 64-bit quantities, whereas the dir/attr block number
type (xfs_dablk_t) is a 32-bit quantity. If an integer truncation
occurs here, we will corrupt the file.

Therefore, check for a file offset that would truncate and return EFBIG
in that case.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
fs/xfs/libxfs/xfs_attr_remote.c | 3 +++
fs/xfs/libxfs/xfs_da_btree.c | 3 +++
fs/xfs/libxfs/xfs_da_format.h | 3 +++
3 files changed, 9 insertions(+)

diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c
index e90a62c61f28..2bd225b1772c 100644
--- a/fs/xfs/libxfs/xfs_attr_remote.c
+++ b/fs/xfs/libxfs/xfs_attr_remote.c
@@ -529,6 +529,9 @@ xfs_attr_rmt_find_hole(
if (error)
return error;

+ if (lfileoff > XFS_MAX_DABLK)
+ return -EFBIG;
+
args->rmtblkno = (xfs_dablk_t)lfileoff;
args->rmtblkcnt = blkcnt;

diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c
index 17d9e6154f19..6c6c7bab87fb 100644
--- a/fs/xfs/libxfs/xfs_da_btree.c
+++ b/fs/xfs/libxfs/xfs_da_btree.c
@@ -2308,6 +2308,9 @@ xfs_da_grow_inode_int(
if (error)
return error;

+ if (*bno > XFS_MAX_DABLK)
+ return -EFBIG;
+
/*
* Try mapping it in one filesystem block.
*/
diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h
index 48bebcd1e226..ee9635c04197 100644
--- a/fs/xfs/libxfs/xfs_da_format.h
+++ b/fs/xfs/libxfs/xfs_da_format.h
@@ -748,6 +748,9 @@ struct xfs_attr3_leafblock {
*/
#define XFS_ATTR_LEAF_NAME_ALIGN ((uint)sizeof(xfs_dablk_t))

+/* Maximum file block offset of a directory or an xattr. */
+#define XFS_MAX_DABLK ((xfs_dablk_t)-1U)
+
static inline int
xfs_attr3_leaf_hdr_size(struct xfs_attr_leafblock *leafp)
{
--
2.47.0