xref: /illumos-gate/usr/src/uts/common/syscall/sigaction.c (revision 4de2612967d06c4fdbf524a62556a1e8118a006f)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 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	"%Z%%M%	%I%	%E% 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 	int sigcld_look = 0;
53 
54 	if (sig <= 0 || sig >= NSIG ||
55 	    (actp != NULL && sigismember(&cantmask, sig)))
56 		return (set_errno(EINVAL));
57 
58 	/*
59 	 * act and oact might be the same address, so copyin act first.
60 	 */
61 	if (actp) {
62 #if defined(__sparc)
63 		void (*handler)();
64 #endif
65 		if (copyin(actp, &act, sizeof (act)))
66 			return (set_errno(EFAULT));
67 #if defined(__sparc)
68 		/*
69 		 * Check alignment of handler
70 		 */
71 		handler = act.sa_handler;
72 		if (handler != SIG_IGN && handler != SIG_DFL &&
73 		    ((uintptr_t)handler & 0x3) != 0)
74 			return (set_errno(EINVAL));
75 #endif
76 	}
77 
78 	p = curproc;
79 	mutex_enter(&p->p_lock);
80 
81 	if (oactp) {
82 		int flags;
83 		void (*disp)();
84 
85 		disp = u.u_signal[sig - 1];
86 
87 		flags = 0;
88 		if (disp != SIG_DFL && disp != SIG_IGN) {
89 			set = u.u_sigmask[sig-1];
90 			if (sigismember(&p->p_siginfo, sig))
91 				flags |= SA_SIGINFO;
92 			if (sigismember(&u.u_sigrestart, sig))
93 				flags |= SA_RESTART;
94 			if (sigismember(&u.u_sigonstack, sig))
95 				flags |= SA_ONSTACK;
96 			if (sigismember(&u.u_sigresethand, sig))
97 				flags |= SA_RESETHAND;
98 			if (sigismember(&u.u_signodefer, sig))
99 				flags |= SA_NODEFER;
100 		} else
101 			sigemptyset(&set);
102 
103 		if (sig == SIGCLD) {
104 			if (p->p_flag & SNOWAIT)
105 				flags |= SA_NOCLDWAIT;
106 			if (!(p->p_flag & SJCTL))
107 				flags |= SA_NOCLDSTOP;
108 		}
109 
110 		oact.sa_handler = disp;
111 		oact.sa_flags = flags;
112 		sigktou(&set, &oact.sa_mask);
113 	}
114 
115 	if (actp) {
116 		if (sig == SIGCLD &&
117 		    act.sa_handler != SIG_IGN &&
118 		    act.sa_handler != SIG_DFL)
119 			sigcld_look = 1;
120 
121 		sigutok(&act.sa_mask, &set);
122 		setsigact(sig, act.sa_handler, set, act.sa_flags);
123 	}
124 
125 	mutex_exit(&p->p_lock);
126 
127 	if (sigcld_look)
128 		sigcld_repost();
129 
130 	if (oactp &&
131 	    copyout(&oact, oactp, sizeof (oact)))
132 		return (set_errno(EFAULT));
133 
134 	return (0);
135 }
136 
137 #ifdef _SYSCALL32_IMPL
138 
139 int
140 sigaction32(int sig, struct sigaction32 *actp, struct sigaction32 *oactp)
141 {
142 	struct sigaction32 act32;
143 	struct sigaction32 oact32;
144 	k_sigset_t set;
145 	proc_t *p;
146 	int sigcld_look = 0;
147 
148 	if (sig <= 0 || sig >= NSIG ||
149 	    (actp != NULL && sigismember(&cantmask, sig)))
150 		return (set_errno(EINVAL));
151 
152 	/*
153 	 * act and oact might be the same address, so copyin act first.
154 	 */
155 	if (actp) {
156 #if defined(__sparc)
157 		void (*handler)();
158 #endif
159 		if (copyin(actp, &act32, sizeof (act32)))
160 			return (set_errno(EFAULT));
161 #if defined(__sparc)
162 		/*
163 		 * Check alignment of handler
164 		 */
165 		handler = (void (*)())act32.sa_handler;
166 		if (handler != SIG_IGN && handler != SIG_DFL &&
167 		    ((uintptr_t)handler & 0x3) != 0)
168 			return (set_errno(EINVAL));
169 #endif
170 	}
171 
172 	p = curproc;
173 	mutex_enter(&p->p_lock);
174 
175 	if (oactp) {
176 		int flags;
177 		void (*disp)();
178 
179 		disp = u.u_signal[sig - 1];
180 
181 		flags = 0;
182 		if (disp != SIG_DFL && disp != SIG_IGN) {
183 			set = u.u_sigmask[sig-1];
184 			if (sigismember(&p->p_siginfo, sig))
185 				flags |= SA_SIGINFO;
186 			if (sigismember(&u.u_sigrestart, sig))
187 				flags |= SA_RESTART;
188 			if (sigismember(&u.u_sigonstack, sig))
189 				flags |= SA_ONSTACK;
190 			if (sigismember(&u.u_sigresethand, sig))
191 				flags |= SA_RESETHAND;
192 			if (sigismember(&u.u_signodefer, sig))
193 				flags |= SA_NODEFER;
194 		} else
195 			sigemptyset(&set);
196 
197 		if (sig == SIGCLD) {
198 			if (p->p_flag & SNOWAIT)
199 				flags |= SA_NOCLDWAIT;
200 			if (!(p->p_flag & SJCTL))
201 				flags |= SA_NOCLDSTOP;
202 		}
203 
204 		oact32.sa_handler = (caddr32_t)(uintptr_t)disp;
205 		oact32.sa_flags = flags;
206 		sigktou(&set, &oact32.sa_mask);
207 	}
208 
209 	if (actp) {
210 		if (sig == SIGCLD &&
211 		    act32.sa_handler != (caddr32_t)SIG_IGN &&
212 		    act32.sa_handler != (caddr32_t)SIG_DFL)
213 			sigcld_look = 1;
214 
215 		sigutok(&act32.sa_mask, &set);
216 		setsigact(sig, (void (*)())(uintptr_t)act32.sa_handler, set,
217 		    act32.sa_flags);
218 	}
219 
220 	mutex_exit(&p->p_lock);
221 
222 	if (sigcld_look)
223 		sigcld_repost();
224 
225 	if (oactp &&
226 	    copyout(&oact32, oactp, sizeof (oact32)))
227 		return (set_errno(EFAULT));
228 
229 	return (0);
230 }
231 #endif /* _SYSCALL32_IMPL */
232