162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson 662306a36Sopenharmony_ci * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes 762306a36Sopenharmony_ci * 2000-12-* x86-64 compatibility mode signal handling by Andi Kleen 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/sched.h> 1162306a36Sopenharmony_ci#include <linux/sched/task_stack.h> 1262306a36Sopenharmony_ci#include <linux/mm.h> 1362306a36Sopenharmony_ci#include <linux/smp.h> 1462306a36Sopenharmony_ci#include <linux/kernel.h> 1562306a36Sopenharmony_ci#include <linux/errno.h> 1662306a36Sopenharmony_ci#include <linux/wait.h> 1762306a36Sopenharmony_ci#include <linux/unistd.h> 1862306a36Sopenharmony_ci#include <linux/stddef.h> 1962306a36Sopenharmony_ci#include <linux/personality.h> 2062306a36Sopenharmony_ci#include <linux/compat.h> 2162306a36Sopenharmony_ci#include <linux/binfmts.h> 2262306a36Sopenharmony_ci#include <linux/syscalls.h> 2362306a36Sopenharmony_ci#include <asm/ucontext.h> 2462306a36Sopenharmony_ci#include <linux/uaccess.h> 2562306a36Sopenharmony_ci#include <asm/fpu/signal.h> 2662306a36Sopenharmony_ci#include <asm/ptrace.h> 2762306a36Sopenharmony_ci#include <asm/user32.h> 2862306a36Sopenharmony_ci#include <uapi/asm/sigcontext.h> 2962306a36Sopenharmony_ci#include <asm/proto.h> 3062306a36Sopenharmony_ci#include <asm/vdso.h> 3162306a36Sopenharmony_ci#include <asm/sigframe.h> 3262306a36Sopenharmony_ci#include <asm/sighandling.h> 3362306a36Sopenharmony_ci#include <asm/smap.h> 3462306a36Sopenharmony_ci#include <asm/gsseg.h> 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#ifdef CONFIG_IA32_EMULATION 3762306a36Sopenharmony_ci#include <asm/ia32_unistd.h> 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic inline void reload_segments(struct sigcontext_32 *sc) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci unsigned int cur; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci savesegment(gs, cur); 4462306a36Sopenharmony_ci if ((sc->gs | 0x03) != cur) 4562306a36Sopenharmony_ci load_gs_index(sc->gs | 0x03); 4662306a36Sopenharmony_ci savesegment(fs, cur); 4762306a36Sopenharmony_ci if ((sc->fs | 0x03) != cur) 4862306a36Sopenharmony_ci loadsegment(fs, sc->fs | 0x03); 4962306a36Sopenharmony_ci savesegment(ds, cur); 5062306a36Sopenharmony_ci if ((sc->ds | 0x03) != cur) 5162306a36Sopenharmony_ci loadsegment(ds, sc->ds | 0x03); 5262306a36Sopenharmony_ci savesegment(es, cur); 5362306a36Sopenharmony_ci if ((sc->es | 0x03) != cur) 5462306a36Sopenharmony_ci loadsegment(es, sc->es | 0x03); 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define sigset32_t compat_sigset_t 5862306a36Sopenharmony_ci#define siginfo32_t compat_siginfo_t 5962306a36Sopenharmony_ci#define restore_altstack32 compat_restore_altstack 6062306a36Sopenharmony_ci#define unsafe_save_altstack32 unsafe_compat_save_altstack 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#else 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#define sigset32_t sigset_t 6562306a36Sopenharmony_ci#define siginfo32_t siginfo_t 6662306a36Sopenharmony_ci#define __NR_ia32_sigreturn __NR_sigreturn 6762306a36Sopenharmony_ci#define __NR_ia32_rt_sigreturn __NR_rt_sigreturn 6862306a36Sopenharmony_ci#define restore_altstack32 restore_altstack 6962306a36Sopenharmony_ci#define unsafe_save_altstack32 unsafe_save_altstack 7062306a36Sopenharmony_ci#define __copy_siginfo_to_user32 copy_siginfo_to_user 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci#endif 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci/* 7562306a36Sopenharmony_ci * Do a signal return; undo the signal stack. 7662306a36Sopenharmony_ci */ 7762306a36Sopenharmony_cistatic bool ia32_restore_sigcontext(struct pt_regs *regs, 7862306a36Sopenharmony_ci struct sigcontext_32 __user *usc) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci struct sigcontext_32 sc; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci /* Always make any pending restarted system calls return -EINTR */ 8362306a36Sopenharmony_ci current->restart_block.fn = do_no_restart_syscall; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci if (unlikely(copy_from_user(&sc, usc, sizeof(sc)))) 8662306a36Sopenharmony_ci return false; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /* Get only the ia32 registers. */ 8962306a36Sopenharmony_ci regs->bx = sc.bx; 9062306a36Sopenharmony_ci regs->cx = sc.cx; 9162306a36Sopenharmony_ci regs->dx = sc.dx; 9262306a36Sopenharmony_ci regs->si = sc.si; 9362306a36Sopenharmony_ci regs->di = sc.di; 9462306a36Sopenharmony_ci regs->bp = sc.bp; 9562306a36Sopenharmony_ci regs->ax = sc.ax; 9662306a36Sopenharmony_ci regs->sp = sc.sp; 9762306a36Sopenharmony_ci regs->ip = sc.ip; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci /* Get CS/SS and force CPL3 */ 10062306a36Sopenharmony_ci regs->cs = sc.cs | 0x03; 10162306a36Sopenharmony_ci regs->ss = sc.ss | 0x03; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci regs->flags = (regs->flags & ~FIX_EFLAGS) | (sc.flags & FIX_EFLAGS); 10462306a36Sopenharmony_ci /* disable syscall checks */ 10562306a36Sopenharmony_ci regs->orig_ax = -1; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci#ifdef CONFIG_IA32_EMULATION 10862306a36Sopenharmony_ci /* 10962306a36Sopenharmony_ci * Reload fs and gs if they have changed in the signal 11062306a36Sopenharmony_ci * handler. This does not handle long fs/gs base changes in 11162306a36Sopenharmony_ci * the handler, but does not clobber them at least in the 11262306a36Sopenharmony_ci * normal case. 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_ci reload_segments(&sc); 11562306a36Sopenharmony_ci#else 11662306a36Sopenharmony_ci loadsegment(gs, sc.gs); 11762306a36Sopenharmony_ci regs->fs = sc.fs; 11862306a36Sopenharmony_ci regs->es = sc.es; 11962306a36Sopenharmony_ci regs->ds = sc.ds; 12062306a36Sopenharmony_ci#endif 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci return fpu__restore_sig(compat_ptr(sc.fpstate), 1); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ciSYSCALL32_DEFINE0(sigreturn) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci struct pt_regs *regs = current_pt_regs(); 12862306a36Sopenharmony_ci struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(regs->sp-8); 12962306a36Sopenharmony_ci sigset_t set; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci if (!access_ok(frame, sizeof(*frame))) 13262306a36Sopenharmony_ci goto badframe; 13362306a36Sopenharmony_ci if (__get_user(set.sig[0], &frame->sc.oldmask) 13462306a36Sopenharmony_ci || __get_user(((__u32 *)&set)[1], &frame->extramask[0])) 13562306a36Sopenharmony_ci goto badframe; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci set_current_blocked(&set); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci if (!ia32_restore_sigcontext(regs, &frame->sc)) 14062306a36Sopenharmony_ci goto badframe; 14162306a36Sopenharmony_ci return regs->ax; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cibadframe: 14462306a36Sopenharmony_ci signal_fault(regs, frame, "32bit sigreturn"); 14562306a36Sopenharmony_ci return 0; 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ciSYSCALL32_DEFINE0(rt_sigreturn) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci struct pt_regs *regs = current_pt_regs(); 15162306a36Sopenharmony_ci struct rt_sigframe_ia32 __user *frame; 15262306a36Sopenharmony_ci sigset_t set; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci if (!access_ok(frame, sizeof(*frame))) 15762306a36Sopenharmony_ci goto badframe; 15862306a36Sopenharmony_ci if (__get_user(*(__u64 *)&set, (__u64 __user *)&frame->uc.uc_sigmask)) 15962306a36Sopenharmony_ci goto badframe; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci set_current_blocked(&set); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci if (!ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext)) 16462306a36Sopenharmony_ci goto badframe; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci if (restore_altstack32(&frame->uc.uc_stack)) 16762306a36Sopenharmony_ci goto badframe; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci return regs->ax; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cibadframe: 17262306a36Sopenharmony_ci signal_fault(regs, frame, "32bit rt sigreturn"); 17362306a36Sopenharmony_ci return 0; 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci/* 17762306a36Sopenharmony_ci * Set up a signal frame. 17862306a36Sopenharmony_ci */ 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci#define get_user_seg(seg) ({ unsigned int v; savesegment(seg, v); v; }) 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic __always_inline int 18362306a36Sopenharmony_ci__unsafe_setup_sigcontext32(struct sigcontext_32 __user *sc, 18462306a36Sopenharmony_ci void __user *fpstate, 18562306a36Sopenharmony_ci struct pt_regs *regs, unsigned int mask) 18662306a36Sopenharmony_ci{ 18762306a36Sopenharmony_ci unsafe_put_user(get_user_seg(gs), (unsigned int __user *)&sc->gs, Efault); 18862306a36Sopenharmony_ci#ifdef CONFIG_IA32_EMULATION 18962306a36Sopenharmony_ci unsafe_put_user(get_user_seg(fs), (unsigned int __user *)&sc->fs, Efault); 19062306a36Sopenharmony_ci unsafe_put_user(get_user_seg(ds), (unsigned int __user *)&sc->ds, Efault); 19162306a36Sopenharmony_ci unsafe_put_user(get_user_seg(es), (unsigned int __user *)&sc->es, Efault); 19262306a36Sopenharmony_ci#else 19362306a36Sopenharmony_ci unsafe_put_user(regs->fs, (unsigned int __user *)&sc->fs, Efault); 19462306a36Sopenharmony_ci unsafe_put_user(regs->es, (unsigned int __user *)&sc->es, Efault); 19562306a36Sopenharmony_ci unsafe_put_user(regs->ds, (unsigned int __user *)&sc->ds, Efault); 19662306a36Sopenharmony_ci#endif 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci unsafe_put_user(regs->di, &sc->di, Efault); 19962306a36Sopenharmony_ci unsafe_put_user(regs->si, &sc->si, Efault); 20062306a36Sopenharmony_ci unsafe_put_user(regs->bp, &sc->bp, Efault); 20162306a36Sopenharmony_ci unsafe_put_user(regs->sp, &sc->sp, Efault); 20262306a36Sopenharmony_ci unsafe_put_user(regs->bx, &sc->bx, Efault); 20362306a36Sopenharmony_ci unsafe_put_user(regs->dx, &sc->dx, Efault); 20462306a36Sopenharmony_ci unsafe_put_user(regs->cx, &sc->cx, Efault); 20562306a36Sopenharmony_ci unsafe_put_user(regs->ax, &sc->ax, Efault); 20662306a36Sopenharmony_ci unsafe_put_user(current->thread.trap_nr, &sc->trapno, Efault); 20762306a36Sopenharmony_ci unsafe_put_user(current->thread.error_code, &sc->err, Efault); 20862306a36Sopenharmony_ci unsafe_put_user(regs->ip, &sc->ip, Efault); 20962306a36Sopenharmony_ci unsafe_put_user(regs->cs, (unsigned int __user *)&sc->cs, Efault); 21062306a36Sopenharmony_ci unsafe_put_user(regs->flags, &sc->flags, Efault); 21162306a36Sopenharmony_ci unsafe_put_user(regs->sp, &sc->sp_at_signal, Efault); 21262306a36Sopenharmony_ci unsafe_put_user(regs->ss, (unsigned int __user *)&sc->ss, Efault); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci unsafe_put_user(ptr_to_compat(fpstate), &sc->fpstate, Efault); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci /* non-iBCS2 extensions.. */ 21762306a36Sopenharmony_ci unsafe_put_user(mask, &sc->oldmask, Efault); 21862306a36Sopenharmony_ci unsafe_put_user(current->thread.cr2, &sc->cr2, Efault); 21962306a36Sopenharmony_ci return 0; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ciEfault: 22262306a36Sopenharmony_ci return -EFAULT; 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci#define unsafe_put_sigcontext32(sc, fp, regs, set, label) \ 22662306a36Sopenharmony_cido { \ 22762306a36Sopenharmony_ci if (__unsafe_setup_sigcontext32(sc, fp, regs, set->sig[0])) \ 22862306a36Sopenharmony_ci goto label; \ 22962306a36Sopenharmony_ci} while(0) 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ciint ia32_setup_frame(struct ksignal *ksig, struct pt_regs *regs) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci sigset32_t *set = (sigset32_t *) sigmask_to_save(); 23462306a36Sopenharmony_ci struct sigframe_ia32 __user *frame; 23562306a36Sopenharmony_ci void __user *restorer; 23662306a36Sopenharmony_ci void __user *fp = NULL; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci /* copy_to_user optimizes that into a single 8 byte store */ 23962306a36Sopenharmony_ci static const struct { 24062306a36Sopenharmony_ci u16 poplmovl; 24162306a36Sopenharmony_ci u32 val; 24262306a36Sopenharmony_ci u16 int80; 24362306a36Sopenharmony_ci } __attribute__((packed)) code = { 24462306a36Sopenharmony_ci 0xb858, /* popl %eax ; movl $...,%eax */ 24562306a36Sopenharmony_ci __NR_ia32_sigreturn, 24662306a36Sopenharmony_ci 0x80cd, /* int $0x80 */ 24762306a36Sopenharmony_ci }; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci frame = get_sigframe(ksig, regs, sizeof(*frame), &fp); 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci if (ksig->ka.sa.sa_flags & SA_RESTORER) { 25262306a36Sopenharmony_ci restorer = ksig->ka.sa.sa_restorer; 25362306a36Sopenharmony_ci } else { 25462306a36Sopenharmony_ci /* Return stub is in 32bit vsyscall page */ 25562306a36Sopenharmony_ci if (current->mm->context.vdso) 25662306a36Sopenharmony_ci restorer = current->mm->context.vdso + 25762306a36Sopenharmony_ci vdso_image_32.sym___kernel_sigreturn; 25862306a36Sopenharmony_ci else 25962306a36Sopenharmony_ci restorer = &frame->retcode; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci if (!user_access_begin(frame, sizeof(*frame))) 26362306a36Sopenharmony_ci return -EFAULT; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci unsafe_put_user(ksig->sig, &frame->sig, Efault); 26662306a36Sopenharmony_ci unsafe_put_sigcontext32(&frame->sc, fp, regs, set, Efault); 26762306a36Sopenharmony_ci unsafe_put_user(set->sig[1], &frame->extramask[0], Efault); 26862306a36Sopenharmony_ci unsafe_put_user(ptr_to_compat(restorer), &frame->pretcode, Efault); 26962306a36Sopenharmony_ci /* 27062306a36Sopenharmony_ci * These are actually not used anymore, but left because some 27162306a36Sopenharmony_ci * gdb versions depend on them as a marker. 27262306a36Sopenharmony_ci */ 27362306a36Sopenharmony_ci unsafe_put_user(*((u64 *)&code), (u64 __user *)frame->retcode, Efault); 27462306a36Sopenharmony_ci user_access_end(); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci /* Set up registers for signal handler */ 27762306a36Sopenharmony_ci regs->sp = (unsigned long) frame; 27862306a36Sopenharmony_ci regs->ip = (unsigned long) ksig->ka.sa.sa_handler; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci /* Make -mregparm=3 work */ 28162306a36Sopenharmony_ci regs->ax = ksig->sig; 28262306a36Sopenharmony_ci regs->dx = 0; 28362306a36Sopenharmony_ci regs->cx = 0; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci#ifdef CONFIG_IA32_EMULATION 28662306a36Sopenharmony_ci loadsegment(ds, __USER_DS); 28762306a36Sopenharmony_ci loadsegment(es, __USER_DS); 28862306a36Sopenharmony_ci#else 28962306a36Sopenharmony_ci regs->ds = __USER_DS; 29062306a36Sopenharmony_ci regs->es = __USER_DS; 29162306a36Sopenharmony_ci#endif 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci regs->cs = __USER32_CS; 29462306a36Sopenharmony_ci regs->ss = __USER_DS; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci return 0; 29762306a36Sopenharmony_ciEfault: 29862306a36Sopenharmony_ci user_access_end(); 29962306a36Sopenharmony_ci return -EFAULT; 30062306a36Sopenharmony_ci} 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ciint ia32_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs) 30362306a36Sopenharmony_ci{ 30462306a36Sopenharmony_ci sigset32_t *set = (sigset32_t *) sigmask_to_save(); 30562306a36Sopenharmony_ci struct rt_sigframe_ia32 __user *frame; 30662306a36Sopenharmony_ci void __user *restorer; 30762306a36Sopenharmony_ci void __user *fp = NULL; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci /* unsafe_put_user optimizes that into a single 8 byte store */ 31062306a36Sopenharmony_ci static const struct { 31162306a36Sopenharmony_ci u8 movl; 31262306a36Sopenharmony_ci u32 val; 31362306a36Sopenharmony_ci u16 int80; 31462306a36Sopenharmony_ci u8 pad; 31562306a36Sopenharmony_ci } __attribute__((packed)) code = { 31662306a36Sopenharmony_ci 0xb8, 31762306a36Sopenharmony_ci __NR_ia32_rt_sigreturn, 31862306a36Sopenharmony_ci 0x80cd, 31962306a36Sopenharmony_ci 0, 32062306a36Sopenharmony_ci }; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci frame = get_sigframe(ksig, regs, sizeof(*frame), &fp); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci if (!user_access_begin(frame, sizeof(*frame))) 32562306a36Sopenharmony_ci return -EFAULT; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci unsafe_put_user(ksig->sig, &frame->sig, Efault); 32862306a36Sopenharmony_ci unsafe_put_user(ptr_to_compat(&frame->info), &frame->pinfo, Efault); 32962306a36Sopenharmony_ci unsafe_put_user(ptr_to_compat(&frame->uc), &frame->puc, Efault); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci /* Create the ucontext. */ 33262306a36Sopenharmony_ci if (static_cpu_has(X86_FEATURE_XSAVE)) 33362306a36Sopenharmony_ci unsafe_put_user(UC_FP_XSTATE, &frame->uc.uc_flags, Efault); 33462306a36Sopenharmony_ci else 33562306a36Sopenharmony_ci unsafe_put_user(0, &frame->uc.uc_flags, Efault); 33662306a36Sopenharmony_ci unsafe_put_user(0, &frame->uc.uc_link, Efault); 33762306a36Sopenharmony_ci unsafe_save_altstack32(&frame->uc.uc_stack, regs->sp, Efault); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci if (ksig->ka.sa.sa_flags & SA_RESTORER) 34062306a36Sopenharmony_ci restorer = ksig->ka.sa.sa_restorer; 34162306a36Sopenharmony_ci else 34262306a36Sopenharmony_ci restorer = current->mm->context.vdso + 34362306a36Sopenharmony_ci vdso_image_32.sym___kernel_rt_sigreturn; 34462306a36Sopenharmony_ci unsafe_put_user(ptr_to_compat(restorer), &frame->pretcode, Efault); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci /* 34762306a36Sopenharmony_ci * Not actually used anymore, but left because some gdb 34862306a36Sopenharmony_ci * versions need it. 34962306a36Sopenharmony_ci */ 35062306a36Sopenharmony_ci unsafe_put_user(*((u64 *)&code), (u64 __user *)frame->retcode, Efault); 35162306a36Sopenharmony_ci unsafe_put_sigcontext32(&frame->uc.uc_mcontext, fp, regs, set, Efault); 35262306a36Sopenharmony_ci unsafe_put_user(*(__u64 *)set, (__u64 __user *)&frame->uc.uc_sigmask, Efault); 35362306a36Sopenharmony_ci user_access_end(); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci if (__copy_siginfo_to_user32(&frame->info, &ksig->info)) 35662306a36Sopenharmony_ci return -EFAULT; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci /* Set up registers for signal handler */ 35962306a36Sopenharmony_ci regs->sp = (unsigned long) frame; 36062306a36Sopenharmony_ci regs->ip = (unsigned long) ksig->ka.sa.sa_handler; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci /* Make -mregparm=3 work */ 36362306a36Sopenharmony_ci regs->ax = ksig->sig; 36462306a36Sopenharmony_ci regs->dx = (unsigned long) &frame->info; 36562306a36Sopenharmony_ci regs->cx = (unsigned long) &frame->uc; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci#ifdef CONFIG_IA32_EMULATION 36862306a36Sopenharmony_ci loadsegment(ds, __USER_DS); 36962306a36Sopenharmony_ci loadsegment(es, __USER_DS); 37062306a36Sopenharmony_ci#else 37162306a36Sopenharmony_ci regs->ds = __USER_DS; 37262306a36Sopenharmony_ci regs->es = __USER_DS; 37362306a36Sopenharmony_ci#endif 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci regs->cs = __USER32_CS; 37662306a36Sopenharmony_ci regs->ss = __USER_DS; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci return 0; 37962306a36Sopenharmony_ciEfault: 38062306a36Sopenharmony_ci user_access_end(); 38162306a36Sopenharmony_ci return -EFAULT; 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci/* 38562306a36Sopenharmony_ci * The siginfo_t structure and handing code is very easy 38662306a36Sopenharmony_ci * to break in several ways. It must always be updated when new 38762306a36Sopenharmony_ci * updates are made to the main siginfo_t, and 38862306a36Sopenharmony_ci * copy_siginfo_to_user32() must be updated when the 38962306a36Sopenharmony_ci * (arch-independent) copy_siginfo_to_user() is updated. 39062306a36Sopenharmony_ci * 39162306a36Sopenharmony_ci * It is also easy to put a new member in the siginfo_t 39262306a36Sopenharmony_ci * which has implicit alignment which can move internal structure 39362306a36Sopenharmony_ci * alignment around breaking the ABI. This can happen if you, 39462306a36Sopenharmony_ci * for instance, put a plain 64-bit value in there. 39562306a36Sopenharmony_ci */ 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci/* 39862306a36Sopenharmony_ci* If adding a new si_code, there is probably new data in 39962306a36Sopenharmony_ci* the siginfo. Make sure folks bumping the si_code 40062306a36Sopenharmony_ci* limits also have to look at this code. Make sure any 40162306a36Sopenharmony_ci* new fields are handled in copy_siginfo_to_user32()! 40262306a36Sopenharmony_ci*/ 40362306a36Sopenharmony_cistatic_assert(NSIGILL == 11); 40462306a36Sopenharmony_cistatic_assert(NSIGFPE == 15); 40562306a36Sopenharmony_cistatic_assert(NSIGSEGV == 10); 40662306a36Sopenharmony_cistatic_assert(NSIGBUS == 5); 40762306a36Sopenharmony_cistatic_assert(NSIGTRAP == 6); 40862306a36Sopenharmony_cistatic_assert(NSIGCHLD == 6); 40962306a36Sopenharmony_cistatic_assert(NSIGSYS == 2); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci/* This is part of the ABI and can never change in size: */ 41262306a36Sopenharmony_cistatic_assert(sizeof(siginfo32_t) == 128); 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci/* This is a part of the ABI and can never change in alignment */ 41562306a36Sopenharmony_cistatic_assert(__alignof__(siginfo32_t) == 4); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci/* 41862306a36Sopenharmony_ci* The offsets of all the (unioned) si_fields are fixed 41962306a36Sopenharmony_ci* in the ABI, of course. Make sure none of them ever 42062306a36Sopenharmony_ci* move and are always at the beginning: 42162306a36Sopenharmony_ci*/ 42262306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, _sifields) == 3 * sizeof(int)); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_signo) == 0); 42562306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_errno) == 4); 42662306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_code) == 8); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci/* 42962306a36Sopenharmony_ci* Ensure that the size of each si_field never changes. 43062306a36Sopenharmony_ci* If it does, it is a sign that the 43162306a36Sopenharmony_ci* copy_siginfo_to_user32() code below needs to updated 43262306a36Sopenharmony_ci* along with the size in the CHECK_SI_SIZE(). 43362306a36Sopenharmony_ci* 43462306a36Sopenharmony_ci* We repeat this check for both the generic and compat 43562306a36Sopenharmony_ci* siginfos. 43662306a36Sopenharmony_ci* 43762306a36Sopenharmony_ci* Note: it is OK for these to grow as long as the whole 43862306a36Sopenharmony_ci* structure stays within the padding size (checked 43962306a36Sopenharmony_ci* above). 44062306a36Sopenharmony_ci*/ 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci#define CHECK_SI_OFFSET(name) \ 44362306a36Sopenharmony_ci static_assert(offsetof(siginfo32_t, _sifields) == \ 44462306a36Sopenharmony_ci offsetof(siginfo32_t, _sifields.name)) 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci#define CHECK_SI_SIZE(name, size) \ 44762306a36Sopenharmony_ci static_assert(sizeof_field(siginfo32_t, _sifields.name) == size) 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ciCHECK_SI_OFFSET(_kill); 45062306a36Sopenharmony_ciCHECK_SI_SIZE (_kill, 2*sizeof(int)); 45162306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_pid) == 0xC); 45262306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_uid) == 0x10); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ciCHECK_SI_OFFSET(_timer); 45562306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 45662306a36Sopenharmony_ci/* compat_siginfo_t doesn't have si_sys_private */ 45762306a36Sopenharmony_ciCHECK_SI_SIZE (_timer, 3*sizeof(int)); 45862306a36Sopenharmony_ci#else 45962306a36Sopenharmony_ciCHECK_SI_SIZE (_timer, 4*sizeof(int)); 46062306a36Sopenharmony_ci#endif 46162306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_tid) == 0x0C); 46262306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_overrun) == 0x10); 46362306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_value) == 0x14); 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ciCHECK_SI_OFFSET(_rt); 46662306a36Sopenharmony_ciCHECK_SI_SIZE (_rt, 3*sizeof(int)); 46762306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_pid) == 0x0C); 46862306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_uid) == 0x10); 46962306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_value) == 0x14); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ciCHECK_SI_OFFSET(_sigchld); 47262306a36Sopenharmony_ciCHECK_SI_SIZE (_sigchld, 5*sizeof(int)); 47362306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_pid) == 0x0C); 47462306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_uid) == 0x10); 47562306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_status) == 0x14); 47662306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_utime) == 0x18); 47762306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_stime) == 0x1C); 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ciCHECK_SI_OFFSET(_sigfault); 48062306a36Sopenharmony_ciCHECK_SI_SIZE (_sigfault, 4*sizeof(int)); 48162306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_addr) == 0x0C); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_trapno) == 0x10); 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_addr_lsb) == 0x10); 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_lower) == 0x14); 48862306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_upper) == 0x18); 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_pkey) == 0x14); 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_perf_data) == 0x10); 49362306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_perf_type) == 0x14); 49462306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_perf_flags) == 0x18); 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ciCHECK_SI_OFFSET(_sigpoll); 49762306a36Sopenharmony_ciCHECK_SI_SIZE (_sigpoll, 2*sizeof(int)); 49862306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_band) == 0x0C); 49962306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_fd) == 0x10); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ciCHECK_SI_OFFSET(_sigsys); 50262306a36Sopenharmony_ciCHECK_SI_SIZE (_sigsys, 3*sizeof(int)); 50362306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_call_addr) == 0x0C); 50462306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_syscall) == 0x10); 50562306a36Sopenharmony_cistatic_assert(offsetof(siginfo32_t, si_arch) == 0x14); 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci/* any new si_fields should be added here */ 508