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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <sys/param.h>
28 #include <sys/types.h>
29 #include <sys/sysmacros.h>
30 #include <sys/systm.h>
31 #include <sys/errno.h>
33 #include <sys/procset.h>
34 #include <sys/fault.h>
35 #include <sys/signal.h>
36 #include <sys/siginfo.h>
37 #include <sys/schedctl.h>
39 #include <sys/debug.h>
40 #include <sys/contract/process_impl.h>
44 copyin_siginfo(model_t datamodel
, void *uaddr
, k_siginfo_t
*ksip
)
46 #ifdef _SYSCALL32_IMPL
49 if (datamodel
== DATAMODEL_NATIVE
) {
51 return (copyin(uaddr
, ksip
, sizeof (k_siginfo_t
)));
52 #ifdef _SYSCALL32_IMPL
56 if (ret
= copyin(uaddr
, &si32
, sizeof (si32
)))
59 siginfo_32tok(&si32
, ksip
);
67 * To find secured 64 bit id for signotify() call
68 * This depends upon as_getmemid() which returns
69 * unique vnode/offset for a user virtual address.
72 get_sigid(proc_t
*p
, caddr_t addr
)
74 u_longlong_t snid
= 0;
76 quad_t
*tquad
= (quad_t
*)&snid
;
78 if (!as_getmemid(p
->p_as
, addr
, &memid
)) {
79 tquad
->val
[0] = (int)memid
.val
[0];
80 tquad
->val
[1] = (int)memid
.val
[1];
85 #define SIGN_PTR(p, n) &((signotifyq_t *)(&p->p_signhdr[1]))[n];
88 signotify(int cmd
, siginfo_t
*siginfo
, signotify_id_t
*sn_id
)
99 model_t datamodel
= get_udatamodel();
101 if (copyin(sn_id
, &id
, sizeof (signotify_id_t
)))
102 return (set_errno(EFAULT
));
104 if (id
.sn_index
>= _SIGNOTIFY_MAX
|| id
.sn_index
< 0)
105 return (set_errno(EINVAL
));
109 /* get snid for the given user address of signotifyid_t */
110 sid
= get_sigid(cp
, (caddr_t
)sn_id
);
113 mutex_enter(&pidlock
);
114 if ((p
= prfind(id
.sn_pid
)) != NULL
) {
115 mutex_enter(&p
->p_lock
);
116 if (p
->p_signhdr
!= NULL
) {
117 snqp
= SIGN_PTR(p
, id
.sn_index
);
118 if (snqp
->sn_snid
== sid
) {
119 mutex_exit(&p
->p_lock
);
120 mutex_exit(&pidlock
);
121 return (set_errno(EBUSY
));
124 mutex_exit(&p
->p_lock
);
126 mutex_exit(&pidlock
);
129 if (copyin_siginfo(datamodel
, siginfo
, &info
))
130 return (set_errno(EFAULT
));
132 /* The si_code value must indicate the signal will be queued */
133 if (!sigwillqueue(info
.si_signo
, info
.si_code
))
134 return (set_errno(EINVAL
));
136 if (cp
->p_signhdr
== NULL
) {
137 /* Allocate signotify pool first time */
138 sqh
= sigqhdralloc(sizeof (signotifyq_t
),
140 mutex_enter(&cp
->p_lock
);
141 if (cp
->p_signhdr
== NULL
) {
142 /* hang the pool head on proc */
145 /* another lwp allocated the pool, free ours */
149 mutex_enter(&cp
->p_lock
);
152 sqp
= sigqalloc(cp
->p_signhdr
);
154 mutex_exit(&cp
->p_lock
);
155 return (set_errno(EAGAIN
));
159 sqp
->sq_info
.si_pid
= cp
->p_pid
;
160 sqp
->sq_info
.si_ctid
= PRCTID(cp
);
161 sqp
->sq_info
.si_zoneid
= getzoneid();
162 sqp
->sq_info
.si_uid
= crgetruid(cr
);
164 /* fill the signotifyq_t fields */
165 ((signotifyq_t
*)sqp
)->sn_snid
= sid
;
167 mutex_exit(&cp
->p_lock
);
169 /* complete the signotify_id_t fields */
170 id
.sn_index
= (signotifyq_t
*)sqp
- SIGN_PTR(cp
, 0);
171 id
.sn_pid
= cp
->p_pid
;
178 sid
= get_sigid(cp
, (caddr_t
)sn_id
);
179 mutex_enter(&pidlock
);
180 if ((id
.sn_pid
<= 0) || ((p
= prfind(id
.sn_pid
)) == NULL
)) {
181 mutex_exit(&pidlock
);
182 return (set_errno(EINVAL
));
184 mutex_enter(&p
->p_lock
);
185 mutex_exit(&pidlock
);
187 if (p
->p_signhdr
== NULL
) {
188 mutex_exit(&p
->p_lock
);
189 return (set_errno(EINVAL
));
192 snqp
= SIGN_PTR(p
, id
.sn_index
);
194 if (snqp
->sn_snid
== 0) {
195 mutex_exit(&p
->p_lock
);
196 return (set_errno(EINVAL
));
199 if (snqp
->sn_snid
!= sid
) {
200 mutex_exit(&p
->p_lock
);
201 return (set_errno(EINVAL
));
206 /* cmd == SN_CANCEL or signo == 0 (SIGEV_NONE) */
207 if (((sigqueue_t
*)snqp
)->sq_info
.si_signo
<= 0)
210 sigqsend(cmd
, p
, 0, (sigqueue_t
*)snqp
);
211 mutex_exit(&p
->p_lock
);
219 return (set_errno(EINVAL
));
222 if (copyout(&id
, sn_id
, sizeof (signotify_id_t
)))
223 return (set_errno(EFAULT
));
229 sigresend(int sig
, siginfo_t
*siginfo
, sigset_t
*mask
)
231 kthread_t
*t
= curthread
;
232 klwp_t
*lwp
= ttolwp(t
);
233 sigqueue_t
*sqp
= kmem_zalloc(sizeof (*sqp
), KM_SLEEP
);
238 if (sig
<= 0 || sig
>= NSIG
|| sigismember(&cantmask
, sig
)) {
243 if (siginfo
== NULL
) {
244 sqp
->sq_info
.si_signo
= sig
;
245 sqp
->sq_info
.si_code
= SI_NOINFO
;
247 if (copyin_siginfo(get_udatamodel(), siginfo
, &sqp
->sq_info
)) {
251 if (sqp
->sq_info
.si_signo
!= sig
) {
257 if (copyin(mask
, &set
, sizeof (set
))) {
261 sigutok(&set
, &kset
);
264 * We don't need to acquire p->p_lock here;
265 * we are manipulating thread-private data.
267 if (lwp
->lwp_cursig
|| lwp
->lwp_curinfo
) {
272 lwp
->lwp_cursig
= sig
;
273 lwp
->lwp_curinfo
= sqp
;
274 schedctl_finish_sigblock(t
);
279 kmem_free(sqp
, sizeof (*sqp
));
280 return (set_errno(error
));