xref: /freebsd/usr.sbin/jail/state.c (revision 7447ca0eb235974642312b9555caec00b57d8fc1)
1 /*-
2  * Copyright (c) 2011 James Gritton
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/uio.h>
31 
32 #include <err.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include "jailp.h"
37 
38 struct cfjails ready = TAILQ_HEAD_INITIALIZER(ready);
39 struct cfjails depend = TAILQ_HEAD_INITIALIZER(depend);
40 
41 static void dep_add(struct cfjail *from, struct cfjail *to, unsigned flags);
42 static int cmp_jailptr(const void *a, const void *b);
43 static int cmp_jailptr_name(const void *a, const void *b);
44 static struct cfjail *find_jail(const char *name);
45 static int running_jid(const char *name, int flags);
46 
47 static struct cfjail **jails_byname;
48 static size_t njails;
49 
50 /*
51  * Set up jail dependency lists.
52  */
53 void
54 dep_setup(int docf)
55 {
56 	struct cfjail *j, *dj;
57 	struct cfparam *p;
58 	struct cfstring *s;
59 	struct cfdepend *d;
60 	const char *cs;
61 	char *pname;
62 	size_t plen;
63 	int deps, ldeps;
64 
65 	if (!docf) {
66 		/*
67 		 * With no config file, let "depend" for a single jail
68 		 * look at currently running jails.
69 		 */
70 		if ((j = TAILQ_FIRST(&cfjails)) &&
71 		    (p = j->intparams[IP_DEPEND])) {
72 			TAILQ_FOREACH(s, &p->val, tq) {
73 				if (running_jid(s->s, 0) < 0) {
74 					warnx("depends on nonexistent jail "
75 					    "\"%s\"", s->s);
76 					j->flags |= JF_FAILED;
77 				}
78 			}
79 		}
80 		return;
81 	}
82 
83 	njails = 0;
84 	TAILQ_FOREACH(j, &cfjails, tq)
85 		njails++;
86 	jails_byname = emalloc(njails * sizeof(struct cfjail *));
87 	njails = 0;
88 	TAILQ_FOREACH(j, &cfjails, tq)
89 		jails_byname[njails++] = j;
90 	qsort(jails_byname, njails, sizeof(struct cfjail *), cmp_jailptr);
91 	deps = 0;
92 	ldeps = 0;
93 	plen = 0;
94 	pname = NULL;
95 	TAILQ_FOREACH(j, &cfjails, tq) {
96 		if (j->flags & JF_FAILED)
97 			continue;
98 		if ((p = j->intparams[IP_DEPEND])) {
99 			TAILQ_FOREACH(s, &p->val, tq) {
100 				dj = find_jail(s->s);
101 				if (dj != NULL) {
102 					deps++;
103 					dep_add(j, dj, 0);
104 				} else {
105 					jail_warnx(j,
106 					    "depends on undefined jail \"%s\"",
107 					    s->s);
108 					j->flags |= JF_FAILED;
109 				}
110 			}
111 		}
112 		/* A jail has an implied dependency on its parent. */
113 		if ((cs = strrchr(j->name, '.')))
114 		{
115 			if (plen < (size_t)(cs - j->name + 1)) {
116 				plen = (cs - j->name) + 1;
117 				pname = erealloc(pname, plen);
118 			}
119 			strlcpy(pname, j->name, plen);
120 			dj = find_jail(pname);
121 			if (dj != NULL) {
122 				ldeps++;
123 				dep_add(j, dj, DF_LIGHT);
124 			}
125 		}
126 	}
127 
128 	/* Look for dependency loops. */
129 	if (deps && (deps > 1 || ldeps)) {
130 		(void)start_state(NULL, 0, 0, 0);
131 		while ((j = TAILQ_FIRST(&ready))) {
132 			requeue(j, &cfjails);
133 			dep_done(j, DF_NOFAIL);
134 		}
135 		while ((j = TAILQ_FIRST(&depend)) != NULL) {
136 			jail_warnx(j, "dependency loop");
137 			j->flags |= JF_FAILED;
138 			do {
139 				requeue(j, &cfjails);
140 				dep_done(j, DF_NOFAIL);
141 			} while ((j = TAILQ_FIRST(&ready)));
142 		}
143 		TAILQ_FOREACH(j, &cfjails, tq)
144 			STAILQ_FOREACH(d, &j->dep[DEP_FROM], tq[DEP_FROM])
145 				d->flags &= ~DF_SEEN;
146 	}
147 	if (pname != NULL)
148 		free(pname);
149 }
150 
151 /*
152  * Return if a jail has dependencies.
153  */
154 int
155 dep_check(struct cfjail *j)
156 {
157 	int reset, depfrom, depto, ndeps, rev;
158 	struct cfjail *dj;
159 	struct cfdepend *d;
160 
161 	static int bits[] = { 0, 1, 1, 2, 1, 2, 2, 3 };
162 
163 	if (j->ndeps == 0)
164 		return 0;
165 	ndeps = 0;
166 	if ((rev = JF_DO_STOP(j->flags))) {
167 		depfrom = DEP_TO;
168 		depto = DEP_FROM;
169 	} else {
170 		depfrom = DEP_FROM;
171 		depto = DEP_TO;
172 	}
173 	STAILQ_FOREACH(d, &j->dep[depfrom], tq[depfrom]) {
174 		if (d->flags & DF_SEEN)
175 			continue;
176 		dj = d->j[depto];
177 		if (dj->flags & JF_FAILED) {
178 			if (!(j->flags & (JF_DEPEND | JF_FAILED)) &&
179 			    verbose >= 0)
180 				jail_warnx(j, "skipped");
181 			j->flags |= JF_FAILED;
182 			continue;
183 		}
184 		/*
185 		 * The dependee's state may be set (or changed) as a result of
186 		 * being in a dependency it wasn't in earlier.
187 		 */
188 		reset = 0;
189 		if (bits[dj->flags & JF_OP_MASK] <= 1) {
190 			if (!(dj->flags & JF_OP_MASK)) {
191 				reset = 1;
192 				dj->flags |= JF_DEPEND;
193 				requeue(dj, &ready);
194 			}
195 			/* Set or change the dependee's state. */
196 			switch (j->flags & JF_OP_MASK) {
197 			case JF_START:
198 				dj->flags |= JF_START;
199 				break;
200 			case JF_SET:
201 				if (!(dj->flags & JF_OP_MASK))
202 					dj->flags |= JF_SET;
203 				else if (dj->flags & JF_STOP)
204 					dj->flags |= JF_START;
205 				break;
206 			case JF_STOP:
207 			case JF_RESTART:
208 				if (!(dj->flags & JF_STOP))
209 					reset = 1;
210 				dj->flags |= JF_STOP;
211 				if (dj->flags & JF_SET)
212 					dj->flags ^= (JF_START | JF_SET);
213 				break;
214 			}
215 		}
216 		if (reset)
217 			dep_reset(dj);
218 		if (!((d->flags & DF_LIGHT) &&
219 		    (rev ? dj->jid < 0 : dj->jid > 0)))
220 			ndeps++;
221 	}
222 	if (ndeps == 0)
223 		return 0;
224 	requeue(j, &depend);
225 	return 1;
226 }
227 
228 /*
229  * Resolve any dependencies from a finished jail.
230  */
231 void
232 dep_done(struct cfjail *j, unsigned flags)
233 {
234 	struct cfjail *dj;
235 	struct cfdepend *d;
236 	int depfrom, depto;
237 
238 	if (JF_DO_STOP(j->flags)) {
239 		depfrom = DEP_TO;
240 		depto = DEP_FROM;
241 	} else {
242 		depfrom = DEP_FROM;
243 		depto = DEP_TO;
244 	}
245 	STAILQ_FOREACH(d, &j->dep[depto], tq[depto]) {
246 		if ((d->flags & DF_SEEN) | (flags & ~d->flags & DF_LIGHT))
247 			continue;
248 		d->flags |= DF_SEEN;
249 		dj = d->j[depfrom];
250 		if (!(flags & DF_NOFAIL) && (j->flags & JF_FAILED) &&
251 		    (j->flags & (JF_OP_MASK | JF_DEPEND)) !=
252 		    (JF_SET | JF_DEPEND)) {
253 			if (!(dj->flags & (JF_DEPEND | JF_FAILED)) &&
254 			    verbose >= 0)
255 				jail_warnx(dj, "skipped");
256 			dj->flags |= JF_FAILED;
257 		}
258 		if (!--dj->ndeps && dj->queue == &depend)
259 			requeue(dj, &ready);
260 	}
261 }
262 
263 /*
264  * Count a jail's dependencies and mark them as unseen.
265  */
266 void
267 dep_reset(struct cfjail *j)
268 {
269 	int depfrom;
270 	struct cfdepend *d;
271 
272 	depfrom = JF_DO_STOP(j->flags) ? DEP_TO : DEP_FROM;
273 	j->ndeps = 0;
274 	STAILQ_FOREACH(d, &j->dep[depfrom], tq[depfrom])
275 		j->ndeps++;
276 }
277 
278 /*
279  * Find the next jail ready to do something.
280  */
281 struct cfjail *
282 next_jail(void)
283 {
284 	struct cfjail *j;
285 
286 	if (!(j = next_proc(!TAILQ_EMPTY(&ready))) &&
287 	    (j = TAILQ_FIRST(&ready)) && JF_DO_STOP(j->flags) &&
288 	    (j = TAILQ_LAST(&ready, cfjails)) && !JF_DO_STOP(j->flags)) {
289 		TAILQ_FOREACH_REVERSE(j, &ready, cfjails, tq)
290 			if (JF_DO_STOP(j->flags))
291 				break;
292 	}
293 	if (j != NULL)
294 		requeue(j, &cfjails);
295 	return j;
296 }
297 
298 /*
299  * Set jails to the proper start state.
300  */
301 int
302 start_state(const char *target, int docf, unsigned state, int running)
303 {
304 	struct iovec jiov[6];
305 	struct cfjail *j, *tj;
306 	int jid;
307 	char namebuf[MAXHOSTNAMELEN];
308 
309 	if (!target || (!docf && state != JF_STOP) ||
310 	    (!running && !strcmp(target, "*"))) {
311 		/*
312 		 * For a global wildcard (including no target specified),
313 		 * set the state on all jails and start with those that
314 		 * have no dependencies.
315 		 */
316 		TAILQ_FOREACH_SAFE(j, &cfjails, tq, tj) {
317 			j->flags = (j->flags & JF_FAILED) | state |
318 			    (docf ? JF_WILD : 0);
319 			dep_reset(j);
320 			requeue(j, j->ndeps ? &depend : &ready);
321 		}
322 	} else if (wild_jail_name(target)) {
323 		/*
324 		 * For targets specified singly, or with a non-global wildcard,
325 		 * set their state and call them ready (even if there are
326 		 * dependencies).  Leave everything else unqueued for now.
327 		 */
328 		if (running) {
329 			/*
330 			 * -R matches its wildcards against currently running
331 			 * jails, not against the config file.
332 			 */
333 			jiov[0].iov_base = __DECONST(char *, "lastjid");
334 			jiov[0].iov_len = sizeof("lastjid");
335 			jiov[1].iov_base = &jid;
336 			jiov[1].iov_len = sizeof(jid);
337 			jiov[2].iov_base = __DECONST(char *, "jid");
338 			jiov[2].iov_len = sizeof("jid");
339 			jiov[3].iov_base = &jid;
340 			jiov[3].iov_len = sizeof(jid);
341 			jiov[4].iov_base = __DECONST(char *, "name");
342 			jiov[4].iov_len = sizeof("name");
343 			jiov[5].iov_base = &namebuf;
344 			jiov[5].iov_len = sizeof(namebuf);
345 			for (jid = 0; jail_get(jiov, 6, 0) > 0; ) {
346 				if (wild_jail_match(namebuf, target)) {
347 					j = add_jail();
348 					j->name = estrdup(namebuf);
349 					j->jid = jid;
350 					j->flags = (j->flags & JF_FAILED) |
351 					    state | JF_WILD;
352 					dep_reset(j);
353 					requeue(j, &ready);
354 				}
355 			}
356 		} else {
357 			TAILQ_FOREACH_SAFE(j, &cfjails, tq, tj) {
358 				if (wild_jail_match(j->name, target)) {
359 					j->flags = (j->flags & JF_FAILED) |
360 					    state | JF_WILD;
361 					dep_reset(j);
362 					requeue(j, &ready);
363 				}
364 			}
365 		}
366 	} else {
367 		j = find_jail(target);
368 		if (j == NULL && state == JF_STOP) {
369 			/* Allow -[rR] to specify a currently running jail. */
370 			if ((jid = running_jid(target, JAIL_DYING)) > 0) {
371 				j = add_jail();
372 				j->name = estrdup(target);
373 				j->jid = jid;
374 			}
375 		}
376 		if (j == NULL) {
377 			warnx("\"%s\" not found", target);
378 			return -1;
379 		}
380 		j->flags = (j->flags & JF_FAILED) | state;
381 		dep_reset(j);
382 		requeue(j, &ready);
383 	}
384 	return 0;
385 }
386 
387 /*
388  * Move a jail to a new list.
389  */
390 void
391 requeue(struct cfjail *j, struct cfjails *queue)
392 {
393 	if (j->queue != queue) {
394 		TAILQ_REMOVE(j->queue, j, tq);
395 		TAILQ_INSERT_TAIL(queue, j, tq);
396 		j->queue = queue;
397 	}
398 }
399 
400 void
401 requeue_head(struct cfjail *j, struct cfjails *queue)
402 {
403     TAILQ_REMOVE(j->queue, j, tq);
404     TAILQ_INSERT_HEAD(queue, j, tq);
405     j->queue = queue;
406 }
407 
408 /*
409  * Add a dependency edge between two jails.
410  */
411 static void
412 dep_add(struct cfjail *from, struct cfjail *to, unsigned flags)
413 {
414 	struct cfdepend *d;
415 
416 	d = emalloc(sizeof(struct cfdepend));
417 	d->flags = flags;
418 	d->j[DEP_FROM] = from;
419 	d->j[DEP_TO] = to;
420 	STAILQ_INSERT_TAIL(&from->dep[DEP_FROM], d, tq[DEP_FROM]);
421 	STAILQ_INSERT_TAIL(&to->dep[DEP_TO], d, tq[DEP_TO]);
422 }
423 
424 /*
425  * Compare jail pointers for qsort/bsearch.
426  */
427 static int
428 cmp_jailptr(const void *a, const void *b)
429 {
430 	return strcmp((*((struct cfjail * const *)a))->name,
431 	    ((*(struct cfjail * const *)b))->name);
432 }
433 
434 static int
435 cmp_jailptr_name(const void *a, const void *b)
436 {
437 	return strcmp((const char *)a, ((*(struct cfjail * const *)b))->name);
438 }
439 
440 /*
441  * Find a jail object by name.
442  */
443 static struct cfjail *
444 find_jail(const char *name)
445 {
446 	struct cfjail **jp;
447 
448 	jp = bsearch(name, jails_byname, njails, sizeof(struct cfjail *),
449 	    cmp_jailptr_name);
450 	return jp ? *jp : NULL;
451 }
452 
453 /*
454  * Return the named jail's jid if it is running, and -1 if it isn't.
455  */
456 static int
457 running_jid(const char *name, int flags)
458 {
459 	struct iovec jiov[2];
460 	char *ep;
461 	int jid;
462 
463 	if ((jid = strtol(name, &ep, 10)) && !*ep) {
464 		jiov[0].iov_base = __DECONST(char *, "jid");
465 		jiov[0].iov_len = sizeof("jid");
466 		jiov[1].iov_base = &jid;
467 		jiov[1].iov_len = sizeof(jid);
468 	} else {
469 		jiov[0].iov_base = __DECONST(char *, "name");
470 		jiov[0].iov_len = sizeof("name");
471 		jiov[1].iov_len = strlen(name) + 1;
472 		jiov[1].iov_base = alloca(jiov[1].iov_len);
473 		strcpy(jiov[1].iov_base, name);
474 	}
475 	return jail_get(jiov, 2, flags);
476 }
477