xref: /illumos-gate/usr/src/uts/common/syscall/sigaction.c (revision 141040e8a310da49386b596573e5dde5580572ec)
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 /*
24  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
29 /*	  All Rights Reserved	*/
30 
31 
32 #pragma ident	"%Z%%M%	%I%	%E% SMI"
33 
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/sysmacros.h>
37 #include <sys/systm.h>
38 #include <sys/user.h>
39 #include <sys/errno.h>
40 #include <sys/proc.h>
41 #include <sys/fault.h>
42 #include <sys/signal.h>
43 #include <sys/siginfo.h>
44 #include <sys/debug.h>
45 
46 int
47 sigaction(int sig, struct sigaction *actp, struct sigaction *oactp)
48 {
49 	struct sigaction act;
50 	struct sigaction oact;
51 	k_sigset_t set;
52 	proc_t *p;
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 	mutex_enter(&p->p_lock);
81 
82 	if (oactp) {
83 		int flags;
84 		void (*disp)();
85 
86 		disp = u.u_signal[sig - 1];
87 
88 		flags = 0;
89 		if (disp != SIG_DFL && disp != SIG_IGN) {
90 			set = u.u_sigmask[sig-1];
91 			if (sigismember(&p->p_siginfo, sig))
92 				flags |= SA_SIGINFO;
93 			if (sigismember(&u.u_sigrestart, sig))
94 				flags |= SA_RESTART;
95 			if (sigismember(&u.u_sigonstack, sig))
96 				flags |= SA_ONSTACK;
97 			if (sigismember(&u.u_sigresethand, sig))
98 				flags |= SA_RESETHAND;
99 			if (sigismember(&u.u_signodefer, sig))
100 				flags |= SA_NODEFER;
101 		} else
102 			sigemptyset(&set);
103 
104 		if (sig == SIGCLD) {
105 			if (p->p_flag & SNOWAIT)
106 				flags |= SA_NOCLDWAIT;
107 			if (!(p->p_flag & SJCTL))
108 				flags |= SA_NOCLDSTOP;
109 		}
110 
111 		oact.sa_handler = disp;
112 		oact.sa_flags = flags;
113 		sigktou(&set, &oact.sa_mask);
114 	}
115 
116 	if (actp) {
117 		if (sig == SIGCLD &&
118 		    act.sa_handler != SIG_IGN &&
119 		    act.sa_handler != SIG_DFL)
120 			sigcld_look = 1;
121 
122 		sigutok(&act.sa_mask, &set);
123 		setsigact(sig, act.sa_handler, set, act.sa_flags);
124 	}
125 
126 	mutex_exit(&p->p_lock);
127 
128 	if (sigcld_look)
129 		sigcld_repost();
130 
131 	if (oactp &&
132 	    copyout(&oact, oactp, sizeof (oact)))
133 		return (set_errno(EFAULT));
134 
135 	return (0);
136 }
137 
138 #ifdef _SYSCALL32_IMPL
139 
140 int
141 sigaction32(int sig, struct sigaction32 *actp, struct sigaction32 *oactp)
142 {
143 	struct sigaction32 act32;
144 	struct sigaction32 oact32;
145 	k_sigset_t set;
146 	proc_t *p;
147 	int sigcld_look = 0;
148 
149 	if (sig <= 0 || sig >= NSIG ||
150 	    (actp != NULL && sigismember(&cantmask, sig)))
151 		return (set_errno(EINVAL));
152 
153 	/*
154 	 * act and oact might be the same address, so copyin act first.
155 	 */
156 	if (actp) {
157 #if defined(__sparc)
158 		void (*handler)();
159 #endif
160 		if (copyin(actp, &act32, sizeof (act32)))
161 			return (set_errno(EFAULT));
162 #if defined(__sparc)
163 		/*
164 		 * Check alignment of handler
165 		 */
166 		handler = (void (*)())(uintptr_t)act32.sa_handler;
167 		if (handler != SIG_IGN && handler != SIG_DFL &&
168 		    ((uintptr_t)handler & 0x3) != 0)
169 			return (set_errno(EINVAL));
170 #endif
171 	}
172 
173 	p = curproc;
174 	mutex_enter(&p->p_lock);
175 
176 	if (oactp) {
177 		int flags;
178 		void (*disp)();
179 
180 		disp = u.u_signal[sig - 1];
181 
182 		flags = 0;
183 		if (disp != SIG_DFL && disp != SIG_IGN) {
184 			set = u.u_sigmask[sig-1];
185 			if (sigismember(&p->p_siginfo, sig))
186 				flags |= SA_SIGINFO;
187 			if (sigismember(&u.u_sigrestart, sig))
188 				flags |= SA_RESTART;
189 			if (sigismember(&u.u_sigonstack, sig))
190 				flags |= SA_ONSTACK;
191 			if (sigismember(&u.u_sigresethand, sig))
192 				flags |= SA_RESETHAND;
193 			if (sigismember(&u.u_signodefer, sig))
194 				flags |= SA_NODEFER;
195 		} else
196 			sigemptyset(&set);
197 
198 		if (sig == SIGCLD) {
199 			if (p->p_flag & SNOWAIT)
200 				flags |= SA_NOCLDWAIT;
201 			if (!(p->p_flag & SJCTL))
202 				flags |= SA_NOCLDSTOP;
203 		}
204 
205 		oact32.sa_handler = (caddr32_t)(uintptr_t)disp;
206 		oact32.sa_flags = flags;
207 		sigktou(&set, &oact32.sa_mask);
208 	}
209 
210 	if (actp) {
211 		if (sig == SIGCLD &&
212 		    act32.sa_handler != (caddr32_t)SIG_IGN &&
213 		    act32.sa_handler != (caddr32_t)SIG_DFL)
214 			sigcld_look = 1;
215 
216 		sigutok(&act32.sa_mask, &set);
217 		setsigact(sig, (void (*)())(uintptr_t)act32.sa_handler, set,
218 		    act32.sa_flags);
219 	}
220 
221 	mutex_exit(&p->p_lock);
222 
223 	if (sigcld_look)
224 		sigcld_repost();
225 
226 	if (oactp &&
227 	    copyout(&oact32, oactp, sizeof (oact32)))
228 		return (set_errno(EFAULT));
229 
230 	return (0);
231 }
232 #endif /* _SYSCALL32_IMPL */
233