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 2010 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
sigaction(int sig,struct sigaction * actp,struct sigaction * oactp)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
sigaction32(int sig,struct sigaction32 * actp,struct sigaction32 * oactp)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