|
@@ -1,319 +0,0 @@
|
|
|
-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
|
|
|
-
|