]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: validate inode di_forkoff
authorEric Sandeen <sandeen@redhat.com>
Tue, 9 Oct 2018 16:49:46 +0000 (11:49 -0500)
committerEric Sandeen <sandeen@redhat.com>
Tue, 9 Oct 2018 16:49:46 +0000 (11:49 -0500)
Source kernel commit: 339e1a3fcdd1990e5ec115325ccb4c6f4cc5ee16

Verify the inode di_forkoff, lifted from xfs_repair's
process_check_inode_forkoff().

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
libxfs/xfs_inode_buf.c

index 03ab18bb1f6098a6c12f2e68d8d2a980ec61af96..503990f79110fc8743fcd3f01a670f04aa2d6efc 100644 (file)
@@ -411,6 +411,31 @@ xfs_dinode_verify_fork(
        return NULL;
 }
 
+static xfs_failaddr_t
+xfs_dinode_verify_forkoff(
+       struct xfs_dinode       *dip,
+       struct xfs_mount        *mp)
+{
+       if (!XFS_DFORK_Q(dip))
+               return NULL;
+
+       switch (dip->di_format)  {
+       case XFS_DINODE_FMT_DEV:
+               if (dip->di_forkoff != (roundup(sizeof(xfs_dev_t), 8) >> 3))
+                       return __this_address;
+               break;
+       case XFS_DINODE_FMT_LOCAL:      /* fall through ... */
+       case XFS_DINODE_FMT_EXTENTS:    /* fall through ... */
+       case XFS_DINODE_FMT_BTREE:
+               if (dip->di_forkoff >= (XFS_LITINO(mp, dip->di_version) >> 3))
+                       return __this_address;
+               break;
+       default:
+               return __this_address;
+       }
+       return NULL;
+}
+
 xfs_failaddr_t
 xfs_dinode_verify(
        struct xfs_mount        *mp,
@@ -466,6 +491,11 @@ xfs_dinode_verify(
        if (mode && (flags & XFS_DIFLAG_REALTIME) && !mp->m_rtdev_targp)
                return __this_address;
 
+       /* check for illegal values of forkoff */
+       fa = xfs_dinode_verify_forkoff(dip, mp);
+       if (fa)
+               return fa;
+
        /* Do we have appropriate data fork formats for the mode? */
        switch (mode & S_IFMT) {
        case S_IFIFO: