From a56e454d630545ea3b7dac3f37492265e3cbbe49 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Wed, 6 Jul 2016 08:36:11 +0200 Subject: sparc: revert this commit until uClibc-ng is fixed --- target/linux/patches/4.4.14/revert-sparc.patch | 319 +++++++++++++++++++++++++ 1 file changed, 319 insertions(+) create mode 100644 target/linux/patches/4.4.14/revert-sparc.patch 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 +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 +--- + 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 + -- cgit v1.2.3