summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustin M. Forbes <jforbes@fedoraproject.org>2018-07-05 09:31:36 -0500
committerJustin M. Forbes <jforbes@fedoraproject.org>2018-07-05 09:31:36 -0500
commit1a9181ff17aa8e6c755e8e9f49b6a3b840c8ce8f (patch)
tree6c6a6fead0f2449d832dfaeb786f305db7413f4d
parent539a3afe2de9751709aaa31c8475b5128d923ee4 (diff)
downloadkernel-1a9181ff17aa8e6c755e8e9f49b6a3b840c8ce8f.tar.gz
kernel-1a9181ff17aa8e6c755e8e9f49b6a3b840c8ce8f.tar.xz
kernel-1a9181ff17aa8e6c755e8e9f49b6a3b840c8ce8f.zip
Fix CVE-2018-13053 CVE-2018-12896 CVE-2018-13093 CVE-2018-13094 CVE-2018-13095
-rw-r--r--0001-xfs-More-robust-inode-extent-count-validation.patch141
-rw-r--r--0001-xfs-don-t-call-xfs_da_shrink_inode-with-NULL-bp.patch43
-rw-r--r--0001-xfs-validate-cached-inodes-are-free-when-allocated.patch155
-rw-r--r--1-2-posix-timers-Make-forward-callback-return-s64.patch86
-rw-r--r--2-2-posix-timers-Sanitize-overrun-handling.patch145
-rw-r--r--alarmtimer-prevent-overflow-for-relative-nanosleep.patch50
-rw-r--r--kernel.spec23
7 files changed, 643 insertions, 0 deletions
diff --git a/0001-xfs-More-robust-inode-extent-count-validation.patch b/0001-xfs-More-robust-inode-extent-count-validation.patch
new file mode 100644
index 000000000..767eb6fac
--- /dev/null
+++ b/0001-xfs-More-robust-inode-extent-count-validation.patch
@@ -0,0 +1,141 @@
+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
+
diff --git a/0001-xfs-don-t-call-xfs_da_shrink_inode-with-NULL-bp.patch b/0001-xfs-don-t-call-xfs_da_shrink_inode-with-NULL-bp.patch
new file mode 100644
index 000000000..874536f24
--- /dev/null
+++ b/0001-xfs-don-t-call-xfs_da_shrink_inode-with-NULL-bp.patch
@@ -0,0 +1,43 @@
+From bb3d48dcf86a97dc25fe9fc2c11938e19cb4399a Mon Sep 17 00:00:00 2001
+From: Eric Sandeen <sandeen@sandeen.net>
+Date: Fri, 8 Jun 2018 09:53:49 -0700
+Subject: [PATCH] xfs: don't call xfs_da_shrink_inode with NULL bp
+
+xfs_attr3_leaf_create may have errored out before instantiating a buffer,
+for example if the blkno is out of range. In that case there is no work
+to do to remove it, and in fact xfs_da_shrink_inode will lead to an oops
+if we try.
+
+This also seems to fix a flaw where the original error from
+xfs_attr3_leaf_create gets overwritten in the cleanup case, and it
+removes a pointless assignment to bp which isn't used after this.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=199969
+Reported-by: Xu, Wen <wen.xu@gatech.edu>
+Tested-by: Xu, Wen <wen.xu@gatech.edu>
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+---
+ fs/xfs/libxfs/xfs_attr_leaf.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
+index 99e0f5749dba..76e90046731c 100644
+--- a/fs/xfs/libxfs/xfs_attr_leaf.c
++++ b/fs/xfs/libxfs/xfs_attr_leaf.c
+@@ -791,9 +791,8 @@ xfs_attr_shortform_to_leaf(
+ ASSERT(blkno == 0);
+ error = xfs_attr3_leaf_create(args, blkno, &bp);
+ if (error) {
+- error = xfs_da_shrink_inode(args, 0, bp);
+- bp = NULL;
+- if (error)
++ /* xfs_attr3_leaf_create may not have instantiated a block */
++ if (bp && (xfs_da_shrink_inode(args, 0, bp) != 0))
+ goto out;
+ xfs_idata_realloc(dp, size, XFS_ATTR_FORK); /* try to put */
+ memcpy(ifp->if_u1.if_data, tmpbuffer, size); /* it back */
+--
+2.17.1
+
diff --git a/0001-xfs-validate-cached-inodes-are-free-when-allocated.patch b/0001-xfs-validate-cached-inodes-are-free-when-allocated.patch
new file mode 100644
index 000000000..ce78bed80
--- /dev/null
+++ b/0001-xfs-validate-cached-inodes-are-free-when-allocated.patch
@@ -0,0 +1,155 @@
+From afca6c5b2595fc44383919fba740c194b0b76aff Mon Sep 17 00:00:00 2001
+From: Dave Chinner <dchinner@redhat.com>
+Date: Tue, 17 Apr 2018 17:17:34 -0700
+Subject: [PATCH] xfs: validate cached inodes are free when allocated
+
+A recent fuzzed filesystem image cached random dcache corruption
+when the reproducer was run. This often showed up as panics in
+lookup_slow() on a null inode->i_ops pointer when doing pathwalks.
+
+BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
+....
+Call Trace:
+ lookup_slow+0x44/0x60
+ walk_component+0x3dd/0x9f0
+ link_path_walk+0x4a7/0x830
+ path_lookupat+0xc1/0x470
+ filename_lookup+0x129/0x270
+ user_path_at_empty+0x36/0x40
+ path_listxattr+0x98/0x110
+ SyS_listxattr+0x13/0x20
+ do_syscall_64+0xf5/0x280
+ entry_SYSCALL_64_after_hwframe+0x42/0xb7
+
+but had many different failure modes including deadlocks trying to
+lock the inode that was just allocated or KASAN reports of
+use-after-free violations.
+
+The cause of the problem was a corrupt INOBT on a v4 fs where the
+root inode was marked as free in the inobt record. Hence when we
+allocated an inode, it chose the root inode to allocate, found it in
+the cache and re-initialised it.
+
+We recently fixed a similar inode allocation issue caused by inobt
+record corruption problem in xfs_iget_cache_miss() in commit
+ee457001ed6c ("xfs: catch inode allocation state mismatch
+corruption"). This change adds similar checks to the cache-hit path
+to catch it, and turns the reproducer into a corruption shutdown
+situation.
+
+Reported-by: Wen Xu <wen.xu@gatech.edu>
+Signed-Off-By: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+[darrick: fix typos in comment]
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+---
+ fs/xfs/xfs_icache.c | 73 +++++++++++++++++++++++++++++----------------
+ 1 file changed, 48 insertions(+), 25 deletions(-)
+
+diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
+index 9a18f69f6e96..817899961f48 100644
+--- a/fs/xfs/xfs_icache.c
++++ b/fs/xfs/xfs_icache.c
+@@ -308,6 +308,46 @@ xfs_reinit_inode(
+ return error;
+ }
+
++/*
++ * If we are allocating a new inode, then check what was returned is
++ * actually a free, empty inode. If we are not allocating an inode,
++ * then check we didn't find a free inode.
++ *
++ * Returns:
++ * 0 if the inode free state matches the lookup context
++ * -ENOENT if the inode is free and we are not allocating
++ * -EFSCORRUPTED if there is any state mismatch at all
++ */
++static int
++xfs_iget_check_free_state(
++ struct xfs_inode *ip,
++ int flags)
++{
++ if (flags & XFS_IGET_CREATE) {
++ /* should be a free inode */
++ if (VFS_I(ip)->i_mode != 0) {
++ xfs_warn(ip->i_mount,
++"Corruption detected! Free inode 0x%llx not marked free! (mode 0x%x)",
++ ip->i_ino, VFS_I(ip)->i_mode);
++ return -EFSCORRUPTED;
++ }
++
++ if (ip->i_d.di_nblocks != 0) {
++ xfs_warn(ip->i_mount,
++"Corruption detected! Free inode 0x%llx has blocks allocated!",
++ ip->i_ino);
++ return -EFSCORRUPTED;
++ }
++ return 0;
++ }
++
++ /* should be an allocated inode */
++ if (VFS_I(ip)->i_mode == 0)
++ return -ENOENT;
++
++ return 0;
++}
++
+ /*
+ * Check the validity of the inode we just found it the cache
+ */
+@@ -357,12 +397,12 @@ xfs_iget_cache_hit(
+ }
+
+ /*
+- * If lookup is racing with unlink return an error immediately.
++ * Check the inode free state is valid. This also detects lookup
++ * racing with unlinks.
+ */
+- if (VFS_I(ip)->i_mode == 0 && !(flags & XFS_IGET_CREATE)) {
+- error = -ENOENT;
++ error = xfs_iget_check_free_state(ip, flags);
++ if (error)
+ goto out_error;
+- }
+
+ /*
+ * If IRECLAIMABLE is set, we've torn down the VFS inode already.
+@@ -485,29 +525,12 @@ xfs_iget_cache_miss(
+
+
+ /*
+- * If we are allocating a new inode, then check what was returned is
+- * actually a free, empty inode. If we are not allocating an inode,
+- * the check we didn't find a free inode.
++ * Check the inode free state is valid. This also detects lookup
++ * racing with unlinks.
+ */
+- if (flags & XFS_IGET_CREATE) {
+- if (VFS_I(ip)->i_mode != 0) {
+- xfs_warn(mp,
+-"Corruption detected! Free inode 0x%llx not marked free on disk",
+- ino);
+- error = -EFSCORRUPTED;
+- goto out_destroy;
+- }
+- if (ip->i_d.di_nblocks != 0) {
+- xfs_warn(mp,
+-"Corruption detected! Free inode 0x%llx has blocks allocated!",
+- ino);
+- error = -EFSCORRUPTED;
+- goto out_destroy;
+- }
+- } else if (VFS_I(ip)->i_mode == 0) {
+- error = -ENOENT;
++ error = xfs_iget_check_free_state(ip, flags);
++ if (error)
+ goto out_destroy;
+- }
+
+ /*
+ * Preload the radix tree so we can insert safely under the
+--
+2.17.1
+
diff --git a/1-2-posix-timers-Make-forward-callback-return-s64.patch b/1-2-posix-timers-Make-forward-callback-return-s64.patch
new file mode 100644
index 000000000..3c48968e8
--- /dev/null
+++ b/1-2-posix-timers-Make-forward-callback-return-s64.patch
@@ -0,0 +1,86 @@
+From patchwork Tue Jun 26 13:21:31 2018
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [1/2] posix-timers: Make forward callback return s64
+From: Thomas Gleixner <tglx@linutronix.de>
+X-Patchwork-Id: 10489059
+Message-Id: <20180626132704.922098090@linutronix.de>
+To: LKML <linux-kernel@vger.kernel.org>
+Cc: John Stultz <john.stultz@linaro.org>,
+ Peter Zijlstra <peterz@infradead.org>,
+ Michael Kerrisk <mtk.manpages@gmail.com>, air icy <icytxw@gmail.com>
+Date: Tue, 26 Jun 2018 15:21:31 +0200
+
+The posix timer ti_overrun handling is broken because the forwarding
+functions can return a huge number of overruns which does not fit in an
+int. As a consequence timer_getoverrun(2) and siginfo::si_overrun can turn
+into random number generators.
+
+As a first step to address that let the timer_forward() callbacks return
+the full 64 bit value.
+
+Cast it to (int) temporarily until k_itimer::ti_overrun is converted to
+64bit and the conversion to user space visible values is sanitized.
+
+Reported-by: air icy <icytxw@gmail.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: John Stultz <john.stultz@linaro.org>
+---
+ kernel/time/alarmtimer.c | 4 ++--
+ kernel/time/posix-timers.c | 6 +++---
+ kernel/time/posix-timers.h | 2 +-
+ 3 files changed, 6 insertions(+), 6 deletions(-)
+
+--- a/kernel/time/alarmtimer.c
++++ b/kernel/time/alarmtimer.c
+@@ -581,11 +581,11 @@ static void alarm_timer_rearm(struct k_i
+ * @timr: Pointer to the posixtimer data struct
+ * @now: Current time to forward the timer against
+ */
+-static int alarm_timer_forward(struct k_itimer *timr, ktime_t now)
++static s64 alarm_timer_forward(struct k_itimer *timr, ktime_t now)
+ {
+ struct alarm *alarm = &timr->it.alarm.alarmtimer;
+
+- return (int) alarm_forward(alarm, timr->it_interval, now);
++ return alarm_forward(alarm, timr->it_interval, now);
+ }
+
+ /**
+--- a/kernel/time/posix-timers.c
++++ b/kernel/time/posix-timers.c
+@@ -645,11 +645,11 @@ static ktime_t common_hrtimer_remaining(
+ return __hrtimer_expires_remaining_adjusted(timer, now);
+ }
+
+-static int common_hrtimer_forward(struct k_itimer *timr, ktime_t now)
++static s64 common_hrtimer_forward(struct k_itimer *timr, ktime_t now)
+ {
+ struct hrtimer *timer = &timr->it.real.timer;
+
+- return (int)hrtimer_forward(timer, now, timr->it_interval);
++ return hrtimer_forward(timer, now, timr->it_interval);
+ }
+
+ /*
+@@ -702,7 +702,7 @@ void common_timer_get(struct k_itimer *t
+ * expiry time forward by intervals, so expiry is > now.
+ */
+ if (iv && (timr->it_requeue_pending & REQUEUE_PENDING || sig_none))
+- timr->it_overrun += kc->timer_forward(timr, now);
++ timr->it_overrun += (int)kc->timer_forward(timr, now);
+
+ remaining = kc->timer_remaining(timr, now);
+ /* Return 0 only, when the timer is expired and not pending */
+--- a/kernel/time/posix-timers.h
++++ b/kernel/time/posix-timers.h
+@@ -19,7 +19,7 @@ struct k_clock {
+ void (*timer_get)(struct k_itimer *timr,
+ struct itimerspec64 *cur_setting);
+ void (*timer_rearm)(struct k_itimer *timr);
+- int (*timer_forward)(struct k_itimer *timr, ktime_t now);
++ s64 (*timer_forward)(struct k_itimer *timr, ktime_t now);
+ ktime_t (*timer_remaining)(struct k_itimer *timr, ktime_t now);
+ int (*timer_try_to_cancel)(struct k_itimer *timr);
+ void (*timer_arm)(struct k_itimer *timr, ktime_t expires,
diff --git a/2-2-posix-timers-Sanitize-overrun-handling.patch b/2-2-posix-timers-Sanitize-overrun-handling.patch
new file mode 100644
index 000000000..4132125aa
--- /dev/null
+++ b/2-2-posix-timers-Sanitize-overrun-handling.patch
@@ -0,0 +1,145 @@
+From patchwork Tue Jun 26 13:21:32 2018
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [2/2] posix-timers: Sanitize overrun handling
+From: Thomas Gleixner <tglx@linutronix.de>
+X-Patchwork-Id: 10489053
+Message-Id: <20180626132705.018623573@linutronix.de>
+To: LKML <linux-kernel@vger.kernel.org>
+Cc: John Stultz <john.stultz@linaro.org>,
+ Peter Zijlstra <peterz@infradead.org>,
+ Michael Kerrisk <mtk.manpages@gmail.com>, air icy <icytxw@gmail.com>
+Date: Tue, 26 Jun 2018 15:21:32 +0200
+
+The posix timer overrun handling is broken because the forwarding functions
+can return a huge number of overruns which does not fit in an int. As a
+consequence timer_getoverrun(2) and siginfo::si_overrun can turn into
+random number generators.
+
+The k_clock::timer_forward() callbacks return a 64 bit value now. Make
+k_itimer::ti_overrun[_last] 64bit as well, so the kernel internal
+accounting is correct. 3Remove the temporary (int) casts.
+
+Add a helper function which clamps the overrun value returned to user space
+via timer_getoverrun(2) or siginfo::si_overrun limited to a positive value
+between 0 and INT_MAX. INT_MAX is an indicator for user space that the
+overrun value has been clamped.
+
+Reported-by: air icy <icytxw@gmail.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: John Stultz <john.stultz@linaro.org>
+---
+ include/linux/posix-timers.h | 4 ++--
+ kernel/time/posix-cpu-timers.c | 2 +-
+ kernel/time/posix-timers.c | 31 ++++++++++++++++++++-----------
+ 3 files changed, 23 insertions(+), 14 deletions(-)
+
+--- a/include/linux/posix-timers.h
++++ b/include/linux/posix-timers.h
+@@ -95,8 +95,8 @@ struct k_itimer {
+ clockid_t it_clock;
+ timer_t it_id;
+ int it_active;
+- int it_overrun;
+- int it_overrun_last;
++ s64 it_overrun;
++ s64 it_overrun_last;
+ int it_requeue_pending;
+ int it_sigev_notify;
+ ktime_t it_interval;
+--- a/kernel/time/posix-cpu-timers.c
++++ b/kernel/time/posix-cpu-timers.c
+@@ -85,7 +85,7 @@ static void bump_cpu_timer(struct k_itim
+ continue;
+
+ timer->it.cpu.expires += incr;
+- timer->it_overrun += 1 << i;
++ timer->it_overrun += 1LL << i;
+ delta -= incr;
+ }
+ }
+--- a/kernel/time/posix-timers.c
++++ b/kernel/time/posix-timers.c
+@@ -283,6 +283,17 @@ static __init int init_posix_timers(void
+ }
+ __initcall(init_posix_timers);
+
++/*
++ * The siginfo si_overrun field and the return value of timer_getoverrun(2)
++ * are of type int. Clamp the overrun value to INT_MAX
++ */
++static inline int timer_overrun_to_int(struct k_itimer *timr, int baseval)
++{
++ s64 sum = timr->it_overrun_last + (s64)baseval;
++
++ return sum > (s64)INT_MAX ? INT_MAX : (int)sum;
++}
++
+ static void common_hrtimer_rearm(struct k_itimer *timr)
+ {
+ struct hrtimer *timer = &timr->it.real.timer;
+@@ -290,9 +301,8 @@ static void common_hrtimer_rearm(struct
+ if (!timr->it_interval)
+ return;
+
+- timr->it_overrun += (unsigned int) hrtimer_forward(timer,
+- timer->base->get_time(),
+- timr->it_interval);
++ timr->it_overrun += hrtimer_forward(timer, timer->base->get_time(),
++ timr->it_interval);
+ hrtimer_restart(timer);
+ }
+
+@@ -321,10 +331,10 @@ void posixtimer_rearm(struct siginfo *in
+
+ timr->it_active = 1;
+ timr->it_overrun_last = timr->it_overrun;
+- timr->it_overrun = -1;
++ timr->it_overrun = -1LL;
+ ++timr->it_requeue_pending;
+
+- info->si_overrun += timr->it_overrun_last;
++ info->si_overrun = timer_overrun_to_int(timr, info->si_overrun);
+ }
+
+ unlock_timer(timr, flags);
+@@ -418,9 +428,8 @@ static enum hrtimer_restart posix_timer_
+ now = ktime_add(now, kj);
+ }
+ #endif
+- timr->it_overrun += (unsigned int)
+- hrtimer_forward(timer, now,
+- timr->it_interval);
++ timr->it_overrun += hrtimer_forward(timer, now,
++ timr->it_interval);
+ ret = HRTIMER_RESTART;
+ ++timr->it_requeue_pending;
+ timr->it_active = 1;
+@@ -524,7 +533,7 @@ static int do_timer_create(clockid_t whi
+ new_timer->it_id = (timer_t) new_timer_id;
+ new_timer->it_clock = which_clock;
+ new_timer->kclock = kc;
+- new_timer->it_overrun = -1;
++ new_timer->it_overrun = -1LL;
+
+ if (event) {
+ rcu_read_lock();
+@@ -702,7 +711,7 @@ void common_timer_get(struct k_itimer *t
+ * expiry time forward by intervals, so expiry is > now.
+ */
+ if (iv && (timr->it_requeue_pending & REQUEUE_PENDING || sig_none))
+- timr->it_overrun += (int)kc->timer_forward(timr, now);
++ timr->it_overrun += kc->timer_forward(timr, now);
+
+ remaining = kc->timer_remaining(timr, now);
+ /* Return 0 only, when the timer is expired and not pending */
+@@ -791,7 +800,7 @@ SYSCALL_DEFINE1(timer_getoverrun, timer_
+ if (!timr)
+ return -EINVAL;
+
+- overrun = timr->it_overrun_last;
++ overrun = timer_overrun_to_int(timr, 0);
+ unlock_timer(timr, flags);
+
+ return overrun;
diff --git a/alarmtimer-prevent-overflow-for-relative-nanosleep.patch b/alarmtimer-prevent-overflow-for-relative-nanosleep.patch
new file mode 100644
index 000000000..1ef0e5ab3
--- /dev/null
+++ b/alarmtimer-prevent-overflow-for-relative-nanosleep.patch
@@ -0,0 +1,50 @@
+From 5f936e19cc0ef97dbe3a56e9498922ad5ba1edef Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Jul 2018 09:34:29 +0200
+Subject: alarmtimer: Prevent overflow for relative nanosleep
+
+Air Icy reported:
+
+ UBSAN: Undefined behaviour in kernel/time/alarmtimer.c:811:7
+ signed integer overflow:
+ 1529859276030040771 + 9223372036854775807 cannot be represented in type 'long long int'
+ Call Trace:
+ alarm_timer_nsleep+0x44c/0x510 kernel/time/alarmtimer.c:811
+ __do_sys_clock_nanosleep kernel/time/posix-timers.c:1235 [inline]
+ __se_sys_clock_nanosleep kernel/time/posix-timers.c:1213 [inline]
+ __x64_sys_clock_nanosleep+0x326/0x4e0 kernel/time/posix-timers.c:1213
+ do_syscall_64+0xb8/0x3a0 arch/x86/entry/common.c:290
+
+alarm_timer_nsleep() uses ktime_add() to add the current time and the
+relative expiry value. ktime_add() has no sanity checks so the addition
+can overflow when the relative timeout is large enough.
+
+Use ktime_add_safe() which has the necessary sanity checks in place and
+limits the result to the valid range.
+
+Fixes: 9a7adcf5c6de ("timers: Posix interface for alarm-timers")
+Reported-by: Team OWL337 <icytxw@gmail.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: John Stultz <john.stultz@linaro.org>
+Link: https://lkml.kernel.org/r/alpine.DEB.2.21.1807020926360.1595@nanos.tec.linutronix.de
+---
+ kernel/time/alarmtimer.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
+index 78a3cc5..fa5de5e 100644
+--- a/kernel/time/alarmtimer.c
++++ b/kernel/time/alarmtimer.c
+@@ -808,7 +808,8 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
+ /* Convert (if necessary) to absolute time */
+ if (flags != TIMER_ABSTIME) {
+ ktime_t now = alarm_bases[type].gettime();
+- exp = ktime_add(now, exp);
++
++ exp = ktime_add_safe(now, exp);
+ }
+
+ ret = alarmtimer_do_nsleep(&alarm, exp, type);
+--
+cgit v1.1
+
diff --git a/kernel.spec b/kernel.spec
index d80833b6d..93cdd61ca 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -649,6 +649,22 @@ Patch515: 0001-signal-Stop-special-casing-TRAP_FIXME-and-FPE_FIXME-.patch
# rhbz 1572944
Patch517: Revert-the-random-series-for-4.16.4.patch
+# CVE-2018-13053 rhbz 1597747 1597748
+Patch518: alarmtimer-prevent-overflow-for-relative-nanosleep.patch
+
+# CVE-2018-12896 rhbz 1597759 1597760
+Patch519: 1-2-posix-timers-Make-forward-callback-return-s64.patch
+Patch520: 2-2-posix-timers-Sanitize-overrun-handling.patch
+
+# CVE-2018-13093 rhbz 1597766 1597767
+Patch521: 0001-xfs-validate-cached-inodes-are-free-when-allocated.patch
+
+# CVE-2018-13094 rhbz 1597771 1597772
+Patch522: 0001-xfs-don-t-call-xfs_da_shrink_inode-with-NULL-bp.patch
+
+# CVE-2018-13095 rhbz 1597775 1597777
+Patch523: 0001-xfs-More-robust-inode-extent-count-validation.patch
+
# END OF PATCH DEFINITIONS
%endif
@@ -1898,6 +1914,13 @@ fi
#
#
%changelog
+* Thu Jul 05 2018 Justin M. Forbes <jforbes@fedoraproject.org>
+- Fix CVE-2018-13053 (rhbz 1597747 1597748)
+- Fix CVE-2018-12896 (rhbz 1597759 1597760)
+- Fix CVE-2018-13093 (rhbz 1597766 1597767)
+- Fix CVE-2018-13094 (rhbz 1597771 1597772)
+- Fix CVE-2018-13095 (rhbz 1597775 1597777)
+
* Tue Jul 03 2018 Justin M. Forbes <jforbes@fedoraproject.org> - 4.17.4-100
- Linux v4.17.4