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