From: Greg Kroah-Hartman Date: Fri, 14 Aug 2015 16:47:01 +0000 (-0700) Subject: 3.14-stable patches X-Git-Tag: v3.10.87~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5f9f562cb11deb82cf1d2e379aa8abed5cba6a8e;p=thirdparty%2Fkernel%2Fstable-queue.git 3.14-stable patches added patches: fold-d_kill-and-d_free.patch signal-fix-information-leak-in-copy_siginfo_from_user32.patch signal-fix-information-leak-in-copy_siginfo_to_user.patch signalfd-fix-information-leak-in-signalfd_copyinfo.patch --- diff --git a/queue-3.14/fold-d_kill-and-d_free.patch b/queue-3.14/fold-d_kill-and-d_free.patch new file mode 100644 index 00000000000..f7c5ebc7b33 --- /dev/null +++ b/queue-3.14/fold-d_kill-and-d_free.patch @@ -0,0 +1,118 @@ +From 03b3b889e79cdb6b806fc0ba9be0d71c186bbfaa Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Tue, 29 Apr 2014 15:45:28 -0400 +Subject: fold d_kill() and d_free() + +From: Al Viro + +commit 03b3b889e79cdb6b806fc0ba9be0d71c186bbfaa upstream. + +Signed-off-by: Al Viro +Cc: "Nicholas A. Bellinger" +Signed-off-by: Greg Kroah-Hartman + + +--- + fs/dcache.c | 77 ++++++++++++++++++------------------------------------------ + 1 file changed, 24 insertions(+), 53 deletions(-) + +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -244,24 +244,6 @@ static void __d_free(struct rcu_head *he + kmem_cache_free(dentry_cache, dentry); + } + +-/* +- * no locks, please. +- */ +-static void d_free(struct dentry *dentry) +-{ +- WARN_ON(!hlist_unhashed(&dentry->d_u.d_alias)); +- BUG_ON((int)dentry->d_lockref.count > 0); +- this_cpu_dec(nr_dentry); +- if (dentry->d_op && dentry->d_op->d_release) +- dentry->d_op->d_release(dentry); +- +- /* if dentry was never visible to RCU, immediate free is OK */ +- if (!(dentry->d_flags & DCACHE_RCUACCESS)) +- __d_free(&dentry->d_u.d_rcu); +- else +- call_rcu(&dentry->d_u.d_rcu, __d_free); +-} +- + /** + * dentry_rcuwalk_barrier - invalidate in-progress rcu-walk lookups + * @dentry: the target dentry +@@ -419,40 +401,6 @@ static void dentry_lru_del(struct dentry + } + + /** +- * d_kill - kill dentry and return parent +- * @dentry: dentry to kill +- * @parent: parent dentry +- * +- * The dentry must already be unhashed and removed from the LRU. +- * +- * If this is the root of the dentry tree, return NULL. +- * +- * dentry->d_lock and parent->d_lock must be held by caller, and are dropped by +- * d_kill. +- */ +-static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) +- __releases(dentry->d_lock) +- __releases(parent->d_lock) +- __releases(dentry->d_inode->i_lock) +-{ +- __list_del_entry(&dentry->d_child); +- /* +- * Inform d_walk() that we are no longer attached to the +- * dentry tree +- */ +- dentry->d_flags |= DCACHE_DENTRY_KILLED; +- if (parent) +- spin_unlock(&parent->d_lock); +- dentry_iput(dentry); +- /* +- * dentry_iput drops the locks, at which point nobody (except +- * transient RCU lookups) can reach this dentry. +- */ +- d_free(dentry); +- return parent; +-} +- +-/** + * d_drop - drop a dentry + * @dentry: dentry to drop + * +@@ -545,7 +493,30 @@ relock: + dentry_lru_del(dentry); + /* if it was on the hash then remove it */ + __d_drop(dentry); +- return d_kill(dentry, parent); ++ __list_del_entry(&dentry->d_child); ++ /* ++ * Inform d_walk() that we are no longer attached to the ++ * dentry tree ++ */ ++ dentry->d_flags |= DCACHE_DENTRY_KILLED; ++ if (parent) ++ spin_unlock(&parent->d_lock); ++ dentry_iput(dentry); ++ /* ++ * dentry_iput drops the locks, at which point nobody (except ++ * transient RCU lookups) can reach this dentry. ++ */ ++ BUG_ON((int)dentry->d_lockref.count > 0); ++ this_cpu_dec(nr_dentry); ++ if (dentry->d_op && dentry->d_op->d_release) ++ dentry->d_op->d_release(dentry); ++ ++ /* if dentry was never visible to RCU, immediate free is OK */ ++ if (!(dentry->d_flags & DCACHE_RCUACCESS)) ++ __d_free(&dentry->d_u.d_rcu); ++ else ++ call_rcu(&dentry->d_u.d_rcu, __d_free); ++ return parent; + } + + /* diff --git a/queue-3.14/series b/queue-3.14/series index b153ea9427f..930341d8450 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -27,3 +27,7 @@ ocfs2-fix-bug-in-ocfs2_downconvert_thread_do_work.patch pci-restore-pci_msix_flags_birmask-definition.patch md-raid1-extend-spinlock-to-protect-raid1_end_read_request-against-inconsistencies.patch sg_start_req-make-sure-that-there-s-not-too-many-elements-in-iovec.patch +signalfd-fix-information-leak-in-signalfd_copyinfo.patch +signal-fix-information-leak-in-copy_siginfo_to_user.patch +signal-fix-information-leak-in-copy_siginfo_from_user32.patch +fold-d_kill-and-d_free.patch diff --git a/queue-3.14/signal-fix-information-leak-in-copy_siginfo_from_user32.patch b/queue-3.14/signal-fix-information-leak-in-copy_siginfo_from_user32.patch new file mode 100644 index 00000000000..6f83474bf1a --- /dev/null +++ b/queue-3.14/signal-fix-information-leak-in-copy_siginfo_from_user32.patch @@ -0,0 +1,105 @@ +From 3c00cb5e68dc719f2fc73a33b1b230aadfcb1309 Mon Sep 17 00:00:00 2001 +From: Amanieu d'Antras +Date: Thu, 6 Aug 2015 15:46:26 -0700 +Subject: signal: fix information leak in copy_siginfo_from_user32 + +From: Amanieu d'Antras + +commit 3c00cb5e68dc719f2fc73a33b1b230aadfcb1309 upstream. + +This function can leak kernel stack data when the user siginfo_t has a +positive si_code value. The top 16 bits of si_code descibe which fields +in the siginfo_t union are active, but they are treated inconsistently +between copy_siginfo_from_user32, copy_siginfo_to_user32 and +copy_siginfo_to_user. + +copy_siginfo_from_user32 is called from rt_sigqueueinfo and +rt_tgsigqueueinfo in which the user has full control overthe top 16 bits +of si_code. + +This fixes the following information leaks: +x86: 8 bytes leaked when sending a signal from a 32-bit process to + itself. This leak grows to 16 bytes if the process uses x32. + (si_code = __SI_CHLD) +x86: 100 bytes leaked when sending a signal from a 32-bit process to + a 64-bit process. (si_code = -1) +sparc: 4 bytes leaked when sending a signal from a 32-bit process to a + 64-bit process. (si_code = any) + +parsic and s390 have similar bugs, but they are not vulnerable because +rt_[tg]sigqueueinfo have checks that prevent sending a positive si_code +to a different process. These bugs are also fixed for consistency. + +Signed-off-by: Amanieu d'Antras +Cc: Oleg Nesterov +Cc: Ingo Molnar +Cc: Russell King +Cc: Ralf Baechle +Cc: Benjamin Herrenschmidt +Cc: Chris Metcalf +Cc: Paul Mackerras +Cc: Michael Ellerman +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm64/kernel/signal32.c | 2 -- + arch/mips/kernel/signal32.c | 2 -- + arch/powerpc/kernel/signal_32.c | 2 -- + kernel/signal.c | 4 ++-- + 4 files changed, 2 insertions(+), 8 deletions(-) + +--- a/arch/arm64/kernel/signal32.c ++++ b/arch/arm64/kernel/signal32.c +@@ -193,8 +193,6 @@ int copy_siginfo_to_user32(compat_siginf + + int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) + { +- memset(to, 0, sizeof *to); +- + if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) || + copy_from_user(to->_sifields._pad, + from->_sifields._pad, SI_PAD_SIZE)) +--- a/arch/mips/kernel/signal32.c ++++ b/arch/mips/kernel/signal32.c +@@ -370,8 +370,6 @@ int copy_siginfo_to_user32(compat_siginf + + int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) + { +- memset(to, 0, sizeof *to); +- + if (copy_from_user(to, from, 3*sizeof(int)) || + copy_from_user(to->_sifields._pad, + from->_sifields._pad, SI_PAD_SIZE32)) +--- a/arch/powerpc/kernel/signal_32.c ++++ b/arch/powerpc/kernel/signal_32.c +@@ -967,8 +967,6 @@ int copy_siginfo_to_user32(struct compat + + int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from) + { +- memset(to, 0, sizeof *to); +- + if (copy_from_user(to, from, 3*sizeof(int)) || + copy_from_user(to->_sifields._pad, + from->_sifields._pad, SI_PAD_SIZE32)) +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -3036,7 +3036,7 @@ COMPAT_SYSCALL_DEFINE3(rt_sigqueueinfo, + int, sig, + struct compat_siginfo __user *, uinfo) + { +- siginfo_t info; ++ siginfo_t info = {}; + int ret = copy_siginfo_from_user32(&info, uinfo); + if (unlikely(ret)) + return ret; +@@ -3082,7 +3082,7 @@ COMPAT_SYSCALL_DEFINE4(rt_tgsigqueueinfo + int, sig, + struct compat_siginfo __user *, uinfo) + { +- siginfo_t info; ++ siginfo_t info = {}; + + if (copy_siginfo_from_user32(&info, uinfo)) + return -EFAULT; diff --git a/queue-3.14/signal-fix-information-leak-in-copy_siginfo_to_user.patch b/queue-3.14/signal-fix-information-leak-in-copy_siginfo_to_user.patch new file mode 100644 index 00000000000..91439c3f4ac --- /dev/null +++ b/queue-3.14/signal-fix-information-leak-in-copy_siginfo_to_user.patch @@ -0,0 +1,54 @@ +From 26135022f85105ad725cda103fa069e29e83bd16 Mon Sep 17 00:00:00 2001 +From: Amanieu d'Antras +Date: Thu, 6 Aug 2015 15:46:29 -0700 +Subject: signal: fix information leak in copy_siginfo_to_user + +From: Amanieu d'Antras + +commit 26135022f85105ad725cda103fa069e29e83bd16 upstream. + +This function may copy the si_addr_lsb, si_lower and si_upper fields to +user mode when they haven't been initialized, which can leak kernel +stack data to user mode. + +Just checking the value of si_code is insufficient because the same +si_code value is shared between multiple signals. This is solved by +checking the value of si_signo in addition to si_code. + +Signed-off-by: Amanieu d'Antras +Cc: Oleg Nesterov +Cc: Ingo Molnar +Cc: Russell King +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm64/kernel/signal32.c | 3 ++- + kernel/signal.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +--- a/arch/arm64/kernel/signal32.c ++++ b/arch/arm64/kernel/signal32.c +@@ -165,7 +165,8 @@ int copy_siginfo_to_user32(compat_siginf + * Other callers might not initialize the si_lsb field, + * so check explicitely for the right codes here. + */ +- if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO) ++ if (from->si_signo == SIGBUS && ++ (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)) + err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb); + #endif + break; +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -2768,7 +2768,8 @@ int copy_siginfo_to_user(siginfo_t __use + * Other callers might not initialize the si_lsb field, + * so check explicitly for the right codes here. + */ +- if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO) ++ if (from->si_signo == SIGBUS && ++ (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)) + err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb); + #endif + break; diff --git a/queue-3.14/signalfd-fix-information-leak-in-signalfd_copyinfo.patch b/queue-3.14/signalfd-fix-information-leak-in-signalfd_copyinfo.patch new file mode 100644 index 00000000000..c7fbba1bff2 --- /dev/null +++ b/queue-3.14/signalfd-fix-information-leak-in-signalfd_copyinfo.patch @@ -0,0 +1,41 @@ +From 3ead7c52bdb0ab44f4bb1feed505a8323cc12ba7 Mon Sep 17 00:00:00 2001 +From: Amanieu d'Antras +Date: Thu, 6 Aug 2015 15:46:33 -0700 +Subject: signalfd: fix information leak in signalfd_copyinfo + +From: Amanieu d'Antras + +commit 3ead7c52bdb0ab44f4bb1feed505a8323cc12ba7 upstream. + +This function may copy the si_addr_lsb field to user mode when it hasn't +been initialized, which can leak kernel stack data to user mode. + +Just checking the value of si_code is insufficient because the same +si_code value is shared between multiple signals. This is solved by +checking the value of si_signo in addition to si_code. + +Signed-off-by: Amanieu d'Antras +Cc: Oleg Nesterov +Cc: Ingo Molnar +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/signalfd.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/fs/signalfd.c ++++ b/fs/signalfd.c +@@ -121,8 +121,9 @@ static int signalfd_copyinfo(struct sign + * Other callers might not initialize the si_lsb field, + * so check explicitly for the right codes here. + */ +- if (kinfo->si_code == BUS_MCEERR_AR || +- kinfo->si_code == BUS_MCEERR_AO) ++ if (kinfo->si_signo == SIGBUS && ++ (kinfo->si_code == BUS_MCEERR_AR || ++ kinfo->si_code == BUS_MCEERR_AO)) + err |= __put_user((short) kinfo->si_addr_lsb, + &uinfo->ssi_addr_lsb); + #endif