diff options
Diffstat (limited to 'arch/x86/kernel/signal_64.c')
-rw-r--r-- | arch/x86/kernel/signal_64.c | 56 |
1 files changed, 27 insertions, 29 deletions
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 2f28252d2d26..823a55bf8c39 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c | |||
@@ -20,9 +20,10 @@ | |||
20 | #include <linux/stddef.h> | 20 | #include <linux/stddef.h> |
21 | #include <linux/personality.h> | 21 | #include <linux/personality.h> |
22 | #include <linux/compiler.h> | 22 | #include <linux/compiler.h> |
23 | #include <linux/uaccess.h> | ||
24 | |||
23 | #include <asm/processor.h> | 25 | #include <asm/processor.h> |
24 | #include <asm/ucontext.h> | 26 | #include <asm/ucontext.h> |
25 | #include <asm/uaccess.h> | ||
26 | #include <asm/i387.h> | 27 | #include <asm/i387.h> |
27 | #include <asm/proto.h> | 28 | #include <asm/proto.h> |
28 | #include <asm/ia32_unistd.h> | 29 | #include <asm/ia32_unistd.h> |
@@ -44,11 +45,6 @@ | |||
44 | # define FIX_EFLAGS __FIX_EFLAGS | 45 | # define FIX_EFLAGS __FIX_EFLAGS |
45 | #endif | 46 | #endif |
46 | 47 | ||
47 | int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | ||
48 | sigset_t *set, struct pt_regs * regs); | ||
49 | int ia32_setup_frame(int sig, struct k_sigaction *ka, | ||
50 | sigset_t *set, struct pt_regs * regs); | ||
51 | |||
52 | asmlinkage long | 48 | asmlinkage long |
53 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 49 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, |
54 | struct pt_regs *regs) | 50 | struct pt_regs *regs) |
@@ -68,7 +64,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
68 | /* Always make any pending restarted system calls return -EINTR */ | 64 | /* Always make any pending restarted system calls return -EINTR */ |
69 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 65 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
70 | 66 | ||
71 | #define COPY(x) err |= __get_user(regs->x, &sc->x) | 67 | #define COPY(x) (err |= __get_user(regs->x, &sc->x)) |
72 | 68 | ||
73 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); | 69 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); |
74 | COPY(dx); COPY(cx); COPY(ip); | 70 | COPY(dx); COPY(cx); COPY(ip); |
@@ -98,7 +94,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
98 | } | 94 | } |
99 | 95 | ||
100 | { | 96 | { |
101 | struct _fpstate __user * buf; | 97 | struct _fpstate __user *buf; |
102 | err |= __get_user(buf, &sc->fpstate); | 98 | err |= __get_user(buf, &sc->fpstate); |
103 | err |= restore_i387_xstate(buf); | 99 | err |= restore_i387_xstate(buf); |
104 | } | 100 | } |
@@ -124,7 +120,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | |||
124 | current->blocked = set; | 120 | current->blocked = set; |
125 | recalc_sigpending(); | 121 | recalc_sigpending(); |
126 | spin_unlock_irq(¤t->sighand->siglock); | 122 | spin_unlock_irq(¤t->sighand->siglock); |
127 | 123 | ||
128 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) | 124 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) |
129 | goto badframe; | 125 | goto badframe; |
130 | 126 | ||
@@ -134,16 +130,17 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | |||
134 | return ax; | 130 | return ax; |
135 | 131 | ||
136 | badframe: | 132 | badframe: |
137 | signal_fault(regs,frame,"sigreturn"); | 133 | signal_fault(regs, frame, "sigreturn"); |
138 | return 0; | 134 | return 0; |
139 | } | 135 | } |
140 | 136 | ||
141 | /* | 137 | /* |
142 | * Set up a signal frame. | 138 | * Set up a signal frame. |
143 | */ | 139 | */ |
144 | 140 | ||
145 | static inline int | 141 | static inline int |
146 | setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me) | 142 | setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, |
143 | unsigned long mask, struct task_struct *me) | ||
147 | { | 144 | { |
148 | int err = 0; | 145 | int err = 0; |
149 | 146 | ||
@@ -199,7 +196,7 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size) | |||
199 | } | 196 | } |
200 | 197 | ||
201 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 198 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
202 | sigset_t *set, struct pt_regs * regs) | 199 | sigset_t *set, struct pt_regs *regs) |
203 | { | 200 | { |
204 | struct rt_sigframe __user *frame; | 201 | struct rt_sigframe __user *frame; |
205 | void __user *fp = NULL; | 202 | void __user *fp = NULL; |
@@ -212,19 +209,19 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
212 | (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; | 209 | (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; |
213 | 210 | ||
214 | if (save_i387_xstate(fp) < 0) | 211 | if (save_i387_xstate(fp) < 0) |
215 | err |= -1; | 212 | err |= -1; |
216 | } else | 213 | } else |
217 | frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; | 214 | frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; |
218 | 215 | ||
219 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 216 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
220 | goto give_sigsegv; | 217 | goto give_sigsegv; |
221 | 218 | ||
222 | if (ka->sa.sa_flags & SA_SIGINFO) { | 219 | if (ka->sa.sa_flags & SA_SIGINFO) { |
223 | err |= copy_siginfo_to_user(&frame->info, info); | 220 | err |= copy_siginfo_to_user(&frame->info, info); |
224 | if (err) | 221 | if (err) |
225 | goto give_sigsegv; | 222 | goto give_sigsegv; |
226 | } | 223 | } |
227 | 224 | ||
228 | /* Create the ucontext. */ | 225 | /* Create the ucontext. */ |
229 | if (cpu_has_xsave) | 226 | if (cpu_has_xsave) |
230 | err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); | 227 | err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); |
@@ -237,9 +234,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
237 | err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); | 234 | err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); |
238 | err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me); | 235 | err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me); |
239 | err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); | 236 | err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); |
240 | if (sizeof(*set) == 16) { | 237 | if (sizeof(*set) == 16) { |
241 | __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); | 238 | __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); |
242 | __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); | 239 | __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); |
243 | } else | 240 | } else |
244 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 241 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
245 | 242 | ||
@@ -250,7 +247,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
250 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | 247 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); |
251 | } else { | 248 | } else { |
252 | /* could use a vstub here */ | 249 | /* could use a vstub here */ |
253 | goto give_sigsegv; | 250 | goto give_sigsegv; |
254 | } | 251 | } |
255 | 252 | ||
256 | if (err) | 253 | if (err) |
@@ -258,7 +255,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
258 | 255 | ||
259 | /* Set up registers for signal handler */ | 256 | /* Set up registers for signal handler */ |
260 | regs->di = sig; | 257 | regs->di = sig; |
261 | /* In case the signal handler was declared without prototypes */ | 258 | /* In case the signal handler was declared without prototypes */ |
262 | regs->ax = 0; | 259 | regs->ax = 0; |
263 | 260 | ||
264 | /* This also works for non SA_SIGINFO handlers because they expect the | 261 | /* This also works for non SA_SIGINFO handlers because they expect the |
@@ -282,7 +279,7 @@ give_sigsegv: | |||
282 | 279 | ||
283 | /* | 280 | /* |
284 | * OK, we're invoking a handler | 281 | * OK, we're invoking a handler |
285 | */ | 282 | */ |
286 | 283 | ||
287 | static int | 284 | static int |
288 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 285 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
@@ -326,7 +323,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
326 | ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); | 323 | ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); |
327 | else | 324 | else |
328 | ret = ia32_setup_frame(sig, ka, oldset, regs); | 325 | ret = ia32_setup_frame(sig, ka, oldset, regs); |
329 | } else | 326 | } else |
330 | #endif | 327 | #endif |
331 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | 328 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
332 | 329 | ||
@@ -352,9 +349,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
352 | regs->flags &= ~X86_EFLAGS_TF; | 349 | regs->flags &= ~X86_EFLAGS_TF; |
353 | 350 | ||
354 | spin_lock_irq(¤t->sighand->siglock); | 351 | spin_lock_irq(¤t->sighand->siglock); |
355 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | 352 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); |
356 | if (!(ka->sa.sa_flags & SA_NODEFER)) | 353 | if (!(ka->sa.sa_flags & SA_NODEFER)) |
357 | sigaddset(¤t->blocked,sig); | 354 | sigaddset(¤t->blocked, sig); |
358 | recalc_sigpending(); | 355 | recalc_sigpending(); |
359 | spin_unlock_irq(¤t->sighand->siglock); | 356 | spin_unlock_irq(¤t->sighand->siglock); |
360 | 357 | ||
@@ -464,14 +461,15 @@ void do_notify_resume(struct pt_regs *regs, void *unused, | |||
464 | } | 461 | } |
465 | 462 | ||
466 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) | 463 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) |
467 | { | 464 | { |
468 | struct task_struct *me = current; | 465 | struct task_struct *me = current; |
469 | if (show_unhandled_signals && printk_ratelimit()) { | 466 | if (show_unhandled_signals && printk_ratelimit()) { |
470 | printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", | 467 | printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", |
471 | me->comm,me->pid,where,frame,regs->ip,regs->sp,regs->orig_ax); | 468 | me->comm, me->pid, where, frame, regs->ip, |
469 | regs->sp, regs->orig_ax); | ||
472 | print_vma_addr(" in ", regs->ip); | 470 | print_vma_addr(" in ", regs->ip); |
473 | printk("\n"); | 471 | printk("\n"); |
474 | } | 472 | } |
475 | 473 | ||
476 | force_sig(SIGSEGV, me); | 474 | force_sig(SIGSEGV, me); |
477 | } | 475 | } |