aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/sys-i386/signal.c59
-rw-r--r--arch/um/sys-x86_64/signal.c56
2 files changed, 85 insertions, 30 deletions
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 7cd1a82dc8c2..33a40f5ef0d2 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -58,7 +58,7 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
58} 58}
59 59
60int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, 60int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
61 struct pt_regs *regs) 61 struct pt_regs *regs, unsigned long sp)
62{ 62{
63 struct sigcontext sc; 63 struct sigcontext sc;
64 unsigned long fpregs[HOST_FP_SIZE]; 64 unsigned long fpregs[HOST_FP_SIZE];
@@ -72,7 +72,7 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
72 sc.edi = REGS_EDI(regs->regs.skas.regs); 72 sc.edi = REGS_EDI(regs->regs.skas.regs);
73 sc.esi = REGS_ESI(regs->regs.skas.regs); 73 sc.esi = REGS_ESI(regs->regs.skas.regs);
74 sc.ebp = REGS_EBP(regs->regs.skas.regs); 74 sc.ebp = REGS_EBP(regs->regs.skas.regs);
75 sc.esp = REGS_SP(regs->regs.skas.regs); 75 sc.esp = sp;
76 sc.ebx = REGS_EBX(regs->regs.skas.regs); 76 sc.ebx = REGS_EBX(regs->regs.skas.regs);
77 sc.edx = REGS_EDX(regs->regs.skas.regs); 77 sc.edx = REGS_EDX(regs->regs.skas.regs);
78 sc.ecx = REGS_ECX(regs->regs.skas.regs); 78 sc.ecx = REGS_ECX(regs->regs.skas.regs);
@@ -132,7 +132,7 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
132} 132}
133 133
134int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, 134int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
135 struct sigcontext *from, int fpsize) 135 struct sigcontext *from, int fpsize, unsigned long sp)
136{ 136{
137 struct _fpstate *to_fp, *from_fp; 137 struct _fpstate *to_fp, *from_fp;
138 int err; 138 int err;
@@ -140,11 +140,18 @@ int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
140 to_fp = (fp ? fp : (struct _fpstate *) (to + 1)); 140 to_fp = (fp ? fp : (struct _fpstate *) (to + 1));
141 from_fp = from->fpstate; 141 from_fp = from->fpstate;
142 err = copy_to_user(to, from, sizeof(*to)); 142 err = copy_to_user(to, from, sizeof(*to));
143
144 /* The SP in the sigcontext is the updated one for the signal
145 * delivery. The sp passed in is the original, and this needs
146 * to be restored, so we stick it in separately.
147 */
148 err |= copy_to_user(&SC_SP(to), sp, sizeof(sp));
149
143 if(from_fp != NULL){ 150 if(from_fp != NULL){
144 err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); 151 err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
145 err |= copy_to_user(to_fp, from_fp, fpsize); 152 err |= copy_to_user(to_fp, from_fp, fpsize);
146 } 153 }
147 return(err); 154 return err;
148} 155}
149#endif 156#endif
150 157
@@ -159,11 +166,11 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from)
159} 166}
160 167
161static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp, 168static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp,
162 struct pt_regs *from) 169 struct pt_regs *from, unsigned long sp)
163{ 170{
164 return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), 171 return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
165 sizeof(*fp)), 172 sizeof(*fp), sp),
166 copy_sc_to_user_skas(to, fp, from))); 173 copy_sc_to_user_skas(to, fp, from, sp)));
167} 174}
168 175
169static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp, 176static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp,
@@ -174,7 +181,7 @@ static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp,
174 err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp); 181 err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
175 err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags); 182 err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
176 err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); 183 err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
177 err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs); 184 err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, sp);
178 err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); 185 err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
179 return(err); 186 return(err);
180} 187}
@@ -207,6 +214,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
207{ 214{
208 struct sigframe __user *frame; 215 struct sigframe __user *frame;
209 void *restorer; 216 void *restorer;
217 unsigned long save_sp = PT_REGS_SP(regs);
210 int err = 0; 218 int err = 0;
211 219
212 stack_top &= -8UL; 220 stack_top &= -8UL;
@@ -218,9 +226,19 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
218 if(ka->sa.sa_flags & SA_RESTORER) 226 if(ka->sa.sa_flags & SA_RESTORER)
219 restorer = ka->sa.sa_restorer; 227 restorer = ka->sa.sa_restorer;
220 228
229 /* Update SP now because the page fault handler refuses to extend
230 * the stack if the faulting address is too far below the current
231 * SP, which frame now certainly is. If there's an error, the original
232 * value is restored on the way out.
233 * When writing the sigcontext to the stack, we have to write the
234 * original value, so that's passed to copy_sc_to_user, which does
235 * the right thing with it.
236 */
237 PT_REGS_SP(regs) = (unsigned long) frame;
238
221 err |= __put_user(restorer, &frame->pretcode); 239 err |= __put_user(restorer, &frame->pretcode);
222 err |= __put_user(sig, &frame->sig); 240 err |= __put_user(sig, &frame->sig);
223 err |= copy_sc_to_user(&frame->sc, NULL, regs); 241 err |= copy_sc_to_user(&frame->sc, NULL, regs, save_sp);
224 err |= __put_user(mask->sig[0], &frame->sc.oldmask); 242 err |= __put_user(mask->sig[0], &frame->sc.oldmask);
225 if (_NSIG_WORDS > 1) 243 if (_NSIG_WORDS > 1)
226 err |= __copy_to_user(&frame->extramask, &mask->sig[1], 244 err |= __copy_to_user(&frame->extramask, &mask->sig[1],
@@ -238,7 +256,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
238 err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); 256 err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));
239 257
240 if(err) 258 if(err)
241 return(err); 259 goto err;
242 260
243 PT_REGS_SP(regs) = (unsigned long) frame; 261 PT_REGS_SP(regs) = (unsigned long) frame;
244 PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; 262 PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
@@ -248,7 +266,11 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
248 266
249 if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) 267 if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
250 ptrace_notify(SIGTRAP); 268 ptrace_notify(SIGTRAP);
251 return(0); 269 return 0;
270
271err:
272 PT_REGS_SP(regs) = save_sp;
273 return err;
252} 274}
253 275
254int setup_signal_stack_si(unsigned long stack_top, int sig, 276int setup_signal_stack_si(unsigned long stack_top, int sig,
@@ -257,6 +279,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
257{ 279{
258 struct rt_sigframe __user *frame; 280 struct rt_sigframe __user *frame;
259 void *restorer; 281 void *restorer;
282 unsigned long save_sp = PT_REGS_SP(regs);
260 int err = 0; 283 int err = 0;
261 284
262 stack_top &= -8UL; 285 stack_top &= -8UL;
@@ -268,13 +291,16 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
268 if(ka->sa.sa_flags & SA_RESTORER) 291 if(ka->sa.sa_flags & SA_RESTORER)
269 restorer = ka->sa.sa_restorer; 292 restorer = ka->sa.sa_restorer;
270 293
294 /* See comment above about why this is here */
295 PT_REGS_SP(regs) = (unsigned long) frame;
296
271 err |= __put_user(restorer, &frame->pretcode); 297 err |= __put_user(restorer, &frame->pretcode);
272 err |= __put_user(sig, &frame->sig); 298 err |= __put_user(sig, &frame->sig);
273 err |= __put_user(&frame->info, &frame->pinfo); 299 err |= __put_user(&frame->info, &frame->pinfo);
274 err |= __put_user(&frame->uc, &frame->puc); 300 err |= __put_user(&frame->uc, &frame->puc);
275 err |= copy_siginfo_to_user(&frame->info, info); 301 err |= copy_siginfo_to_user(&frame->info, info);
276 err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask, 302 err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
277 PT_REGS_SP(regs)); 303 save_sp);
278 304
279 /* 305 /*
280 * This is movl $,%eax ; int $0x80 306 * This is movl $,%eax ; int $0x80
@@ -288,9 +314,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
288 err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); 314 err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));
289 315
290 if(err) 316 if(err)
291 return(err); 317 goto err;
292 318
293 PT_REGS_SP(regs) = (unsigned long) frame;
294 PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; 319 PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
295 PT_REGS_EAX(regs) = (unsigned long) sig; 320 PT_REGS_EAX(regs) = (unsigned long) sig;
296 PT_REGS_EDX(regs) = (unsigned long) &frame->info; 321 PT_REGS_EDX(regs) = (unsigned long) &frame->info;
@@ -298,7 +323,11 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
298 323
299 if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) 324 if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
300 ptrace_notify(SIGTRAP); 325 ptrace_notify(SIGTRAP);
301 return(0); 326 return 0;
327
328err:
329 PT_REGS_SP(regs) = save_sp;
330 return err;
302} 331}
303 332
304long sys_sigreturn(struct pt_regs regs) 333long sys_sigreturn(struct pt_regs regs)
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index fe1d065332b1..e75c4e1838b0 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -55,7 +55,8 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
55} 55}
56 56
57int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, 57int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
58 struct pt_regs *regs, unsigned long mask) 58 struct pt_regs *regs, unsigned long mask,
59 unsigned long sp)
59{ 60{
60 struct faultinfo * fi = &current->thread.arch.faultinfo; 61 struct faultinfo * fi = &current->thread.arch.faultinfo;
61 int err = 0; 62 int err = 0;
@@ -70,7 +71,11 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
70 err |= PUTREG(regs, RDI, to, rdi); 71 err |= PUTREG(regs, RDI, to, rdi);
71 err |= PUTREG(regs, RSI, to, rsi); 72 err |= PUTREG(regs, RSI, to, rsi);
72 err |= PUTREG(regs, RBP, to, rbp); 73 err |= PUTREG(regs, RBP, to, rbp);
73 err |= PUTREG(regs, RSP, to, rsp); 74 /* Must use orignal RSP, which is passed in, rather than what's in
75 * the pt_regs, because that's already been updated to point at the
76 * signal frame.
77 */
78 err |= __put_user(sp, &to->rsp);
74 err |= PUTREG(regs, RBX, to, rbx); 79 err |= PUTREG(regs, RBX, to, rbx);
75 err |= PUTREG(regs, RDX, to, rdx); 80 err |= PUTREG(regs, RDX, to, rdx);
76 err |= PUTREG(regs, RCX, to, rcx); 81 err |= PUTREG(regs, RCX, to, rcx);
@@ -102,7 +107,7 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
102 107
103#ifdef CONFIG_MODE_TT 108#ifdef CONFIG_MODE_TT
104int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from, 109int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
105 int fpsize) 110 int fpsize)
106{ 111{
107 struct _fpstate *to_fp, *from_fp; 112 struct _fpstate *to_fp, *from_fp;
108 unsigned long sigs; 113 unsigned long sigs;
@@ -120,7 +125,7 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
120} 125}
121 126
122int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, 127int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
123 struct sigcontext *from, int fpsize) 128 struct sigcontext *from, int fpsize, unsigned long sp)
124{ 129{
125 struct _fpstate *to_fp, *from_fp; 130 struct _fpstate *to_fp, *from_fp;
126 int err; 131 int err;
@@ -128,11 +133,17 @@ int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
128 to_fp = (fp ? fp : (struct _fpstate *) (to + 1)); 133 to_fp = (fp ? fp : (struct _fpstate *) (to + 1));
129 from_fp = from->fpstate; 134 from_fp = from->fpstate;
130 err = copy_to_user(to, from, sizeof(*to)); 135 err = copy_to_user(to, from, sizeof(*to));
136 /* The SP in the sigcontext is the updated one for the signal
137 * delivery. The sp passed in is the original, and this needs
138 * to be restored, so we stick it in separately.
139 */
140 err |= copy_to_user(&SC_SP(to), sp, sizeof(sp));
141
131 if(from_fp != NULL){ 142 if(from_fp != NULL){
132 err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); 143 err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
133 err |= copy_to_user(to_fp, from_fp, fpsize); 144 err |= copy_to_user(to_fp, from_fp, fpsize);
134 } 145 }
135 return(err); 146 return err;
136} 147}
137 148
138#endif 149#endif
@@ -148,11 +159,12 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from)
148} 159}
149 160
150static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp, 161static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp,
151 struct pt_regs *from, unsigned long mask) 162 struct pt_regs *from, unsigned long mask,
163 unsigned long sp)
152{ 164{
153 return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), 165 return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
154 sizeof(*fp)), 166 sizeof(*fp), sp),
155 copy_sc_to_user_skas(to, fp, from, mask))); 167 copy_sc_to_user_skas(to, fp, from, mask, sp)));
156} 168}
157 169
158struct rt_sigframe 170struct rt_sigframe
@@ -170,6 +182,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
170{ 182{
171 struct rt_sigframe __user *frame; 183 struct rt_sigframe __user *frame;
172 struct _fpstate __user *fp = NULL; 184 struct _fpstate __user *fp = NULL;
185 unsigned long save_sp = PT_REGS_RSP(regs);
173 int err = 0; 186 int err = 0;
174 struct task_struct *me = current; 187 struct task_struct *me = current;
175 188
@@ -193,14 +206,25 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
193 goto out; 206 goto out;
194 } 207 }
195 208
209 /* Update SP now because the page fault handler refuses to extend
210 * the stack if the faulting address is too far below the current
211 * SP, which frame now certainly is. If there's an error, the original
212 * value is restored on the way out.
213 * When writing the sigcontext to the stack, we have to write the
214 * original value, so that's passed to copy_sc_to_user, which does
215 * the right thing with it.
216 */
217 PT_REGS_RSP(regs) = (unsigned long) frame;
218
196 /* Create the ucontext. */ 219 /* Create the ucontext. */
197 err |= __put_user(0, &frame->uc.uc_flags); 220 err |= __put_user(0, &frame->uc.uc_flags);
198 err |= __put_user(0, &frame->uc.uc_link); 221 err |= __put_user(0, &frame->uc.uc_link);
199 err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); 222 err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
200 err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)), 223 err |= __put_user(sas_ss_flags(save_sp),
201 &frame->uc.uc_stack.ss_flags); 224 &frame->uc.uc_stack.ss_flags);
202 err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); 225 err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
203 err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); 226 err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0],
227 save_sp);
204 err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); 228 err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate);
205 if (sizeof(*set) == 16) { 229 if (sizeof(*set) == 16) {
206 __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); 230 __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
@@ -217,10 +241,10 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
217 err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); 241 err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
218 else 242 else
219 /* could use a vstub here */ 243 /* could use a vstub here */
220 goto out; 244 goto restore_sp;
221 245
222 if (err) 246 if (err)
223 goto out; 247 goto restore_sp;
224 248
225 /* Set up registers for signal handler */ 249 /* Set up registers for signal handler */
226 { 250 {
@@ -238,10 +262,12 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
238 PT_REGS_RSI(regs) = (unsigned long) &frame->info; 262 PT_REGS_RSI(regs) = (unsigned long) &frame->info;
239 PT_REGS_RDX(regs) = (unsigned long) &frame->uc; 263 PT_REGS_RDX(regs) = (unsigned long) &frame->uc;
240 PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; 264 PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;
241
242 PT_REGS_RSP(regs) = (unsigned long) frame;
243 out: 265 out:
244 return(err); 266 return err;
267
268restore_sp:
269 PT_REGS_RSP(regs) = save_sp;
270 return err;
245} 271}
246 272
247long sys_rt_sigreturn(struct pt_regs *regs) 273long sys_rt_sigreturn(struct pt_regs *regs)