Home | History | Annotate | Download | only in syscall
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     28 /*	  All Rights Reserved	*/
     29 
     30 #include <sys/param.h>
     31 #include <sys/types.h>
     32 #include <sys/sysmacros.h>
     33 #include <sys/systm.h>
     34 #include <sys/user.h>
     35 #include <sys/errno.h>
     36 #include <sys/proc.h>
     37 #include <sys/fault.h>
     38 #include <sys/signal.h>
     39 #include <sys/siginfo.h>
     40 #include <sys/debug.h>
     41 
     42 int
     43 sigaction(int sig, struct sigaction *actp, struct sigaction *oactp)
     44 {
     45 	struct sigaction act;
     46 	struct sigaction oact;
     47 	k_sigset_t set;
     48 	proc_t *p;
     49 	user_t *ua;
     50 	int sigcld_look = 0;
     51 
     52 	if (sig <= 0 || sig >= NSIG ||
     53 	    (actp != NULL && sigismember(&cantmask, sig)))
     54 		return (set_errno(EINVAL));
     55 
     56 	/*
     57 	 * act and oact might be the same address, so copyin act first.
     58 	 */
     59 	if (actp) {
     60 #if defined(__sparc)
     61 		void (*handler)();
     62 #endif
     63 		if (copyin(actp, &act, sizeof (act)))
     64 			return (set_errno(EFAULT));
     65 #if defined(__sparc)
     66 		/*
     67 		 * Check alignment of handler
     68 		 */
     69 		handler = act.sa_handler;
     70 		if (handler != SIG_IGN && handler != SIG_DFL &&
     71 		    ((uintptr_t)handler & 0x3) != 0)
     72 			return (set_errno(EINVAL));
     73 #endif
     74 	}
     75 
     76 	p = curproc;
     77 	ua = PTOU(p);
     78 	mutex_enter(&p->p_lock);
     79 
     80 	if (oactp) {
     81 		int flags;
     82 		void (*disp)();
     83 
     84 		disp = ua->u_signal[sig - 1];
     85 
     86 		flags = 0;
     87 		if (disp != SIG_DFL && disp != SIG_IGN) {
     88 			set = ua->u_sigmask[sig-1];
     89 			if (sigismember(&p->p_siginfo, sig))
     90 				flags |= SA_SIGINFO;
     91 			if (sigismember(&ua->u_sigrestart, sig))
     92 				flags |= SA_RESTART;
     93 			if (sigismember(&ua->u_sigonstack, sig))
     94 				flags |= SA_ONSTACK;
     95 			if (sigismember(&ua->u_sigresethand, sig))
     96 				flags |= SA_RESETHAND;
     97 			if (sigismember(&ua->u_signodefer, sig))
     98 				flags |= SA_NODEFER;
     99 		} else
    100 			sigemptyset(&set);
    101 
    102 		if (sig == SIGCLD) {
    103 			if (p->p_flag & SNOWAIT)
    104 				flags |= SA_NOCLDWAIT;
    105 			if (!(p->p_flag & SJCTL))
    106 				flags |= SA_NOCLDSTOP;
    107 		}
    108 
    109 		oact.sa_handler = disp;
    110 		oact.sa_flags = flags;
    111 		sigktou(&set, &oact.sa_mask);
    112 	}
    113 
    114 	if (actp) {
    115 		if (sig == SIGCLD)
    116 			sigcld_look = 1;
    117 		sigutok(&act.sa_mask, &set);
    118 		setsigact(sig, act.sa_handler, set, act.sa_flags);
    119 	}
    120 
    121 	mutex_exit(&p->p_lock);
    122 
    123 	if (sigcld_look)
    124 		sigcld_repost();
    125 
    126 	if (oactp &&
    127 	    copyout(&oact, oactp, sizeof (oact)))
    128 		return (set_errno(EFAULT));
    129 
    130 	return (0);
    131 }
    132 
    133 #ifdef _SYSCALL32_IMPL
    134 
    135 int
    136 sigaction32(int sig, struct sigaction32 *actp, struct sigaction32 *oactp)
    137 {
    138 	struct sigaction32 act32;
    139 	struct sigaction32 oact32;
    140 	k_sigset_t set;
    141 	proc_t *p;
    142 	user_t *ua;
    143 	int sigcld_look = 0;
    144 
    145 	if (sig <= 0 || sig >= NSIG ||
    146 	    (actp != NULL && sigismember(&cantmask, sig)))
    147 		return (set_errno(EINVAL));
    148 
    149 	/*
    150 	 * act and oact might be the same address, so copyin act first.
    151 	 */
    152 	if (actp) {
    153 #if defined(__sparc)
    154 		void (*handler)();
    155 #endif
    156 		if (copyin(actp, &act32, sizeof (act32)))
    157 			return (set_errno(EFAULT));
    158 #if defined(__sparc)
    159 		/*
    160 		 * Check alignment of handler
    161 		 */
    162 		handler = (void (*)())(uintptr_t)act32.sa_handler;
    163 		if (handler != SIG_IGN && handler != SIG_DFL &&
    164 		    ((uintptr_t)handler & 0x3) != 0)
    165 			return (set_errno(EINVAL));
    166 #endif
    167 	}
    168 
    169 	p = curproc;
    170 	ua = PTOU(p);
    171 	mutex_enter(&p->p_lock);
    172 
    173 	if (oactp) {
    174 		int flags;
    175 		void (*disp)();
    176 
    177 		disp = ua->u_signal[sig - 1];
    178 
    179 		flags = 0;
    180 		if (disp != SIG_DFL && disp != SIG_IGN) {
    181 			set = ua->u_sigmask[sig-1];
    182 			if (sigismember(&p->p_siginfo, sig))
    183 				flags |= SA_SIGINFO;
    184 			if (sigismember(&ua->u_sigrestart, sig))
    185 				flags |= SA_RESTART;
    186 			if (sigismember(&ua->u_sigonstack, sig))
    187 				flags |= SA_ONSTACK;
    188 			if (sigismember(&ua->u_sigresethand, sig))
    189 				flags |= SA_RESETHAND;
    190 			if (sigismember(&ua->u_signodefer, sig))
    191 				flags |= SA_NODEFER;
    192 		} else
    193 			sigemptyset(&set);
    194 
    195 		if (sig == SIGCLD) {
    196 			if (p->p_flag & SNOWAIT)
    197 				flags |= SA_NOCLDWAIT;
    198 			if (!(p->p_flag & SJCTL))
    199 				flags |= SA_NOCLDSTOP;
    200 		}
    201 
    202 		oact32.sa_handler = (caddr32_t)(uintptr_t)disp;
    203 		oact32.sa_flags = flags;
    204 		sigktou(&set, &oact32.sa_mask);
    205 	}
    206 
    207 	if (actp) {
    208 		if (sig == SIGCLD)
    209 			sigcld_look = 1;
    210 		sigutok(&act32.sa_mask, &set);
    211 		setsigact(sig, (void (*)())(uintptr_t)act32.sa_handler, set,
    212 		    act32.sa_flags);
    213 	}
    214 
    215 	mutex_exit(&p->p_lock);
    216 
    217 	if (sigcld_look)
    218 		sigcld_repost();
    219 
    220 	if (oactp &&
    221 	    copyout(&oact32, oactp, sizeof (oact32)))
    222 		return (set_errno(EFAULT));
    223 
    224 	return (0);
    225 }
    226 #endif /* _SYSCALL32_IMPL */
    227