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	"%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 	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