xref: /freebsd/usr.sbin/jail/state.c (revision 8d20be1e22095c27faf8fe8b2f0d089739cc742e)
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 error, 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 	error = 0;
92 	deps = 0;
93 	ldeps = 0;
94 	plen = 0;
95 	pname = NULL;
96 	TAILQ_FOREACH(j, &cfjails, tq) {
97 		if (j->flags & JF_FAILED)
98 			continue;
99 		if ((p = j->intparams[IP_DEPEND])) {
100 			TAILQ_FOREACH(s, &p->val, tq) {
101 				dj = find_jail(s->s);
102 				if (dj != NULL) {
103 					deps++;
104 					dep_add(j, dj, 0);
105 				} else {
106 					jail_warnx(j,
107 					    "depends on undefined jail \"%s\"",
108 					    s->s);
109 					j->flags |= JF_FAILED;
110 				}
111 			}
112 		}
113 		/* A jail has an implied dependency on its parent. */
114 		if ((cs = strrchr(j->name, '.')))
115 		{
116 			if (plen < (size_t)(cs - j->name + 1)) {
117 				plen = (cs - j->name) + 1;
118 				pname = erealloc(pname, plen);
119 			}
120 			strlcpy(pname, j->name, plen);
121 			dj = find_jail(pname);
122 			if (dj != NULL) {
123 				ldeps++;
124 				dep_add(j, dj, DF_LIGHT);
125 			}
126 		}
127 	}
128 
129 	/* Look for dependency loops. */
130 	if (deps && (deps > 1 || ldeps)) {
131 		(void)start_state(NULL, 0, 0, 0);
132 		while ((j = TAILQ_FIRST(&ready))) {
133 			requeue(j, &cfjails);
134 			dep_done(j, DF_NOFAIL);
135 		}
136 		while ((j = TAILQ_FIRST(&depend)) != NULL) {
137 			jail_warnx(j, "dependency loop");
138 			j->flags |= JF_FAILED;
139 			do {
140 				requeue(j, &cfjails);
141 				dep_done(j, DF_NOFAIL);
142 			} while ((j = TAILQ_FIRST(&ready)));
143 		}
144 		TAILQ_FOREACH(j, &cfjails, tq)
145 			STAILQ_FOREACH(d, &j->dep[DEP_FROM], tq[DEP_FROM])
146 				d->flags &= ~DF_SEEN;
147 	}
148 	if (pname != NULL)
149 		free(pname);
150 }
151 
152 /*
153  * Return if a jail has dependencies.
154  */
155 int
156 dep_check(struct cfjail *j)
157 {
158 	int reset, depfrom, depto, ndeps, rev;
159 	struct cfjail *dj;
160 	struct cfdepend *d;
161 
162 	static int bits[] = { 0, 1, 1, 2, 1, 2, 2, 3 };
163 
164 	if (j->ndeps == 0)
165 		return 0;
166 	ndeps = 0;
167 	if ((rev = JF_DO_STOP(j->flags))) {
168 		depfrom = DEP_TO;
169 		depto = DEP_FROM;
170 	} else {
171 		depfrom = DEP_FROM;
172 		depto = DEP_TO;
173 	}
174 	STAILQ_FOREACH(d, &j->dep[depfrom], tq[depfrom]) {
175 		if (d->flags & DF_SEEN)
176 			continue;
177 		dj = d->j[depto];
178 		if (dj->flags & JF_FAILED) {
179 			if (!(j->flags & (JF_DEPEND | JF_FAILED)) &&
180 			    verbose >= 0)
181 				jail_warnx(j, "skipped");
182 			j->flags |= JF_FAILED;
183 			continue;
184 		}
185 		/*
186 		 * The dependee's state may be set (or changed) as a result of
187 		 * being in a dependency it wasn't in earlier.
188 		 */
189 		reset = 0;
190 		if (bits[dj->flags & JF_OP_MASK] <= 1) {
191 			if (!(dj->flags & JF_OP_MASK)) {
192 				reset = 1;
193 				dj->flags |= JF_DEPEND;
194 				requeue(dj, &ready);
195 			}
196 			/* Set or change the dependee's state. */
197 			switch (j->flags & JF_OP_MASK) {
198 			case JF_START:
199 				dj->flags |= JF_START;
200 				break;
201 			case JF_SET:
202 				if (!(dj->flags & JF_OP_MASK))
203 					dj->flags |= JF_SET;
204 				else if (dj->flags & JF_STOP)
205 					dj->flags |= JF_START;
206 				break;
207 			case JF_STOP:
208 			case JF_RESTART:
209 				if (!(dj->flags & JF_STOP))
210 					reset = 1;
211 				dj->flags |= JF_STOP;
212 				if (dj->flags & JF_SET)
213 					dj->flags ^= (JF_START | JF_SET);
214 				break;
215 			}
216 		}
217 		if (reset)
218 			dep_reset(dj);
219 		if (!((d->flags & DF_LIGHT) &&
220 		    (rev ? dj->jid < 0 : dj->jid > 0)))
221 			ndeps++;
222 	}
223 	if (ndeps == 0)
224 		return 0;
225 	requeue(j, &depend);
226 	return 1;
227 }
228 
229 /*
230  * Resolve any dependencies from a finished jail.
231  */
232 void
233 dep_done(struct cfjail *j, unsigned flags)
234 {
235 	struct cfjail *dj;
236 	struct cfdepend *d;
237 	int depfrom, depto;
238 
239 	if (JF_DO_STOP(j->flags)) {
240 		depfrom = DEP_TO;
241 		depto = DEP_FROM;
242 	} else {
243 		depfrom = DEP_FROM;
244 		depto = DEP_TO;
245 	}
246 	STAILQ_FOREACH(d, &j->dep[depto], tq[depto]) {
247 		if ((d->flags & DF_SEEN) | (flags & ~d->flags & DF_LIGHT))
248 			continue;
249 		d->flags |= DF_SEEN;
250 		dj = d->j[depfrom];
251 		if (!(flags & DF_NOFAIL) && (j->flags & JF_FAILED) &&
252 		    (j->flags & (JF_OP_MASK | JF_DEPEND)) !=
253 		    (JF_SET | JF_DEPEND)) {
254 			if (!(dj->flags & (JF_DEPEND | JF_FAILED)) &&
255 			    verbose >= 0)
256 				jail_warnx(dj, "skipped");
257 			dj->flags |= JF_FAILED;
258 		}
259 		if (!--dj->ndeps && dj->queue == &depend)
260 			requeue(dj, &ready);
261 	}
262 }
263 
264 /*
265  * Count a jail's dependencies and mark them as unseen.
266  */
267 void
268 dep_reset(struct cfjail *j)
269 {
270 	int depfrom;
271 	struct cfdepend *d;
272 
273 	depfrom = JF_DO_STOP(j->flags) ? DEP_TO : DEP_FROM;
274 	j->ndeps = 0;
275 	STAILQ_FOREACH(d, &j->dep[depfrom], tq[depfrom])
276 		j->ndeps++;
277 }
278 
279 /*
280  * Find the next jail ready to do something.
281  */
282 struct cfjail *
283 next_jail(void)
284 {
285 	struct cfjail *j;
286 
287 	if (!(j = next_proc(!TAILQ_EMPTY(&ready))) &&
288 	    (j = TAILQ_FIRST(&ready)) && JF_DO_STOP(j->flags) &&
289 	    (j = TAILQ_LAST(&ready, cfjails)) && !JF_DO_STOP(j->flags)) {
290 		TAILQ_FOREACH_REVERSE(j, &ready, cfjails, tq)
291 			if (JF_DO_STOP(j->flags))
292 				break;
293 	}
294 	if (j != NULL)
295 		requeue(j, &cfjails);
296 	return j;
297 }
298 
299 /*
300  * Set jails to the proper start state.
301  */
302 int
303 start_state(const char *target, int docf, unsigned state, int running)
304 {
305 	struct iovec jiov[6];
306 	struct cfjail *j, *tj;
307 	int jid;
308 	char namebuf[MAXHOSTNAMELEN];
309 
310 	if (!target || (!docf && state != JF_STOP) ||
311 	    (!running && !strcmp(target, "*"))) {
312 		/*
313 		 * For a global wildcard (including no target specified),
314 		 * set the state on all jails and start with those that
315 		 * have no dependencies.
316 		 */
317 		TAILQ_FOREACH_SAFE(j, &cfjails, tq, tj) {
318 			j->flags = (j->flags & JF_FAILED) | state |
319 			    (docf ? JF_WILD : 0);
320 			dep_reset(j);
321 			requeue(j, j->ndeps ? &depend : &ready);
322 		}
323 	} else if (wild_jail_name(target)) {
324 		/*
325 		 * For targets specified singly, or with a non-global wildcard,
326 		 * set their state and call them ready (even if there are
327 		 * dependencies).  Leave everything else unqueued for now.
328 		 */
329 		if (running) {
330 			/*
331 			 * -R matches its wildcards against currently running
332 			 * jails, not against the config file.
333 			 */
334 			*(const void **)&jiov[0].iov_base = "lastjid";
335 			jiov[0].iov_len = sizeof("lastjid");
336 			jiov[1].iov_base = &jid;
337 			jiov[1].iov_len = sizeof(jid);
338 			*(const void **)&jiov[2].iov_base = "jid";
339 			jiov[2].iov_len = sizeof("jid");
340 			jiov[3].iov_base = &jid;
341 			jiov[3].iov_len = sizeof(jid);
342 			*(const void **)&jiov[4].iov_base = "name";
343 			jiov[4].iov_len = sizeof("name");
344 			jiov[5].iov_base = &namebuf;
345 			jiov[5].iov_len = sizeof(namebuf);
346 			for (jid = 0; jail_get(jiov, 6, 0) > 0; ) {
347 				if (wild_jail_match(namebuf, target)) {
348 					j = add_jail();
349 					j->name = estrdup(namebuf);
350 					j->jid = jid;
351 					j->flags = (j->flags & JF_FAILED) |
352 					    state | JF_WILD;
353 					dep_reset(j);
354 					requeue(j, &ready);
355 				}
356 			}
357 		} else {
358 			TAILQ_FOREACH_SAFE(j, &cfjails, tq, tj) {
359 				if (wild_jail_match(j->name, target)) {
360 					j->flags = (j->flags & JF_FAILED) |
361 					    state | JF_WILD;
362 					dep_reset(j);
363 					requeue(j, &ready);
364 				}
365 			}
366 		}
367 	} else {
368 		j = find_jail(target);
369 		if (j == NULL && state == JF_STOP) {
370 			/* Allow -[rR] to specify a currently running jail. */
371 			if ((jid = running_jid(target, JAIL_DYING)) > 0) {
372 				j = add_jail();
373 				j->name = estrdup(target);
374 				j->jid = jid;
375 			}
376 		}
377 		if (j == NULL) {
378 			warnx("\"%s\" not found", target);
379 			return -1;
380 		}
381 		j->flags = (j->flags & JF_FAILED) | state;
382 		dep_reset(j);
383 		requeue(j, &ready);
384 	}
385 	return 0;
386 }
387 
388 /*
389  * Move a jail to a new list.
390  */
391 void
392 requeue(struct cfjail *j, struct cfjails *queue)
393 {
394 	if (j->queue != queue) {
395 		TAILQ_REMOVE(j->queue, j, tq);
396 		TAILQ_INSERT_TAIL(queue, j, tq);
397 		j->queue = queue;
398 	}
399 }
400 
401 /*
402  * Add a dependency edge between two jails.
403  */
404 static void
405 dep_add(struct cfjail *from, struct cfjail *to, unsigned flags)
406 {
407 	struct cfdepend *d;
408 
409 	d = emalloc(sizeof(struct cfdepend));
410 	d->flags = flags;
411 	d->j[DEP_FROM] = from;
412 	d->j[DEP_TO] = to;
413 	STAILQ_INSERT_TAIL(&from->dep[DEP_FROM], d, tq[DEP_FROM]);
414 	STAILQ_INSERT_TAIL(&to->dep[DEP_TO], d, tq[DEP_TO]);
415 }
416 
417 /*
418  * Compare jail pointers for qsort/bsearch.
419  */
420 static int
421 cmp_jailptr(const void *a, const void *b)
422 {
423 	return strcmp((*((struct cfjail * const *)a))->name,
424 	    ((*(struct cfjail * const *)b))->name);
425 }
426 
427 static int
428 cmp_jailptr_name(const void *a, const void *b)
429 {
430 	return strcmp((const char *)a, ((*(struct cfjail * const *)b))->name);
431 }
432 
433 /*
434  * Find a jail object by name.
435  */
436 static struct cfjail *
437 find_jail(const char *name)
438 {
439 	struct cfjail **jp;
440 
441 	jp = bsearch(name, jails_byname, njails, sizeof(struct cfjail *),
442 	    cmp_jailptr_name);
443 	return jp ? *jp : NULL;
444 }
445 
446 /*
447  * Return the named jail's jid if it is running, and -1 if it isn't.
448  */
449 static int
450 running_jid(const char *name, int flags)
451 {
452 	struct iovec jiov[2];
453 	char *ep;
454 	int jid;
455 
456 	if ((jid = strtol(name, &ep, 10)) && !*ep) {
457 		*(const void **)&jiov[0].iov_base = "jid";
458 		jiov[0].iov_len = sizeof("jid");
459 		jiov[1].iov_base = &jid;
460 		jiov[1].iov_len = sizeof(jid);
461 	} else {
462 		*(const void **)&jiov[0].iov_base = "name";
463 		jiov[0].iov_len = sizeof("name");
464 		jiov[1].iov_len = strlen(name) + 1;
465 		jiov[1].iov_base = alloca(jiov[1].iov_len);
466 		strcpy(jiov[1].iov_base, name);
467 	}
468 	return jail_get(jiov, 2, flags);
469 }
470