13b31921jamie/*-
27551d83pfg * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
37551d83pfg *
48d425bfjamie * Copyright (c) 2011 James Gritton.
53b31921jamie * All rights reserved.
63b31921jamie *
73b31921jamie * Redistribution and use in source and binary forms, with or without
83b31921jamie * modification, are permitted provided that the following conditions
93b31921jamie * are met:
103b31921jamie * 1. Redistributions of source code must retain the above copyright
113b31921jamie *    notice, this list of conditions and the following disclaimer.
123b31921jamie * 2. Redistributions in binary form must reproduce the above copyright
133b31921jamie *    notice, this list of conditions and the following disclaimer in the
143b31921jamie *    documentation and/or other materials provided with the distribution.
153b31921jamie *
163b31921jamie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
173b31921jamie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
183b31921jamie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
193b31921jamie * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
203b31921jamie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
213b31921jamie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
223b31921jamie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
233b31921jamie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
243b31921jamie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
253b31921jamie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
263b31921jamie * SUCH DAMAGE.
273b31921jamie *
283b31921jamie * $FreeBSD$
293b31921jamie */
303b31921jamie
313b31921jamie#include <sys/param.h>
323b31921jamie#include <sys/types.h>
333b31921jamie#include <sys/jail.h>
343b31921jamie#include <sys/queue.h>
353b31921jamie#include <sys/time.h>
363b31921jamie
373b31921jamie#include <jail.h>
383b31921jamie
393b31921jamie#define CONF_FILE	"/etc/jail.conf"
403b31921jamie
413b31921jamie#define DEP_FROM	0
423b31921jamie#define DEP_TO		1
433b31921jamie
443b31921jamie#define DF_SEEN		0x01	/* Dependency has been followed */
453b31921jamie#define DF_LIGHT	0x02	/* Implied dependency on jail existence only */
4621a3003eadler#define DF_NOFAIL	0x04	/* Don't propagate failed jails */
473b31921jamie
483b31921jamie#define PF_VAR		0x01	/* This is a variable, not a true parameter */
493b31921jamie#define PF_APPEND	0x02	/* Append to existing parameter list */
503b31921jamie#define PF_BAD		0x04	/* Unable to resolve parameter value */
513b31921jamie#define PF_INTERNAL	0x08	/* Internal parameter, not passed to kernel */
523b31921jamie#define PF_BOOL		0x10	/* Boolean parameter */
533b31921jamie#define PF_INT		0x20	/* Integer parameter */
54235aefejamie#define PF_CONV		0x40	/* Parameter duplicated in converted form */
5582d5811jamie#define PF_REV		0x80	/* Run commands in reverse order on stopping */
566a6f426hrs#define	PF_IMMUTABLE	0x100	/* Immutable parameter */
573b31921jamie
583b31921jamie#define JF_START	0x0001	/* -c */
593b31921jamie#define JF_SET		0x0002	/* -m */
603b31921jamie#define JF_STOP		0x0004	/* -r */
613b31921jamie#define JF_DEPEND	0x0008	/* Operation required by dependency */
623b31921jamie#define JF_WILD		0x0010	/* Not specified on the command line */
633b31921jamie#define JF_FAILED	0x0020	/* Operation failed */
6494aa5f7jamie#define JF_PARAMS	0x0040	/* Parameters checked and imported */
6594aa5f7jamie#define JF_RDTUN	0x0080	/* Create-only parameter check has been done */
66bf5da84jamie#define JF_PERSIST	0x0100	/* Jail is temporarily persistent */
67bf5da84jamie#define JF_TIMEOUT	0x0200	/* A command (or process kill) timed out */
68bf5da84jamie#define JF_SLEEPQ	0x0400	/* Waiting on a command and/or timeout */
690e8a4f4jamie#define JF_FROM_RUNQ	0x0800	/* Has already been on the run queue */
707e81b08eugen#define JF_SHOW		0x1000	/* -e Exhibit list of configured jails */
713b31921jamie
723b31921jamie#define JF_OP_MASK		(JF_START | JF_SET | JF_STOP)
733b31921jamie#define JF_RESTART		(JF_START | JF_STOP)
743b31921jamie#define JF_START_SET		(JF_START | JF_SET)
753b31921jamie#define JF_SET_RESTART		(JF_SET | JF_STOP)
763b31921jamie#define JF_START_SET_RESTART	(JF_START | JF_SET | JF_STOP)
773b31921jamie#define JF_DO_STOP(js)		(((js) & (JF_SET | JF_STOP)) == JF_STOP)
783b31921jamie
793b31921jamieenum intparam {
8018b00cejamie	IP__NULL = 0,		/* Null command */
8118b00cejamie	IP_ALLOW_DYING,		/* Allow making changes to a dying jail */
823b31921jamie	IP_COMMAND,		/* Command run inside jail at creation */
833b31921jamie	IP_DEPEND,		/* Jail starts after (stops before) another */
843b31921jamie	IP_EXEC_CLEAN,		/* Run commands in a clean environment */
853b31921jamie	IP_EXEC_CONSOLELOG,	/* Redirect optput for commands run in jail */
863b31921jamie	IP_EXEC_FIB,		/* Run jailed commands with this FIB */
873b31921jamie	IP_EXEC_JAIL_USER,	/* Run jailed commands as this user */
883b31921jamie	IP_EXEC_POSTSTART,	/* Commands run outside jail after creating */
893b31921jamie	IP_EXEC_POSTSTOP,	/* Commands run outside jail after removing */
903b31921jamie	IP_EXEC_PRESTART,	/* Commands run outside jail before creating */
913b31921jamie	IP_EXEC_PRESTOP,	/* Commands run outside jail before removing */
9242ccecbnetchild	IP_EXEC_CREATED,	/* Commands run outside jail right after it was started */
933b31921jamie	IP_EXEC_START,		/* Commands run inside jail on creation */
943b31921jamie	IP_EXEC_STOP,		/* Commands run inside jail on removal */
953b31921jamie	IP_EXEC_SYSTEM_JAIL_USER,/* Get jail_user from system passwd file */
963b31921jamie	IP_EXEC_SYSTEM_USER,	/* Run non-jailed commands as this user */
973b31921jamie	IP_EXEC_TIMEOUT,	/* Time to wait for a command to complete */
986811668jamie#if defined(INET) || defined(INET6)
993b31921jamie	IP_INTERFACE,		/* Add IP addresses to this interface */
1003b31921jamie	IP_IP_HOSTNAME,		/* Get jail IP address(es) from hostname */
1016811668jamie#endif
1023b31921jamie	IP_MOUNT,		/* Mount points in fstab(5) form */
1033b31921jamie	IP_MOUNT_DEVFS,		/* Mount /dev under prison root */
104513bdd9hrs	IP_MOUNT_FDESCFS,	/* Mount /dev/fd under prison root */
1056064614jamie	IP_MOUNT_PROCFS,	/* Mount /proc under prison root */
106235aefejamie	IP_MOUNT_FSTAB,		/* A standard fstab(5) file */
1073b31921jamie	IP_STOP_TIMEOUT,	/* Time to wait after sending SIGTERM */
108235aefejamie	IP_VNET_INTERFACE,	/* Assign interface(s) to vnet jail */
1096811668jamie#ifdef INET
1103b31921jamie	IP__IP4_IFADDR,		/* Copy of ip4.addr with interface/netmask */
1116811668jamie#endif
1123b31921jamie#ifdef INET6
1133b31921jamie	IP__IP6_IFADDR,		/* Copy of ip6.addr with interface/prefixlen */
1143b31921jamie#endif
1158576789jamie	IP__MOUNT_FROM_FSTAB,	/* Line from mount.fstab file */
116bf5da84jamie	IP__OP,			/* Placeholder for requested operation */
117235aefejamie	KP_ALLOW_CHFLAGS,
118235aefejamie	KP_ALLOW_MOUNT,
119235aefejamie	KP_ALLOW_RAW_SOCKETS,
120235aefejamie	KP_ALLOW_SET_HOSTNAME,
121235aefejamie	KP_ALLOW_SOCKET_AF,
122235aefejamie	KP_ALLOW_SYSVIPC,
1236fe59c6jamie	KP_DEVFS_RULESET,
124235aefejamie	KP_HOST_HOSTNAME,
1256811668jamie#ifdef INET
1263b31921jamie	KP_IP4_ADDR,
1276811668jamie#endif
1283b31921jamie#ifdef INET6
1293b31921jamie	KP_IP6_ADDR,
1303b31921jamie#endif
1313b31921jamie	KP_JID,
1323b31921jamie	KP_NAME,
1333b31921jamie	KP_PATH,
1343b31921jamie	KP_PERSIST,
135235aefejamie	KP_SECURELEVEL,
1363b31921jamie	KP_VNET,
1373b31921jamie	IP_NPARAM
1383b31921jamie};
1393b31921jamie
1403b31921jamieSTAILQ_HEAD(cfvars, cfvar);
1413b31921jamie
1423b31921jamiestruct cfvar {
1433b31921jamie	STAILQ_ENTRY(cfvar)	tq;
1443b31921jamie	char			*name;
1453b31921jamie	size_t			pos;
1463b31921jamie};
1473b31921jamie
1480e5ec9djamieTAILQ_HEAD(cfstrings, cfstring);
1493b31921jamie
1503b31921jamiestruct cfstring {
1510e5ec9djamie	TAILQ_ENTRY(cfstring)	tq;
1523b31921jamie	char			*s;
1533b31921jamie	size_t			len;
1543b31921jamie	struct cfvars		vars;
1553b31921jamie};
1563b31921jamie
1573b31921jamieTAILQ_HEAD(cfparams, cfparam);
1583b31921jamie
1593b31921jamiestruct cfparam {
1603b31921jamie	TAILQ_ENTRY(cfparam)	tq;
1613b31921jamie	char			*name;
1623b31921jamie	struct cfstrings	val;
1633b31921jamie	unsigned		flags;
1643b31921jamie	int			gen;
1653b31921jamie};
1663b31921jamie
1673b31921jamieTAILQ_HEAD(cfjails, cfjail);
1683b31921jamieSTAILQ_HEAD(cfdepends, cfdepend);
1693b31921jamie
1703b31921jamiestruct cfjail {
1713b31921jamie	TAILQ_ENTRY(cfjail)	tq;
1723b31921jamie	char			*name;
1733b31921jamie	char			*comline;
1743b31921jamie	struct cfparams		params;
1753b31921jamie	struct cfdepends	dep[2];
1763b31921jamie	struct cfjails		*queue;
1773b31921jamie	struct cfparam		*intparams[IP_NPARAM];
1783b31921jamie	struct cfstring		*comstring;
1793b31921jamie	struct jailparam	*jp;
1803b31921jamie	struct timespec		timeout;
181bf5da84jamie	const enum intparam	*comparam;
1823b31921jamie	unsigned		flags;
1833b31921jamie	int			jid;
1843b31921jamie	int			seq;
1853b31921jamie	int			pstatus;
1863b31921jamie	int			ndeps;
1873b31921jamie	int			njp;
1883b31921jamie	int			nprocs;
1893b31921jamie};
1903b31921jamie
1913b31921jamiestruct cfdepend {
1923b31921jamie	STAILQ_ENTRY(cfdepend)	tq[2];
1933b31921jamie	struct cfjail		*j[2];
1943b31921jamie	unsigned		flags;
1953b31921jamie};
1963b31921jamie
1973b31921jamieextern void *emalloc(size_t);
1983b31921jamieextern void *erealloc(void *, size_t);
1993b31921jamieextern char *estrdup(const char *);
200b3870a1jamieextern int create_jail(struct cfjail *j);
2013b31921jamieextern void failed(struct cfjail *j);
2023b31921jamieextern void jail_note(const struct cfjail *j, const char *fmt, ...);
2033b31921jamieextern void jail_warnx(const struct cfjail *j, const char *fmt, ...);
2043b31921jamie
205bf5da84jamieextern int next_command(struct cfjail *j);
2063a156b8jamieextern int finish_command(struct cfjail *j);
2073b31921jamieextern struct cfjail *next_proc(int nonblock);
2083b31921jamie
2093b31921jamieextern void load_config(void);
2103b31921jamieextern struct cfjail *add_jail(void);
2113b31921jamieextern void add_param(struct cfjail *j, const struct cfparam *p,
212235aefejamie    enum intparam ipnum, const char *value);
2133b31921jamieextern int bool_param(const struct cfparam *p);
2143b31921jamieextern int int_param(const struct cfparam *p, int *ip);
2153b31921jamieextern const char *string_param(const struct cfparam *p);
21694aa5f7jamieextern int check_intparams(struct cfjail *j);
2173b31921jamieextern int import_params(struct cfjail *j);
2183b31921jamieextern int equalopts(const char *opt1, const char *opt2);
2193b31921jamieextern int wild_jail_name(const char *wname);
2203b31921jamieextern int wild_jail_match(const char *jname, const char *wname);
2213b31921jamie
2223b31921jamieextern void dep_setup(int docf);
2233b31921jamieextern int dep_check(struct cfjail *j);
2243b31921jamieextern void dep_done(struct cfjail *j, unsigned flags);
2253b31921jamieextern void dep_reset(struct cfjail *j);
2263b31921jamieextern struct cfjail *next_jail(void);
227a85d762jamieextern int start_state(const char *target, int docf, unsigned state,
228a85d762jamie    int running);
2293b31921jamieextern void requeue(struct cfjail *j, struct cfjails *queue);
2300e8a4f4jamieextern void requeue_head(struct cfjail *j, struct cfjails *queue);
2313b31921jamie
2323b31921jamieextern void yyerror(const char *);
2333b31921jamieextern int yylex(void);
2343b31921jamie
2353b31921jamieextern struct cfjails cfjails;
2363b31921jamieextern struct cfjails ready;
2373a156b8jamieextern struct cfjails depend;
2383b31921jamieextern const char *cfname;
2395ddbe53jamieextern int iflag;
240b3870a1jamieextern int note_remove;
2413a156b8jamieextern int paralimit;
2423b31921jamieextern int verbose;
243