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 2007 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 
     31 #pragma ident	"@(#)sigaction.c	1.16	07/01/10 SMI"
     32 
     33 #include <sys/param.h>
     34 #include <sys/types.h>
     35 #include <sys/sysmacros.h>
     36 #include <sys/systm.h>
     37 #include <sys/user.h>
     38 #include <sys/errno.h>
     39 #include <sys/proc.h>
     40 #include <sys/fault.h>
     41 #include <sys/signal.h>
     42 #include <sys/siginfo.h>
     43 #include <sys/debug.h>
     44 
     45 int
     46 sigaction(int sig, struct sigaction *actp, struct sigaction *oactp)
     47 {
     48 	struct sigaction act;
     49 	struct sigaction oact;
     50 	k_sigset_t set;
     51 	proc_t *p;
     52 	user_t *ua;
     53 	int sigcld_look = 0;
     54 
     55 	if (sig <= 0 || sig >= NSIG ||
     56 	    (actp != NULL && sigismember(&cantmask, sig)))
     57 		return (set_errno(EINVAL));
     58 
     59 	/*
     60 	 * act and oact might be the same address, so copyin act first.
     61 	 */
     62 	if (actp) {
     63 #if defined(__sparc)
     64 		void (*handler)();
     65 #endif
     66 		if (copyin(actp, &act, sizeof (act)))
     67 			return (set_errno(EFAULT));
     68 #if defined(__sparc)
     69 		/*
     70 		 * Check alignment of handler
     71 		 */
     72 		handler = act.sa_handler;
     73 		if (handler != SIG_IGN && handler != SIG_DFL &&
     74 		    ((uintptr_t)handler & 0x3) != 0)
     75 			return (set_errno(EINVAL));
     76 #endif
     77 	}
     78 
     79 	p = curproc;
     80 	ua = PTOU(p);
     81 	mutex_enter(&p->p_lock);
     82 
     83 	if (oactp) {
     84 		int flags;
     85 		void (*disp)();
     86 
     87 		disp = ua->u_signal[sig - 1];
     88 
     89 		flags = 0;
     90 		if (disp != SIG_DFL && disp != SIG_IGN) {
     91 			set = ua->u_sigmask[sig-1];
     92 			if (sigismember(&p->p_siginfo, sig))
     93 				flags |= SA_SIGINFO;
     94 			if (sigismember(&ua->u_sigrestart, sig))
     95 				flags |= SA_RESTART;
     96 			if (sigismember(&ua->u_sigonstack, sig))
     97 				flags |= SA_ONSTACK;
     98 			if (sigismember(&ua->u_sigresethand, sig))
     99 				flags |= SA_RESETHAND;
    100 			if (sigismember(&ua->u_signodefer, sig))
    101 				flags |= SA_NODEFER;
    102 		} else
    103 			sigemptyset(&set);
    104 
    105 		if (sig == SIGCLD) {
    106 			if (p->p_flag & SNOWAIT)
    107 				flags |= SA_NOCLDWAIT;
    108 			if (!(p->p_flag & SJCTL))
    109 				flags |= SA_NOCLDSTOP;
    110 		}
    111 
    112 		oact.sa_handler = disp;
    113 		oact.sa_flags = flags;
    114 		sigktou(&set, &oact.sa_mask);
    115 	}
    116 
    117 	if (actp) {
    118 		if (sig == SIGCLD &&
    119 		    act.sa_handler != SIG_IGN &&
    120 		    act.sa_handler != SIG_DFL)
    121 			sigcld_look = 1;
    122 
    123 		sigutok(&act.sa_mask, &set);
    124 		setsigact(sig, act.sa_handler, set, act.sa_flags);
    125 	}
    126 
    127 	mutex_exit(&p->p_lock);
    128 
    129 	if (sigcld_look)
    130 		sigcld_repost();
    131 
    132 	if (oactp &&
    133 	    copyout(&oact, oactp, sizeof (oact)))
    134 		return (set_errno(EFAULT));
    135 
    136 	return (0);
    137 }
    138 
    139 #ifdef _SYSCALL32_IMPL
    140 
    141 int
    142 sigaction32(int sig, struct sigaction32 *actp, struct sigaction32 *oactp)
    143 {
    144 	struct sigaction32 act32;
    145 	struct sigaction32 oact32;
    146 	k_sigset_t set;
    147 	proc_t *p;
    148 	user_t *ua;
    149 	int sigcld_look = 0;
    150 
    151 	if (sig <= 0 || sig >= NSIG ||
    152 	    (actp != NULL && sigismember(&cantmask, sig)))
    153 		return (set_errno(EINVAL));
    154 
    155 	/*
    156 	 * act and oact might be the same address, so copyin act first.
    157 	 */
    158 	if (actp) {
    159 #if defined(__sparc)
    160 		void (*handler)();
    161 #endif
    162 		if (copyin(actp, &act32, sizeof (act32)))
    163 			return (set_errno(EFAULT));
    164 #if defined(__sparc)
    165 		/*
    166 		 * Check alignment of handler
    167 		 */
    168 		handler = (void (*)())(uintptr_t)act32.sa_handler;
    169 		if (handler != SIG_IGN && handler != SIG_DFL &&
    170 		    ((uintptr_t)handler & 0x3) != 0)
    171 			return (set_errno(EINVAL));
    172 #endif
    173 	}
    174 
    175 	p = curproc;
    176 	ua = PTOU(p);
    177 	mutex_enter(&p->p_lock);
    178 
    179 	if (oactp) {
    180 		int flags;
    181 		void (*disp)();
    182 
    183 		disp = ua->u_signal[sig - 1];
    184 
    185 		flags = 0;
    186 		if (disp != SIG_DFL && disp != SIG_IGN) {
    187 			set = ua->u_sigmask[sig-1];
    188 			if (sigismember(&p->p_siginfo, sig))
    189 				flags |= SA_SIGINFO;
    190 			if (sigismember(&ua->u_sigrestart, sig))
    191 				flags |= SA_RESTART;
    192 			if (sigismember(&ua->u_sigonstack, sig))
    193 				flags |= SA_ONSTACK;
    194 			if (sigismember(&ua->u_sigresethand, sig))
    195 				flags |= SA_RESETHAND;
    196 			if (sigismember(&ua->u_signodefer, sig))
    197 				flags |= SA_NODEFER;
    198 		} else
    199 			sigemptyset(&set);
    200 
    201 		if (sig == SIGCLD) {
    202 			if (p->p_flag & SNOWAIT)
    203 				flags |= SA_NOCLDWAIT;
    204 			if (!(p->p_flag & SJCTL))
    205 				flags |= SA_NOCLDSTOP;
    206 		}
    207 
    208 		oact32.sa_handler = (caddr32_t)(uintptr_t)disp;
    209 		oact32.sa_flags = flags;
    210 		sigktou(&set, &oact32.sa_mask);
    211 	}
    212 
    213 	if (actp) {
    214 		if (sig == SIGCLD &&
    215 		    act32.sa_handler != (caddr32_t)SIG_IGN &&
    216 		    act32.sa_handler != (caddr32_t)SIG_DFL)
    217 			sigcld_look = 1;
    218 
    219 		sigutok(&act32.sa_mask, &set);
    220 		setsigact(sig, (void (*)())(uintptr_t)act32.sa_handler, set,
    221 		    act32.sa_flags);
    222 	}
    223 
    224 	mutex_exit(&p->p_lock);
    225 
    226 	if (sigcld_look)
    227 		sigcld_repost();
    228 
    229 	if (oactp &&
    230 	    copyout(&oact32, oactp, sizeof (oact32)))
    231 		return (set_errno(EFAULT));
    232 
    233 	return (0);
    234 }
    235 #endif /* _SYSCALL32_IMPL */
    236