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 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29
30 #include <sys/types.h>
31 #include <sys/systm.h>
32 #include <sys/errno.h>
33 #include <sys/proc.h>
34 #include <sys/zone.h>
35 #include <sys/thread.h>
36 #include <sys/signal.h>
37 #include <sys/brand.h>
38 #include <sys/lx_brand.h>
39 #include <sys/lx_pid.h>
40 #include <lx_signum.h>
41
42 extern int kill(pid_t, int);
43
44 /*
45 * Check if it is legal to send this signal to the init process. Linux
46 * kill(2) semantics dictate that no _unhandled_ signal may be sent to pid
47 * 1.
48 */
49 static int
50 init_sig_check(int sig, pid_t pid)
51 {
52 proc_t *p;
53 int rv = 0;
54
55 mutex_enter(&pidlock);
56
57 if (((p = prfind(pid)) == NULL) || (p->p_stat == SIDL))
58 rv = ESRCH;
59 else if (sig && (sigismember(&cantmask, sig) ||
60 (PTOU(p)->u_signal[sig-1] == SIG_DFL) ||
61 (PTOU(p)->u_signal[sig-1] == SIG_IGN)))
62 rv = EPERM;
63
64 mutex_exit(&pidlock);
65
66 return (rv);
67 }
68
69 long
70 lx_tkill(pid_t pid, int lx_sig)
71 {
72 kthread_t *t;
73 proc_t *pp;
74 pid_t initpid;
75 sigqueue_t *sqp;
76 struct lx_lwp_data *br = ttolxlwp(curthread);
77 int tid = 1; /* default tid */
78 int sig, rv;
79
80 /*
81 * Unlike kill(2), Linux tkill(2) doesn't allow signals to
82 * be sent to process IDs <= 0 as it doesn't overlay any special
83 * semantics on the pid.
84 */
85 if ((pid <= 0) || ((lx_sig < 0) || (lx_sig >= LX_NSIG)) ||
86 ((sig = ltos_signo[lx_sig]) < 0))
87 return (set_errno(EINVAL));
88
89 /*
90 * If the Linux pid is 1, translate the pid to the actual init
91 * pid for the zone. Note that Linux dictates that no unhandled
92 * signals may be sent to init, so check for that, too.
93 *
94 * Otherwise, extract the tid and real pid from the Linux pid.
95 */
96 initpid = curproc->p_zone->zone_proc_initpid;
97 if (pid == 1)
98 pid = initpid;
99 if ((pid == initpid) && ((rv = init_sig_check(sig, pid)) != 0))
100 return (set_errno(rv));
101 else if (lx_lpid_to_spair(pid, &pid, &tid) < 0)
102 return (set_errno(ESRCH));
103
104 sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP);
105
106 /*
107 * Find the process for the passed pid...
108 */
109 mutex_enter(&pidlock);
110 if (((pp = prfind(pid)) == NULL) || (pp->p_stat == SIDL)) {
111 mutex_exit(&pidlock);
112 rv = set_errno(ESRCH);
113 goto free_and_exit;
114 }
115 mutex_enter(&pp->p_lock);
116 mutex_exit(&pidlock);
117
118 /*
119 * Deny permission to send the signal if either of the following
120 * is true:
121 *
122 * + The signal is SIGCONT and the target pid is not in the same
123 * session as the sender
124 *
125 * + prochasprocperm() shows the user lacks sufficient permission
126 * to send the signal to the target pid
127 */
128 if (((sig == SIGCONT) && (pp->p_sessp != curproc->p_sessp)) ||
129 (!prochasprocperm(pp, curproc, CRED()))) {
130 mutex_exit(&pp->p_lock);
131 rv = set_errno(EPERM);
132 goto free_and_exit;
133 }
134
135 /* check for the tid */
136 if ((t = idtot(pp, tid)) == NULL) {
137 mutex_exit(&pp->p_lock);
138 rv = set_errno(ESRCH);
139 goto free_and_exit;
140 }
141
142 /* a signal of 0 means just check for the existence of the thread */
143 if (lx_sig == 0) {
144 mutex_exit(&pp->p_lock);
145 rv = 0;
146 goto free_and_exit;
147 }
148
149 sqp->sq_info.si_signo = sig;
150 sqp->sq_info.si_code = SI_LWP;
151 sqp->sq_info.si_pid = br->br_pid;
152 sqp->sq_info.si_uid = crgetruid(CRED());
153 sigaddqa(pp, t, sqp);
154
155 mutex_exit(&pp->p_lock);
156
157 return (0);
158
159 free_and_exit:
160 kmem_free(sqp, sizeof (sigqueue_t));
161 return (rv);
162 }
163
164 long
165 lx_kill(pid_t lx_pid, int lx_sig)
166 {
167 pid_t s_pid, initpid;
168 sigsend_t v;
169 zone_t *zone = curproc->p_zone;
170 struct proc *p;
171 int err, sig, nfound;
172
173 if ((lx_sig < 0) || (lx_sig >= LX_NSIG) ||
174 ((sig = ltos_signo[lx_sig]) < 0))
175 return (set_errno(EINVAL));
176
177 /*
178 * Since some linux apps rely on init(1M) having PID 1, we
179 * transparently translate 1 to the real init(1M)'s pid. We then
180 * check to be sure that it is legal for this process to send this
181 * signal to init(1M).
182 */
183 initpid = zone->zone_proc_initpid;
184 if (lx_pid == 1 || lx_pid == -1) {
185 s_pid = initpid;
186 } else if (lx_pid == 0) {
187 s_pid = 0;
188 } else if (lx_pid > 0) {
189 if (lx_lpid_to_spair(lx_pid, &s_pid, NULL) != 0) {
190 /*
191 * If we didn't find this pid that means it doesn't
192 * exist in this zone.
193 */
194 return (set_errno(ESRCH));
195 }
196 } else {
197 ASSERT(lx_pid < 0);
198 if (lx_lpid_to_spair(-lx_pid, &s_pid, NULL) != 0) {
199 /*
200 * If we didn't find this pid it means that the
201 * process group leader doesn't exist in this zone.
202 * In this case assuming that the Linux pid is
203 * the same as the Solaris pid will get us the
204 * correct behavior.
205 */
206 s_pid = -lx_pid;
207 }
208 }
209
210 if ((s_pid == initpid) && ((err = init_sig_check(sig, s_pid)) != 0))
211 return (set_errno(err));
212
213 /*
214 * For individual processes, kill() semantics are the same between
215 * Solaris and Linux.
216 */
217 if (lx_pid >= 0)
218 return (kill(s_pid, sig));
219
220 /*
221 * In Solaris, sending a signal to -pid means "send a signal to
222 * everyone in process group pid." In Linux it means "send a
223 * signal to everyone in the group other than init." Sending a
224 * signal to -1 means "send a signal to every process except init
225 * and myself."
226 */
227
228 bzero(&v, sizeof (v));
229 v.sig = sig;
230 v.checkperm = 1;
231 v.sicode = SI_USER;
232 err = 0;
233
234 mutex_enter(&pidlock);
235
236 p = (lx_pid == -1) ? practive : pgfind(s_pid);
237 nfound = 0;
238 while (err == 0 && p != NULL) {
239 if ((p->p_zone == zone) && (p->p_stat != SIDL) &&
240 (p->p_pid != initpid) && (lx_pid < -1 || p != curproc)) {
241 nfound++;
242 err = sigsendproc(p, &v);
243 }
244
245 p = (lx_pid == -1) ? p->p_next : p->p_pglink;
246 }
247 mutex_exit(&pidlock);
248 if (nfound == 0)
249 err = ESRCH;
250 else if (err == 0 && v.perm == 0)
251 err = EPERM;
252 return (err ? set_errno(err) : 0);
253 }