diff options
Diffstat (limited to '0001-xfs-More-robust-inode-extent-count-validation.patch')
-rw-r--r-- | 0001-xfs-More-robust-inode-extent-count-validation.patch | 223 |
1 files changed, 0 insertions, 223 deletions
diff --git a/0001-xfs-More-robust-inode-extent-count-validation.patch b/0001-xfs-More-robust-inode-extent-count-validation.patch deleted file mode 100644 index f24aa88d2..000000000 --- a/0001-xfs-More-robust-inode-extent-count-validation.patch +++ /dev/null @@ -1,223 +0,0 @@ -From 7d71a671a2d900606d3a62ed5976d3b0feada3a6 Mon Sep 17 00:00:00 2001 -From: Dave Chinner <dchinner@redhat.com> -Date: Tue, 5 Jun 2018 10:06:44 -0700 -Subject: [PATCH] xfs: verify extent size hint is valid in inode verifier - -There are rules for vald extent size hints. We enforce them when -applications set them, but fuzzers violate those rules and that -screws us over. - -This results in alignment assertion failures when setting up -allocations such as this in direct IO: - -XFS: Assertion failed: ap->length, file: fs/xfs/libxfs/xfs_bmap.c, line: 3432 -.... -Call Trace: - xfs_bmap_btalloc+0x415/0x910 - xfs_bmapi_write+0x71c/0x12e0 - xfs_iomap_write_direct+0x2a9/0x420 - xfs_file_iomap_begin+0x4dc/0xa70 - iomap_apply+0x43/0x100 - iomap_file_buffered_write+0x62/0x90 - xfs_file_buffered_aio_write+0xba/0x300 - __vfs_write+0xd5/0x150 - vfs_write+0xb6/0x180 - ksys_write+0x45/0xa0 - do_syscall_64+0x5a/0x180 - entry_SYSCALL_64_after_hwframe+0x49/0xbe - -And from xfs_db: - -core.extsize = 10380288 - -Which is not an integer multiple of the block size, and so violates -Rule #7 for setting extent size hints. Validate extent size hint -rules in the inode verifier to catch this. - -Signed-off-by: Dave Chinner <dchinner@redhat.com> -Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com> -Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> -Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> -Signed-off-by: Jeremy Cline <jcline@redhat.com> ---- - fs/xfs/libxfs/xfs_inode_buf.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c -index 1201107eabc6..1fe18555b451 100644 ---- a/fs/xfs/libxfs/xfs_inode_buf.c -+++ b/fs/xfs/libxfs/xfs_inode_buf.c -@@ -397,6 +397,7 @@ xfs_dinode_verify( - xfs_ino_t ino, - struct xfs_dinode *dip) - { -+ xfs_failaddr_t fa; - uint16_t mode; - uint16_t flags; - uint64_t flags2; -@@ -513,6 +514,12 @@ xfs_dinode_verify( - return __this_address; - } - -+ /* extent size hint validation */ -+ fa = xfs_inode_validate_extsize(mp, be32_to_cpu(dip->di_extsize), -+ mode, flags); -+ if (fa) -+ return fa; -+ - /* only version 3 or greater inodes are extensively verified here */ - if (dip->di_version < 3) - return NULL; -@@ -521,7 +528,7 @@ xfs_dinode_verify( - - /* don't allow reflink/cowextsize if we don't have reflink */ - if ((flags2 & (XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE)) && -- !xfs_sb_version_hasreflink(&mp->m_sb)) -+ !xfs_sb_version_hasreflink(&mp->m_sb)) - return __this_address; - - /* only regular files get reflink */ --- -2.17.1 - -From 23fcb3340d033d9f081e21e6c12c2db7eaa541d3 Mon Sep 17 00:00:00 2001 -From: Dave Chinner <dchinner@redhat.com> -Date: Thu, 21 Jun 2018 23:25:57 -0700 -Subject: [PATCH] xfs: More robust inode extent count validation - -When the inode is in extent format, it can't have more extents that -fit in the inode fork. We don't currenty check this, and so this -corruption goes unnoticed by the inode verifiers. This can lead to -crashes operating on invalid in-memory structures. - -Attempts to access such a inode will now error out in the verifier -rather than allowing modification operations to proceed. - -Reported-by: Wen Xu <wen.xu@gatech.edu> -Signed-off-by: Dave Chinner <dchinner@redhat.com> -Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> -[darrick: fix a typedef, add some braces and breaks to shut up compiler warnings] -Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> ---- - fs/xfs/libxfs/xfs_format.h | 3 ++ - fs/xfs/libxfs/xfs_inode_buf.c | 76 ++++++++++++++++++++++------------- - 2 files changed, 50 insertions(+), 29 deletions(-) - -diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h -index 1c5a8aaf2bfc..7b4a43deb83e 100644 ---- a/fs/xfs/libxfs/xfs_format.h -+++ b/fs/xfs/libxfs/xfs_format.h -@@ -962,6 +962,9 @@ typedef enum xfs_dinode_fmt { - XFS_DFORK_DSIZE(dip, mp) : \ - XFS_DFORK_ASIZE(dip, mp)) - -+#define XFS_DFORK_MAXEXT(dip, mp, w) \ -+ (XFS_DFORK_SIZE(dip, mp, w) / sizeof(struct xfs_bmbt_rec)) -+ - /* - * Return pointers to the data or attribute forks. - */ -diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c -index d38d724534c4..33dc34655ac3 100644 ---- a/fs/xfs/libxfs/xfs_inode_buf.c -+++ b/fs/xfs/libxfs/xfs_inode_buf.c -@@ -374,6 +374,47 @@ xfs_log_dinode_to_disk( - } - } - -+static xfs_failaddr_t -+xfs_dinode_verify_fork( -+ struct xfs_dinode *dip, -+ struct xfs_mount *mp, -+ int whichfork) -+{ -+ uint32_t di_nextents = XFS_DFORK_NEXTENTS(dip, whichfork); -+ -+ switch (XFS_DFORK_FORMAT(dip, whichfork)) { -+ case XFS_DINODE_FMT_LOCAL: -+ /* -+ * no local regular files yet -+ */ -+ if (whichfork == XFS_DATA_FORK) { -+ if (S_ISREG(be16_to_cpu(dip->di_mode))) -+ return __this_address; -+ if (be64_to_cpu(dip->di_size) > -+ XFS_DFORK_SIZE(dip, mp, whichfork)) -+ return __this_address; -+ } -+ if (di_nextents) -+ return __this_address; -+ break; -+ case XFS_DINODE_FMT_EXTENTS: -+ if (di_nextents > XFS_DFORK_MAXEXT(dip, mp, whichfork)) -+ return __this_address; -+ break; -+ case XFS_DINODE_FMT_BTREE: -+ if (whichfork == XFS_ATTR_FORK) { -+ if (di_nextents > MAXAEXTNUM) -+ return __this_address; -+ } else if (di_nextents > MAXEXTNUM) { -+ return __this_address; -+ } -+ break; -+ default: -+ return __this_address; -+ } -+ return NULL; -+} -+ - xfs_failaddr_t - xfs_dinode_verify( - struct xfs_mount *mp, -@@ -441,24 +482,9 @@ xfs_dinode_verify( - case S_IFREG: - case S_IFLNK: - case S_IFDIR: -- switch (dip->di_format) { -- case XFS_DINODE_FMT_LOCAL: -- /* -- * no local regular files yet -- */ -- if (S_ISREG(mode)) -- return __this_address; -- if (di_size > XFS_DFORK_DSIZE(dip, mp)) -- return __this_address; -- if (dip->di_nextents) -- return __this_address; -- /* fall through */ -- case XFS_DINODE_FMT_EXTENTS: -- case XFS_DINODE_FMT_BTREE: -- break; -- default: -- return __this_address; -- } -+ fa = xfs_dinode_verify_fork(dip, mp, XFS_DATA_FORK); -+ if (fa) -+ return fa; - break; - case 0: - /* Uninitialized inode ok. */ -@@ -468,17 +494,9 @@ xfs_dinode_verify( - } - - if (XFS_DFORK_Q(dip)) { -- switch (dip->di_aformat) { -- case XFS_DINODE_FMT_LOCAL: -- if (dip->di_anextents) -- return __this_address; -- /* fall through */ -- case XFS_DINODE_FMT_EXTENTS: -- case XFS_DINODE_FMT_BTREE: -- break; -- default: -- return __this_address; -- } -+ fa = xfs_dinode_verify_fork(dip, mp, XFS_ATTR_FORK); -+ if (fa) -+ return fa; - } else { - /* - * If there is no fork offset, this may be a freshly-made inode --- -2.17.1 - |