aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/signal_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/signal_32.c')
-rw-r--r--arch/sparc/kernel/signal_32.c41
1 files changed, 26 insertions, 15 deletions
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
index 52aa5e4ce5e7..c3c12efe0bc0 100644
--- a/arch/sparc/kernel/signal_32.c
+++ b/arch/sparc/kernel/signal_32.c
@@ -60,10 +60,22 @@ struct rt_signal_frame {
60#define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7))) 60#define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7)))
61#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) 61#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7)))
62 62
63/* Checks if the fp is valid. We always build signal frames which are
64 * 16-byte aligned, therefore we can always enforce that the restore
65 * frame has that property as well.
66 */
67static inline bool invalid_frame_pointer(void __user *fp, int fplen)
68{
69 if ((((unsigned long) fp) & 15) || !__access_ok((unsigned long)fp, fplen))
70 return true;
71
72 return false;
73}
74
63asmlinkage void do_sigreturn(struct pt_regs *regs) 75asmlinkage void do_sigreturn(struct pt_regs *regs)
64{ 76{
77 unsigned long up_psr, pc, npc, ufp;
65 struct signal_frame __user *sf; 78 struct signal_frame __user *sf;
66 unsigned long up_psr, pc, npc;
67 sigset_t set; 79 sigset_t set;
68 __siginfo_fpu_t __user *fpu_save; 80 __siginfo_fpu_t __user *fpu_save;
69 __siginfo_rwin_t __user *rwin_save; 81 __siginfo_rwin_t __user *rwin_save;
@@ -77,10 +89,13 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
77 sf = (struct signal_frame __user *) regs->u_regs[UREG_FP]; 89 sf = (struct signal_frame __user *) regs->u_regs[UREG_FP];
78 90
79 /* 1. Make sure we are not getting garbage from the user */ 91 /* 1. Make sure we are not getting garbage from the user */
80 if (!access_ok(VERIFY_READ, sf, sizeof(*sf))) 92 if (!invalid_frame_pointer(sf, sizeof(*sf)))
93 goto segv_and_exit;
94
95 if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
81 goto segv_and_exit; 96 goto segv_and_exit;
82 97
83 if (((unsigned long) sf) & 3) 98 if (ufp & 0x7)
84 goto segv_and_exit; 99 goto segv_and_exit;
85 100
86 err = __get_user(pc, &sf->info.si_regs.pc); 101 err = __get_user(pc, &sf->info.si_regs.pc);
@@ -127,7 +142,7 @@ segv_and_exit:
127asmlinkage void do_rt_sigreturn(struct pt_regs *regs) 142asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
128{ 143{
129 struct rt_signal_frame __user *sf; 144 struct rt_signal_frame __user *sf;
130 unsigned int psr, pc, npc; 145 unsigned int psr, pc, npc, ufp;
131 __siginfo_fpu_t __user *fpu_save; 146 __siginfo_fpu_t __user *fpu_save;
132 __siginfo_rwin_t __user *rwin_save; 147 __siginfo_rwin_t __user *rwin_save;
133 sigset_t set; 148 sigset_t set;
@@ -135,8 +150,13 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
135 150
136 synchronize_user_stack(); 151 synchronize_user_stack();
137 sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP]; 152 sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP];
138 if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || 153 if (!invalid_frame_pointer(sf, sizeof(*sf)))
139 (((unsigned long) sf) & 0x03)) 154 goto segv;
155
156 if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
157 goto segv;
158
159 if (ufp & 0x7)
140 goto segv; 160 goto segv;
141 161
142 err = __get_user(pc, &sf->regs.pc); 162 err = __get_user(pc, &sf->regs.pc);
@@ -178,15 +198,6 @@ segv:
178 force_sig(SIGSEGV, current); 198 force_sig(SIGSEGV, current);
179} 199}
180 200
181/* Checks if the fp is valid */
182static inline int invalid_frame_pointer(void __user *fp, int fplen)
183{
184 if ((((unsigned long) fp) & 7) || !__access_ok((unsigned long)fp, fplen))
185 return 1;
186
187 return 0;
188}
189
190static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize) 201static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
191{ 202{
192 unsigned long sp = regs->u_regs[UREG_FP]; 203 unsigned long sp = regs->u_regs[UREG_FP];