Page MenuHomeFreeBSD

D46284.1775286562.diff
No OneTemporary

Size
3 KB
Referenced Files
None
Subscribers
None

D46284.1775286562.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>
@@ -306,10 +310,79 @@
--depth;
}
+extern char **environ;
+
+static FILE *
+open_config(const char *cfname, pid_t pid[static 1])
+{
+
+ int read_fd, write_fd, exec_fd, pipes[2];
+ char *argv[] = { __DECONST(char *, cfname), __DECONST(char *, cfname), NULL };
+ FILE *file;
+
+ /* Invalidate the child PID. */
+ *pid = -1;
+
+ /* The configuration must be readable. */
+ read_fd = open(cfname, O_RDONLY);
+ 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 = fdopen(read_fd, "r");
+ if (file == NULL)
+ 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 = -1;
void *scanner;
yylex_init_extra(&cflex, &scanner);
@@ -317,7 +390,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);
@@ -325,6 +398,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
Sat, Apr 4, 7:09 AM (10 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28258184
Default Alt Text
D46284.1775286562.diff (3 KB)

Event Timeline