diff --git a/libexec/rc/rc.d/jail b/libexec/rc/rc.d/jail --- a/libexec/rc/rc.d/jail +++ b/libexec/rc/rc.d/jail @@ -574,7 +574,7 @@ eval command=\${jail_${_jv}_program:-$jail_program} echo -n " ${_hostname:-${_j}}" _tmp=`mktemp -t jail` || exit 3 - $command -q -f $_conf -r $_j >> $_tmp 2>&1 + $command $jail_flags -q -f $_conf -r $_j >> $_tmp 2>&1 if $jail_jls -j $_j > /dev/null 2>&1; then cat $_tmp else diff --git a/usr.sbin/jail/config.c b/usr.sbin/jail/config.c --- a/usr.sbin/jail/config.c +++ b/usr.sbin/jail/config.c @@ -32,12 +32,14 @@ #include #include #include +#include #include -#include #include +#include #include +#include #include #include #include @@ -123,11 +125,25 @@ [KP_VNET] = {"vnet", 0}, }; +static const char *conf_files[] = { + "/etc/jail.conf", + "/etc/jail.conf.d/*.conf", + "/etc/jail.*.conf" +}; + +static void +check_glob_err(int rc) { + if (rc == GLOB_NOSPACE) + err(1, "Failed to allocate memory for glob!"); + else if (rc == GLOB_ABORTED) + err(1, "Error encountered parsing glob!"); +} + /* * Parse the jail configuration file. */ void -load_config(void) +load_config(int op) { struct cfjails wild; struct cfparams opp; @@ -135,19 +151,52 @@ struct cfparam *p, *vp, *tp; struct cfstring *s, *vs, *ns; struct cfvar *v, *vv; + struct stat st = {0}; + const char *mycfname = cfname; + glob_t g = {0}; char *ep; - int did_self, jseq, pgen; - - if (!strcmp(cfname, "-")) { - cfname = "STDIN"; - yyin = stdin; - } else { - yyin = fopen(cfname, "r"); - if (!yyin) - err(1, "%s", cfname); + size_t si; + int did_self, jseq, pgen, rc; + + if (op & JF_CONF_ALL) { + si = sizeof(conf_files) / sizeof(conf_files[0]); + for (size_t i = 0; i < si; i++) { + rc = glob(conf_files[i], GLOB_APPEND, NULL, &g); + check_glob_err(rc); + } + for (size_t i = 0; i < g.gl_pathc; i++) { + cfname = g.gl_pathv[i]; + yyin = fopen(cfname, "r"); + if (!yyin) + err(1, "%s", cfname); + if (yyparse() || yynerrs) { + fclose(yyin); + exit(1); + } + fclose(yyin); + } + } + cfname = mycfname; + if (cfname != NULL) { + if (strcmp(cfname, "-")) { + if (stat(cfname, &st) != 0) + err(1, "No such file %s!", cfname); + yyin = fopen(cfname, "r"); + if (!yyin) + err(1, "%s", cfname); + if (yyparse() || yynerrs) { + fclose(yyin); + exit(1); + } + fclose(yyin); + } else { + cfname = "STDIN"; + yyin = stdin; + if (yyparse() || yynerrs) { + exit(1); + } + } } - if (yyparse() || yynerrs) - exit(1); /* Separate the wildcard jails out from the actual jails. */ jseq = 0; diff --git a/usr.sbin/jail/jail.c b/usr.sbin/jail/jail.c --- a/usr.sbin/jail/jail.c +++ b/usr.sbin/jail/jail.c @@ -134,7 +134,6 @@ int main(int argc, char **argv) { - struct stat st; FILE *jfp; struct cfjail *j; char *JidFile; @@ -152,10 +151,10 @@ op = 0; dflag = Rflag = 0; docf = 1; - cfname = CONF_FILE; + cfname = NULL; JidFile = NULL; - while ((ch = getopt(argc, argv, "cde:f:hiJ:lmn:p:qrRs:u:U:v")) != -1) { + while ((ch = getopt(argc, argv, "cde:f:FhiJ:lmn:p:qrRs:u:U:v")) != -1) { switch (ch) { case 'c': op |= JF_START; @@ -170,6 +169,9 @@ case 'f': cfname = optarg; break; + case 'F': + op |= JF_CONF_ALL; + break; case 'h': #if defined(INET) || defined(INET6) add_param(NULL, NULL, IP_IP_HOSTNAME, NULL); @@ -287,20 +289,20 @@ } else if (op == JF_STOP || op == JF_SHOW) { /* Just print list of all configured non-wildcard jails */ if (op == JF_SHOW) { - load_config(); + load_config(op); show_jails(); exit(0); } /* Jail remove, perhaps using the config file */ if (!docf || argc == 0) usage(); - if (!Rflag) + docf = !Rflag; + if (docf) { for (i = 0; i < argc; i++) if (strchr(argv[i], '=')) usage(); - if ((docf = !Rflag && - (!strcmp(cfname, "-") || stat(cfname, &st) == 0))) - load_config(); + load_config(op); + } note_remove = docf || argc > 1 || wild_jail_name(argv[0]); } else if (argc > 1 || (argc == 1 && strchr(argv[0], '='))) { /* Single jail specified on the command line */ @@ -348,7 +350,7 @@ /* From the config file, perhaps with a specified jail */ if (Rflag || !docf) usage(); - load_config(); + load_config(op); } /* Find out which jails will be run. */ diff --git a/usr.sbin/jail/jailp.h b/usr.sbin/jail/jailp.h --- a/usr.sbin/jail/jailp.h +++ b/usr.sbin/jail/jailp.h @@ -36,8 +36,6 @@ #include -#define CONF_FILE "/etc/jail.conf" - #define DEP_FROM 0 #define DEP_TO 1 @@ -68,6 +66,7 @@ #define JF_SLEEPQ 0x0400 /* Waiting on a command and/or timeout */ #define JF_FROM_RUNQ 0x0800 /* Has already been on the run queue */ #define JF_SHOW 0x1000 /* -e Exhibit list of configured jails */ +#define JF_CONF_ALL 0x2000 /* jail.conf, jail.conf.d and jail..conf */ #define JF_OP_MASK (JF_START | JF_SET | JF_STOP) #define JF_RESTART (JF_START | JF_STOP) @@ -208,7 +207,7 @@ extern int finish_command(struct cfjail *j); extern struct cfjail *next_proc(int nonblock); -extern void load_config(void); +extern void load_config(int op); extern struct cfjail *add_jail(void); extern void add_param(struct cfjail *j, const struct cfparam *p, enum intparam ipnum, const char *value);