17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5a3c55825Sraf * Common Development and Distribution License (the "License"). 6a3c55825Sraf * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21a3c55825Sraf 227c478bd9Sstevel@tonic-gate /* 23*bdf0047cSRoger A. Faulkner * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ 287c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ 297c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <sys/types.h> 327c478bd9Sstevel@tonic-gate #include <sys/param.h> 337c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 347c478bd9Sstevel@tonic-gate #include <sys/signal.h> 357c478bd9Sstevel@tonic-gate #include <sys/systm.h> 367c478bd9Sstevel@tonic-gate #include <sys/user.h> 377c478bd9Sstevel@tonic-gate #include <sys/mman.h> 387c478bd9Sstevel@tonic-gate #include <sys/class.h> 397c478bd9Sstevel@tonic-gate #include <sys/proc.h> 407c478bd9Sstevel@tonic-gate #include <sys/procfs.h> 417c478bd9Sstevel@tonic-gate #include <sys/buf.h> 427c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 437c478bd9Sstevel@tonic-gate #include <sys/cred.h> 447c478bd9Sstevel@tonic-gate #include <sys/archsystm.h> 457c478bd9Sstevel@tonic-gate #include <sys/vmparam.h> 467c478bd9Sstevel@tonic-gate #include <sys/prsystm.h> 477c478bd9Sstevel@tonic-gate #include <sys/reboot.h> 487c478bd9Sstevel@tonic-gate #include <sys/uadmin.h> 497c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 507c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 517c478bd9Sstevel@tonic-gate #include <sys/file.h> 527c478bd9Sstevel@tonic-gate #include <sys/session.h> 537c478bd9Sstevel@tonic-gate #include <sys/ucontext.h> 547c478bd9Sstevel@tonic-gate #include <sys/dnlc.h> 557c478bd9Sstevel@tonic-gate #include <sys/var.h> 567c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 577c478bd9Sstevel@tonic-gate #include <sys/debugreg.h> 587c478bd9Sstevel@tonic-gate #include <sys/thread.h> 597c478bd9Sstevel@tonic-gate #include <sys/vtrace.h> 607c478bd9Sstevel@tonic-gate #include <sys/consdev.h> 617c478bd9Sstevel@tonic-gate #include <sys/psw.h> 627c478bd9Sstevel@tonic-gate #include <sys/regset.h> 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate #include <sys/privregs.h> 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate #include <sys/stack.h> 677c478bd9Sstevel@tonic-gate #include <sys/swap.h> 687c478bd9Sstevel@tonic-gate #include <vm/hat.h> 697c478bd9Sstevel@tonic-gate #include <vm/anon.h> 707c478bd9Sstevel@tonic-gate #include <vm/as.h> 717c478bd9Sstevel@tonic-gate #include <vm/page.h> 727c478bd9Sstevel@tonic-gate #include <vm/seg.h> 737c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 747c478bd9Sstevel@tonic-gate #include <vm/seg_map.h> 757c478bd9Sstevel@tonic-gate #include <vm/seg_vn.h> 767c478bd9Sstevel@tonic-gate #include <sys/exec.h> 777c478bd9Sstevel@tonic-gate #include <sys/acct.h> 787c478bd9Sstevel@tonic-gate #include <sys/core.h> 797c478bd9Sstevel@tonic-gate #include <sys/corectl.h> 807c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 817c478bd9Sstevel@tonic-gate #include <sys/tuneable.h> 827c478bd9Sstevel@tonic-gate #include <c2/audit.h> 837c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 847c478bd9Sstevel@tonic-gate #include <sys/dumphdr.h> 857c478bd9Sstevel@tonic-gate #include <sys/promif.h> 867c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 877c478bd9Sstevel@tonic-gate #include <sys/kdi.h> 887c478bd9Sstevel@tonic-gate #include <sys/contract_impl.h> 897c478bd9Sstevel@tonic-gate #include <sys/x86_archext.h> 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate /* 927c478bd9Sstevel@tonic-gate * Construct the execution environment for the user's signal 937c478bd9Sstevel@tonic-gate * handler and arrange for control to be given to it on return 947c478bd9Sstevel@tonic-gate * to userland. The library code now calls setcontext() to 957c478bd9Sstevel@tonic-gate * clean up after the signal handler, so sigret() is no longer 967c478bd9Sstevel@tonic-gate * needed. 977c478bd9Sstevel@tonic-gate * 987c478bd9Sstevel@tonic-gate * (The various 'volatile' declarations are need to ensure that values 997c478bd9Sstevel@tonic-gate * are correct on the error return from on_fault().) 1007c478bd9Sstevel@tonic-gate */ 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate #if defined(__amd64) 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* 1057c478bd9Sstevel@tonic-gate * An amd64 signal frame looks like this on the stack: 1067c478bd9Sstevel@tonic-gate * 1077c478bd9Sstevel@tonic-gate * old %rsp: 1087c478bd9Sstevel@tonic-gate * <128 bytes of untouched stack space> 1097c478bd9Sstevel@tonic-gate * <a siginfo_t [optional]> 1107c478bd9Sstevel@tonic-gate * <a ucontext_t> 1117c478bd9Sstevel@tonic-gate * <siginfo_t *> 1127c478bd9Sstevel@tonic-gate * <signal number> 1137c478bd9Sstevel@tonic-gate * new %rsp: <return address (deliberately invalid)> 1147c478bd9Sstevel@tonic-gate * 1157c478bd9Sstevel@tonic-gate * The signal number and siginfo_t pointer are only pushed onto the stack in 1167c478bd9Sstevel@tonic-gate * order to allow stack backtraces. The actual signal handling code expects the 1177c478bd9Sstevel@tonic-gate * arguments in registers. 1187c478bd9Sstevel@tonic-gate */ 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate struct sigframe { 1217c478bd9Sstevel@tonic-gate caddr_t retaddr; 1227c478bd9Sstevel@tonic-gate long signo; 1237c478bd9Sstevel@tonic-gate siginfo_t *sip; 1247c478bd9Sstevel@tonic-gate }; 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate int 1277c478bd9Sstevel@tonic-gate sendsig(int sig, k_siginfo_t *sip, void (*hdlr)()) 1287c478bd9Sstevel@tonic-gate { 1297c478bd9Sstevel@tonic-gate volatile int minstacksz; 1307c478bd9Sstevel@tonic-gate int newstack; 1317c478bd9Sstevel@tonic-gate label_t ljb; 1327c478bd9Sstevel@tonic-gate volatile caddr_t sp; 1337c478bd9Sstevel@tonic-gate caddr_t fp; 1347c478bd9Sstevel@tonic-gate volatile struct regs *rp; 1357c478bd9Sstevel@tonic-gate volatile greg_t upc; 1367c478bd9Sstevel@tonic-gate volatile proc_t *p = ttoproc(curthread); 137a0de58d6SRoger A. Faulkner struct as *as = p->p_as; 1387c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 1397c478bd9Sstevel@tonic-gate ucontext_t *volatile tuc = NULL; 1407c478bd9Sstevel@tonic-gate ucontext_t *uc; 1417c478bd9Sstevel@tonic-gate siginfo_t *sip_addr; 1427c478bd9Sstevel@tonic-gate volatile int watched; 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /* 1457c478bd9Sstevel@tonic-gate * This routine is utterly dependent upon STACK_ALIGN being 1467c478bd9Sstevel@tonic-gate * 16 and STACK_ENTRY_ALIGN being 8. Let's just acknowledge 1477c478bd9Sstevel@tonic-gate * that and require it. 1487c478bd9Sstevel@tonic-gate */ 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate #if STACK_ALIGN != 16 || STACK_ENTRY_ALIGN != 8 1517c478bd9Sstevel@tonic-gate #error "sendsig() amd64 did not find the expected stack alignments" 1527c478bd9Sstevel@tonic-gate #endif 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate rp = lwptoregs(lwp); 1557c478bd9Sstevel@tonic-gate upc = rp->r_pc; 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate /* 1587c478bd9Sstevel@tonic-gate * Since we're setting up to run the signal handler we have to 1597c478bd9Sstevel@tonic-gate * arrange that the stack at entry to the handler is (only) 1607c478bd9Sstevel@tonic-gate * STACK_ENTRY_ALIGN (i.e. 8) byte aligned so that when the handler 1617c478bd9Sstevel@tonic-gate * executes its push of %rbp, the stack realigns to STACK_ALIGN 1627c478bd9Sstevel@tonic-gate * (i.e. 16) correctly. 1637c478bd9Sstevel@tonic-gate * 1647c478bd9Sstevel@tonic-gate * The new sp will point to the sigframe and the ucontext_t. The 1657c478bd9Sstevel@tonic-gate * above means that sp (and thus sigframe) will be 8-byte aligned, 1667c478bd9Sstevel@tonic-gate * but not 16-byte aligned. ucontext_t, however, contains %xmm regs 1677c478bd9Sstevel@tonic-gate * which must be 16-byte aligned. Because of this, for correct 1687c478bd9Sstevel@tonic-gate * alignment, sigframe must be a multiple of 8-bytes in length, but 1697c478bd9Sstevel@tonic-gate * not 16-bytes. This will place ucontext_t at a nice 16-byte boundary. 1707c478bd9Sstevel@tonic-gate */ 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* LINTED: logical expression always true: op "||" */ 1737c478bd9Sstevel@tonic-gate ASSERT((sizeof (struct sigframe) % 16) == 8); 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate minstacksz = sizeof (struct sigframe) + SA(sizeof (*uc)); 1767c478bd9Sstevel@tonic-gate if (sip != NULL) 1777c478bd9Sstevel@tonic-gate minstacksz += SA(sizeof (siginfo_t)); 1787c478bd9Sstevel@tonic-gate ASSERT((minstacksz & (STACK_ENTRY_ALIGN - 1ul)) == 0); 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate /* 1817c478bd9Sstevel@tonic-gate * Figure out whether we will be handling this signal on 1827c478bd9Sstevel@tonic-gate * an alternate stack specified by the user. Then allocate 1837c478bd9Sstevel@tonic-gate * and validate the stack requirements for the signal handler 1847c478bd9Sstevel@tonic-gate * context. on_fault will catch any faults. 1857c478bd9Sstevel@tonic-gate */ 186ae115bc7Smrj newstack = sigismember(&PTOU(curproc)->u_sigonstack, sig) && 1877c478bd9Sstevel@tonic-gate !(lwp->lwp_sigaltstack.ss_flags & (SS_ONSTACK|SS_DISABLE)); 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate if (newstack) { 1907c478bd9Sstevel@tonic-gate fp = (caddr_t)(SA((uintptr_t)lwp->lwp_sigaltstack.ss_sp) + 1917c478bd9Sstevel@tonic-gate SA(lwp->lwp_sigaltstack.ss_size) - STACK_ALIGN); 1927c478bd9Sstevel@tonic-gate } else { 1937c478bd9Sstevel@tonic-gate /* 1947c478bd9Sstevel@tonic-gate * Drop below the 128-byte reserved region of the stack frame 1957c478bd9Sstevel@tonic-gate * we're interrupting. 1967c478bd9Sstevel@tonic-gate */ 1977c478bd9Sstevel@tonic-gate fp = (caddr_t)rp->r_sp - STACK_RESERVE; 1987c478bd9Sstevel@tonic-gate } 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate /* 201a3c55825Sraf * Force proper stack pointer alignment, even in the face of a 202a3c55825Sraf * misaligned stack pointer from user-level before the signal. 203a3c55825Sraf */ 204a3c55825Sraf fp = (caddr_t)((uintptr_t)fp & ~(STACK_ENTRY_ALIGN - 1ul)); 205a3c55825Sraf 206a3c55825Sraf /* 2077c478bd9Sstevel@tonic-gate * Most of the time during normal execution, the stack pointer 2087c478bd9Sstevel@tonic-gate * is aligned on a STACK_ALIGN (i.e. 16 byte) boundary. However, 2097c478bd9Sstevel@tonic-gate * (for example) just after a call instruction (which pushes 2107c478bd9Sstevel@tonic-gate * the return address), the callers stack misaligns until the 2117c478bd9Sstevel@tonic-gate * 'push %rbp' happens in the callee prolog. So while we should 2127c478bd9Sstevel@tonic-gate * expect the stack pointer to be always at least STACK_ENTRY_ALIGN 2137c478bd9Sstevel@tonic-gate * aligned, we should -not- expect it to always be STACK_ALIGN aligned. 2147c478bd9Sstevel@tonic-gate * We now adjust to ensure that the new sp is aligned to 2157c478bd9Sstevel@tonic-gate * STACK_ENTRY_ALIGN but not to STACK_ALIGN. 2167c478bd9Sstevel@tonic-gate */ 2177c478bd9Sstevel@tonic-gate sp = fp - minstacksz; 2187c478bd9Sstevel@tonic-gate if (((uintptr_t)sp & (STACK_ALIGN - 1ul)) == 0) { 2197c478bd9Sstevel@tonic-gate sp -= STACK_ENTRY_ALIGN; 2207c478bd9Sstevel@tonic-gate minstacksz = fp - sp; 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate /* 2247c478bd9Sstevel@tonic-gate * Now, make sure the resulting signal frame address is sane 2257c478bd9Sstevel@tonic-gate */ 226a0de58d6SRoger A. Faulkner if (sp >= as->a_userlimit || fp >= as->a_userlimit) { 2277c478bd9Sstevel@tonic-gate #ifdef DEBUG 2287c478bd9Sstevel@tonic-gate printf("sendsig: bad signal stack cmd=%s, pid=%d, sig=%d\n", 2297c478bd9Sstevel@tonic-gate PTOU(p)->u_comm, p->p_pid, sig); 2307c478bd9Sstevel@tonic-gate printf("sigsp = 0x%p, action = 0x%p, upc = 0x%lx\n", 2317c478bd9Sstevel@tonic-gate (void *)sp, (void *)hdlr, (uintptr_t)upc); 2327c478bd9Sstevel@tonic-gate printf("sp above USERLIMIT\n"); 2337c478bd9Sstevel@tonic-gate #endif 2347c478bd9Sstevel@tonic-gate return (0); 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate watched = watch_disable_addr((caddr_t)sp, minstacksz, S_WRITE); 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate if (on_fault(&ljb)) 2407c478bd9Sstevel@tonic-gate goto badstack; 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate if (sip != NULL) { 2437c478bd9Sstevel@tonic-gate zoneid_t zoneid; 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate fp -= SA(sizeof (siginfo_t)); 2467c478bd9Sstevel@tonic-gate uzero(fp, sizeof (siginfo_t)); 2477c478bd9Sstevel@tonic-gate if (SI_FROMUSER(sip) && 2487c478bd9Sstevel@tonic-gate (zoneid = p->p_zone->zone_id) != GLOBAL_ZONEID && 2497c478bd9Sstevel@tonic-gate zoneid != sip->si_zoneid) { 2507c478bd9Sstevel@tonic-gate k_siginfo_t sani_sip = *sip; 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate sani_sip.si_pid = p->p_zone->zone_zsched->p_pid; 2537c478bd9Sstevel@tonic-gate sani_sip.si_uid = 0; 2547c478bd9Sstevel@tonic-gate sani_sip.si_ctid = -1; 2557c478bd9Sstevel@tonic-gate sani_sip.si_zoneid = zoneid; 2567c478bd9Sstevel@tonic-gate copyout_noerr(&sani_sip, fp, sizeof (sani_sip)); 2577c478bd9Sstevel@tonic-gate } else 2587c478bd9Sstevel@tonic-gate copyout_noerr(sip, fp, sizeof (*sip)); 2597c478bd9Sstevel@tonic-gate sip_addr = (siginfo_t *)fp; 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate if (sig == SIGPROF && 2627c478bd9Sstevel@tonic-gate curthread->t_rprof != NULL && 2637c478bd9Sstevel@tonic-gate curthread->t_rprof->rp_anystate) { 2647c478bd9Sstevel@tonic-gate /* 2657c478bd9Sstevel@tonic-gate * We stand on our head to deal with 2667c478bd9Sstevel@tonic-gate * the real time profiling signal. 2677c478bd9Sstevel@tonic-gate * Fill in the stuff that doesn't fit 2687c478bd9Sstevel@tonic-gate * in a normal k_siginfo structure. 2697c478bd9Sstevel@tonic-gate */ 2707c478bd9Sstevel@tonic-gate int i = sip->si_nsysarg; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate while (--i >= 0) 2737c478bd9Sstevel@tonic-gate sulword_noerr( 2747c478bd9Sstevel@tonic-gate (ulong_t *)&(sip_addr->si_sysarg[i]), 2757c478bd9Sstevel@tonic-gate (ulong_t)lwp->lwp_arg[i]); 2767c478bd9Sstevel@tonic-gate copyout_noerr(curthread->t_rprof->rp_state, 2777c478bd9Sstevel@tonic-gate sip_addr->si_mstate, 2787c478bd9Sstevel@tonic-gate sizeof (curthread->t_rprof->rp_state)); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate } else 2817c478bd9Sstevel@tonic-gate sip_addr = NULL; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate /* 2847c478bd9Sstevel@tonic-gate * save the current context on the user stack directly after the 2857c478bd9Sstevel@tonic-gate * sigframe. Since sigframe is 8-byte-but-not-16-byte aligned, 2867c478bd9Sstevel@tonic-gate * and since sizeof (struct sigframe) is 24, this guarantees 2877c478bd9Sstevel@tonic-gate * 16-byte alignment for ucontext_t and its %xmm registers. 2887c478bd9Sstevel@tonic-gate */ 2897c478bd9Sstevel@tonic-gate uc = (ucontext_t *)(sp + sizeof (struct sigframe)); 2907c478bd9Sstevel@tonic-gate tuc = kmem_alloc(sizeof (*tuc), KM_SLEEP); 291*bdf0047cSRoger A. Faulkner savecontext(tuc, &lwp->lwp_sigoldmask); 2927c478bd9Sstevel@tonic-gate copyout_noerr(tuc, uc, sizeof (*tuc)); 2937c478bd9Sstevel@tonic-gate kmem_free(tuc, sizeof (*tuc)); 2947c478bd9Sstevel@tonic-gate tuc = NULL; 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate lwp->lwp_oldcontext = (uintptr_t)uc; 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate if (newstack) { 2997c478bd9Sstevel@tonic-gate lwp->lwp_sigaltstack.ss_flags |= SS_ONSTACK; 3007c478bd9Sstevel@tonic-gate if (lwp->lwp_ustack) 3017c478bd9Sstevel@tonic-gate copyout_noerr(&lwp->lwp_sigaltstack, 3027c478bd9Sstevel@tonic-gate (stack_t *)lwp->lwp_ustack, sizeof (stack_t)); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate /* 3067c478bd9Sstevel@tonic-gate * Set up signal handler return and stack linkage 3077c478bd9Sstevel@tonic-gate */ 3087c478bd9Sstevel@tonic-gate { 3097c478bd9Sstevel@tonic-gate struct sigframe frame; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate /* 3127c478bd9Sstevel@tonic-gate * ensure we never return "normally" 3137c478bd9Sstevel@tonic-gate */ 3147c478bd9Sstevel@tonic-gate frame.retaddr = (caddr_t)(uintptr_t)-1L; 3157c478bd9Sstevel@tonic-gate frame.signo = sig; 3167c478bd9Sstevel@tonic-gate frame.sip = sip_addr; 3177c478bd9Sstevel@tonic-gate copyout_noerr(&frame, sp, sizeof (frame)); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate no_fault(); 3217c478bd9Sstevel@tonic-gate if (watched) 3227c478bd9Sstevel@tonic-gate watch_enable_addr((caddr_t)sp, minstacksz, S_WRITE); 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate /* 3257c478bd9Sstevel@tonic-gate * Set up user registers for execution of signal handler. 3267c478bd9Sstevel@tonic-gate */ 3277c478bd9Sstevel@tonic-gate rp->r_sp = (greg_t)sp; 3287c478bd9Sstevel@tonic-gate rp->r_pc = (greg_t)hdlr; 3297c478bd9Sstevel@tonic-gate rp->r_ps = PSL_USER | (rp->r_ps & PS_IOPL); 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate rp->r_rdi = sig; 3327c478bd9Sstevel@tonic-gate rp->r_rsi = (uintptr_t)sip_addr; 3337c478bd9Sstevel@tonic-gate rp->r_rdx = (uintptr_t)uc; 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate if ((rp->r_cs & 0xffff) != UCS_SEL || 3367c478bd9Sstevel@tonic-gate (rp->r_ss & 0xffff) != UDS_SEL) { 3377c478bd9Sstevel@tonic-gate /* 3387c478bd9Sstevel@tonic-gate * Try our best to deliver the signal. 3397c478bd9Sstevel@tonic-gate */ 3407c478bd9Sstevel@tonic-gate rp->r_cs = UCS_SEL; 3417c478bd9Sstevel@tonic-gate rp->r_ss = UDS_SEL; 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate /* 3457c478bd9Sstevel@tonic-gate * Don't set lwp_eosys here. sendsig() is called via psig() after 3467c478bd9Sstevel@tonic-gate * lwp_eosys is handled, so setting it here would affect the next 3477c478bd9Sstevel@tonic-gate * system call. 3487c478bd9Sstevel@tonic-gate */ 3497c478bd9Sstevel@tonic-gate return (1); 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate badstack: 3527c478bd9Sstevel@tonic-gate no_fault(); 3537c478bd9Sstevel@tonic-gate if (watched) 3547c478bd9Sstevel@tonic-gate watch_enable_addr((caddr_t)sp, minstacksz, S_WRITE); 3557c478bd9Sstevel@tonic-gate if (tuc) 3567c478bd9Sstevel@tonic-gate kmem_free(tuc, sizeof (*tuc)); 3577c478bd9Sstevel@tonic-gate #ifdef DEBUG 3587c478bd9Sstevel@tonic-gate printf("sendsig: bad signal stack cmd=%s, pid=%d, sig=%d\n", 3597c478bd9Sstevel@tonic-gate PTOU(p)->u_comm, p->p_pid, sig); 3607c478bd9Sstevel@tonic-gate printf("on fault, sigsp = 0x%p, action = 0x%p, upc = 0x%lx\n", 3617c478bd9Sstevel@tonic-gate (void *)sp, (void *)hdlr, (uintptr_t)upc); 3627c478bd9Sstevel@tonic-gate #endif 3637c478bd9Sstevel@tonic-gate return (0); 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate /* 3697c478bd9Sstevel@tonic-gate * An i386 SVR4/ABI signal frame looks like this on the stack: 3707c478bd9Sstevel@tonic-gate * 3717c478bd9Sstevel@tonic-gate * old %esp: 3727c478bd9Sstevel@tonic-gate * <a siginfo32_t [optional]> 3737c478bd9Sstevel@tonic-gate * <a ucontext32_t> 3747c478bd9Sstevel@tonic-gate * <pointer to that ucontext32_t> 3757c478bd9Sstevel@tonic-gate * <pointer to that siginfo32_t> 3767c478bd9Sstevel@tonic-gate * <signo> 3777c478bd9Sstevel@tonic-gate * new %esp: <return address (deliberately invalid)> 3787c478bd9Sstevel@tonic-gate */ 3797c478bd9Sstevel@tonic-gate struct sigframe32 { 3807c478bd9Sstevel@tonic-gate caddr32_t retaddr; 3817c478bd9Sstevel@tonic-gate uint32_t signo; 3827c478bd9Sstevel@tonic-gate caddr32_t sip; 3837c478bd9Sstevel@tonic-gate caddr32_t ucp; 3847c478bd9Sstevel@tonic-gate }; 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate int 3877c478bd9Sstevel@tonic-gate sendsig32(int sig, k_siginfo_t *sip, void (*hdlr)()) 3887c478bd9Sstevel@tonic-gate { 3897c478bd9Sstevel@tonic-gate volatile int minstacksz; 3907c478bd9Sstevel@tonic-gate int newstack; 3917c478bd9Sstevel@tonic-gate label_t ljb; 3927c478bd9Sstevel@tonic-gate volatile caddr_t sp; 3937c478bd9Sstevel@tonic-gate caddr_t fp; 3947c478bd9Sstevel@tonic-gate volatile struct regs *rp; 3957c478bd9Sstevel@tonic-gate volatile greg_t upc; 3967c478bd9Sstevel@tonic-gate volatile proc_t *p = ttoproc(curthread); 3977c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 3987c478bd9Sstevel@tonic-gate ucontext32_t *volatile tuc = NULL; 3997c478bd9Sstevel@tonic-gate ucontext32_t *uc; 4007c478bd9Sstevel@tonic-gate siginfo32_t *sip_addr; 4017c478bd9Sstevel@tonic-gate volatile int watched; 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate rp = lwptoregs(lwp); 4047c478bd9Sstevel@tonic-gate upc = rp->r_pc; 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate minstacksz = SA32(sizeof (struct sigframe32)) + SA32(sizeof (*uc)); 4077c478bd9Sstevel@tonic-gate if (sip != NULL) 4087c478bd9Sstevel@tonic-gate minstacksz += SA32(sizeof (siginfo32_t)); 4097c478bd9Sstevel@tonic-gate ASSERT((minstacksz & (STACK_ALIGN32 - 1)) == 0); 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate /* 4127c478bd9Sstevel@tonic-gate * Figure out whether we will be handling this signal on 4137c478bd9Sstevel@tonic-gate * an alternate stack specified by the user. Then allocate 4147c478bd9Sstevel@tonic-gate * and validate the stack requirements for the signal handler 4157c478bd9Sstevel@tonic-gate * context. on_fault will catch any faults. 4167c478bd9Sstevel@tonic-gate */ 417ae115bc7Smrj newstack = sigismember(&PTOU(curproc)->u_sigonstack, sig) && 4187c478bd9Sstevel@tonic-gate !(lwp->lwp_sigaltstack.ss_flags & (SS_ONSTACK|SS_DISABLE)); 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate if (newstack) { 4217c478bd9Sstevel@tonic-gate fp = (caddr_t)(SA32((uintptr_t)lwp->lwp_sigaltstack.ss_sp) + 4227c478bd9Sstevel@tonic-gate SA32(lwp->lwp_sigaltstack.ss_size) - STACK_ALIGN32); 4237c478bd9Sstevel@tonic-gate } else if ((rp->r_ss & 0xffff) != UDS_SEL) { 4247c478bd9Sstevel@tonic-gate user_desc_t *ldt; 4257c478bd9Sstevel@tonic-gate /* 4267c478bd9Sstevel@tonic-gate * If the stack segment selector is -not- pointing at 4277c478bd9Sstevel@tonic-gate * the UDS_SEL descriptor and we have an LDT entry for 4287c478bd9Sstevel@tonic-gate * it instead, add the base address to find the effective va. 4297c478bd9Sstevel@tonic-gate */ 4307c478bd9Sstevel@tonic-gate if ((ldt = p->p_ldt) != NULL) 4317c478bd9Sstevel@tonic-gate fp = (caddr_t)rp->r_sp + 4327c478bd9Sstevel@tonic-gate USEGD_GETBASE(&ldt[SELTOIDX(rp->r_ss)]); 4337c478bd9Sstevel@tonic-gate else 4347c478bd9Sstevel@tonic-gate fp = (caddr_t)rp->r_sp; 4357c478bd9Sstevel@tonic-gate } else 4367c478bd9Sstevel@tonic-gate fp = (caddr_t)rp->r_sp; 437a3c55825Sraf 438a3c55825Sraf /* 439a3c55825Sraf * Force proper stack pointer alignment, even in the face of a 440a3c55825Sraf * misaligned stack pointer from user-level before the signal. 441a3c55825Sraf * Don't use the SA32() macro because that rounds up, not down. 442a3c55825Sraf */ 443a3c55825Sraf fp = (caddr_t)((uintptr_t)fp & ~(STACK_ALIGN32 - 1)); 4447c478bd9Sstevel@tonic-gate sp = fp - minstacksz; 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate /* 4477c478bd9Sstevel@tonic-gate * Make sure lwp hasn't trashed its stack 4487c478bd9Sstevel@tonic-gate */ 449a3c55825Sraf if (sp >= (caddr_t)(uintptr_t)USERLIMIT32 || 4507c478bd9Sstevel@tonic-gate fp >= (caddr_t)(uintptr_t)USERLIMIT32) { 4517c478bd9Sstevel@tonic-gate #ifdef DEBUG 4527c478bd9Sstevel@tonic-gate printf("sendsig32: bad signal stack cmd=%s, pid=%d, sig=%d\n", 4537c478bd9Sstevel@tonic-gate PTOU(p)->u_comm, p->p_pid, sig); 4547c478bd9Sstevel@tonic-gate printf("sigsp = 0x%p, action = 0x%p, upc = 0x%lx\n", 4557c478bd9Sstevel@tonic-gate (void *)sp, (void *)hdlr, (uintptr_t)upc); 4567c478bd9Sstevel@tonic-gate printf("sp above USERLIMIT\n"); 4577c478bd9Sstevel@tonic-gate #endif 4587c478bd9Sstevel@tonic-gate return (0); 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate watched = watch_disable_addr((caddr_t)sp, minstacksz, S_WRITE); 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate if (on_fault(&ljb)) 4647c478bd9Sstevel@tonic-gate goto badstack; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate if (sip != NULL) { 4677c478bd9Sstevel@tonic-gate siginfo32_t si32; 4687c478bd9Sstevel@tonic-gate zoneid_t zoneid; 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate siginfo_kto32(sip, &si32); 4717c478bd9Sstevel@tonic-gate if (SI_FROMUSER(sip) && 4727c478bd9Sstevel@tonic-gate (zoneid = p->p_zone->zone_id) != GLOBAL_ZONEID && 4737c478bd9Sstevel@tonic-gate zoneid != sip->si_zoneid) { 4747c478bd9Sstevel@tonic-gate si32.si_pid = p->p_zone->zone_zsched->p_pid; 4757c478bd9Sstevel@tonic-gate si32.si_uid = 0; 4767c478bd9Sstevel@tonic-gate si32.si_ctid = -1; 4777c478bd9Sstevel@tonic-gate si32.si_zoneid = zoneid; 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate fp -= SA32(sizeof (si32)); 4807c478bd9Sstevel@tonic-gate uzero(fp, sizeof (si32)); 4817c478bd9Sstevel@tonic-gate copyout_noerr(&si32, fp, sizeof (si32)); 4827c478bd9Sstevel@tonic-gate sip_addr = (siginfo32_t *)fp; 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate if (sig == SIGPROF && 4857c478bd9Sstevel@tonic-gate curthread->t_rprof != NULL && 4867c478bd9Sstevel@tonic-gate curthread->t_rprof->rp_anystate) { 4877c478bd9Sstevel@tonic-gate /* 4887c478bd9Sstevel@tonic-gate * We stand on our head to deal with 4897c478bd9Sstevel@tonic-gate * the real-time profiling signal. 4907c478bd9Sstevel@tonic-gate * Fill in the stuff that doesn't fit 4917c478bd9Sstevel@tonic-gate * in a normal k_siginfo structure. 4927c478bd9Sstevel@tonic-gate */ 4937c478bd9Sstevel@tonic-gate int i = sip->si_nsysarg; 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate while (--i >= 0) 4967c478bd9Sstevel@tonic-gate suword32_noerr(&(sip_addr->si_sysarg[i]), 4977c478bd9Sstevel@tonic-gate (uint32_t)lwp->lwp_arg[i]); 4987c478bd9Sstevel@tonic-gate copyout_noerr(curthread->t_rprof->rp_state, 4997c478bd9Sstevel@tonic-gate sip_addr->si_mstate, 5007c478bd9Sstevel@tonic-gate sizeof (curthread->t_rprof->rp_state)); 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate } else 5037c478bd9Sstevel@tonic-gate sip_addr = NULL; 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate /* save the current context on the user stack */ 5067c478bd9Sstevel@tonic-gate fp -= SA32(sizeof (*tuc)); 5077c478bd9Sstevel@tonic-gate uc = (ucontext32_t *)fp; 5087c478bd9Sstevel@tonic-gate tuc = kmem_alloc(sizeof (*tuc), KM_SLEEP); 509*bdf0047cSRoger A. Faulkner savecontext32(tuc, &lwp->lwp_sigoldmask); 5107c478bd9Sstevel@tonic-gate copyout_noerr(tuc, uc, sizeof (*tuc)); 5117c478bd9Sstevel@tonic-gate kmem_free(tuc, sizeof (*tuc)); 5127c478bd9Sstevel@tonic-gate tuc = NULL; 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate lwp->lwp_oldcontext = (uintptr_t)uc; 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate if (newstack) { 5177c478bd9Sstevel@tonic-gate lwp->lwp_sigaltstack.ss_flags |= SS_ONSTACK; 5187c478bd9Sstevel@tonic-gate if (lwp->lwp_ustack) { 5197c478bd9Sstevel@tonic-gate stack32_t stk32; 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate stk32.ss_sp = (caddr32_t)(uintptr_t) 5227c478bd9Sstevel@tonic-gate lwp->lwp_sigaltstack.ss_sp; 5237c478bd9Sstevel@tonic-gate stk32.ss_size = (size32_t) 5247c478bd9Sstevel@tonic-gate lwp->lwp_sigaltstack.ss_size; 5257c478bd9Sstevel@tonic-gate stk32.ss_flags = (int32_t) 5267c478bd9Sstevel@tonic-gate lwp->lwp_sigaltstack.ss_flags; 5277c478bd9Sstevel@tonic-gate copyout_noerr(&stk32, 5287c478bd9Sstevel@tonic-gate (stack32_t *)lwp->lwp_ustack, sizeof (stk32)); 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate /* 5337c478bd9Sstevel@tonic-gate * Set up signal handler arguments 5347c478bd9Sstevel@tonic-gate */ 5357c478bd9Sstevel@tonic-gate { 5367c478bd9Sstevel@tonic-gate struct sigframe32 frame32; 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate frame32.sip = (caddr32_t)(uintptr_t)sip_addr; 5397c478bd9Sstevel@tonic-gate frame32.ucp = (caddr32_t)(uintptr_t)uc; 5407c478bd9Sstevel@tonic-gate frame32.signo = sig; 5417c478bd9Sstevel@tonic-gate frame32.retaddr = 0xffffffff; /* never return! */ 5427c478bd9Sstevel@tonic-gate copyout_noerr(&frame32, sp, sizeof (frame32)); 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate no_fault(); 5467c478bd9Sstevel@tonic-gate if (watched) 5477c478bd9Sstevel@tonic-gate watch_enable_addr((caddr_t)sp, minstacksz, S_WRITE); 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate rp->r_sp = (greg_t)(uintptr_t)sp; 5507c478bd9Sstevel@tonic-gate rp->r_pc = (greg_t)(uintptr_t)hdlr; 5517c478bd9Sstevel@tonic-gate rp->r_ps = PSL_USER | (rp->r_ps & PS_IOPL); 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate if ((rp->r_cs & 0xffff) != U32CS_SEL || 5547c478bd9Sstevel@tonic-gate (rp->r_ss & 0xffff) != UDS_SEL) { 5557c478bd9Sstevel@tonic-gate /* 5567c478bd9Sstevel@tonic-gate * Try our best to deliver the signal. 5577c478bd9Sstevel@tonic-gate */ 5587c478bd9Sstevel@tonic-gate rp->r_cs = U32CS_SEL; 5597c478bd9Sstevel@tonic-gate rp->r_ss = UDS_SEL; 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate /* 5637c478bd9Sstevel@tonic-gate * Don't set lwp_eosys here. sendsig() is called via psig() after 5647c478bd9Sstevel@tonic-gate * lwp_eosys is handled, so setting it here would affect the next 5657c478bd9Sstevel@tonic-gate * system call. 5667c478bd9Sstevel@tonic-gate */ 5677c478bd9Sstevel@tonic-gate return (1); 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate badstack: 5707c478bd9Sstevel@tonic-gate no_fault(); 5717c478bd9Sstevel@tonic-gate if (watched) 5727c478bd9Sstevel@tonic-gate watch_enable_addr((caddr_t)sp, minstacksz, S_WRITE); 5737c478bd9Sstevel@tonic-gate if (tuc) 5747c478bd9Sstevel@tonic-gate kmem_free(tuc, sizeof (*tuc)); 5757c478bd9Sstevel@tonic-gate #ifdef DEBUG 5767c478bd9Sstevel@tonic-gate printf("sendsig32: bad signal stack cmd=%s pid=%d, sig=%d\n", 5777c478bd9Sstevel@tonic-gate PTOU(p)->u_comm, p->p_pid, sig); 5787c478bd9Sstevel@tonic-gate printf("on fault, sigsp = 0x%p, action = 0x%p, upc = 0x%lx\n", 5797c478bd9Sstevel@tonic-gate (void *)sp, (void *)hdlr, (uintptr_t)upc); 5807c478bd9Sstevel@tonic-gate #endif 5817c478bd9Sstevel@tonic-gate return (0); 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate #elif defined(__i386) 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate /* 5897c478bd9Sstevel@tonic-gate * An i386 SVR4/ABI signal frame looks like this on the stack: 5907c478bd9Sstevel@tonic-gate * 5917c478bd9Sstevel@tonic-gate * old %esp: 5927c478bd9Sstevel@tonic-gate * <a siginfo32_t [optional]> 5937c478bd9Sstevel@tonic-gate * <a ucontext32_t> 5947c478bd9Sstevel@tonic-gate * <pointer to that ucontext32_t> 5957c478bd9Sstevel@tonic-gate * <pointer to that siginfo32_t> 5967c478bd9Sstevel@tonic-gate * <signo> 5977c478bd9Sstevel@tonic-gate * new %esp: <return address (deliberately invalid)> 5987c478bd9Sstevel@tonic-gate */ 5997c478bd9Sstevel@tonic-gate struct sigframe { 6007c478bd9Sstevel@tonic-gate void (*retaddr)(); 6017c478bd9Sstevel@tonic-gate uint_t signo; 6027c478bd9Sstevel@tonic-gate siginfo_t *sip; 6037c478bd9Sstevel@tonic-gate ucontext_t *ucp; 6047c478bd9Sstevel@tonic-gate }; 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate int 6077c478bd9Sstevel@tonic-gate sendsig(int sig, k_siginfo_t *sip, void (*hdlr)()) 6087c478bd9Sstevel@tonic-gate { 6097c478bd9Sstevel@tonic-gate volatile int minstacksz; 6107c478bd9Sstevel@tonic-gate int newstack; 6117c478bd9Sstevel@tonic-gate label_t ljb; 6127c478bd9Sstevel@tonic-gate volatile caddr_t sp; 6137c478bd9Sstevel@tonic-gate caddr_t fp; 6147c478bd9Sstevel@tonic-gate struct regs *rp; 6157c478bd9Sstevel@tonic-gate volatile greg_t upc; 6167c478bd9Sstevel@tonic-gate volatile proc_t *p = ttoproc(curthread); 6177c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 6187c478bd9Sstevel@tonic-gate ucontext_t *volatile tuc = NULL; 6197c478bd9Sstevel@tonic-gate ucontext_t *uc; 6207c478bd9Sstevel@tonic-gate siginfo_t *sip_addr; 6217c478bd9Sstevel@tonic-gate volatile int watched; 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate rp = lwptoregs(lwp); 6247c478bd9Sstevel@tonic-gate upc = rp->r_pc; 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate minstacksz = SA(sizeof (struct sigframe)) + SA(sizeof (*uc)); 6277c478bd9Sstevel@tonic-gate if (sip != NULL) 6287c478bd9Sstevel@tonic-gate minstacksz += SA(sizeof (siginfo_t)); 6297c478bd9Sstevel@tonic-gate ASSERT((minstacksz & (STACK_ALIGN - 1ul)) == 0); 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate /* 6327c478bd9Sstevel@tonic-gate * Figure out whether we will be handling this signal on 6337c478bd9Sstevel@tonic-gate * an alternate stack specified by the user. Then allocate 6347c478bd9Sstevel@tonic-gate * and validate the stack requirements for the signal handler 6357c478bd9Sstevel@tonic-gate * context. on_fault will catch any faults. 6367c478bd9Sstevel@tonic-gate */ 637ae115bc7Smrj newstack = sigismember(&PTOU(curproc)->u_sigonstack, sig) && 6387c478bd9Sstevel@tonic-gate !(lwp->lwp_sigaltstack.ss_flags & (SS_ONSTACK|SS_DISABLE)); 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate if (newstack) { 6417c478bd9Sstevel@tonic-gate fp = (caddr_t)(SA((uintptr_t)lwp->lwp_sigaltstack.ss_sp) + 6427c478bd9Sstevel@tonic-gate SA(lwp->lwp_sigaltstack.ss_size) - STACK_ALIGN); 6437c478bd9Sstevel@tonic-gate } else if ((rp->r_ss & 0xffff) != UDS_SEL) { 6447c478bd9Sstevel@tonic-gate user_desc_t *ldt; 6457c478bd9Sstevel@tonic-gate /* 6467c478bd9Sstevel@tonic-gate * If the stack segment selector is -not- pointing at 6477c478bd9Sstevel@tonic-gate * the UDS_SEL descriptor and we have an LDT entry for 6487c478bd9Sstevel@tonic-gate * it instead, add the base address to find the effective va. 6497c478bd9Sstevel@tonic-gate */ 6507c478bd9Sstevel@tonic-gate if ((ldt = p->p_ldt) != NULL) 6517c478bd9Sstevel@tonic-gate fp = (caddr_t)rp->r_sp + 6527c478bd9Sstevel@tonic-gate USEGD_GETBASE(&ldt[SELTOIDX(rp->r_ss)]); 6537c478bd9Sstevel@tonic-gate else 6547c478bd9Sstevel@tonic-gate fp = (caddr_t)rp->r_sp; 6557c478bd9Sstevel@tonic-gate } else 6567c478bd9Sstevel@tonic-gate fp = (caddr_t)rp->r_sp; 657a3c55825Sraf 658a3c55825Sraf /* 659a3c55825Sraf * Force proper stack pointer alignment, even in the face of a 660a3c55825Sraf * misaligned stack pointer from user-level before the signal. 661a3c55825Sraf * Don't use the SA() macro because that rounds up, not down. 662a3c55825Sraf */ 663a3c55825Sraf fp = (caddr_t)((uintptr_t)fp & ~(STACK_ALIGN - 1ul)); 6647c478bd9Sstevel@tonic-gate sp = fp - minstacksz; 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate /* 6677c478bd9Sstevel@tonic-gate * Make sure lwp hasn't trashed its stack. 6687c478bd9Sstevel@tonic-gate */ 669a3c55825Sraf if (sp >= (caddr_t)USERLIMIT || fp >= (caddr_t)USERLIMIT) { 6707c478bd9Sstevel@tonic-gate #ifdef DEBUG 6717c478bd9Sstevel@tonic-gate printf("sendsig: bad signal stack cmd=%s, pid=%d, sig=%d\n", 6727c478bd9Sstevel@tonic-gate PTOU(p)->u_comm, p->p_pid, sig); 6737c478bd9Sstevel@tonic-gate printf("sigsp = 0x%p, action = 0x%p, upc = 0x%lx\n", 6747c478bd9Sstevel@tonic-gate (void *)sp, (void *)hdlr, (uintptr_t)upc); 6757c478bd9Sstevel@tonic-gate printf("sp above USERLIMIT\n"); 6767c478bd9Sstevel@tonic-gate #endif 6777c478bd9Sstevel@tonic-gate return (0); 6787c478bd9Sstevel@tonic-gate } 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate watched = watch_disable_addr((caddr_t)sp, minstacksz, S_WRITE); 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate if (on_fault(&ljb)) 6837c478bd9Sstevel@tonic-gate goto badstack; 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate if (sip != NULL) { 6867c478bd9Sstevel@tonic-gate zoneid_t zoneid; 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate fp -= SA(sizeof (siginfo_t)); 6897c478bd9Sstevel@tonic-gate uzero(fp, sizeof (siginfo_t)); 6907c478bd9Sstevel@tonic-gate if (SI_FROMUSER(sip) && 6917c478bd9Sstevel@tonic-gate (zoneid = p->p_zone->zone_id) != GLOBAL_ZONEID && 6927c478bd9Sstevel@tonic-gate zoneid != sip->si_zoneid) { 6937c478bd9Sstevel@tonic-gate k_siginfo_t sani_sip = *sip; 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate sani_sip.si_pid = p->p_zone->zone_zsched->p_pid; 6967c478bd9Sstevel@tonic-gate sani_sip.si_uid = 0; 6977c478bd9Sstevel@tonic-gate sani_sip.si_ctid = -1; 6987c478bd9Sstevel@tonic-gate sani_sip.si_zoneid = zoneid; 6997c478bd9Sstevel@tonic-gate copyout_noerr(&sani_sip, fp, sizeof (sani_sip)); 7007c478bd9Sstevel@tonic-gate } else 7017c478bd9Sstevel@tonic-gate copyout_noerr(sip, fp, sizeof (*sip)); 7027c478bd9Sstevel@tonic-gate sip_addr = (siginfo_t *)fp; 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate if (sig == SIGPROF && 7057c478bd9Sstevel@tonic-gate curthread->t_rprof != NULL && 7067c478bd9Sstevel@tonic-gate curthread->t_rprof->rp_anystate) { 7077c478bd9Sstevel@tonic-gate /* 7087c478bd9Sstevel@tonic-gate * We stand on our head to deal with 7097c478bd9Sstevel@tonic-gate * the real time profiling signal. 7107c478bd9Sstevel@tonic-gate * Fill in the stuff that doesn't fit 7117c478bd9Sstevel@tonic-gate * in a normal k_siginfo structure. 7127c478bd9Sstevel@tonic-gate */ 7137c478bd9Sstevel@tonic-gate int i = sip->si_nsysarg; 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate while (--i >= 0) 7167c478bd9Sstevel@tonic-gate suword32_noerr(&(sip_addr->si_sysarg[i]), 7177c478bd9Sstevel@tonic-gate (uint32_t)lwp->lwp_arg[i]); 7187c478bd9Sstevel@tonic-gate copyout_noerr(curthread->t_rprof->rp_state, 7197c478bd9Sstevel@tonic-gate sip_addr->si_mstate, 7207c478bd9Sstevel@tonic-gate sizeof (curthread->t_rprof->rp_state)); 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate } else 7237c478bd9Sstevel@tonic-gate sip_addr = NULL; 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate /* save the current context on the user stack */ 7267c478bd9Sstevel@tonic-gate fp -= SA(sizeof (*tuc)); 7277c478bd9Sstevel@tonic-gate uc = (ucontext_t *)fp; 7287c478bd9Sstevel@tonic-gate tuc = kmem_alloc(sizeof (*tuc), KM_SLEEP); 729*bdf0047cSRoger A. Faulkner savecontext(tuc, &lwp->lwp_sigoldmask); 7307c478bd9Sstevel@tonic-gate copyout_noerr(tuc, uc, sizeof (*tuc)); 7317c478bd9Sstevel@tonic-gate kmem_free(tuc, sizeof (*tuc)); 7327c478bd9Sstevel@tonic-gate tuc = NULL; 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate lwp->lwp_oldcontext = (uintptr_t)uc; 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate if (newstack) { 7377c478bd9Sstevel@tonic-gate lwp->lwp_sigaltstack.ss_flags |= SS_ONSTACK; 7387c478bd9Sstevel@tonic-gate if (lwp->lwp_ustack) 7397c478bd9Sstevel@tonic-gate copyout_noerr(&lwp->lwp_sigaltstack, 7407c478bd9Sstevel@tonic-gate (stack_t *)lwp->lwp_ustack, sizeof (stack_t)); 7417c478bd9Sstevel@tonic-gate } 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate /* 7447c478bd9Sstevel@tonic-gate * Set up signal handler arguments 7457c478bd9Sstevel@tonic-gate */ 7467c478bd9Sstevel@tonic-gate { 7477c478bd9Sstevel@tonic-gate struct sigframe frame; 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate frame.sip = sip_addr; 7507c478bd9Sstevel@tonic-gate frame.ucp = uc; 7517c478bd9Sstevel@tonic-gate frame.signo = sig; 7527c478bd9Sstevel@tonic-gate frame.retaddr = (void (*)())0xffffffff; /* never return! */ 7537c478bd9Sstevel@tonic-gate copyout_noerr(&frame, sp, sizeof (frame)); 7547c478bd9Sstevel@tonic-gate } 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate no_fault(); 7577c478bd9Sstevel@tonic-gate if (watched) 7587c478bd9Sstevel@tonic-gate watch_enable_addr((caddr_t)sp, minstacksz, S_WRITE); 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate rp->r_sp = (greg_t)sp; 7617c478bd9Sstevel@tonic-gate rp->r_pc = (greg_t)hdlr; 7627c478bd9Sstevel@tonic-gate rp->r_ps = PSL_USER | (rp->r_ps & PS_IOPL); 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate if ((rp->r_cs & 0xffff) != UCS_SEL || 7657c478bd9Sstevel@tonic-gate (rp->r_ss & 0xffff) != UDS_SEL) { 7667c478bd9Sstevel@tonic-gate rp->r_cs = UCS_SEL; 7677c478bd9Sstevel@tonic-gate rp->r_ss = UDS_SEL; 7687c478bd9Sstevel@tonic-gate } 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate /* 7717c478bd9Sstevel@tonic-gate * Don't set lwp_eosys here. sendsig() is called via psig() after 7727c478bd9Sstevel@tonic-gate * lwp_eosys is handled, so setting it here would affect the next 7737c478bd9Sstevel@tonic-gate * system call. 7747c478bd9Sstevel@tonic-gate */ 7757c478bd9Sstevel@tonic-gate return (1); 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate badstack: 7787c478bd9Sstevel@tonic-gate no_fault(); 7797c478bd9Sstevel@tonic-gate if (watched) 7807c478bd9Sstevel@tonic-gate watch_enable_addr((caddr_t)sp, minstacksz, S_WRITE); 7817c478bd9Sstevel@tonic-gate if (tuc) 7827c478bd9Sstevel@tonic-gate kmem_free(tuc, sizeof (*tuc)); 7837c478bd9Sstevel@tonic-gate #ifdef DEBUG 7847c478bd9Sstevel@tonic-gate printf("sendsig: bad signal stack cmd=%s, pid=%d, sig=%d\n", 7857c478bd9Sstevel@tonic-gate PTOU(p)->u_comm, p->p_pid, sig); 7867c478bd9Sstevel@tonic-gate printf("on fault, sigsp = 0x%p, action = 0x%p, upc = 0x%lx\n", 7877c478bd9Sstevel@tonic-gate (void *)sp, (void *)hdlr, (uintptr_t)upc); 7887c478bd9Sstevel@tonic-gate #endif 7897c478bd9Sstevel@tonic-gate return (0); 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate #endif /* __i386 */ 793