[SRU][XENIAL][CVE-2018-10322][PATCH v2 2/4] xfs: sanity check directory inode di_size
William Breathitt Gray
william.gray at canonical.com
Wed Sep 2 19:41:36 UTC 2020
From: Amir Goldstein <amir73il at gmail.com>
This changes fixes an assertion hit when fuzzing on-disk
i_mode values.
The easy case to fix is when changing an empty file
i_mode to S_IFDIR. In this case, xfs_dinode_verify()
detects an illegal zero size for directory and fails
to load the inode structure from disk.
For the case of non empty file whose i_mode is changed
to S_IFDIR, the ASSERT() statement in xfs_dir2_isblock()
is replaced with return -EFSCORRUPTED, to avoid interacting
with corrupted jusk also when XFS_DEBUG is disabled.
Suggested-by: Darrick J. Wong <darrick.wong at oracle.com>
Reviewed-by: Christoph Hellwig <hch at lst.de>
Signed-off-by: Amir Goldstein <amir73il at gmail.com>
Reviewed-by: Darrick J. Wong <darrick.wong at oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong at oracle.com>
CVE-2018-10322
(backported from commit 3c6f46eacd876bd723a9bad3c6882714c052fd8e)
[ vilhelmgray: context adjustment ]
Signed-off-by: William Breathitt Gray <william.gray at canonical.com>
---
fs/xfs/libxfs/xfs_dir2.c | 3 ++-
fs/xfs/libxfs/xfs_inode_buf.c | 8 ++++++--
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c
index 2fb53a5c0a74..8441a1b41a82 100644
--- a/fs/xfs/libxfs/xfs_dir2.c
+++ b/fs/xfs/libxfs/xfs_dir2.c
@@ -630,7 +630,8 @@ xfs_dir2_isblock(
if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
return rval;
rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize;
- ASSERT(rval == 0 || args->dp->i_d.di_size == args->geo->blksize);
+ if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize)
+ return -EFSCORRUPTED;
*vp = rval;
return 0;
}
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index bcf233337724..20fcace5fecc 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -296,6 +296,8 @@ xfs_dinode_verify(
xfs_ino_t ino,
struct xfs_dinode *dip)
{
+ uint16_t mode;
+
if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC))
return false;
@@ -303,8 +305,10 @@ xfs_dinode_verify(
if (be64_to_cpu(dip->di_size) & (1ULL << 63))
return false;
- /* No zero-length symlinks. */
- if (S_ISLNK(be16_to_cpu(dip->di_mode)) && dip->di_size == 0)
+ mode = be16_to_cpu(dip->di_mode);
+
+ /* No zero-length symlinks/dirs. */
+ if ((S_ISLNK(mode) || S_ISDIR(mode)) && dip->di_size == 0)
return false;
/* only version 3 or greater inodes are extensively verified here */
--
2.25.1
More information about the kernel-team
mailing list