~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/x86/ia32/ia32_signal.c

Version: ~ [ linux-5.3-rc4 ] ~ [ linux-5.2.8 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.66 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.138 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.189 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.189 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.71 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/arch/x86_64/ia32/ia32_signal.c
  3  *
  4  *  Copyright (C) 1991, 1992  Linus Torvalds
  5  *
  6  *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
  7  *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
  8  *  2000-12-*   x86-64 compatibility mode signal handling by Andi Kleen
  9  */
 10 
 11 #include <linux/sched.h>
 12 #include <linux/mm.h>
 13 #include <linux/smp.h>
 14 #include <linux/kernel.h>
 15 #include <linux/errno.h>
 16 #include <linux/wait.h>
 17 #include <linux/unistd.h>
 18 #include <linux/stddef.h>
 19 #include <linux/personality.h>
 20 #include <linux/compat.h>
 21 #include <linux/binfmts.h>
 22 #include <asm/ucontext.h>
 23 #include <asm/uaccess.h>
 24 #include <asm/i387.h>
 25 #include <asm/fpu-internal.h>
 26 #include <asm/ptrace.h>
 27 #include <asm/ia32_unistd.h>
 28 #include <asm/user32.h>
 29 #include <asm/sigcontext32.h>
 30 #include <asm/proto.h>
 31 #include <asm/vdso.h>
 32 #include <asm/sigframe.h>
 33 #include <asm/sighandling.h>
 34 #include <asm/sys_ia32.h>
 35 
 36 #define FIX_EFLAGS      __FIX_EFLAGS
 37 
 38 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 39 {
 40         int err = 0;
 41         bool ia32 = test_thread_flag(TIF_IA32);
 42 
 43         if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
 44                 return -EFAULT;
 45 
 46         put_user_try {
 47                 /* If you change siginfo_t structure, please make sure that
 48                    this code is fixed accordingly.
 49                    It should never copy any pad contained in the structure
 50                    to avoid security leaks, but must copy the generic
 51                    3 ints plus the relevant union member.  */
 52                 put_user_ex(from->si_signo, &to->si_signo);
 53                 put_user_ex(from->si_errno, &to->si_errno);
 54                 put_user_ex((short)from->si_code, &to->si_code);
 55 
 56                 if (from->si_code < 0) {
 57                         put_user_ex(from->si_pid, &to->si_pid);
 58                         put_user_ex(from->si_uid, &to->si_uid);
 59                         put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
 60                 } else {
 61                         /*
 62                          * First 32bits of unions are always present:
 63                          * si_pid === si_band === si_tid === si_addr(LS half)
 64                          */
 65                         put_user_ex(from->_sifields._pad[0],
 66                                           &to->_sifields._pad[0]);
 67                         switch (from->si_code >> 16) {
 68                         case __SI_FAULT >> 16:
 69                                 break;
 70                         case __SI_CHLD >> 16:
 71                                 if (ia32) {
 72                                         put_user_ex(from->si_utime, &to->si_utime);
 73                                         put_user_ex(from->si_stime, &to->si_stime);
 74                                 } else {
 75                                         put_user_ex(from->si_utime, &to->_sifields._sigchld_x32._utime);
 76                                         put_user_ex(from->si_stime, &to->_sifields._sigchld_x32._stime);
 77                                 }
 78                                 put_user_ex(from->si_status, &to->si_status);
 79                                 /* FALL THROUGH */
 80                         default:
 81                         case __SI_KILL >> 16:
 82                                 put_user_ex(from->si_uid, &to->si_uid);
 83                                 break;
 84                         case __SI_POLL >> 16:
 85                                 put_user_ex(from->si_fd, &to->si_fd);
 86                                 break;
 87                         case __SI_TIMER >> 16:
 88                                 put_user_ex(from->si_overrun, &to->si_overrun);
 89                                 put_user_ex(ptr_to_compat(from->si_ptr),
 90                                             &to->si_ptr);
 91                                 break;
 92                                  /* This is not generated by the kernel as of now.  */
 93                         case __SI_RT >> 16:
 94                         case __SI_MESGQ >> 16:
 95                                 put_user_ex(from->si_uid, &to->si_uid);
 96                                 put_user_ex(from->si_int, &to->si_int);
 97                                 break;
 98                         }
 99                 }
100         } put_user_catch(err);
101 
102         return err;
103 }
104 
105 int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
106 {
107         int err = 0;
108         u32 ptr32;
109 
110         if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
111                 return -EFAULT;
112 
113         get_user_try {
114                 get_user_ex(to->si_signo, &from->si_signo);
115                 get_user_ex(to->si_errno, &from->si_errno);
116                 get_user_ex(to->si_code, &from->si_code);
117 
118                 get_user_ex(to->si_pid, &from->si_pid);
119                 get_user_ex(to->si_uid, &from->si_uid);
120                 get_user_ex(ptr32, &from->si_ptr);
121                 to->si_ptr = compat_ptr(ptr32);
122         } get_user_catch(err);
123 
124         return err;
125 }
126 
127 asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
128 {
129         sigset_t blocked;
130 
131         current->saved_sigmask = current->blocked;
132 
133         mask &= _BLOCKABLE;
134         siginitset(&blocked, mask);
135         set_current_blocked(&blocked);
136 
137         current->state = TASK_INTERRUPTIBLE;
138         schedule();
139 
140         set_restore_sigmask();
141         return -ERESTARTNOHAND;
142 }
143 
144 asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
145                                   stack_ia32_t __user *uoss_ptr,
146                                   struct pt_regs *regs)
147 {
148         stack_t uss, uoss;
149         int ret, err = 0;
150         mm_segment_t seg;
151 
152         if (uss_ptr) {
153                 u32 ptr;
154 
155                 memset(&uss, 0, sizeof(stack_t));
156                 if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)))
157                         return -EFAULT;
158 
159                 get_user_try {
160                         get_user_ex(ptr, &uss_ptr->ss_sp);
161                         get_user_ex(uss.ss_flags, &uss_ptr->ss_flags);
162                         get_user_ex(uss.ss_size, &uss_ptr->ss_size);
163                 } get_user_catch(err);
164 
165                 if (err)
166                         return -EFAULT;
167                 uss.ss_sp = compat_ptr(ptr);
168         }
169         seg = get_fs();
170         set_fs(KERNEL_DS);
171         ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp);
172         set_fs(seg);
173         if (ret >= 0 && uoss_ptr)  {
174                 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)))
175                         return -EFAULT;
176 
177                 put_user_try {
178                         put_user_ex(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp);
179                         put_user_ex(uoss.ss_flags, &uoss_ptr->ss_flags);
180                         put_user_ex(uoss.ss_size, &uoss_ptr->ss_size);
181                 } put_user_catch(err);
182 
183                 if (err)
184                         ret = -EFAULT;
185         }
186         return ret;
187 }
188 
189 /*
190  * Do a signal return; undo the signal stack.
191  */
192 #define loadsegment_gs(v)       load_gs_index(v)
193 #define loadsegment_fs(v)       loadsegment(fs, v)
194 #define loadsegment_ds(v)       loadsegment(ds, v)
195 #define loadsegment_es(v)       loadsegment(es, v)
196 
197 #define get_user_seg(seg)       ({ unsigned int v; savesegment(seg, v); v; })
198 #define set_user_seg(seg, v)    loadsegment_##seg(v)
199 
200 #define COPY(x)                 {               \
201         get_user_ex(regs->x, &sc->x);           \
202 }
203 
204 #define GET_SEG(seg)            ({                      \
205         unsigned short tmp;                             \
206         get_user_ex(tmp, &sc->seg);                     \
207         tmp;                                            \
208 })
209 
210 #define COPY_SEG_CPL3(seg)      do {                    \
211         regs->seg = GET_SEG(seg) | 3;                   \
212 } while (0)
213 
214 #define RELOAD_SEG(seg)         {               \
215         unsigned int pre = GET_SEG(seg);        \
216         unsigned int cur = get_user_seg(seg);   \
217         pre |= 3;                               \
218         if (pre != cur)                         \
219                 set_user_seg(seg, pre);         \
220 }
221 
222 static int ia32_restore_sigcontext(struct pt_regs *regs,
223                                    struct sigcontext_ia32 __user *sc,
224                                    unsigned int *pax)
225 {
226         unsigned int tmpflags, err = 0;
227         void __user *buf;
228         u32 tmp;
229 
230         /* Always make any pending restarted system calls return -EINTR */
231         current_thread_info()->restart_block.fn = do_no_restart_syscall;
232 
233         get_user_try {
234                 /*
235                  * Reload fs and gs if they have changed in the signal
236                  * handler.  This does not handle long fs/gs base changes in
237                  * the handler, but does not clobber them at least in the
238                  * normal case.
239                  */
240                 RELOAD_SEG(gs);
241                 RELOAD_SEG(fs);
242                 RELOAD_SEG(ds);
243                 RELOAD_SEG(es);
244 
245                 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
246                 COPY(dx); COPY(cx); COPY(ip);
247                 /* Don't touch extended registers */
248 
249                 COPY_SEG_CPL3(cs);
250                 COPY_SEG_CPL3(ss);
251 
252                 get_user_ex(tmpflags, &sc->flags);
253                 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
254                 /* disable syscall checks */
255                 regs->orig_ax = -1;
256 
257                 get_user_ex(tmp, &sc->fpstate);
258                 buf = compat_ptr(tmp);
259                 err |= restore_i387_xstate_ia32(buf);
260 
261                 get_user_ex(*pax, &sc->ax);
262         } get_user_catch(err);
263 
264         return err;
265 }
266 
267 asmlinkage long sys32_sigreturn(struct pt_regs *regs)
268 {
269         struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(regs->sp-8);
270         sigset_t set;
271         unsigned int ax;
272 
273         if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
274                 goto badframe;
275         if (__get_user(set.sig[0], &frame->sc.oldmask)
276             || (_COMPAT_NSIG_WORDS > 1
277                 && __copy_from_user((((char *) &set.sig) + 4),
278                                     &frame->extramask,
279                                     sizeof(frame->extramask))))
280                 goto badframe;
281 
282         sigdelsetmask(&set, ~_BLOCKABLE);
283         set_current_blocked(&set);
284 
285         if (ia32_restore_sigcontext(regs, &frame->sc, &ax))
286                 goto badframe;
287         return ax;
288 
289 badframe:
290         signal_fault(regs, frame, "32bit sigreturn");
291         return 0;
292 }
293 
294 asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
295 {
296         struct rt_sigframe_ia32 __user *frame;
297         sigset_t set;
298         unsigned int ax;
299         struct pt_regs tregs;
300 
301         frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4);
302 
303         if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
304                 goto badframe;
305         if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
306                 goto badframe;
307 
308         sigdelsetmask(&set, ~_BLOCKABLE);
309         set_current_blocked(&set);
310 
311         if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
312                 goto badframe;
313 
314         tregs = *regs;
315         if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
316                 goto badframe;
317 
318         return ax;
319 
320 badframe:
321         signal_fault(regs, frame, "32bit rt sigreturn");
322         return 0;
323 }
324 
325 /*
326  * Set up a signal frame.
327  */
328 
329 static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
330                                  void __user *fpstate,
331                                  struct pt_regs *regs, unsigned int mask)
332 {
333         int err = 0;
334 
335         put_user_try {
336                 put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs);
337                 put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
338                 put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds);
339                 put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es);
340 
341                 put_user_ex(regs->di, &sc->di);
342                 put_user_ex(regs->si, &sc->si);
343                 put_user_ex(regs->bp, &sc->bp);
344                 put_user_ex(regs->sp, &sc->sp);
345                 put_user_ex(regs->bx, &sc->bx);
346                 put_user_ex(regs->dx, &sc->dx);
347                 put_user_ex(regs->cx, &sc->cx);
348                 put_user_ex(regs->ax, &sc->ax);
349                 put_user_ex(current->thread.trap_nr, &sc->trapno);
350                 put_user_ex(current->thread.error_code, &sc->err);
351                 put_user_ex(regs->ip, &sc->ip);
352                 put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
353                 put_user_ex(regs->flags, &sc->flags);
354                 put_user_ex(regs->sp, &sc->sp_at_signal);
355                 put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
356 
357                 put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
358 
359                 /* non-iBCS2 extensions.. */
360                 put_user_ex(mask, &sc->oldmask);
361                 put_user_ex(current->thread.cr2, &sc->cr2);
362         } put_user_catch(err);
363 
364         return err;
365 }
366 
367 /*
368  * Determine which stack to use..
369  */
370 static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
371                                  size_t frame_size,
372                                  void **fpstate)
373 {
374         unsigned long sp;
375 
376         /* Default to using normal stack */
377         sp = regs->sp;
378 
379         /* This is the X/Open sanctioned signal stack switching.  */
380         if (ka->sa.sa_flags & SA_ONSTACK) {
381                 if (sas_ss_flags(sp) == 0)
382                         sp = current->sas_ss_sp + current->sas_ss_size;
383         }
384 
385         /* This is the legacy signal stack switching. */
386         else if ((regs->ss & 0xffff) != __USER32_DS &&
387                 !(ka->sa.sa_flags & SA_RESTORER) &&
388                  ka->sa.sa_restorer)
389                 sp = (unsigned long) ka->sa.sa_restorer;
390 
391         if (used_math()) {
392                 sp = sp - sig_xstate_ia32_size;
393                 *fpstate = (struct _fpstate_ia32 *) sp;
394                 if (save_i387_xstate_ia32(*fpstate) < 0)
395                         return (void __user *) -1L;
396         }
397 
398         sp -= frame_size;
399         /* Align the stack pointer according to the i386 ABI,
400          * i.e. so that on function entry ((sp + 4) & 15) == 0. */
401         sp = ((sp + 4) & -16ul) - 4;
402         return (void __user *) sp;
403 }
404 
405 int ia32_setup_frame(int sig, struct k_sigaction *ka,
406                      compat_sigset_t *set, struct pt_regs *regs)
407 {
408         struct sigframe_ia32 __user *frame;
409         void __user *restorer;
410         int err = 0;
411         void __user *fpstate = NULL;
412 
413         /* copy_to_user optimizes that into a single 8 byte store */
414         static const struct {
415                 u16 poplmovl;
416                 u32 val;
417                 u16 int80;
418         } __attribute__((packed)) code = {
419                 0xb858,          /* popl %eax ; movl $...,%eax */
420                 __NR_ia32_sigreturn,
421                 0x80cd,         /* int $0x80 */
422         };
423 
424         frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
425 
426         if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
427                 return -EFAULT;
428 
429         if (__put_user(sig, &frame->sig))
430                 return -EFAULT;
431 
432         if (ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]))
433                 return -EFAULT;
434 
435         if (_COMPAT_NSIG_WORDS > 1) {
436                 if (__copy_to_user(frame->extramask, &set->sig[1],
437                                    sizeof(frame->extramask)))
438                         return -EFAULT;
439         }
440 
441         if (ka->sa.sa_flags & SA_RESTORER) {
442                 restorer = ka->sa.sa_restorer;
443         } else {
444                 /* Return stub is in 32bit vsyscall page */
445                 if (current->mm->context.vdso)
446                         restorer = VDSO32_SYMBOL(current->mm->context.vdso,
447                                                  sigreturn);
448                 else
449                         restorer = &frame->retcode;
450         }
451 
452         put_user_try {
453                 put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
454 
455                 /*
456                  * These are actually not used anymore, but left because some
457                  * gdb versions depend on them as a marker.
458                  */
459                 put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
460         } put_user_catch(err);
461 
462         if (err)
463                 return -EFAULT;
464 
465         /* Set up registers for signal handler */
466         regs->sp = (unsigned long) frame;
467         regs->ip = (unsigned long) ka->sa.sa_handler;
468 
469         /* Make -mregparm=3 work */
470         regs->ax = sig;
471         regs->dx = 0;
472         regs->cx = 0;
473 
474         loadsegment(ds, __USER32_DS);
475         loadsegment(es, __USER32_DS);
476 
477         regs->cs = __USER32_CS;
478         regs->ss = __USER32_DS;
479 
480         return 0;
481 }
482 
483 int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
484                         compat_sigset_t *set, struct pt_regs *regs)
485 {
486         struct rt_sigframe_ia32 __user *frame;
487         void __user *restorer;
488         int err = 0;
489         void __user *fpstate = NULL;
490 
491         /* __copy_to_user optimizes that into a single 8 byte store */
492         static const struct {
493                 u8 movl;
494                 u32 val;
495                 u16 int80;
496                 u8  pad;
497         } __attribute__((packed)) code = {
498                 0xb8,
499                 __NR_ia32_rt_sigreturn,
500                 0x80cd,
501                 0,
502         };
503 
504         frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
505 
506         if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
507                 return -EFAULT;
508 
509         put_user_try {
510                 put_user_ex(sig, &frame->sig);
511                 put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo);
512                 put_user_ex(ptr_to_compat(&frame->uc), &frame->puc);
513                 err |= copy_siginfo_to_user32(&frame->info, info);
514 
515                 /* Create the ucontext.  */
516                 if (cpu_has_xsave)
517                         put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
518                 else
519                         put_user_ex(0, &frame->uc.uc_flags);
520                 put_user_ex(0, &frame->uc.uc_link);
521                 put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
522                 put_user_ex(sas_ss_flags(regs->sp),
523                             &frame->uc.uc_stack.ss_flags);
524                 put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
525                 err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
526                                              regs, set->sig[0]);
527                 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
528 
529                 if (ka->sa.sa_flags & SA_RESTORER)
530                         restorer = ka->sa.sa_restorer;
531                 else
532                         restorer = VDSO32_SYMBOL(current->mm->context.vdso,
533                                                  rt_sigreturn);
534                 put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
535 
536                 /*
537                  * Not actually used anymore, but left because some gdb
538                  * versions need it.
539                  */
540                 put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
541         } put_user_catch(err);
542 
543         if (err)
544                 return -EFAULT;
545 
546         /* Set up registers for signal handler */
547         regs->sp = (unsigned long) frame;
548         regs->ip = (unsigned long) ka->sa.sa_handler;
549 
550         /* Make -mregparm=3 work */
551         regs->ax = sig;
552         regs->dx = (unsigned long) &frame->info;
553         regs->cx = (unsigned long) &frame->uc;
554 
555         loadsegment(ds, __USER32_DS);
556         loadsegment(es, __USER32_DS);
557 
558         regs->cs = __USER32_CS;
559         regs->ss = __USER32_DS;
560 
561         return 0;
562 }
563 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp