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

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

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

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