1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 1999 Poul-Henning Kamp.
5 * Copyright (c) 2009-2012 James Gritton
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: stable/11/usr.sbin/jail/jail.c 369582 2021-04-09 03:28:33Z jamie $");
32
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <sys/socket.h>
36#include <sys/sysctl.h>
37
38#include <arpa/inet.h>
39#include <netinet/in.h>
40
41#include <err.h>
42#include <errno.h>
43#include <stdarg.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <unistd.h>
48
49#include "jailp.h"
50
51#define JP_RDTUN(jp)	(((jp)->jp_ctltype & CTLFLAG_RDTUN) == CTLFLAG_RDTUN)
52
53struct permspec {
54	const char	*name;
55	enum intparam	ipnum;
56	int		rev;
57};
58
59const char *cfname;
60int iflag;
61int note_remove;
62int verbose;
63const char *separator = "\t";
64
65static void clear_persist(struct cfjail *j);
66static int update_jail(struct cfjail *j);
67static int rdtun_params(struct cfjail *j, int dofail);
68static void running_jid(struct cfjail *j, int dflag);
69static void jail_quoted_warnx(const struct cfjail *j, const char *name_msg,
70    const char *noname_msg);
71static int jailparam_set_note(const struct cfjail *j, struct jailparam *jp,
72    unsigned njp, int flags);
73static void print_jail(FILE *fp, struct cfjail *j, int oldcl, int running);
74static void print_param(FILE *fp, const struct cfparam *p, int sep, int doname);
75static void show_jails(void);
76static void quoted_print(FILE *fp, char *str);
77static void usage(void);
78
79static struct permspec perm_sysctl[] = {
80    { "security.jail.set_hostname_allowed", KP_ALLOW_SET_HOSTNAME, 0 },
81    { "security.jail.sysvipc_allowed", KP_ALLOW_SYSVIPC, 0 },
82    { "security.jail.allow_raw_sockets", KP_ALLOW_RAW_SOCKETS, 0 },
83    { "security.jail.chflags_allowed", KP_ALLOW_CHFLAGS, 0 },
84    { "security.jail.mount_allowed", KP_ALLOW_MOUNT, 0 },
85    { "security.jail.socket_unixiproute_only", KP_ALLOW_SOCKET_AF, 1 },
86};
87
88static const enum intparam startcommands[] = {
89    IP__NULL,
90#ifdef INET
91    IP__IP4_IFADDR,
92#endif
93#ifdef INET6
94    IP__IP6_IFADDR,
95#endif
96    IP_MOUNT,
97    IP__MOUNT_FROM_FSTAB,
98    IP_MOUNT_DEVFS,
99    IP_MOUNT_FDESCFS,
100    IP_MOUNT_PROCFS,
101    IP_EXEC_PRESTART,
102    IP__OP,
103    IP_VNET_INTERFACE,
104    IP_EXEC_START,
105    IP_COMMAND,
106    IP_EXEC_POSTSTART,
107    IP__NULL
108};
109
110static const enum intparam stopcommands[] = {
111    IP__NULL,
112    IP_EXEC_PRESTOP,
113    IP_EXEC_STOP,
114    IP_STOP_TIMEOUT,
115    IP__OP,
116    IP_EXEC_POSTSTOP,
117    IP_MOUNT_PROCFS,
118    IP_MOUNT_FDESCFS,
119    IP_MOUNT_DEVFS,
120    IP__MOUNT_FROM_FSTAB,
121    IP_MOUNT,
122#ifdef INET6
123    IP__IP6_IFADDR,
124#endif
125#ifdef INET
126    IP__IP4_IFADDR,
127#endif
128    IP__NULL
129};
130
131int
132main(int argc, char **argv)
133{
134	struct stat st;
135	FILE *jfp;
136	struct cfjail *j;
137	char *JidFile;
138	size_t sysvallen;
139	unsigned op, pi;
140	int ch, docf, error, i, oldcl, sysval;
141	int dflag, Rflag;
142	char enforce_statfs[4];
143#if defined(INET) || defined(INET6)
144	char *cs, *ncs;
145#endif
146#if defined(INET) && defined(INET6)
147	struct in6_addr addr6;
148#endif
149
150	op = 0;
151	dflag = Rflag = 0;
152	docf = 1;
153	cfname = CONF_FILE;
154	JidFile = NULL;
155
156	while ((ch = getopt(argc, argv, "cde:f:hiJ:lmn:p:qrRs:u:U:v")) != -1) {
157		switch (ch) {
158		case 'c':
159			op |= JF_START;
160			break;
161		case 'd':
162			dflag = 1;
163			break;
164		case 'e':
165			op |= JF_SHOW;
166			separator = optarg;
167			break;
168		case 'f':
169			cfname = optarg;
170			break;
171		case 'h':
172#if defined(INET) || defined(INET6)
173			add_param(NULL, NULL, IP_IP_HOSTNAME, NULL);
174#endif
175			docf = 0;
176			break;
177		case 'i':
178			iflag = 1;
179			verbose = -1;
180			break;
181		case 'J':
182			JidFile = optarg;
183			break;
184		case 'l':
185			add_param(NULL, NULL, IP_EXEC_CLEAN, NULL);
186			docf = 0;
187			break;
188		case 'm':
189			op |= JF_SET;
190			break;
191		case 'n':
192			add_param(NULL, NULL, KP_NAME, optarg);
193			docf = 0;
194			break;
195		case 'p':
196			paralimit = strtol(optarg, NULL, 10);
197			if (paralimit == 0)
198				paralimit = -1;
199			break;
200		case 'q':
201			verbose = -1;
202			break;
203		case 'r':
204			op |= JF_STOP;
205			break;
206		case 'R':
207			op |= JF_STOP;
208			Rflag = 1;
209			break;
210		case 's':
211			add_param(NULL, NULL, KP_SECURELEVEL, optarg);
212			docf = 0;
213			break;
214		case 'u':
215			add_param(NULL, NULL, IP_EXEC_JAIL_USER, optarg);
216			add_param(NULL, NULL, IP_EXEC_SYSTEM_JAIL_USER, NULL);
217			docf = 0;
218			break;
219		case 'U':
220			add_param(NULL, NULL, IP_EXEC_JAIL_USER, optarg);
221			add_param(NULL, NULL, IP_EXEC_SYSTEM_JAIL_USER,
222			    "false");
223			docf = 0;
224			break;
225		case 'v':
226			verbose = 1;
227			break;
228		default:
229			usage();
230		}
231	}
232	argc -= optind;
233	argv += optind;
234
235	/* Find out which of the four command line styles this is. */
236	oldcl = 0;
237	if (!op) {
238		/* Old-style command line with four fixed parameters */
239		if (argc < 4 || argv[0][0] != '/')
240			usage();
241		op = JF_START;
242		docf = 0;
243		oldcl = 1;
244		add_param(NULL, NULL, KP_PATH, argv[0]);
245		add_param(NULL, NULL, KP_HOST_HOSTNAME, argv[1]);
246#if defined(INET) || defined(INET6)
247		if (argv[2][0] != '\0') {
248			for (cs = argv[2];; cs = ncs + 1) {
249				ncs = strchr(cs, ',');
250				if (ncs)
251					*ncs = '\0';
252				add_param(NULL, NULL,
253#if defined(INET) && defined(INET6)
254				    inet_pton(AF_INET6, cs, &addr6) == 1
255				    ? KP_IP6_ADDR : KP_IP4_ADDR,
256#elif defined(INET)
257				    KP_IP4_ADDR,
258#elif defined(INET6)
259				    KP_IP6_ADDR,
260#endif
261				    cs);
262				if (!ncs)
263					break;
264			}
265		}
266#endif
267		for (i = 3; i < argc; i++)
268			add_param(NULL, NULL, IP_COMMAND, argv[i]);
269		/* Emulate the defaults from security.jail.* sysctls. */
270		sysvallen = sizeof(sysval);
271		if (sysctlbyname("security.jail.jailed", &sysval, &sysvallen,
272		    NULL, 0) == 0 && sysval == 0) {
273			for (pi = 0; pi < sizeof(perm_sysctl) /
274			     sizeof(perm_sysctl[0]); pi++) {
275				sysvallen = sizeof(sysval);
276				if (sysctlbyname(perm_sysctl[pi].name,
277				    &sysval, &sysvallen, NULL, 0) == 0)
278					add_param(NULL, NULL,
279					    perm_sysctl[pi].ipnum,
280					    (sysval ? 1 : 0) ^
281					    perm_sysctl[pi].rev
282					    ? NULL : "false");
283			}
284			sysvallen = sizeof(sysval);
285			if (sysctlbyname("security.jail.enforce_statfs",
286			    &sysval, &sysvallen, NULL, 0) == 0) {
287				snprintf(enforce_statfs,
288				    sizeof(enforce_statfs), "%d", sysval);
289				add_param(NULL, NULL, KP_ENFORCE_STATFS,
290				    enforce_statfs);
291			}
292		}
293	} else if (op == JF_STOP || op == JF_SHOW) {
294		/* Just print list of all configured non-wildcard jails */
295		if (op == JF_SHOW) {
296			load_config();
297			show_jails();
298			exit(0);
299		}
300		/* Jail remove, perhaps using the config file */
301		if (!docf || argc == 0)
302			usage();
303		if (!Rflag)
304			for (i = 0; i < argc; i++)
305				if (strchr(argv[i], '='))
306					usage();
307		if ((docf = !Rflag &&
308		     (!strcmp(cfname, "-") || stat(cfname, &st) == 0)))
309			load_config();
310		note_remove = docf || argc > 1 || wild_jail_name(argv[0]);
311	} else if (argc > 1 || (argc == 1 && strchr(argv[0], '='))) {
312		/* Single jail specified on the command line */
313		if (Rflag)
314			usage();
315		docf = 0;
316		for (i = 0; i < argc; i++) {
317			if (!strncmp(argv[i], "command", 7) &&
318			    (argv[i][7] == '\0' || argv[i][7] == '=')) {
319				if (argv[i][7]  == '=')
320					add_param(NULL, NULL, IP_COMMAND,
321					    argv[i] + 8);
322				for (i++; i < argc; i++)
323					add_param(NULL, NULL, IP_COMMAND,
324					    argv[i]);
325			}
326#ifdef INET
327			else if (!strncmp(argv[i], "ip4.addr=", 9)) {
328				for (cs = argv[i] + 9;; cs = ncs + 1) {
329					ncs = strchr(cs, ',');
330					if (ncs)
331						*ncs = '\0';
332					add_param(NULL, NULL, KP_IP4_ADDR, cs);
333					if (!ncs)
334						break;
335				}
336			}
337#endif
338#ifdef INET6
339			else if (!strncmp(argv[i], "ip6.addr=", 9)) {
340				for (cs = argv[i] + 9;; cs = ncs + 1) {
341					ncs = strchr(cs, ',');
342					if (ncs)
343						*ncs = '\0';
344					add_param(NULL, NULL, KP_IP6_ADDR, cs);
345					if (!ncs)
346						break;
347				}
348			}
349#endif
350			else
351				add_param(NULL, NULL, 0, argv[i]);
352		}
353	} else {
354		/* From the config file, perhaps with a specified jail */
355		if (Rflag || !docf)
356			usage();
357		load_config();
358	}
359
360	/* Find out which jails will be run. */
361	dep_setup(docf);
362	error = 0;
363	if (op == JF_STOP) {
364		for (i = 0; i < argc; i++)
365			if (start_state(argv[i], docf, op, Rflag) < 0)
366				error = 1;
367	} else {
368		if (start_state(argv[0], docf, op, 0) < 0)
369			exit(1);
370	}
371
372	jfp = NULL;
373	if (JidFile != NULL) {
374		jfp = fopen(JidFile, "w");
375		if (jfp == NULL)
376			err(1, "open %s", JidFile);
377		setlinebuf(jfp);
378	}
379	setlinebuf(stdout);
380
381	/*
382	 * The main loop: Get an available jail and perform the required
383	 * operation on it.  When that is done, the jail may be finished,
384	 * or it may go back for the next step.
385	 */
386	while ((j = next_jail()))
387	{
388		if (j->flags & JF_FAILED) {
389			error = 1;
390			if (j->comparam == NULL) {
391				dep_done(j, 0);
392				continue;
393			}
394		}
395		if (!(j->flags & JF_PARAMS))
396		{
397			j->flags |= JF_PARAMS;
398			if (dflag)
399				add_param(j, NULL, IP_ALLOW_DYING, NULL);
400			if (check_intparams(j) < 0)
401				continue;
402			if ((j->flags & (JF_START | JF_SET)) &&
403			    import_params(j) < 0)
404				continue;
405		}
406		if (!j->jid)
407			running_jid(j,
408			    (j->flags & (JF_SET | JF_DEPEND)) == JF_SET
409			    ? dflag || bool_param(j->intparams[IP_ALLOW_DYING])
410			    : 0);
411		if (finish_command(j))
412			continue;
413
414		switch (j->flags & JF_OP_MASK) {
415			/*
416			 * These operations just turn into a different op
417			 * depending on the jail's current status.
418			 */
419		case JF_START_SET:
420			j->flags = j->jid < 0 ? JF_START : JF_SET;
421			break;
422		case JF_SET_RESTART:
423			if (j->jid < 0) {
424				jail_quoted_warnx(j, "not found",
425				    "no jail specified");
426				failed(j);
427				continue;
428			}
429			j->flags = rdtun_params(j, 0) ? JF_RESTART : JF_SET;
430			if (j->flags == JF_RESTART)
431				dep_reset(j);
432			break;
433		case JF_START_SET_RESTART:
434			j->flags = j->jid < 0 ? JF_START
435			    : rdtun_params(j, 0) ? JF_RESTART : JF_SET;
436			if (j->flags == JF_RESTART)
437				dep_reset(j);
438		}
439
440		switch (j->flags & JF_OP_MASK) {
441		case JF_START:
442			if (j->comparam == NULL) {
443				if (j->jid > 0 &&
444				    !(j->flags & (JF_DEPEND | JF_WILD))) {
445					jail_quoted_warnx(j, "already exists",
446					    NULL);
447					failed(j);
448					continue;
449				}
450				if (dep_check(j))
451					continue;
452				if (j->jid > 0)
453					goto jail_create_done;
454				j->comparam = startcommands;
455				j->comstring = NULL;
456			}
457			if (next_command(j))
458				continue;
459		jail_create_done:
460			clear_persist(j);
461			if (jfp != NULL)
462				print_jail(jfp, j, oldcl, 1);
463			dep_done(j, 0);
464			break;
465
466		case JF_SET:
467			if (j->jid < 0 && !(j->flags & JF_DEPEND)) {
468				jail_quoted_warnx(j, "not found",
469				    "no jail specified");
470				failed(j);
471				continue;
472			}
473			if (dep_check(j))
474				continue;
475			if (!(j->flags & JF_DEPEND)) {
476				if (rdtun_params(j, 1) < 0 ||
477				    update_jail(j) < 0)
478					continue;
479				if (verbose >= 0 && (j->name || verbose > 0))
480					jail_note(j, "updated\n");
481			}
482			dep_done(j, 0);
483			break;
484
485		case JF_STOP:
486		case JF_RESTART:
487			if (j->comparam == NULL) {
488				if (dep_check(j))
489					continue;
490				if (j->jid < 0) {
491					if (!(j->flags & (JF_DEPEND|JF_WILD))) {
492						if (verbose >= 0)
493							jail_quoted_warnx(j,
494							    "not found", NULL);
495						failed(j);
496					}
497					goto jail_remove_done;
498				}
499				j->comparam = stopcommands;
500				j->comstring = NULL;
501			} else if ((j->flags & JF_FAILED) && j->jid > 0)
502				goto jail_remove_done;
503			if (next_command(j))
504				continue;
505		jail_remove_done:
506			dep_done(j, 0);
507			if ((j->flags & (JF_START | JF_FAILED)) == JF_START) {
508				j->comparam = NULL;
509				j->flags &= ~JF_STOP;
510				dep_reset(j);
511				requeue(j, j->ndeps ? &depend : &ready);
512			}
513			break;
514		}
515	}
516
517	if (jfp != NULL)
518		fclose(jfp);
519	exit(error);
520}
521
522/*
523 * Mark a jail's failure for future handling.
524 */
525void
526failed(struct cfjail *j)
527{
528	j->flags |= JF_FAILED;
529	TAILQ_REMOVE(j->queue, j, tq);
530	TAILQ_INSERT_HEAD(&ready, j, tq);
531	j->queue = &ready;
532}
533
534/*
535 * Exit slightly more gracefully when out of memory.
536 */
537void *
538emalloc(size_t size)
539{
540	void *p;
541
542	p = malloc(size);
543	if (!p)
544		err(1, "malloc");
545	return p;
546}
547
548void *
549erealloc(void *ptr, size_t size)
550{
551	void *p;
552
553	p = realloc(ptr, size);
554	if (!p)
555		err(1, "malloc");
556	return p;
557}
558
559char *
560estrdup(const char *str)
561{
562	char *ns;
563
564	ns = strdup(str);
565	if (!ns)
566		err(1, "malloc");
567	return ns;
568}
569
570/*
571 * Print a message including an optional jail name.
572 */
573void
574jail_note(const struct cfjail *j, const char *fmt, ...)
575{
576	va_list ap, tap;
577	char *cs;
578	size_t len;
579
580	va_start(ap, fmt);
581	va_copy(tap, ap);
582	len = vsnprintf(NULL, 0, fmt, tap);
583	va_end(tap);
584	cs = alloca(len + 1);
585	(void)vsnprintf(cs, len + 1, fmt, ap);
586	va_end(ap);
587	if (j->name)
588		printf("%s: %s", j->name, cs);
589	else
590		printf("%s", cs);
591}
592
593/*
594 * Print a warning message including an optional jail name.
595 */
596void
597jail_warnx(const struct cfjail *j, const char *fmt, ...)
598{
599	va_list ap, tap;
600	char *cs;
601	size_t len;
602
603	va_start(ap, fmt);
604	va_copy(tap, ap);
605	len = vsnprintf(NULL, 0, fmt, tap);
606	va_end(tap);
607	cs = alloca(len + 1);
608	(void)vsnprintf(cs, len + 1, fmt, ap);
609	va_end(ap);
610	if (j->name)
611		warnx("%s: %s", j->name, cs);
612	else
613		warnx("%s", cs);
614}
615
616/*
617 * Create a new jail.
618 */
619int
620create_jail(struct cfjail *j)
621{
622	struct iovec jiov[4];
623	struct stat st;
624	struct jailparam *jp, *setparams, *setparams2, *sjp;
625	const char *path;
626	int dopersist, ns, jid, dying, didfail;
627
628	/*
629	 * Check the jail's path, with a better error message than jail_set
630	 * gives.
631	 */
632	if ((path = string_param(j->intparams[KP_PATH]))) {
633		if (j->name != NULL && path[0] != '/') {
634			jail_warnx(j, "path %s: not an absolute pathname",
635			    path);
636			return -1;
637		}
638		if (stat(path, &st) < 0) {
639			jail_warnx(j, "path %s: %s", path, strerror(errno));
640			return -1;
641		}
642		if (!S_ISDIR(st.st_mode)) {
643			jail_warnx(j, "path %s: %s", path, strerror(ENOTDIR));
644			return -1;
645		}
646	}
647
648	/*
649	 * Copy all the parameters, except that "persist" is always set when
650	 * there are commands to run later.
651	 */
652	dopersist = !bool_param(j->intparams[KP_PERSIST]) &&
653	    (j->intparams[IP_EXEC_START] || j->intparams[IP_COMMAND] ||
654	     j->intparams[IP_EXEC_POSTSTART]);
655	sjp = setparams =
656	    alloca((j->njp + dopersist) * sizeof(struct jailparam));
657	if (dopersist && jailparam_init(sjp++, "persist") < 0) {
658		jail_warnx(j, "%s", jail_errmsg);
659		return -1;
660	}
661	for (jp = j->jp; jp < j->jp + j->njp; jp++)
662		if (!dopersist || !equalopts(jp->jp_name, "persist"))
663			*sjp++ = *jp;
664	ns = sjp - setparams;
665
666	didfail = 0;
667	j->jid = jailparam_set_note(j, setparams, ns, JAIL_CREATE);
668	if (j->jid < 0 && errno == EEXIST &&
669	    bool_param(j->intparams[IP_ALLOW_DYING]) &&
670	    int_param(j->intparams[KP_JID], &jid) && jid != 0) {
671		/*
672		 * The jail already exists, but may be dying.
673		 * Make sure it is, in which case an update is appropriate.
674		 */
675		jiov[0].iov_base = __DECONST(char *, "jid");
676		jiov[0].iov_len = sizeof("jid");
677		jiov[1].iov_base = &jid;
678		jiov[1].iov_len = sizeof(jid);
679		jiov[2].iov_base = __DECONST(char *, "dying");
680		jiov[2].iov_len = sizeof("dying");
681		jiov[3].iov_base = &dying;
682		jiov[3].iov_len = sizeof(dying);
683		if (jail_get(jiov, 4, JAIL_DYING) < 0) {
684			/*
685			 * It could be that the jail just barely finished
686			 * dying, or it could be that the jid never existed
687			 * but the name does.  In either case, another try
688			 * at creating the jail should do the right thing.
689			 */
690			if (errno == ENOENT)
691				j->jid = jailparam_set_note(j, setparams, ns,
692				    JAIL_CREATE);
693		} else if (dying) {
694			j->jid = jid;
695			if (rdtun_params(j, 1) < 0) {
696				j->jid = -1;
697				didfail = 1;
698			} else {
699				sjp = setparams2 = alloca((j->njp + dopersist) *
700				    sizeof(struct jailparam));
701				for (jp = setparams; jp < setparams + ns; jp++)
702					if (!JP_RDTUN(jp) ||
703					    !strcmp(jp->jp_name, "jid"))
704						*sjp++ = *jp;
705				j->jid = jailparam_set_note(j, setparams2,
706				    sjp - setparams2, JAIL_UPDATE | JAIL_DYING);
707				/*
708				 * Again, perhaps the jail just finished dying.
709				 */
710				if (j->jid < 0 && errno == ENOENT)
711					j->jid = jailparam_set_note(j,
712					    setparams, ns, JAIL_CREATE);
713			}
714		}
715	}
716	if (j->jid < 0 && !didfail) {
717		jail_warnx(j, "%s", jail_errmsg);
718		failed(j);
719	}
720	if (dopersist) {
721		jailparam_free(setparams, 1);
722		if (j->jid > 0)
723			j->flags |= JF_PERSIST;
724	}
725	return j->jid;
726}
727
728/*
729 * Remove a temporarily set "persist" parameter.
730 */
731static void
732clear_persist(struct cfjail *j)
733{
734	struct iovec jiov[4];
735	int jid;
736
737	if (!(j->flags & JF_PERSIST))
738		return;
739	j->flags &= ~JF_PERSIST;
740	jiov[0].iov_base = __DECONST(char *, "jid");
741	jiov[0].iov_len = sizeof("jid");
742	jiov[1].iov_base = &j->jid;
743	jiov[1].iov_len = sizeof(j->jid);
744	jiov[2].iov_base = __DECONST(char *, "nopersist");
745	jiov[2].iov_len = sizeof("nopersist");
746	jiov[3].iov_base = NULL;
747	jiov[3].iov_len = 0;
748	jid = jail_set(jiov, 4, JAIL_UPDATE);
749	if (verbose > 0)
750		jail_note(j, "jail_set(JAIL_UPDATE) jid=%d nopersist%s%s\n",
751		    j->jid, jid < 0 ? ": " : "",
752		    jid < 0 ? strerror(errno) : "");
753}
754
755/*
756 * Set a jail's parameters.
757 */
758static int
759update_jail(struct cfjail *j)
760{
761	struct jailparam *jp, *setparams, *sjp;
762	int ns, jid;
763
764	ns = 0;
765	for (jp = j->jp; jp < j->jp + j->njp; jp++)
766		if (!JP_RDTUN(jp))
767			ns++;
768	if (ns == 0)
769		return 0;
770	sjp = setparams = alloca(++ns * sizeof(struct jailparam));
771	if (jailparam_init(sjp, "jid") < 0 ||
772	    jailparam_import_raw(sjp, &j->jid, sizeof j->jid) < 0) {
773		jail_warnx(j, "%s", jail_errmsg);
774		failed(j);
775		return -1;
776	}
777	for (jp = j->jp; jp < j->jp + j->njp; jp++)
778		if (!JP_RDTUN(jp))
779			*++sjp = *jp;
780
781	jid = jailparam_set_note(j, setparams, ns,
782	    bool_param(j->intparams[IP_ALLOW_DYING])
783	    ? JAIL_UPDATE | JAIL_DYING : JAIL_UPDATE);
784	if (jid < 0) {
785		jail_warnx(j, "%s", jail_errmsg);
786		failed(j);
787	}
788	jailparam_free(setparams, 1);
789	return jid;
790}
791
792/*
793 * Return if a jail set would change any create-only parameters.
794 */
795static int
796rdtun_params(struct cfjail *j, int dofail)
797{
798	struct jailparam *jp, *rtparams, *rtjp;
799	int nrt, rval;
800
801	if (j->flags & JF_RDTUN)
802		return 0;
803	j->flags |= JF_RDTUN;
804	nrt = 0;
805	for (jp = j->jp; jp < j->jp + j->njp; jp++)
806		if (JP_RDTUN(jp) && strcmp(jp->jp_name, "jid"))
807			nrt++;
808	if (nrt == 0)
809		return 0;
810	rtjp = rtparams = alloca(++nrt * sizeof(struct jailparam));
811	if (jailparam_init(rtjp, "jid") < 0 ||
812	    jailparam_import_raw(rtjp, &j->jid, sizeof j->jid) < 0) {
813		jail_warnx(j, "%s", jail_errmsg);
814		exit(1);
815	}
816	for (jp = j->jp; jp < j->jp + j->njp; jp++)
817		if (JP_RDTUN(jp) && strcmp(jp->jp_name, "jid")) {
818			*++rtjp = *jp;
819			rtjp->jp_value = NULL;
820		}
821	rval = 0;
822	if (jailparam_get(rtparams, nrt,
823	    bool_param(j->intparams[IP_ALLOW_DYING]) ? JAIL_DYING : 0) > 0) {
824		rtjp = rtparams + 1;
825		for (jp = j->jp; rtjp < rtparams + nrt; jp++) {
826			if (JP_RDTUN(jp) && strcmp(jp->jp_name, "jid")) {
827				if (!((jp->jp_flags & (JP_BOOL | JP_NOBOOL)) &&
828				    jp->jp_valuelen == 0 &&
829				    *(int *)jp->jp_value) &&
830				    !(rtjp->jp_valuelen == jp->jp_valuelen &&
831				    !((jp->jp_ctltype & CTLTYPE) ==
832				    CTLTYPE_STRING ? strncmp(rtjp->jp_value,
833				    jp->jp_value, jp->jp_valuelen) :
834				    memcmp(rtjp->jp_value, jp->jp_value,
835				    jp->jp_valuelen)))) {
836					if (dofail) {
837						jail_warnx(j, "%s cannot be "
838						    "changed after creation",
839						    jp->jp_name);
840						failed(j);
841						rval = -1;
842					} else
843						rval = 1;
844					break;
845				}
846				rtjp++;
847			}
848		}
849	}
850	for (rtjp = rtparams + 1; rtjp < rtparams + nrt; rtjp++)
851		rtjp->jp_name = NULL;
852	jailparam_free(rtparams, nrt);
853	return rval;
854}
855
856/*
857 * Get the jail's jid if it is running.
858 */
859static void
860running_jid(struct cfjail *j, int dflag)
861{
862	struct iovec jiov[2];
863	const char *pval;
864	char *ep;
865	int jid;
866
867	if ((pval = string_param(j->intparams[KP_JID]))) {
868		if (!(jid = strtol(pval, &ep, 10)) || *ep) {
869			j->jid = -1;
870			return;
871		}
872		jiov[0].iov_base = __DECONST(char *, "jid");
873		jiov[0].iov_len = sizeof("jid");
874		jiov[1].iov_base = &jid;
875		jiov[1].iov_len = sizeof(jid);
876	} else if ((pval = string_param(j->intparams[KP_NAME]))) {
877		jiov[0].iov_base = __DECONST(char *, "name");
878		jiov[0].iov_len = sizeof("name");
879		jiov[1].iov_len = strlen(pval) + 1;
880		jiov[1].iov_base = alloca(jiov[1].iov_len);
881		strcpy(jiov[1].iov_base, pval);
882	} else {
883		j->jid = -1;
884		return;
885	}
886	j->jid = jail_get(jiov, 2, dflag ? JAIL_DYING : 0);
887}
888
889static void
890jail_quoted_warnx(const struct cfjail *j, const char *name_msg,
891    const char *noname_msg)
892{
893	const char *pval;
894
895	if ((pval = j->name) || (pval = string_param(j->intparams[KP_JID])) ||
896	    (pval = string_param(j->intparams[KP_NAME])))
897		warnx("\"%s\" %s", pval, name_msg);
898	else
899		warnx("%s", noname_msg);
900}
901
902/*
903 * Set jail parameters and possibly print them out.
904 */
905static int
906jailparam_set_note(const struct cfjail *j, struct jailparam *jp, unsigned njp,
907    int flags)
908{
909	char *value;
910	int jid;
911	unsigned i;
912
913	jid = jailparam_set(jp, njp, flags);
914	if (verbose > 0) {
915		jail_note(j, "jail_set(%s%s)",
916		    (flags & (JAIL_CREATE | JAIL_UPDATE)) == JAIL_CREATE
917		    ? "JAIL_CREATE" : "JAIL_UPDATE",
918		    (flags & JAIL_DYING) ? " | JAIL_DYING" : "");
919		for (i = 0; i < njp; i++) {
920			printf(" %s", jp[i].jp_name);
921			if (jp[i].jp_value == NULL)
922				continue;
923			putchar('=');
924			value = jailparam_export(jp + i);
925			if (value == NULL)
926				err(1, "jailparam_export");
927			quoted_print(stdout, value);
928			free(value);
929		}
930		if (jid < 0)
931			printf(": %s", strerror(errno));
932		printf("\n");
933	}
934	return jid;
935}
936
937/*
938 * Print a jail record.
939 */
940static void
941print_jail(FILE *fp, struct cfjail *j, int oldcl, int running)
942{
943	struct cfparam *p;
944	int printsep;
945
946	if (oldcl) {
947		if (running)
948			fprintf(fp, "%d%s", j->jid, separator);
949		print_param(fp, j->intparams[KP_PATH], ',', 0);
950		fputs(separator, fp);
951		print_param(fp, j->intparams[KP_HOST_HOSTNAME], ',', 0);
952		fputs(separator, fp);
953#ifdef INET
954		print_param(fp, j->intparams[KP_IP4_ADDR], ',', 0);
955#ifdef INET6
956		if (j->intparams[KP_IP4_ADDR] &&
957		    !TAILQ_EMPTY(&j->intparams[KP_IP4_ADDR]->val) &&
958		    j->intparams[KP_IP6_ADDR] &&
959		    !TAILQ_EMPTY(&j->intparams[KP_IP6_ADDR]->val))
960		    putc(',', fp);
961#endif
962#endif
963#ifdef INET6
964		print_param(fp, j->intparams[KP_IP6_ADDR], ',', 0);
965#endif
966		fputs(separator, fp);
967		print_param(fp, j->intparams[IP_COMMAND], ' ', 0);
968	} else {
969		printsep = 0;
970		if (running) {
971			fprintf(fp, "jid=%d", j->jid);
972			printsep = 1;
973		}
974		TAILQ_FOREACH(p, &j->params, tq)
975			if (strcmp(p->name, "jid")) {
976				if (printsep)
977					fputs(separator, fp);
978				else
979					printsep = 1;
980				print_param(fp, p, ',', 1);
981			}
982	}
983	putc('\n', fp);
984}
985
986/*
987 * Exhibit list of all configured non-wildcard jails
988 */
989static void
990show_jails(void)
991{
992	struct cfjail *j;
993
994	TAILQ_FOREACH(j, &cfjails, tq)
995		print_jail(stdout, j, 0, 0);
996}
997
998/*
999 * Print a parameter value, or a name=value pair.
1000 */
1001static void
1002print_param(FILE *fp, const struct cfparam *p, int sep, int doname)
1003{
1004	const struct cfstring *s, *ts;
1005
1006	if (doname)
1007		fputs(p->name, fp);
1008	if (p == NULL || TAILQ_EMPTY(&p->val))
1009		return;
1010	if (doname)
1011		putc('=', fp);
1012	TAILQ_FOREACH_SAFE(s, &p->val, tq, ts) {
1013		quoted_print(fp, s->s);
1014		if (ts != NULL)
1015			putc(sep, fp);
1016	}
1017}
1018
1019/*
1020 * Print a string with quotes around spaces.
1021 */
1022static void
1023quoted_print(FILE *fp, char *str)
1024{
1025	int c, qc;
1026	char *p = str;
1027
1028	qc = !*p ? '"'
1029	    : strchr(p, '\'') ? '"'
1030	    : strchr(p, '"') ? '\''
1031	    : strchr(p, ' ') || strchr(p, '\t') ? '"'
1032	    : 0;
1033	if (qc)
1034		putc(qc, fp);
1035	while ((c = *p++)) {
1036		if (c == '\\' || c == qc)
1037			putc('\\', fp);
1038		putc(c, fp);
1039	}
1040	if (qc)
1041		putc(qc, fp);
1042}
1043
1044static void
1045usage(void)
1046{
1047
1048	(void)fprintf(stderr,
1049	    "usage: jail [-dhilqv] [-J jid_file] [-u username] [-U username]\n"
1050	    "            -[cmr] param=value ... [command=command ...]\n"
1051	    "       jail [-dqv] [-f file] -[cmr] [jail]\n"
1052	    "       jail [-qv] [-f file] -[rR] ['*' | jail ...]\n"
1053	    "       jail [-dhilqv] [-J jid_file] [-u username] [-U username]\n"
1054	    "            [-n jailname] [-s securelevel]\n"
1055	    "            path hostname ip[,...] command ...\n"
1056	    "       jail [-f file] -e separator\n");
1057	exit(1);
1058}
1059