summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@uclibc-ng.org>2016-07-06 08:36:11 +0200
committerWaldemar Brodkorb <wbx@uclibc-ng.org>2016-07-06 08:36:11 +0200
commita56e454d630545ea3b7dac3f37492265e3cbbe49 (patch)
treef2443c2267889bb9c346a0d7238184658692f151
parent35092dbab8cd58856d9bf429fafdabc364008159 (diff)
sparc: revert this commit until uClibc-ng is fixed
-rw-r--r--target/linux/patches/4.4.14/revert-sparc.patch319
1 files changed, 319 insertions, 0 deletions
diff --git a/target/linux/patches/4.4.14/revert-sparc.patch b/target/linux/patches/4.4.14/revert-sparc.patch
new file mode 100644
index 000000000..296be0e4a
--- /dev/null
+++ b/target/linux/patches/4.4.14/revert-sparc.patch
@@ -0,0 +1,319 @@
+From fff1ade5bd7576b053b6bbc9c9b72c2572092c06 Mon Sep 17 00:00:00 2001
+From: Waldemar Brodkorb <wbx@uclibc-ng.org>
+Date: Wed, 6 Jul 2016 08:16:59 +0200
+Subject: [PATCH] Revert "sparc: Harden signal return frame checks."
+
+This reverts commit 1fda90c39d8ef6acbedfd3cd9bd710a5bcc490c3.
+
+Signed-off-by: Waldemar Brodkorb <wbx@uclibc-ng.org>
+---
+ arch/sparc/kernel/signal32.c | 46 ++++++++++++++--------------------------
+ arch/sparc/kernel/signal_32.c | 41 +++++++++++++----------------------
+ arch/sparc/kernel/signal_64.c | 31 ++++++++++-----------------
+ arch/sparc/kernel/sigutil_32.c | 9 +-------
+ arch/sparc/kernel/sigutil_64.c | 10 ++-------
+ 5 files changed, 45 insertions(+), 92 deletions(-)
+
+diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c
+index 77655f0..4eed773 100644
+--- a/arch/sparc/kernel/signal32.c
++++ b/arch/sparc/kernel/signal32.c
+@@ -138,24 +138,12 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
+ return 0;
+ }
+
+-/* Checks if the fp is valid. We always build signal frames which are
+- * 16-byte aligned, therefore we can always enforce that the restore
+- * frame has that property as well.
+- */
+-static bool invalid_frame_pointer(void __user *fp, int fplen)
+-{
+- if ((((unsigned long) fp) & 15) ||
+- ((unsigned long)fp) > 0x100000000ULL - fplen)
+- return true;
+- return false;
+-}
+-
+ void do_sigreturn32(struct pt_regs *regs)
+ {
+ struct signal_frame32 __user *sf;
+ compat_uptr_t fpu_save;
+ compat_uptr_t rwin_save;
+- unsigned int psr, ufp;
++ unsigned int psr;
+ unsigned pc, npc;
+ sigset_t set;
+ compat_sigset_t seta;
+@@ -170,16 +158,11 @@ void do_sigreturn32(struct pt_regs *regs)
+ sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP];
+
+ /* 1. Make sure we are not getting garbage from the user */
+- if (invalid_frame_pointer(sf, sizeof(*sf)))
+- goto segv;
+-
+- if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
+- goto segv;
+-
+- if (ufp & 0x7)
++ if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
++ (((unsigned long) sf) & 3))
+ goto segv;
+
+- if (__get_user(pc, &sf->info.si_regs.pc) ||
++ if (get_user(pc, &sf->info.si_regs.pc) ||
+ __get_user(npc, &sf->info.si_regs.npc))
+ goto segv;
+
+@@ -244,7 +227,7 @@ segv:
+ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
+ {
+ struct rt_signal_frame32 __user *sf;
+- unsigned int psr, pc, npc, ufp;
++ unsigned int psr, pc, npc;
+ compat_uptr_t fpu_save;
+ compat_uptr_t rwin_save;
+ sigset_t set;
+@@ -259,16 +242,11 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
+ sf = (struct rt_signal_frame32 __user *) regs->u_regs[UREG_FP];
+
+ /* 1. Make sure we are not getting garbage from the user */
+- if (invalid_frame_pointer(sf, sizeof(*sf)))
++ if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
++ (((unsigned long) sf) & 3))
+ goto segv;
+
+- if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
+- goto segv;
+-
+- if (ufp & 0x7)
+- goto segv;
+-
+- if (__get_user(pc, &sf->regs.pc) ||
++ if (get_user(pc, &sf->regs.pc) ||
+ __get_user(npc, &sf->regs.npc))
+ goto segv;
+
+@@ -329,6 +307,14 @@ segv:
+ force_sig(SIGSEGV, current);
+ }
+
++/* Checks if the fp is valid */
++static int invalid_frame_pointer(void __user *fp, int fplen)
++{
++ if ((((unsigned long) fp) & 7) || ((unsigned long)fp) > 0x100000000ULL - fplen)
++ return 1;
++ return 0;
++}
++
+ static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
+ {
+ unsigned long sp;
+diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
+index c3c12ef..52aa5e4 100644
+--- a/arch/sparc/kernel/signal_32.c
++++ b/arch/sparc/kernel/signal_32.c
+@@ -60,22 +60,10 @@ struct rt_signal_frame {
+ #define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7)))
+ #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7)))
+
+-/* Checks if the fp is valid. We always build signal frames which are
+- * 16-byte aligned, therefore we can always enforce that the restore
+- * frame has that property as well.
+- */
+-static inline bool invalid_frame_pointer(void __user *fp, int fplen)
+-{
+- if ((((unsigned long) fp) & 15) || !__access_ok((unsigned long)fp, fplen))
+- return true;
+-
+- return false;
+-}
+-
+ asmlinkage void do_sigreturn(struct pt_regs *regs)
+ {
+- unsigned long up_psr, pc, npc, ufp;
+ struct signal_frame __user *sf;
++ unsigned long up_psr, pc, npc;
+ sigset_t set;
+ __siginfo_fpu_t __user *fpu_save;
+ __siginfo_rwin_t __user *rwin_save;
+@@ -89,13 +77,10 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
+ sf = (struct signal_frame __user *) regs->u_regs[UREG_FP];
+
+ /* 1. Make sure we are not getting garbage from the user */
+- if (!invalid_frame_pointer(sf, sizeof(*sf)))
+- goto segv_and_exit;
+-
+- if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
++ if (!access_ok(VERIFY_READ, sf, sizeof(*sf)))
+ goto segv_and_exit;
+
+- if (ufp & 0x7)
++ if (((unsigned long) sf) & 3)
+ goto segv_and_exit;
+
+ err = __get_user(pc, &sf->info.si_regs.pc);
+@@ -142,7 +127,7 @@ segv_and_exit:
+ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
+ {
+ struct rt_signal_frame __user *sf;
+- unsigned int psr, pc, npc, ufp;
++ unsigned int psr, pc, npc;
+ __siginfo_fpu_t __user *fpu_save;
+ __siginfo_rwin_t __user *rwin_save;
+ sigset_t set;
+@@ -150,13 +135,8 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
+
+ synchronize_user_stack();
+ sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP];
+- if (!invalid_frame_pointer(sf, sizeof(*sf)))
+- goto segv;
+-
+- if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
+- goto segv;
+-
+- if (ufp & 0x7)
++ if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
++ (((unsigned long) sf) & 0x03))
+ goto segv;
+
+ err = __get_user(pc, &sf->regs.pc);
+@@ -198,6 +178,15 @@ segv:
+ force_sig(SIGSEGV, current);
+ }
+
++/* Checks if the fp is valid */
++static inline int invalid_frame_pointer(void __user *fp, int fplen)
++{
++ if ((((unsigned long) fp) & 7) || !__access_ok((unsigned long)fp, fplen))
++ return 1;
++
++ return 0;
++}
++
+ static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
+ {
+ unsigned long sp = regs->u_regs[UREG_FP];
+diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
+index 5ee930c..39aaec1 100644
+--- a/arch/sparc/kernel/signal_64.c
++++ b/arch/sparc/kernel/signal_64.c
+@@ -234,17 +234,6 @@ do_sigsegv:
+ goto out;
+ }
+
+-/* Checks if the fp is valid. We always build rt signal frames which
+- * are 16-byte aligned, therefore we can always enforce that the
+- * restore frame has that property as well.
+- */
+-static bool invalid_frame_pointer(void __user *fp)
+-{
+- if (((unsigned long) fp) & 15)
+- return true;
+- return false;
+-}
+-
+ struct rt_signal_frame {
+ struct sparc_stackf ss;
+ siginfo_t info;
+@@ -257,8 +246,8 @@ struct rt_signal_frame {
+
+ void do_rt_sigreturn(struct pt_regs *regs)
+ {
+- unsigned long tpc, tnpc, tstate, ufp;
+ struct rt_signal_frame __user *sf;
++ unsigned long tpc, tnpc, tstate;
+ __siginfo_fpu_t __user *fpu_save;
+ __siginfo_rwin_t __user *rwin_save;
+ sigset_t set;
+@@ -272,16 +261,10 @@ void do_rt_sigreturn(struct pt_regs *regs)
+ (regs->u_regs [UREG_FP] + STACK_BIAS);
+
+ /* 1. Make sure we are not getting garbage from the user */
+- if (invalid_frame_pointer(sf))
+- goto segv;
+-
+- if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
++ if (((unsigned long) sf) & 3)
+ goto segv;
+
+- if ((ufp + STACK_BIAS) & 0x7)
+- goto segv;
+-
+- err = __get_user(tpc, &sf->regs.tpc);
++ err = get_user(tpc, &sf->regs.tpc);
+ err |= __get_user(tnpc, &sf->regs.tnpc);
+ if (test_thread_flag(TIF_32BIT)) {
+ tpc &= 0xffffffff;
+@@ -325,6 +308,14 @@ segv:
+ force_sig(SIGSEGV, current);
+ }
+
++/* Checks if the fp is valid */
++static int invalid_frame_pointer(void __user *fp)
++{
++ if (((unsigned long) fp) & 15)
++ return 1;
++ return 0;
++}
++
+ static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
+ {
+ unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS;
+diff --git a/arch/sparc/kernel/sigutil_32.c b/arch/sparc/kernel/sigutil_32.c
+index e5fe8ce..0f6eebe 100644
+--- a/arch/sparc/kernel/sigutil_32.c
++++ b/arch/sparc/kernel/sigutil_32.c
+@@ -48,10 +48,6 @@ int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
+ int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
+ {
+ int err;
+-
+- if (((unsigned long) fpu) & 3)
+- return -EFAULT;
+-
+ #ifdef CONFIG_SMP
+ if (test_tsk_thread_flag(current, TIF_USEDFPU))
+ regs->psr &= ~PSR_EF;
+@@ -101,10 +97,7 @@ int restore_rwin_state(__siginfo_rwin_t __user *rp)
+ struct thread_info *t = current_thread_info();
+ int i, wsaved, err;
+
+- if (((unsigned long) rp) & 3)
+- return -EFAULT;
+-
+- get_user(wsaved, &rp->wsaved);
++ __get_user(wsaved, &rp->wsaved);
+ if (wsaved > NSWINS)
+ return -EFAULT;
+
+diff --git a/arch/sparc/kernel/sigutil_64.c b/arch/sparc/kernel/sigutil_64.c
+index 36aadcb..387834a 100644
+--- a/arch/sparc/kernel/sigutil_64.c
++++ b/arch/sparc/kernel/sigutil_64.c
+@@ -37,10 +37,7 @@ int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
+ unsigned long fprs;
+ int err;
+
+- if (((unsigned long) fpu) & 7)
+- return -EFAULT;
+-
+- err = get_user(fprs, &fpu->si_fprs);
++ err = __get_user(fprs, &fpu->si_fprs);
+ fprs_write(0);
+ regs->tstate &= ~TSTATE_PEF;
+ if (fprs & FPRS_DL)
+@@ -75,10 +72,7 @@ int restore_rwin_state(__siginfo_rwin_t __user *rp)
+ struct thread_info *t = current_thread_info();
+ int i, wsaved, err;
+
+- if (((unsigned long) rp) & 7)
+- return -EFAULT;
+-
+- get_user(wsaved, &rp->wsaved);
++ __get_user(wsaved, &rp->wsaved);
+ if (wsaved > NSWINS)
+ return -EFAULT;
+
+--
+1.7.10.4
+