aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Bramkamp <crest+freebsd@rlwinm.de>2026-05-06 23:28:53 +0000
committerKyle Evans <kevans@FreeBSD.org>2026-05-06 23:28:53 +0000
commit276d9b88a9e6fd6fd90e57c36444756ad297d2ab (patch)
treef177de9270a5f702c2313bd18117ee4bede4589f
parent3348fa7a45fdf14a7af509e306229bd211444f1e (diff)
jail: avoid leaking jail config fds to exec.* hooks
The jail(8) command must not leave parsed configuration files open since the file descriptors will be leaked to child processes including the untrusted exec.start or exec.stop hooks. While fopen() doesn't provide direct access to O_CLOEXEC, it does provide access to FD_CLOEXEC via "e" in the mode string which provides the desired defense in depth against leaking file descriptors into exec.* hooks since those always execve() into a shell. Jail configuration is potentially sensitive and some hooks execute from within the jail context, leaving some opening for the jail to exfiltrate information about the host environment. (Commit message wordsmithed by kevans) PR: 295052 Reviewed by: kevans MFC after: 3 days
-rw-r--r--usr.sbin/jail/config.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/usr.sbin/jail/config.c b/usr.sbin/jail/config.c
index 1bad04ccde68..f1e2da215790 100644
--- a/usr.sbin/jail/config.c
+++ b/usr.sbin/jail/config.c
@@ -321,6 +321,7 @@ static void
parse_config(const char *cfname, int is_stdin)
{
struct cflex cflex = {.cfname = cfname, .error = 0};
+ FILE *yfp = NULL;
void *scanner;
yylex_init_extra(&cflex, &scanner);
@@ -328,7 +329,7 @@ parse_config(const char *cfname, int is_stdin)
cflex.cfname = "STDIN";
yyset_in(stdin, scanner);
} else {
- FILE *yfp = fopen(cfname, "r");
+ yfp = fopen(cfname, "re");
if (!yfp)
err(1, "%s", cfname);
yyset_in(yfp, scanner);
@@ -336,6 +337,8 @@ parse_config(const char *cfname, int is_stdin)
if (yyparse(scanner) || cflex.error)
exit(1);
yylex_destroy(scanner);
+ if (yfp != NULL)
+ fclose(yfp);
}
/*