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

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

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

~ [ 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