Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115749309
D40188.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D40188.diff
View Options
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
@@ -38,6 +38,7 @@
#include <netinet/in.h>
#include <err.h>
+#include <glob.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
@@ -46,6 +47,8 @@
#include "jailp.h"
+#define MAX_INCLUDE_DEPTH 32
+
struct ipspec {
const char *name;
unsigned flags;
@@ -58,8 +61,8 @@
struct cfjails cfjails = TAILQ_HEAD_INITIALIZER(cfjails);
+static void parse_config(const char *fname, int is_stdin);
static void free_param(struct cfparams *pp, struct cfparam *p);
-static void free_param_strings(struct cfparam *p);
static const struct ipspec intparams[] = {
[IP_ALLOW_DYING] = {"allow.dying", PF_INTERNAL | PF_BOOL},
@@ -135,26 +138,10 @@
struct cfparam *p, *vp, *tp;
struct cfstring *s, *vs, *ns;
struct cfvar *v, *vv;
- struct cflex cflex;
char *ep;
- void *scanner;
int did_self, jseq, pgen;
- cflex.cfname = cfname;
- cflex.error = 0;
- yylex_init_extra(&cflex, &scanner);
- if (!strcmp(cfname, "-")) {
- cflex.cfname = "STDIN";
- yyset_in(stdin, scanner);
- } else {
- FILE *yfp = fopen(cfname, "r");
- if (!yfp)
- err(1, "%s", cfname);
- yyset_in(yfp, scanner);
- }
- if (yyparse(scanner) || cflex.error)
- exit(1);
- yylex_destroy(scanner);
+ parse_config(cfname, !strcmp(cfname, "-"));
/* Separate the wildcard jails out from the actual jails. */
jseq = 0;
@@ -281,6 +268,67 @@
}
}
+void
+include_config(void *scanner, const char *cfname)
+{
+ static unsigned int depth;
+ glob_t g = {0};
+ const char *slash;
+ char *fullpath = NULL;
+
+ /* Simple sanity check for include loops. */
+ if (++depth > MAX_INCLUDE_DEPTH)
+ errx(1, "maximum include depth exceeded");
+ /* Base relative pathnames on the current config file. */
+ if (yyget_in(scanner) != stdin && cfname[0] != '/') {
+ const char *outer_cfname = yyget_extra(scanner)->cfname;
+ if ((slash = strrchr(outer_cfname, '/')) != NULL) {
+ size_t dirlen = (slash - outer_cfname) + 1;
+
+ fullpath = emalloc(dirlen + strlen(cfname) + 1);
+ strncpy(fullpath, outer_cfname, dirlen);
+ strcpy(fullpath + dirlen, cfname);
+ cfname = fullpath;
+ }
+ }
+ /*
+ * Check if the include statement had a filename glob.
+ * Globbing doesn't need to catch any files, but a non-glob
+ * file needs to exist (enforced by parse_config).
+ */
+ if (glob(cfname, GLOB_NOCHECK, NULL, &g) != 0)
+ errx(1, "%s: filename glob failed", cfname);
+ if (g.gl_flags & GLOB_MAGCHAR) {
+ for (size_t gi = 0; gi < g.gl_matchc; gi++)
+ parse_config(g.gl_pathv[gi], 0);
+ } else
+ parse_config(cfname, 0);
+ if (fullpath)
+ free(fullpath);
+ --depth;
+}
+
+static void
+parse_config(const char *cfname, int is_stdin)
+{
+ struct cflex cflex = {.cfname = cfname, .error = 0};
+ void *scanner;
+
+ yylex_init_extra(&cflex, &scanner);
+ if (is_stdin) {
+ cflex.cfname = "STDIN";
+ yyset_in(stdin, scanner);
+ } else {
+ FILE *yfp = fopen(cfname, "r");
+ if (!yfp)
+ err(1, "%s", cfname);
+ yyset_in(yfp, scanner);
+ }
+ if (yyparse(scanner) || cflex.error)
+ exit(1);
+ yylex_destroy(scanner);
+}
+
/*
* Create a new jail record.
*/
@@ -843,7 +891,7 @@
free(p);
}
-static void
+void
free_param_strings(struct cfparam *p)
{
struct cfstring *s;
diff --git a/usr.sbin/jail/jail.conf.5 b/usr.sbin/jail/jail.conf.5
--- a/usr.sbin/jail/jail.conf.5
+++ b/usr.sbin/jail/jail.conf.5
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 8, 2022
+.Dd Jun 3, 2023
.Dt JAIL.CONF 5
.Os
.Sh NAME
@@ -163,6 +163,14 @@
.Dq foo.bar
and
.Dq foo.bar.baz .
+.Ss Includes
+A line of the form
+.Bd -literal -offset ident
+.include "filename";
+.Ed
+.Pp
+will include another file in the configuration. The filename must be
+a literal string, and cannot contain variable expansions.
.Ss Comments
The configuration file may contain comments in the common C, C++, and
shell formats:
@@ -212,6 +220,13 @@
mount.nodevfs;
persist; // Required because there are no processes
}
+
+# Include configurations from standard locations.
+\[char46]include "/etc/jail.conf.d/*.conf";
+\[char46]include "/etc/jail.*.conf";
+\[char46]include "/usr/local/etc/jail[.]conf";
+\[char46]include "/usr/local/etc/jail.conf.d/*.conf";
+\[char46]include "/usr/local/etc/jail.*.conf";
.Ed
.Sh SEE ALSO
.Xr jail_set 2 ,
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
@@ -35,6 +35,7 @@
#include <sys/time.h>
#include <jail.h>
+#include <stdio.h>
#define CONF_FILE "/etc/jail.conf"
@@ -45,15 +46,16 @@
#define DF_LIGHT 0x02 /* Implied dependency on jail existence only */
#define DF_NOFAIL 0x04 /* Don't propagate failed jails */
-#define PF_VAR 0x01 /* This is a variable, not a true parameter */
-#define PF_APPEND 0x02 /* Append to existing parameter list */
-#define PF_BAD 0x04 /* Unable to resolve parameter value */
-#define PF_INTERNAL 0x08 /* Internal parameter, not passed to kernel */
-#define PF_BOOL 0x10 /* Boolean parameter */
-#define PF_INT 0x20 /* Integer parameter */
-#define PF_CONV 0x40 /* Parameter duplicated in converted form */
-#define PF_REV 0x80 /* Run commands in reverse order on stopping */
-#define PF_IMMUTABLE 0x100 /* Immutable parameter */
+#define PF_VAR 0x0001 /* This is a variable, not a true parameter */
+#define PF_APPEND 0x0002 /* Append to existing parameter list */
+#define PF_BAD 0x0004 /* Unable to resolve parameter value */
+#define PF_INTERNAL 0x0008 /* Internal parameter, not passed to kernel */
+#define PF_BOOL 0x0010 /* Boolean parameter */
+#define PF_INT 0x0020 /* Integer parameter */
+#define PF_CONV 0x0040 /* Parameter duplicated in converted form */
+#define PF_REV 0x0080 /* Run commands in reverse order on stopping */
+#define PF_IMMUTABLE 0x0100 /* Immutable parameter */
+#define PF_NAMEVAL 0x0200 /* Parameter is in "name value" form */
#define JF_START 0x0001 /* -c */
#define JF_SET 0x0002 /* -m */
@@ -215,6 +217,7 @@
extern struct cfjail *next_proc(int nonblock);
extern void load_config(const char *cfname);
+extern void include_config(void *scanner, const char *cfname);
extern struct cfjail *add_jail(void);
extern void add_param(struct cfjail *j, const struct cfparam *p,
enum intparam ipnum, const char *value);
@@ -226,6 +229,7 @@
extern int equalopts(const char *opt1, const char *opt2);
extern int wild_jail_name(const char *wname);
extern int wild_jail_match(const char *jname, const char *wname);
+extern void free_param_strings(struct cfparam *p);
extern void dep_setup(int docf);
extern int dep_check(struct cfjail *j);
@@ -237,6 +241,11 @@
extern void requeue(struct cfjail *j, struct cfjails *queue);
extern void requeue_head(struct cfjail *j, struct cfjails *queue);
+extern struct cflex *yyget_extra(void *scanner);
+extern FILE *yyget_in(void *scanner);
+extern int yyget_lineno(void *scanner);
+extern char *yyget_text(void *scanner);
+
extern struct cfjails cfjails;
extern struct cfjails ready;
extern struct cfjails depend;
diff --git a/usr.sbin/jail/jailparse.y b/usr.sbin/jail/jailparse.y
--- a/usr.sbin/jail/jailparse.y
+++ b/usr.sbin/jail/jailparse.y
@@ -73,16 +73,18 @@
| conf jail
| conf param ';'
{
- struct cfjail *j = current_jail;
+ if (!special_param($2, scanner)) {
+ struct cfjail *j = current_jail;
- if (j == NULL) {
- if (global_jail == NULL) {
- global_jail = add_jail();
- global_jail->name = estrdup("*");
+ if (j == NULL) {
+ if (global_jail == NULL) {
+ global_jail = add_jail();
+ global_jail->name = estrdup("*");
+ }
+ j = global_jail;
}
- j = global_jail;
+ TAILQ_INSERT_TAIL(&j->params, $2, tq);
}
- TAILQ_INSERT_TAIL(&j->params, $2, tq);
}
| conf ';'
;
@@ -141,6 +143,7 @@
{
$$ = $1;
TAILQ_CONCAT(&$$->val, $2, tq);
+ $$->flags |= PF_NAMEVAL;
free($2);
}
| error
@@ -230,10 +233,6 @@
extern int YYLEX_DECL();
-extern struct cflex *yyget_extra(void *scanner);
-extern int yyget_lineno(void *scanner);
-extern char *yyget_text(void *scanner);
-
static void
YYERROR_DECL()
{
@@ -248,3 +247,29 @@
yyget_extra(scanner)->cfname, yyget_lineno(scanner),
yyget_text(scanner), s);
}
+
+/* Handle special parameters (i.e. the include directive).
+ * Return true if the parameter was specially handled.
+ */
+static int
+special_param(struct cfparam *p, void *scanner)
+{
+ if ((p->flags & (PF_VAR | PF_APPEND | PF_NAMEVAL)) != PF_NAMEVAL
+ || strcmp(p->name, ".include"))
+ return 0;
+ struct cfstring *s;
+ TAILQ_FOREACH(s, &p->val, tq) {
+ if (STAILQ_EMPTY(&s->vars))
+ include_config(scanner, s->s);
+ else {
+ warnx("%s line %d: "
+ "variables not permitted in '.include' filename",
+ yyget_extra(scanner)->cfname,
+ yyget_lineno(scanner));
+ yyget_extra(scanner)->error = 1;
+ }
+ }
+ free_param_strings(p);
+ free(p);
+ return 1;
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Apr 29, 2:35 AM (10 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17836221
Default Alt Text
D40188.diff (8 KB)
Attached To
Mode
D40188: Add ".include" directive to jail.conf
Attached
Detach File
Event Timeline
Log In to Comment