Page MenuHomeFreeBSD

D46284.id176733.diff
No OneTemporary

D46284.id176733.diff

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
@@ -29,14 +29,18 @@
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/sysctl.h>
+#include <sys/wait.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <err.h>
+#include <fcntl.h>
#include <glob.h>
#include <netdb.h>
+#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -317,10 +321,77 @@
--depth;
}
+extern char **environ;
+
+static FILE *
+open_config(const char *cfname, pid_t pid[static 1])
+{
+
+ int read_fd = open(cfname, O_RDONLY), write_fd, exec_fd, pipes[2];
+ char *argv[] = { (char*)(uintptr_t)cfname, (char *)(uintptr_t)cfname, NULL }; // DECONST *sigh*
+
+ // Invalidate the child PID.
+ *pid = -1;
+
+ // The configuration must be readable.
+ if (read_fd < 0)
+ err(1, "open(): %s", cfname);
+
+ // Try to open the configuration for execution (to parse its standard output config instead).
+ exec_fd = openat(read_fd, "", O_EMPTY_PATH|O_EXEC);
+ if (exec_fd < 0) {
+ if (errno != EACCES)
+ err(1, "openat(): %s", cfname);
+ } else {
+ // Read from the pipe instead of the configuration.
+ close(read_fd);
+ if (pipe(pipes))
+ err(1, "pipe(): %s", cfname);
+ read_fd = pipes[0];
+ write_fd = pipes[1];
+
+ // Run the configuration as child process.
+ switch ((*pid = fork())) {
+ // Failure to fork is fatal.
+ case -1:
+ err(1, "fork(): %s", cfname);
+ break;
+
+ // Redirect the child's standard output into the pipe.
+ case 0:
+ close(read_fd);
+ if (write_fd != STDOUT_FILENO) {
+ if ( dup2(write_fd, STDOUT_FILENO) != STDOUT_FILENO )
+ err(1, "dup2(): %s", cfname);
+ close(write_fd);
+ }
+
+ // Replace the forked child with the configuration command.
+ fexecve(exec_fd, argv, environ);
+ err(1, "fexecve(): %s", cfname);
+ break;
+
+ // Close the write end of the pipe and the executable file descriptor in the parent.
+ default:
+ close(write_fd);
+ close(exec_fd);
+ break;
+ }
+ }
+
+ // Wrap a FILE handle around the read-only file descriptor.
+ FILE *file = fdopen(read_fd, "r");
+ if (!file)
+ err(1, "fdopen(): %s", cfname);
+
+ return file;
+}
+
static void
parse_config(const char *cfname, int is_stdin)
{
struct cflex cflex = {.cfname = cfname, .error = 0};
+ pid_t child;
void *scanner;
yylex_init_extra(&cflex, &scanner);
@@ -328,7 +399,7 @@
cflex.cfname = "STDIN";
yyset_in(stdin, scanner);
} else {
- FILE *yfp = fopen(cfname, "r");
+ FILE *yfp = open_config(cfname, &child);
if (!yfp)
err(1, "%s", cfname);
yyset_in(yfp, scanner);
@@ -336,6 +407,16 @@
if (yyparse(scanner) || cflex.error)
exit(1);
yylex_destroy(scanner);
+ if ( child > 0 ) {
+ pid_t exited;
+ int status;
+ do {
+ exited = waitpid(child, &status, 0);
+ } while ( exited < 0 || errno == EINTR );
+ status = WEXITSTATUS(status);
+ if ( status != 0 )
+ errx(status, "Config child failed with status=%i): %s", status, cfname);
+ }
}
/*

File Metadata

Mime Type
text/plain
Expires
Wed, Jul 15, 8:04 AM (7 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32186465
Default Alt Text
D46284.id176733.diff (3 KB)

Event Timeline