diff options
Diffstat (limited to 'arch/um/sys-i386/signal.c')
-rw-r--r-- | arch/um/sys-i386/signal.c | 409 |
1 files changed, 257 insertions, 152 deletions
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c index 1cbf95f6858a..0147227ce18d 100644 --- a/arch/um/sys-i386/signal.c +++ b/arch/um/sys-i386/signal.c | |||
@@ -1,189 +1,293 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/signal.h" | ||
7 | #include "linux/ptrace.h" | 6 | #include "linux/ptrace.h" |
8 | #include "asm/current.h" | ||
9 | #include "asm/ucontext.h" | ||
10 | #include "asm/uaccess.h" | ||
11 | #include "asm/unistd.h" | 7 | #include "asm/unistd.h" |
8 | #include "asm/uaccess.h" | ||
9 | #include "asm/ucontext.h" | ||
12 | #include "frame_kern.h" | 10 | #include "frame_kern.h" |
13 | #include "sigcontext.h" | ||
14 | #include "registers.h" | ||
15 | #include "mode.h" | ||
16 | |||
17 | #ifdef CONFIG_MODE_SKAS | ||
18 | |||
19 | #include "skas.h" | 11 | #include "skas.h" |
20 | 12 | ||
21 | void copy_sc(union uml_pt_regs *regs, void *from) | 13 | void copy_sc(struct uml_pt_regs *regs, void *from) |
22 | { | 14 | { |
23 | struct sigcontext *sc = from; | 15 | struct sigcontext *sc = from; |
24 | 16 | ||
25 | REGS_GS(regs->skas.regs) = sc->gs; | 17 | REGS_GS(regs->gp) = sc->gs; |
26 | REGS_FS(regs->skas.regs) = sc->fs; | 18 | REGS_FS(regs->gp) = sc->fs; |
27 | REGS_ES(regs->skas.regs) = sc->es; | 19 | REGS_ES(regs->gp) = sc->es; |
28 | REGS_DS(regs->skas.regs) = sc->ds; | 20 | REGS_DS(regs->gp) = sc->ds; |
29 | REGS_EDI(regs->skas.regs) = sc->edi; | 21 | REGS_EDI(regs->gp) = sc->edi; |
30 | REGS_ESI(regs->skas.regs) = sc->esi; | 22 | REGS_ESI(regs->gp) = sc->esi; |
31 | REGS_EBP(regs->skas.regs) = sc->ebp; | 23 | REGS_EBP(regs->gp) = sc->ebp; |
32 | REGS_SP(regs->skas.regs) = sc->esp; | 24 | REGS_SP(regs->gp) = sc->esp; |
33 | REGS_EBX(regs->skas.regs) = sc->ebx; | 25 | REGS_EBX(regs->gp) = sc->ebx; |
34 | REGS_EDX(regs->skas.regs) = sc->edx; | 26 | REGS_EDX(regs->gp) = sc->edx; |
35 | REGS_ECX(regs->skas.regs) = sc->ecx; | 27 | REGS_ECX(regs->gp) = sc->ecx; |
36 | REGS_EAX(regs->skas.regs) = sc->eax; | 28 | REGS_EAX(regs->gp) = sc->eax; |
37 | REGS_IP(regs->skas.regs) = sc->eip; | 29 | REGS_IP(regs->gp) = sc->eip; |
38 | REGS_CS(regs->skas.regs) = sc->cs; | 30 | REGS_CS(regs->gp) = sc->cs; |
39 | REGS_EFLAGS(regs->skas.regs) = sc->eflags; | 31 | REGS_EFLAGS(regs->gp) = sc->eflags; |
40 | REGS_SS(regs->skas.regs) = sc->ss; | 32 | REGS_SS(regs->gp) = sc->ss; |
41 | } | 33 | } |
42 | 34 | ||
43 | static int copy_sc_from_user_skas(struct pt_regs *regs, | 35 | /* |
44 | struct sigcontext __user *from) | 36 | * FPU tag word conversions. |
37 | */ | ||
38 | |||
39 | static inline unsigned short twd_i387_to_fxsr(unsigned short twd) | ||
45 | { | 40 | { |
46 | struct sigcontext sc; | 41 | unsigned int tmp; /* to avoid 16 bit prefixes in the code */ |
47 | unsigned long fpregs[HOST_FP_SIZE]; | 42 | |
48 | int err; | 43 | /* Transform each pair of bits into 01 (valid) or 00 (empty) */ |
44 | tmp = ~twd; | ||
45 | tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ | ||
46 | /* and move the valid bits to the lower byte. */ | ||
47 | tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ | ||
48 | tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ | ||
49 | tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ | ||
50 | return tmp; | ||
51 | } | ||
49 | 52 | ||
50 | err = copy_from_user(&sc, from, sizeof(sc)); | 53 | static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave) |
51 | err |= copy_from_user(fpregs, sc.fpstate, sizeof(fpregs)); | 54 | { |
52 | if(err) | 55 | struct _fpxreg *st = NULL; |
53 | return err; | 56 | unsigned long twd = (unsigned long) fxsave->twd; |
57 | unsigned long tag; | ||
58 | unsigned long ret = 0xffff0000; | ||
59 | int i; | ||
60 | |||
61 | #define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16); | ||
62 | |||
63 | for (i = 0; i < 8; i++) { | ||
64 | if (twd & 0x1) { | ||
65 | st = (struct _fpxreg *) FPREG_ADDR(fxsave, i); | ||
66 | |||
67 | switch (st->exponent & 0x7fff) { | ||
68 | case 0x7fff: | ||
69 | tag = 2; /* Special */ | ||
70 | break; | ||
71 | case 0x0000: | ||
72 | if ( !st->significand[0] && | ||
73 | !st->significand[1] && | ||
74 | !st->significand[2] && | ||
75 | !st->significand[3] ) { | ||
76 | tag = 1; /* Zero */ | ||
77 | } else { | ||
78 | tag = 2; /* Special */ | ||
79 | } | ||
80 | break; | ||
81 | default: | ||
82 | if (st->significand[3] & 0x8000) { | ||
83 | tag = 0; /* Valid */ | ||
84 | } else { | ||
85 | tag = 2; /* Special */ | ||
86 | } | ||
87 | break; | ||
88 | } | ||
89 | } else { | ||
90 | tag = 3; /* Empty */ | ||
91 | } | ||
92 | ret |= (tag << (2 * i)); | ||
93 | twd = twd >> 1; | ||
94 | } | ||
95 | return ret; | ||
96 | } | ||
54 | 97 | ||
55 | copy_sc(®s->regs, &sc); | 98 | static int convert_fxsr_to_user(struct _fpstate __user *buf, |
99 | struct user_fxsr_struct *fxsave) | ||
100 | { | ||
101 | unsigned long env[7]; | ||
102 | struct _fpreg __user *to; | ||
103 | struct _fpxreg *from; | ||
104 | int i; | ||
105 | |||
106 | env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul; | ||
107 | env[1] = (unsigned long)fxsave->swd | 0xffff0000ul; | ||
108 | env[2] = twd_fxsr_to_i387(fxsave); | ||
109 | env[3] = fxsave->fip; | ||
110 | env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16); | ||
111 | env[5] = fxsave->foo; | ||
112 | env[6] = fxsave->fos; | ||
113 | |||
114 | if (__copy_to_user(buf, env, 7 * sizeof(unsigned long))) | ||
115 | return 1; | ||
56 | 116 | ||
57 | err = restore_fp_registers(userspace_pid[0], fpregs); | 117 | to = &buf->_st[0]; |
58 | if(err < 0) { | 118 | from = (struct _fpxreg *) &fxsave->st_space[0]; |
59 | printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, " | 119 | for (i = 0; i < 8; i++, to++, from++) { |
60 | "errno = %d\n", -err); | 120 | unsigned long __user *t = (unsigned long __user *)to; |
61 | return err; | 121 | unsigned long *f = (unsigned long *)from; |
62 | } | ||
63 | 122 | ||
123 | if (__put_user(*f, t) || | ||
124 | __put_user(*(f + 1), t + 1) || | ||
125 | __put_user(from->exponent, &to->exponent)) | ||
126 | return 1; | ||
127 | } | ||
64 | return 0; | 128 | return 0; |
65 | } | 129 | } |
66 | 130 | ||
67 | int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp, | 131 | static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave, |
68 | struct pt_regs *regs, unsigned long sp) | 132 | struct _fpstate __user *buf) |
69 | { | 133 | { |
70 | struct sigcontext sc; | 134 | unsigned long env[7]; |
71 | unsigned long fpregs[HOST_FP_SIZE]; | 135 | struct _fpxreg *to; |
72 | struct faultinfo * fi = ¤t->thread.arch.faultinfo; | 136 | struct _fpreg __user *from; |
73 | int err; | 137 | int i; |
74 | 138 | ||
75 | sc.gs = REGS_GS(regs->regs.skas.regs); | 139 | if (copy_from_user( env, buf, 7 * sizeof(long))) |
76 | sc.fs = REGS_FS(regs->regs.skas.regs); | ||
77 | sc.es = REGS_ES(regs->regs.skas.regs); | ||
78 | sc.ds = REGS_DS(regs->regs.skas.regs); | ||
79 | sc.edi = REGS_EDI(regs->regs.skas.regs); | ||
80 | sc.esi = REGS_ESI(regs->regs.skas.regs); | ||
81 | sc.ebp = REGS_EBP(regs->regs.skas.regs); | ||
82 | sc.esp = sp; | ||
83 | sc.ebx = REGS_EBX(regs->regs.skas.regs); | ||
84 | sc.edx = REGS_EDX(regs->regs.skas.regs); | ||
85 | sc.ecx = REGS_ECX(regs->regs.skas.regs); | ||
86 | sc.eax = REGS_EAX(regs->regs.skas.regs); | ||
87 | sc.eip = REGS_IP(regs->regs.skas.regs); | ||
88 | sc.cs = REGS_CS(regs->regs.skas.regs); | ||
89 | sc.eflags = REGS_EFLAGS(regs->regs.skas.regs); | ||
90 | sc.esp_at_signal = regs->regs.skas.regs[UESP]; | ||
91 | sc.ss = regs->regs.skas.regs[SS]; | ||
92 | sc.cr2 = fi->cr2; | ||
93 | sc.err = fi->error_code; | ||
94 | sc.trapno = fi->trap_no; | ||
95 | |||
96 | err = save_fp_registers(userspace_pid[0], fpregs); | ||
97 | if(err < 0){ | ||
98 | printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, " | ||
99 | "errno = %d\n", err); | ||
100 | return 1; | 140 | return 1; |
101 | } | ||
102 | to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); | ||
103 | sc.fpstate = to_fp; | ||
104 | 141 | ||
105 | if(err) | 142 | fxsave->cwd = (unsigned short)(env[0] & 0xffff); |
106 | return err; | 143 | fxsave->swd = (unsigned short)(env[1] & 0xffff); |
107 | 144 | fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff)); | |
108 | return copy_to_user(to, &sc, sizeof(sc)) || | 145 | fxsave->fip = env[3]; |
109 | copy_to_user(to_fp, fpregs, sizeof(fpregs)); | 146 | fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16); |
147 | fxsave->fcs = (env[4] & 0xffff); | ||
148 | fxsave->foo = env[5]; | ||
149 | fxsave->fos = env[6]; | ||
150 | |||
151 | to = (struct _fpxreg *) &fxsave->st_space[0]; | ||
152 | from = &buf->_st[0]; | ||
153 | for (i = 0; i < 8; i++, to++, from++) { | ||
154 | unsigned long *t = (unsigned long *)to; | ||
155 | unsigned long __user *f = (unsigned long __user *)from; | ||
156 | |||
157 | if (__get_user(*t, f) || | ||
158 | __get_user(*(t + 1), f + 1) || | ||
159 | __get_user(to->exponent, &from->exponent)) | ||
160 | return 1; | ||
161 | } | ||
162 | return 0; | ||
110 | } | 163 | } |
111 | #endif | ||
112 | 164 | ||
113 | #ifdef CONFIG_MODE_TT | 165 | extern int have_fpx_regs; |
114 | 166 | ||
115 | /* These copy a sigcontext to/from userspace. They copy the fpstate pointer, | 167 | static int copy_sc_from_user(struct pt_regs *regs, |
116 | * blowing away the old, good one. So, that value is saved, and then restored | 168 | struct sigcontext __user *from) |
117 | * after the sigcontext copy. In copy_from, the variable holding the saved | ||
118 | * fpstate pointer, and the sigcontext that it should be restored to are both | ||
119 | * in the kernel, so we can just restore using an assignment. In copy_to, the | ||
120 | * saved pointer is in the kernel, but the sigcontext is in userspace, so we | ||
121 | * copy_to_user it. | ||
122 | */ | ||
123 | int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from, | ||
124 | int fpsize) | ||
125 | { | 169 | { |
126 | struct _fpstate *to_fp; | 170 | struct sigcontext sc; |
127 | struct _fpstate __user *from_fp; | ||
128 | unsigned long sigs; | ||
129 | int err; | 171 | int err; |
130 | 172 | ||
131 | to_fp = to->fpstate; | 173 | err = copy_from_user(&sc, from, sizeof(sc)); |
132 | sigs = to->oldmask; | 174 | if (err) |
133 | err = copy_from_user(to, from, sizeof(*to)); | 175 | return err; |
134 | from_fp = to->fpstate; | 176 | |
135 | to->oldmask = sigs; | 177 | copy_sc(®s->regs, &sc); |
136 | to->fpstate = to_fp; | 178 | if (have_fpx_regs) { |
137 | if(to_fp != NULL) | 179 | struct user_fxsr_struct fpx; |
138 | err |= copy_from_user(to_fp, from_fp, fpsize); | 180 | |
139 | return err; | 181 | err = copy_from_user(&fpx, &sc.fpstate->_fxsr_env[0], |
182 | sizeof(struct user_fxsr_struct)); | ||
183 | if (err) | ||
184 | return 1; | ||
185 | |||
186 | err = convert_fxsr_from_user(&fpx, sc.fpstate); | ||
187 | if (err) | ||
188 | return 1; | ||
189 | |||
190 | err = restore_fpx_registers(userspace_pid[current_thread->cpu], | ||
191 | (unsigned long *) &fpx); | ||
192 | if (err < 0) { | ||
193 | printk(KERN_ERR "copy_sc_from_user - " | ||
194 | "restore_fpx_registers failed, errno = %d\n", | ||
195 | -err); | ||
196 | return 1; | ||
197 | } | ||
198 | } | ||
199 | else { | ||
200 | struct user_i387_struct fp; | ||
201 | |||
202 | err = copy_from_user(&fp, sc.fpstate, | ||
203 | sizeof(struct user_i387_struct)); | ||
204 | if (err) | ||
205 | return 1; | ||
206 | |||
207 | err = restore_fp_registers(userspace_pid[current_thread->cpu], | ||
208 | (unsigned long *) &fp); | ||
209 | if (err < 0) { | ||
210 | printk(KERN_ERR "copy_sc_from_user - " | ||
211 | "restore_fp_registers failed, errno = %d\n", | ||
212 | -err); | ||
213 | return 1; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | return 0; | ||
140 | } | 218 | } |
141 | 219 | ||
142 | int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp, | 220 | static int copy_sc_to_user(struct sigcontext __user *to, |
143 | struct sigcontext *from, int fpsize, unsigned long sp) | 221 | struct _fpstate __user *to_fp, struct pt_regs *regs, |
222 | unsigned long sp) | ||
144 | { | 223 | { |
145 | struct _fpstate __user *to_fp; | 224 | struct sigcontext sc; |
146 | struct _fpstate *from_fp; | 225 | struct faultinfo * fi = ¤t->thread.arch.faultinfo; |
147 | int err; | 226 | int err; |
148 | 227 | ||
149 | to_fp = (fp ? fp : (struct _fpstate __user *) (to + 1)); | 228 | sc.gs = REGS_GS(regs->regs.gp); |
150 | from_fp = from->fpstate; | 229 | sc.fs = REGS_FS(regs->regs.gp); |
151 | err = copy_to_user(to, from, sizeof(*to)); | 230 | sc.es = REGS_ES(regs->regs.gp); |
231 | sc.ds = REGS_DS(regs->regs.gp); | ||
232 | sc.edi = REGS_EDI(regs->regs.gp); | ||
233 | sc.esi = REGS_ESI(regs->regs.gp); | ||
234 | sc.ebp = REGS_EBP(regs->regs.gp); | ||
235 | sc.esp = sp; | ||
236 | sc.ebx = REGS_EBX(regs->regs.gp); | ||
237 | sc.edx = REGS_EDX(regs->regs.gp); | ||
238 | sc.ecx = REGS_ECX(regs->regs.gp); | ||
239 | sc.eax = REGS_EAX(regs->regs.gp); | ||
240 | sc.eip = REGS_IP(regs->regs.gp); | ||
241 | sc.cs = REGS_CS(regs->regs.gp); | ||
242 | sc.eflags = REGS_EFLAGS(regs->regs.gp); | ||
243 | sc.esp_at_signal = regs->regs.gp[UESP]; | ||
244 | sc.ss = regs->regs.gp[SS]; | ||
245 | sc.cr2 = fi->cr2; | ||
246 | sc.err = fi->error_code; | ||
247 | sc.trapno = fi->trap_no; | ||
152 | 248 | ||
153 | /* The SP in the sigcontext is the updated one for the signal | 249 | to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); |
154 | * delivery. The sp passed in is the original, and this needs | 250 | sc.fpstate = to_fp; |
155 | * to be restored, so we stick it in separately. | ||
156 | */ | ||
157 | err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp)); | ||
158 | 251 | ||
159 | if(from_fp != NULL){ | 252 | if (have_fpx_regs) { |
160 | err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); | 253 | struct user_fxsr_struct fpx; |
161 | err |= copy_to_user(to_fp, from_fp, fpsize); | 254 | |
255 | err = save_fpx_registers(userspace_pid[current_thread->cpu], | ||
256 | (unsigned long *) &fpx); | ||
257 | if (err < 0){ | ||
258 | printk(KERN_ERR "copy_sc_to_user - save_fpx_registers " | ||
259 | "failed, errno = %d\n", err); | ||
260 | return 1; | ||
261 | } | ||
262 | |||
263 | err = convert_fxsr_to_user(to_fp, &fpx); | ||
264 | if (err) | ||
265 | return 1; | ||
266 | |||
267 | err |= __put_user(fpx.swd, &to_fp->status); | ||
268 | err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic); | ||
269 | if (err) | ||
270 | return 1; | ||
271 | |||
272 | if (copy_to_user(&to_fp->_fxsr_env[0], &fpx, | ||
273 | sizeof(struct user_fxsr_struct))) | ||
274 | return 1; | ||
162 | } | 275 | } |
163 | return err; | 276 | else { |
164 | } | 277 | struct user_i387_struct fp; |
165 | #endif | ||
166 | |||
167 | static int copy_sc_from_user(struct pt_regs *to, void __user *from) | ||
168 | { | ||
169 | int ret; | ||
170 | 278 | ||
171 | ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, | 279 | err = save_fp_registers(userspace_pid[current_thread->cpu], |
172 | sizeof(struct _fpstate)), | 280 | (unsigned long *) &fp); |
173 | copy_sc_from_user_skas(to, from)); | 281 | if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct))) |
174 | return ret; | 282 | return 1; |
175 | } | 283 | } |
176 | 284 | ||
177 | static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp, | 285 | return copy_to_user(to, &sc, sizeof(sc)); |
178 | struct pt_regs *from, unsigned long sp) | ||
179 | { | ||
180 | return CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), | ||
181 | sizeof(*fp), sp), | ||
182 | copy_sc_to_user_skas(to, fp, from, sp)); | ||
183 | } | 286 | } |
184 | 287 | ||
185 | static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp, | 288 | static int copy_ucontext_to_user(struct ucontext __user *uc, |
186 | sigset_t *set, unsigned long sp) | 289 | struct _fpstate __user *fp, sigset_t *set, |
290 | unsigned long sp) | ||
187 | { | 291 | { |
188 | int err = 0; | 292 | int err = 0; |
189 | 293 | ||
@@ -233,7 +337,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, | |||
233 | return 1; | 337 | return 1; |
234 | 338 | ||
235 | restorer = frame->retcode; | 339 | restorer = frame->retcode; |
236 | if(ka->sa.sa_flags & SA_RESTORER) | 340 | if (ka->sa.sa_flags & SA_RESTORER) |
237 | restorer = ka->sa.sa_restorer; | 341 | restorer = ka->sa.sa_restorer; |
238 | 342 | ||
239 | /* Update SP now because the page fault handler refuses to extend | 343 | /* Update SP now because the page fault handler refuses to extend |
@@ -265,7 +369,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, | |||
265 | err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2)); | 369 | err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2)); |
266 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); | 370 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); |
267 | 371 | ||
268 | if(err) | 372 | if (err) |
269 | goto err; | 373 | goto err; |
270 | 374 | ||
271 | PT_REGS_SP(regs) = (unsigned long) frame; | 375 | PT_REGS_SP(regs) = (unsigned long) frame; |
@@ -298,7 +402,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
298 | return 1; | 402 | return 1; |
299 | 403 | ||
300 | restorer = frame->retcode; | 404 | restorer = frame->retcode; |
301 | if(ka->sa.sa_flags & SA_RESTORER) | 405 | if (ka->sa.sa_flags & SA_RESTORER) |
302 | restorer = ka->sa.sa_restorer; | 406 | restorer = ka->sa.sa_restorer; |
303 | 407 | ||
304 | /* See comment above about why this is here */ | 408 | /* See comment above about why this is here */ |
@@ -323,7 +427,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
323 | err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1)); | 427 | err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1)); |
324 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); | 428 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); |
325 | 429 | ||
326 | if(err) | 430 | if (err) |
327 | goto err; | 431 | goto err; |
328 | 432 | ||
329 | PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; | 433 | PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; |
@@ -350,8 +454,8 @@ long sys_sigreturn(struct pt_regs regs) | |||
350 | unsigned long __user *extramask = frame->extramask; | 454 | unsigned long __user *extramask = frame->extramask; |
351 | int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); | 455 | int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); |
352 | 456 | ||
353 | if(copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) || | 457 | if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) || |
354 | copy_from_user(&set.sig[1], extramask, sig_size)) | 458 | copy_from_user(&set.sig[1], extramask, sig_size)) |
355 | goto segfault; | 459 | goto segfault; |
356 | 460 | ||
357 | sigdelsetmask(&set, ~_BLOCKABLE); | 461 | sigdelsetmask(&set, ~_BLOCKABLE); |
@@ -361,7 +465,7 @@ long sys_sigreturn(struct pt_regs regs) | |||
361 | recalc_sigpending(); | 465 | recalc_sigpending(); |
362 | spin_unlock_irq(¤t->sighand->siglock); | 466 | spin_unlock_irq(¤t->sighand->siglock); |
363 | 467 | ||
364 | if(copy_sc_from_user(¤t->thread.regs, sc)) | 468 | if (copy_sc_from_user(¤t->thread.regs, sc)) |
365 | goto segfault; | 469 | goto segfault; |
366 | 470 | ||
367 | /* Avoid ERESTART handling */ | 471 | /* Avoid ERESTART handling */ |
@@ -376,12 +480,13 @@ long sys_sigreturn(struct pt_regs regs) | |||
376 | long sys_rt_sigreturn(struct pt_regs regs) | 480 | long sys_rt_sigreturn(struct pt_regs regs) |
377 | { | 481 | { |
378 | unsigned long sp = PT_REGS_SP(¤t->thread.regs); | 482 | unsigned long sp = PT_REGS_SP(¤t->thread.regs); |
379 | struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (sp - 4); | 483 | struct rt_sigframe __user *frame = |
484 | (struct rt_sigframe __user *) (sp - 4); | ||
380 | sigset_t set; | 485 | sigset_t set; |
381 | struct ucontext __user *uc = &frame->uc; | 486 | struct ucontext __user *uc = &frame->uc; |
382 | int sig_size = _NSIG_WORDS * sizeof(unsigned long); | 487 | int sig_size = _NSIG_WORDS * sizeof(unsigned long); |
383 | 488 | ||
384 | if(copy_from_user(&set, &uc->uc_sigmask, sig_size)) | 489 | if (copy_from_user(&set, &uc->uc_sigmask, sig_size)) |
385 | goto segfault; | 490 | goto segfault; |
386 | 491 | ||
387 | sigdelsetmask(&set, ~_BLOCKABLE); | 492 | sigdelsetmask(&set, ~_BLOCKABLE); |
@@ -391,7 +496,7 @@ long sys_rt_sigreturn(struct pt_regs regs) | |||
391 | recalc_sigpending(); | 496 | recalc_sigpending(); |
392 | spin_unlock_irq(¤t->sighand->siglock); | 497 | spin_unlock_irq(¤t->sighand->siglock); |
393 | 498 | ||
394 | if(copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) | 499 | if (copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) |
395 | goto segfault; | 500 | goto segfault; |
396 | 501 | ||
397 | /* Avoid ERESTART handling */ | 502 | /* Avoid ERESTART handling */ |