diff options
Diffstat (limited to 'arch/x86/kernel/signal_32.c')
-rw-r--r-- | arch/x86/kernel/signal_32.c | 303 |
1 files changed, 154 insertions, 149 deletions
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 0157a6f0f41f..f1b117930837 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c | |||
@@ -4,32 +4,44 @@ | |||
4 | * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson | 4 | * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson |
5 | * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes | 5 | * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes |
6 | */ | 6 | */ |
7 | #include <linux/list.h> | ||
7 | 8 | ||
8 | #include <linux/sched.h> | 9 | #include <linux/personality.h> |
9 | #include <linux/mm.h> | 10 | #include <linux/binfmts.h> |
10 | #include <linux/smp.h> | 11 | #include <linux/suspend.h> |
11 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/ptrace.h> | ||
12 | #include <linux/signal.h> | 14 | #include <linux/signal.h> |
15 | #include <linux/stddef.h> | ||
16 | #include <linux/unistd.h> | ||
13 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
18 | #include <linux/sched.h> | ||
14 | #include <linux/wait.h> | 19 | #include <linux/wait.h> |
15 | #include <linux/unistd.h> | ||
16 | #include <linux/stddef.h> | ||
17 | #include <linux/personality.h> | ||
18 | #include <linux/suspend.h> | ||
19 | #include <linux/ptrace.h> | ||
20 | #include <linux/elf.h> | 20 | #include <linux/elf.h> |
21 | #include <linux/binfmts.h> | 21 | #include <linux/smp.h> |
22 | #include <linux/mm.h> | ||
23 | |||
22 | #include <asm/processor.h> | 24 | #include <asm/processor.h> |
23 | #include <asm/ucontext.h> | 25 | #include <asm/ucontext.h> |
24 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
25 | #include <asm/i387.h> | 27 | #include <asm/i387.h> |
26 | #include <asm/vdso.h> | 28 | #include <asm/vdso.h> |
27 | #include "sigframe_32.h" | ||
28 | 29 | ||
29 | #define DEBUG_SIG 0 | 30 | #include "sigframe.h" |
30 | 31 | ||
31 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 32 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
32 | 33 | ||
34 | #define __FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \ | ||
35 | X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \ | ||
36 | X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \ | ||
37 | X86_EFLAGS_CF) | ||
38 | |||
39 | #ifdef CONFIG_X86_32 | ||
40 | # define FIX_EFLAGS (__FIX_EFLAGS | X86_EFLAGS_RF) | ||
41 | #else | ||
42 | # define FIX_EFLAGS __FIX_EFLAGS | ||
43 | #endif | ||
44 | |||
33 | /* | 45 | /* |
34 | * Atomically swap in the new signal mask, and wait for a signal. | 46 | * Atomically swap in the new signal mask, and wait for a signal. |
35 | */ | 47 | */ |
@@ -46,10 +58,11 @@ sys_sigsuspend(int history0, int history1, old_sigset_t mask) | |||
46 | current->state = TASK_INTERRUPTIBLE; | 58 | current->state = TASK_INTERRUPTIBLE; |
47 | schedule(); | 59 | schedule(); |
48 | set_thread_flag(TIF_RESTORE_SIGMASK); | 60 | set_thread_flag(TIF_RESTORE_SIGMASK); |
61 | |||
49 | return -ERESTARTNOHAND; | 62 | return -ERESTARTNOHAND; |
50 | } | 63 | } |
51 | 64 | ||
52 | asmlinkage int | 65 | asmlinkage int |
53 | sys_sigaction(int sig, const struct old_sigaction __user *act, | 66 | sys_sigaction(int sig, const struct old_sigaction __user *act, |
54 | struct old_sigaction __user *oact) | 67 | struct old_sigaction __user *oact) |
55 | { | 68 | { |
@@ -58,10 +71,12 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
58 | 71 | ||
59 | if (act) { | 72 | if (act) { |
60 | old_sigset_t mask; | 73 | old_sigset_t mask; |
74 | |||
61 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | 75 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || |
62 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | 76 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || |
63 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) | 77 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) |
64 | return -EFAULT; | 78 | return -EFAULT; |
79 | |||
65 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); | 80 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); |
66 | __get_user(mask, &act->sa_mask); | 81 | __get_user(mask, &act->sa_mask); |
67 | siginitset(&new_ka.sa.sa_mask, mask); | 82 | siginitset(&new_ka.sa.sa_mask, mask); |
@@ -74,6 +89,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
74 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | 89 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || |
75 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) | 90 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) |
76 | return -EFAULT; | 91 | return -EFAULT; |
92 | |||
77 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | 93 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); |
78 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | 94 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); |
79 | } | 95 | } |
@@ -81,10 +97,12 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
81 | return ret; | 97 | return ret; |
82 | } | 98 | } |
83 | 99 | ||
84 | asmlinkage int | 100 | asmlinkage int sys_sigaltstack(unsigned long bx) |
85 | sys_sigaltstack(unsigned long bx) | ||
86 | { | 101 | { |
87 | /* This is needed to make gcc realize it doesn't own the "struct pt_regs" */ | 102 | /* |
103 | * This is needed to make gcc realize it doesn't own the | ||
104 | * "struct pt_regs" | ||
105 | */ | ||
88 | struct pt_regs *regs = (struct pt_regs *)&bx; | 106 | struct pt_regs *regs = (struct pt_regs *)&bx; |
89 | const stack_t __user *uss = (const stack_t __user *)bx; | 107 | const stack_t __user *uss = (const stack_t __user *)bx; |
90 | stack_t __user *uoss = (stack_t __user *)regs->cx; | 108 | stack_t __user *uoss = (stack_t __user *)regs->cx; |
@@ -96,9 +114,9 @@ sys_sigaltstack(unsigned long bx) | |||
96 | /* | 114 | /* |
97 | * Do a signal return; undo the signal stack. | 115 | * Do a signal return; undo the signal stack. |
98 | */ | 116 | */ |
99 | |||
100 | static int | 117 | static int |
101 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax) | 118 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, |
119 | unsigned long *pax) | ||
102 | { | 120 | { |
103 | unsigned int err = 0; | 121 | unsigned int err = 0; |
104 | 122 | ||
@@ -120,37 +138,29 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax | |||
120 | #define GET_SEG(seg) \ | 138 | #define GET_SEG(seg) \ |
121 | { unsigned short tmp; \ | 139 | { unsigned short tmp; \ |
122 | err |= __get_user(tmp, &sc->seg); \ | 140 | err |= __get_user(tmp, &sc->seg); \ |
123 | loadsegment(seg,tmp); } | 141 | loadsegment(seg, tmp); } |
124 | |||
125 | #define FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_RF | \ | ||
126 | X86_EFLAGS_OF | X86_EFLAGS_DF | \ | ||
127 | X86_EFLAGS_TF | X86_EFLAGS_SF | X86_EFLAGS_ZF | \ | ||
128 | X86_EFLAGS_AF | X86_EFLAGS_PF | X86_EFLAGS_CF) | ||
129 | 142 | ||
130 | GET_SEG(gs); | 143 | GET_SEG(gs); |
131 | COPY_SEG(fs); | 144 | COPY_SEG(fs); |
132 | COPY_SEG(es); | 145 | COPY_SEG(es); |
133 | COPY_SEG(ds); | 146 | COPY_SEG(ds); |
134 | COPY(di); | 147 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); |
135 | COPY(si); | 148 | COPY(dx); COPY(cx); COPY(ip); |
136 | COPY(bp); | ||
137 | COPY(sp); | ||
138 | COPY(bx); | ||
139 | COPY(dx); | ||
140 | COPY(cx); | ||
141 | COPY(ip); | ||
142 | COPY_SEG_STRICT(cs); | 149 | COPY_SEG_STRICT(cs); |
143 | COPY_SEG_STRICT(ss); | 150 | COPY_SEG_STRICT(ss); |
144 | 151 | ||
145 | { | 152 | { |
146 | unsigned int tmpflags; | 153 | unsigned int tmpflags; |
154 | |||
147 | err |= __get_user(tmpflags, &sc->flags); | 155 | err |= __get_user(tmpflags, &sc->flags); |
148 | regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); | 156 | regs->flags = (regs->flags & ~FIX_EFLAGS) | |
157 | (tmpflags & FIX_EFLAGS); | ||
149 | regs->orig_ax = -1; /* disable syscall checks */ | 158 | regs->orig_ax = -1; /* disable syscall checks */ |
150 | } | 159 | } |
151 | 160 | ||
152 | { | 161 | { |
153 | struct _fpstate __user * buf; | 162 | struct _fpstate __user *buf; |
163 | |||
154 | err |= __get_user(buf, &sc->fpstate); | 164 | err |= __get_user(buf, &sc->fpstate); |
155 | if (buf) { | 165 | if (buf) { |
156 | if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) | 166 | if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) |
@@ -158,6 +168,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax | |||
158 | err |= restore_i387(buf); | 168 | err |= restore_i387(buf); |
159 | } else { | 169 | } else { |
160 | struct task_struct *me = current; | 170 | struct task_struct *me = current; |
171 | |||
161 | if (used_math()) { | 172 | if (used_math()) { |
162 | clear_fpu(me); | 173 | clear_fpu(me); |
163 | clear_used_math(); | 174 | clear_used_math(); |
@@ -165,24 +176,26 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax | |||
165 | } | 176 | } |
166 | } | 177 | } |
167 | 178 | ||
168 | err |= __get_user(*peax, &sc->ax); | 179 | err |= __get_user(*pax, &sc->ax); |
169 | return err; | 180 | return err; |
170 | 181 | ||
171 | badframe: | 182 | badframe: |
172 | return 1; | 183 | return 1; |
173 | } | 184 | } |
174 | 185 | ||
175 | asmlinkage int sys_sigreturn(unsigned long __unused) | 186 | asmlinkage unsigned long sys_sigreturn(unsigned long __unused) |
176 | { | 187 | { |
177 | struct pt_regs *regs = (struct pt_regs *) &__unused; | 188 | struct sigframe __user *frame; |
178 | struct sigframe __user *frame = (struct sigframe __user *)(regs->sp - 8); | 189 | struct pt_regs *regs; |
190 | unsigned long ax; | ||
179 | sigset_t set; | 191 | sigset_t set; |
180 | int ax; | 192 | |
193 | regs = (struct pt_regs *) &__unused; | ||
194 | frame = (struct sigframe __user *)(regs->sp - 8); | ||
181 | 195 | ||
182 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 196 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
183 | goto badframe; | 197 | goto badframe; |
184 | if (__get_user(set.sig[0], &frame->sc.oldmask) | 198 | if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1 |
185 | || (_NSIG_WORDS > 1 | ||
186 | && __copy_from_user(&set.sig[1], &frame->extramask, | 199 | && __copy_from_user(&set.sig[1], &frame->extramask, |
187 | sizeof(frame->extramask)))) | 200 | sizeof(frame->extramask)))) |
188 | goto badframe; | 201 | goto badframe; |
@@ -192,33 +205,35 @@ asmlinkage int sys_sigreturn(unsigned long __unused) | |||
192 | current->blocked = set; | 205 | current->blocked = set; |
193 | recalc_sigpending(); | 206 | recalc_sigpending(); |
194 | spin_unlock_irq(¤t->sighand->siglock); | 207 | spin_unlock_irq(¤t->sighand->siglock); |
195 | 208 | ||
196 | if (restore_sigcontext(regs, &frame->sc, &ax)) | 209 | if (restore_sigcontext(regs, &frame->sc, &ax)) |
197 | goto badframe; | 210 | goto badframe; |
198 | return ax; | 211 | return ax; |
199 | 212 | ||
200 | badframe: | 213 | badframe: |
201 | if (show_unhandled_signals && printk_ratelimit()) { | 214 | if (show_unhandled_signals && printk_ratelimit()) { |
202 | printk("%s%s[%d] bad frame in sigreturn frame:%p ip:%lx" | 215 | printk(KERN_INFO "%s%s[%d] bad frame in sigreturn frame:" |
203 | " sp:%lx oeax:%lx", | 216 | "%p ip:%lx sp:%lx oeax:%lx", |
204 | task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, | 217 | task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, |
205 | current->comm, task_pid_nr(current), frame, regs->ip, | 218 | current->comm, task_pid_nr(current), frame, regs->ip, |
206 | regs->sp, regs->orig_ax); | 219 | regs->sp, regs->orig_ax); |
207 | print_vma_addr(" in ", regs->ip); | 220 | print_vma_addr(" in ", regs->ip); |
208 | printk("\n"); | 221 | printk(KERN_CONT "\n"); |
209 | } | 222 | } |
210 | 223 | ||
211 | force_sig(SIGSEGV, current); | 224 | force_sig(SIGSEGV, current); |
225 | |||
212 | return 0; | 226 | return 0; |
213 | } | 227 | } |
214 | 228 | ||
215 | asmlinkage int sys_rt_sigreturn(unsigned long __unused) | 229 | asmlinkage int sys_rt_sigreturn(unsigned long __unused) |
216 | { | 230 | { |
217 | struct pt_regs *regs = (struct pt_regs *) &__unused; | 231 | struct pt_regs *regs = (struct pt_regs *)&__unused; |
218 | struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(regs->sp - 4); | 232 | struct rt_sigframe __user *frame; |
233 | unsigned long ax; | ||
219 | sigset_t set; | 234 | sigset_t set; |
220 | int ax; | ||
221 | 235 | ||
236 | frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long)); | ||
222 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 237 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
223 | goto badframe; | 238 | goto badframe; |
224 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) | 239 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) |
@@ -229,7 +244,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused) | |||
229 | current->blocked = set; | 244 | current->blocked = set; |
230 | recalc_sigpending(); | 245 | recalc_sigpending(); |
231 | spin_unlock_irq(¤t->sighand->siglock); | 246 | spin_unlock_irq(¤t->sighand->siglock); |
232 | 247 | ||
233 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) | 248 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) |
234 | goto badframe; | 249 | goto badframe; |
235 | 250 | ||
@@ -241,12 +256,11 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused) | |||
241 | badframe: | 256 | badframe: |
242 | force_sig(SIGSEGV, current); | 257 | force_sig(SIGSEGV, current); |
243 | return 0; | 258 | return 0; |
244 | } | 259 | } |
245 | 260 | ||
246 | /* | 261 | /* |
247 | * Set up a signal frame. | 262 | * Set up a signal frame. |
248 | */ | 263 | */ |
249 | |||
250 | static int | 264 | static int |
251 | setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, | 265 | setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, |
252 | struct pt_regs *regs, unsigned long mask) | 266 | struct pt_regs *regs, unsigned long mask) |
@@ -277,9 +291,9 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, | |||
277 | 291 | ||
278 | tmp = save_i387(fpstate); | 292 | tmp = save_i387(fpstate); |
279 | if (tmp < 0) | 293 | if (tmp < 0) |
280 | err = 1; | 294 | err = 1; |
281 | else | 295 | else |
282 | err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate); | 296 | err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate); |
283 | 297 | ||
284 | /* non-iBCS2 extensions.. */ | 298 | /* non-iBCS2 extensions.. */ |
285 | err |= __put_user(mask, &sc->oldmask); | 299 | err |= __put_user(mask, &sc->oldmask); |
@@ -292,7 +306,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, | |||
292 | * Determine which stack to use.. | 306 | * Determine which stack to use.. |
293 | */ | 307 | */ |
294 | static inline void __user * | 308 | static inline void __user * |
295 | get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) | 309 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) |
296 | { | 310 | { |
297 | unsigned long sp; | 311 | unsigned long sp; |
298 | 312 | ||
@@ -310,32 +324,30 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) | |||
310 | if (ka->sa.sa_flags & SA_ONSTACK) { | 324 | if (ka->sa.sa_flags & SA_ONSTACK) { |
311 | if (sas_ss_flags(sp) == 0) | 325 | if (sas_ss_flags(sp) == 0) |
312 | sp = current->sas_ss_sp + current->sas_ss_size; | 326 | sp = current->sas_ss_sp + current->sas_ss_size; |
313 | } | 327 | } else { |
314 | 328 | /* This is the legacy signal stack switching. */ | |
315 | /* This is the legacy signal stack switching. */ | 329 | if ((regs->ss & 0xffff) != __USER_DS && |
316 | else if ((regs->ss & 0xffff) != __USER_DS && | 330 | !(ka->sa.sa_flags & SA_RESTORER) && |
317 | !(ka->sa.sa_flags & SA_RESTORER) && | 331 | ka->sa.sa_restorer) |
318 | ka->sa.sa_restorer) { | 332 | sp = (unsigned long) ka->sa.sa_restorer; |
319 | sp = (unsigned long) ka->sa.sa_restorer; | ||
320 | } | 333 | } |
321 | 334 | ||
322 | sp -= frame_size; | 335 | sp -= frame_size; |
323 | /* Align the stack pointer according to the i386 ABI, | 336 | /* |
324 | * i.e. so that on function entry ((sp + 4) & 15) == 0. */ | 337 | * Align the stack pointer according to the i386 ABI, |
338 | * i.e. so that on function entry ((sp + 4) & 15) == 0. | ||
339 | */ | ||
325 | sp = ((sp + 4) & -16ul) - 4; | 340 | sp = ((sp + 4) & -16ul) - 4; |
341 | |||
326 | return (void __user *) sp; | 342 | return (void __user *) sp; |
327 | } | 343 | } |
328 | 344 | ||
329 | /* These symbols are defined with the addresses in the vsyscall page. | 345 | static int |
330 | See vsyscall-sigreturn.S. */ | 346 | setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, |
331 | extern void __user __kernel_sigreturn; | 347 | struct pt_regs *regs) |
332 | extern void __user __kernel_rt_sigreturn; | ||
333 | |||
334 | static int setup_frame(int sig, struct k_sigaction *ka, | ||
335 | sigset_t *set, struct pt_regs * regs) | ||
336 | { | 348 | { |
337 | void __user *restorer; | ||
338 | struct sigframe __user *frame; | 349 | struct sigframe __user *frame; |
350 | void __user *restorer; | ||
339 | int err = 0; | 351 | int err = 0; |
340 | int usig; | 352 | int usig; |
341 | 353 | ||
@@ -365,7 +377,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
365 | goto give_sigsegv; | 377 | goto give_sigsegv; |
366 | } | 378 | } |
367 | 379 | ||
368 | if (current->binfmt->hasvdso) | 380 | if (current->mm->context.vdso) |
369 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, sigreturn); | 381 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, sigreturn); |
370 | else | 382 | else |
371 | restorer = &frame->retcode; | 383 | restorer = &frame->retcode; |
@@ -374,9 +386,9 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
374 | 386 | ||
375 | /* Set up to return from userspace. */ | 387 | /* Set up to return from userspace. */ |
376 | err |= __put_user(restorer, &frame->pretcode); | 388 | err |= __put_user(restorer, &frame->pretcode); |
377 | 389 | ||
378 | /* | 390 | /* |
379 | * This is popl %eax ; movl $,%eax ; int $0x80 | 391 | * This is popl %eax ; movl $__NR_sigreturn, %eax ; int $0x80 |
380 | * | 392 | * |
381 | * WE DO NOT USE IT ANY MORE! It's only left here for historical | 393 | * WE DO NOT USE IT ANY MORE! It's only left here for historical |
382 | * reasons and because gdb uses it as a signature to notice | 394 | * reasons and because gdb uses it as a signature to notice |
@@ -390,11 +402,11 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
390 | goto give_sigsegv; | 402 | goto give_sigsegv; |
391 | 403 | ||
392 | /* Set up registers for signal handler */ | 404 | /* Set up registers for signal handler */ |
393 | regs->sp = (unsigned long) frame; | 405 | regs->sp = (unsigned long)frame; |
394 | regs->ip = (unsigned long) ka->sa.sa_handler; | 406 | regs->ip = (unsigned long)ka->sa.sa_handler; |
395 | regs->ax = (unsigned long) sig; | 407 | regs->ax = (unsigned long)sig; |
396 | regs->dx = (unsigned long) 0; | 408 | regs->dx = 0; |
397 | regs->cx = (unsigned long) 0; | 409 | regs->cx = 0; |
398 | 410 | ||
399 | regs->ds = __USER_DS; | 411 | regs->ds = __USER_DS; |
400 | regs->es = __USER_DS; | 412 | regs->es = __USER_DS; |
@@ -407,15 +419,10 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
407 | * The tracer may want to single-step inside the | 419 | * The tracer may want to single-step inside the |
408 | * handler too. | 420 | * handler too. |
409 | */ | 421 | */ |
410 | regs->flags &= ~(TF_MASK | X86_EFLAGS_DF); | 422 | regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF); |
411 | if (test_thread_flag(TIF_SINGLESTEP)) | 423 | if (test_thread_flag(TIF_SINGLESTEP)) |
412 | ptrace_notify(SIGTRAP); | 424 | ptrace_notify(SIGTRAP); |
413 | 425 | ||
414 | #if DEBUG_SIG | ||
415 | printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", | ||
416 | current->comm, current->pid, frame, regs->ip, frame->pretcode); | ||
417 | #endif | ||
418 | |||
419 | return 0; | 426 | return 0; |
420 | 427 | ||
421 | give_sigsegv: | 428 | give_sigsegv: |
@@ -424,10 +431,10 @@ give_sigsegv: | |||
424 | } | 431 | } |
425 | 432 | ||
426 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 433 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
427 | sigset_t *set, struct pt_regs * regs) | 434 | sigset_t *set, struct pt_regs *regs) |
428 | { | 435 | { |
429 | void __user *restorer; | ||
430 | struct rt_sigframe __user *frame; | 436 | struct rt_sigframe __user *frame; |
437 | void __user *restorer; | ||
431 | int err = 0; | 438 | int err = 0; |
432 | int usig; | 439 | int usig; |
433 | 440 | ||
@@ -457,7 +464,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
457 | &frame->uc.uc_stack.ss_flags); | 464 | &frame->uc.uc_stack.ss_flags); |
458 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | 465 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); |
459 | err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, | 466 | err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, |
460 | regs, set->sig[0]); | 467 | regs, set->sig[0]); |
461 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 468 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
462 | if (err) | 469 | if (err) |
463 | goto give_sigsegv; | 470 | goto give_sigsegv; |
@@ -467,9 +474,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
467 | if (ka->sa.sa_flags & SA_RESTORER) | 474 | if (ka->sa.sa_flags & SA_RESTORER) |
468 | restorer = ka->sa.sa_restorer; | 475 | restorer = ka->sa.sa_restorer; |
469 | err |= __put_user(restorer, &frame->pretcode); | 476 | err |= __put_user(restorer, &frame->pretcode); |
470 | 477 | ||
471 | /* | 478 | /* |
472 | * This is movl $,%ax ; int $0x80 | 479 | * This is movl $__NR_rt_sigreturn, %ax ; int $0x80 |
473 | * | 480 | * |
474 | * WE DO NOT USE IT ANY MORE! It's only left here for historical | 481 | * WE DO NOT USE IT ANY MORE! It's only left here for historical |
475 | * reasons and because gdb uses it as a signature to notice | 482 | * reasons and because gdb uses it as a signature to notice |
@@ -483,11 +490,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
483 | goto give_sigsegv; | 490 | goto give_sigsegv; |
484 | 491 | ||
485 | /* Set up registers for signal handler */ | 492 | /* Set up registers for signal handler */ |
486 | regs->sp = (unsigned long) frame; | 493 | regs->sp = (unsigned long)frame; |
487 | regs->ip = (unsigned long) ka->sa.sa_handler; | 494 | regs->ip = (unsigned long)ka->sa.sa_handler; |
488 | regs->ax = (unsigned long) usig; | 495 | regs->ax = (unsigned long)usig; |
489 | regs->dx = (unsigned long) &frame->info; | 496 | regs->dx = (unsigned long)&frame->info; |
490 | regs->cx = (unsigned long) &frame->uc; | 497 | regs->cx = (unsigned long)&frame->uc; |
491 | 498 | ||
492 | regs->ds = __USER_DS; | 499 | regs->ds = __USER_DS; |
493 | regs->es = __USER_DS; | 500 | regs->es = __USER_DS; |
@@ -500,15 +507,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
500 | * The tracer may want to single-step inside the | 507 | * The tracer may want to single-step inside the |
501 | * handler too. | 508 | * handler too. |
502 | */ | 509 | */ |
503 | regs->flags &= ~(TF_MASK | X86_EFLAGS_DF); | 510 | regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF); |
504 | if (test_thread_flag(TIF_SINGLESTEP)) | 511 | if (test_thread_flag(TIF_SINGLESTEP)) |
505 | ptrace_notify(SIGTRAP); | 512 | ptrace_notify(SIGTRAP); |
506 | 513 | ||
507 | #if DEBUG_SIG | ||
508 | printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", | ||
509 | current->comm, current->pid, frame, regs->ip, frame->pretcode); | ||
510 | #endif | ||
511 | |||
512 | return 0; | 514 | return 0; |
513 | 515 | ||
514 | give_sigsegv: | 516 | give_sigsegv: |
@@ -517,33 +519,33 @@ give_sigsegv: | |||
517 | } | 519 | } |
518 | 520 | ||
519 | /* | 521 | /* |
520 | * OK, we're invoking a handler | 522 | * OK, we're invoking a handler: |
521 | */ | 523 | */ |
522 | |||
523 | static int | 524 | static int |
524 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 525 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
525 | sigset_t *oldset, struct pt_regs * regs) | 526 | sigset_t *oldset, struct pt_regs *regs) |
526 | { | 527 | { |
527 | int ret; | 528 | int ret; |
528 | 529 | ||
529 | /* Are we from a system call? */ | 530 | /* Are we from a system call? */ |
530 | if (regs->orig_ax >= 0) { | 531 | if ((long)regs->orig_ax >= 0) { |
531 | /* If so, check system call restarting.. */ | 532 | /* If so, check system call restarting.. */ |
532 | switch (regs->ax) { | 533 | switch (regs->ax) { |
533 | case -ERESTART_RESTARTBLOCK: | 534 | case -ERESTART_RESTARTBLOCK: |
534 | case -ERESTARTNOHAND: | 535 | case -ERESTARTNOHAND: |
536 | regs->ax = -EINTR; | ||
537 | break; | ||
538 | |||
539 | case -ERESTARTSYS: | ||
540 | if (!(ka->sa.sa_flags & SA_RESTART)) { | ||
535 | regs->ax = -EINTR; | 541 | regs->ax = -EINTR; |
536 | break; | 542 | break; |
537 | 543 | } | |
538 | case -ERESTARTSYS: | 544 | /* fallthrough */ |
539 | if (!(ka->sa.sa_flags & SA_RESTART)) { | 545 | case -ERESTARTNOINTR: |
540 | regs->ax = -EINTR; | 546 | regs->ax = regs->orig_ax; |
541 | break; | 547 | regs->ip -= 2; |
542 | } | 548 | break; |
543 | /* fallthrough */ | ||
544 | case -ERESTARTNOINTR: | ||
545 | regs->ax = regs->orig_ax; | ||
546 | regs->ip -= 2; | ||
547 | } | 549 | } |
548 | } | 550 | } |
549 | 551 | ||
@@ -561,16 +563,17 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
561 | else | 563 | else |
562 | ret = setup_frame(sig, ka, oldset, regs); | 564 | ret = setup_frame(sig, ka, oldset, regs); |
563 | 565 | ||
564 | if (ret == 0) { | 566 | if (ret) |
565 | spin_lock_irq(¤t->sighand->siglock); | 567 | return ret; |
566 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | ||
567 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
568 | sigaddset(¤t->blocked,sig); | ||
569 | recalc_sigpending(); | ||
570 | spin_unlock_irq(¤t->sighand->siglock); | ||
571 | } | ||
572 | 568 | ||
573 | return ret; | 569 | spin_lock_irq(¤t->sighand->siglock); |
570 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | ||
571 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
572 | sigaddset(¤t->blocked, sig); | ||
573 | recalc_sigpending(); | ||
574 | spin_unlock_irq(¤t->sighand->siglock); | ||
575 | |||
576 | return 0; | ||
574 | } | 577 | } |
575 | 578 | ||
576 | /* | 579 | /* |
@@ -580,18 +583,17 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
580 | */ | 583 | */ |
581 | static void do_signal(struct pt_regs *regs) | 584 | static void do_signal(struct pt_regs *regs) |
582 | { | 585 | { |
586 | struct k_sigaction ka; | ||
583 | siginfo_t info; | 587 | siginfo_t info; |
584 | int signr; | 588 | int signr; |
585 | struct k_sigaction ka; | ||
586 | sigset_t *oldset; | 589 | sigset_t *oldset; |
587 | 590 | ||
588 | /* | 591 | /* |
589 | * We want the common case to go fast, which | 592 | * We want the common case to go fast, which is why we may in certain |
590 | * is why we may in certain cases get here from | 593 | * cases get here from kernel mode. Just return without doing anything |
591 | * kernel mode. Just return without doing anything | 594 | * if so. |
592 | * if so. vm86 regs switched out by assembly code | 595 | * X86_32: vm86 regs switched out by assembly code before reaching |
593 | * before reaching here, so testing against kernel | 596 | * here, so testing against kernel CS suffices. |
594 | * CS suffices. | ||
595 | */ | 597 | */ |
596 | if (!user_mode(regs)) | 598 | if (!user_mode(regs)) |
597 | return; | 599 | return; |
@@ -603,29 +605,31 @@ static void do_signal(struct pt_regs *regs) | |||
603 | 605 | ||
604 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 606 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
605 | if (signr > 0) { | 607 | if (signr > 0) { |
606 | /* Re-enable any watchpoints before delivering the | 608 | /* |
609 | * Re-enable any watchpoints before delivering the | ||
607 | * signal to user space. The processor register will | 610 | * signal to user space. The processor register will |
608 | * have been cleared if the watchpoint triggered | 611 | * have been cleared if the watchpoint triggered |
609 | * inside the kernel. | 612 | * inside the kernel. |
610 | */ | 613 | */ |
611 | if (unlikely(current->thread.debugreg7)) | 614 | if (current->thread.debugreg7) |
612 | set_debugreg(current->thread.debugreg7, 7); | 615 | set_debugreg(current->thread.debugreg7, 7); |
613 | 616 | ||
614 | /* Whee! Actually deliver the signal. */ | 617 | /* Whee! Actually deliver the signal. */ |
615 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { | 618 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { |
616 | /* a signal was successfully delivered; the saved | 619 | /* |
620 | * a signal was successfully delivered; the saved | ||
617 | * sigmask will have been stored in the signal frame, | 621 | * sigmask will have been stored in the signal frame, |
618 | * and will be restored by sigreturn, so we can simply | 622 | * and will be restored by sigreturn, so we can simply |
619 | * clear the TIF_RESTORE_SIGMASK flag */ | 623 | * clear the TIF_RESTORE_SIGMASK flag |
624 | */ | ||
620 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | 625 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
621 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 626 | clear_thread_flag(TIF_RESTORE_SIGMASK); |
622 | } | 627 | } |
623 | |||
624 | return; | 628 | return; |
625 | } | 629 | } |
626 | 630 | ||
627 | /* Did we come from a system call? */ | 631 | /* Did we come from a system call? */ |
628 | if (regs->orig_ax >= 0) { | 632 | if ((long)regs->orig_ax >= 0) { |
629 | /* Restart the system call - no handlers present */ | 633 | /* Restart the system call - no handlers present */ |
630 | switch (regs->ax) { | 634 | switch (regs->ax) { |
631 | case -ERESTARTNOHAND: | 635 | case -ERESTARTNOHAND: |
@@ -642,8 +646,10 @@ static void do_signal(struct pt_regs *regs) | |||
642 | } | 646 | } |
643 | } | 647 | } |
644 | 648 | ||
645 | /* if there's no signal to deliver, we just put the saved sigmask | 649 | /* |
646 | * back */ | 650 | * If there's no signal to deliver, we just put the saved sigmask |
651 | * back. | ||
652 | */ | ||
647 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | 653 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { |
648 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 654 | clear_thread_flag(TIF_RESTORE_SIGMASK); |
649 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | 655 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); |
@@ -654,13 +660,12 @@ static void do_signal(struct pt_regs *regs) | |||
654 | * notification of userspace execution resumption | 660 | * notification of userspace execution resumption |
655 | * - triggered by the TIF_WORK_MASK flags | 661 | * - triggered by the TIF_WORK_MASK flags |
656 | */ | 662 | */ |
657 | __attribute__((regparm(3))) | 663 | void |
658 | void do_notify_resume(struct pt_regs *regs, void *_unused, | 664 | do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) |
659 | __u32 thread_info_flags) | ||
660 | { | 665 | { |
661 | /* Pending single-step? */ | 666 | /* Pending single-step? */ |
662 | if (thread_info_flags & _TIF_SINGLESTEP) { | 667 | if (thread_info_flags & _TIF_SINGLESTEP) { |
663 | regs->flags |= TF_MASK; | 668 | regs->flags |= X86_EFLAGS_TF; |
664 | clear_thread_flag(TIF_SINGLESTEP); | 669 | clear_thread_flag(TIF_SINGLESTEP); |
665 | } | 670 | } |
666 | 671 | ||
@@ -670,6 +675,6 @@ void do_notify_resume(struct pt_regs *regs, void *_unused, | |||
670 | 675 | ||
671 | if (thread_info_flags & _TIF_HRTICK_RESCHED) | 676 | if (thread_info_flags & _TIF_HRTICK_RESCHED) |
672 | hrtick_resched(); | 677 | hrtick_resched(); |
673 | 678 | ||
674 | clear_thread_flag(TIF_IRET); | 679 | clear_thread_flag(TIF_IRET); |
675 | } | 680 | } |