diff options
Diffstat (limited to 'target/linux/patches/4.6.6/revert-sparc.patch')
-rw-r--r-- | target/linux/patches/4.6.6/revert-sparc.patch | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/target/linux/patches/4.6.6/revert-sparc.patch b/target/linux/patches/4.6.6/revert-sparc.patch new file mode 100644 index 000000000..d5bb8ad37 --- /dev/null +++ b/target/linux/patches/4.6.6/revert-sparc.patch @@ -0,0 +1,295 @@ +diff -Nur linux-4.6.4.orig/arch/sparc/kernel/signal_32.c linux-4.6.4/arch/sparc/kernel/signal_32.c +--- linux-4.6.4.orig/arch/sparc/kernel/signal_32.c 2016-07-11 18:30:07.000000000 +0200 ++++ linux-4.6.4/arch/sparc/kernel/signal_32.c 2016-07-18 21:55:43.720763787 +0200 +@@ -60,22 +60,10 @@ + #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 @@ + 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))) ++ if (!access_ok(VERIFY_READ, sf, sizeof(*sf))) + goto segv_and_exit; + +- if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP])) +- 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 @@ + 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 @@ + + 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 @@ + 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 -Nur linux-4.6.4.orig/arch/sparc/kernel/signal32.c linux-4.6.4/arch/sparc/kernel/signal32.c +--- linux-4.6.4.orig/arch/sparc/kernel/signal32.c 2016-07-11 18:30:07.000000000 +0200 ++++ linux-4.6.4/arch/sparc/kernel/signal32.c 2016-07-18 21:56:41.807007836 +0200 +@@ -138,24 +138,12 @@ + 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 int pc, npc; + sigset_t set; + compat_sigset_t seta; +@@ -170,16 +158,11 @@ + 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 @@ + 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 @@ + 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 @@ + 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 -Nur linux-4.6.4.orig/arch/sparc/kernel/signal_64.c linux-4.6.4/arch/sparc/kernel/signal_64.c +--- linux-4.6.4.orig/arch/sparc/kernel/signal_64.c 2016-07-11 18:30:07.000000000 +0200 ++++ linux-4.6.4/arch/sparc/kernel/signal_64.c 2016-07-18 21:55:43.720763787 +0200 +@@ -234,17 +234,6 @@ + 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 @@ + + 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 @@ + (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 @@ + 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 -Nur linux-4.6.4.orig/arch/sparc/kernel/sigutil_32.c linux-4.6.4/arch/sparc/kernel/sigutil_32.c +--- linux-4.6.4.orig/arch/sparc/kernel/sigutil_32.c 2016-07-11 18:30:07.000000000 +0200 ++++ linux-4.6.4/arch/sparc/kernel/sigutil_32.c 2016-07-18 21:55:43.720763787 +0200 +@@ -48,10 +48,6 @@ + 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 @@ + 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 -Nur linux-4.6.4.orig/arch/sparc/kernel/sigutil_64.c linux-4.6.4/arch/sparc/kernel/sigutil_64.c +--- linux-4.6.4.orig/arch/sparc/kernel/sigutil_64.c 2016-07-11 18:30:07.000000000 +0200 ++++ linux-4.6.4/arch/sparc/kernel/sigutil_64.c 2016-07-18 21:55:43.720763787 +0200 +@@ -37,10 +37,7 @@ + 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 @@ + 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; + |