Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE
firejail.13682
fix-CVE-2020-17368.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File fix-CVE-2020-17368.patch of Package firejail.13682
From 34193604fed04cad2b7b6b0f1a3a0428afd9ed5b Mon Sep 17 00:00:00 2001 From: Reiner Herrmann <reiner@reiner-h.de> Date: Wed, 29 Jul 2020 20:22:52 +0200 Subject: [PATCH] firejail: don't pass command line through shell when redirecting output When redirecting output via --output or --output-stderr, firejail was concatenating all command line arguments into a single string that was passed to a shell. As the arguments were no longer escaped, the shell was able to interpret them. Someone who has control over the command line arguments of the sandboxed application could use this to run arbitrary other commands. Instead of passing it through a shell for piping the output to ftee, the pipeline is now manually created and the processes are executed directly. Fixes: CVE-2020-17368 Reported-by: Tim Starling <tstarling@wikimedia.org> --- src/firejail/output.c | 80 +++++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 26 deletions(-) diff --git a/src/firejail/output.c b/src/firejail/output.c index 6e678afd3..0e961bb61 100644 --- a/src/firejail/output.c +++ b/src/firejail/output.c @@ -77,38 +77,66 @@ void check_output(int argc, char **argv) { } } - // build the new command line - int len = 0; - for (i = 0; i < argc; i++) { - len += strlen(argv[i]) + 1; // + ' ' + int pipefd[2]; + if (pipe(pipefd) == -1) { + errExit("pipe"); } - len += 100 + strlen(LIBDIR) + strlen(outfile); // tee command - char *cmd = malloc(len + 1); // + '\0' - if (!cmd) - errExit("malloc"); + pid_t pid = fork(); + if (pid == -1) { + errExit("fork"); + } else if (pid == 0) { + /* child */ + if (dup2(pipefd[0], STDIN_FILENO) == -1) { + errExit("dup2"); + } + close(pipefd[1]); + if (pipefd[0] != STDIN_FILENO) { + close(pipefd[0]); + } - char *ptr = cmd; - for (i = 0; i < argc; i++) { - if (strncmp(argv[i], "--output=", 9) == 0) - continue; - if (strncmp(argv[i], "--output-stderr=", 16) == 0) - continue; - ptr += sprintf(ptr, "%s ", argv[i]); + char *args[3]; + args[0] = LIBDIR "/firejail/ftee"; + args[1] = outfile; + args[2] = NULL; + execv(args[0], args); + perror("execvp"); + exit(1); } - if (enable_stderr) - sprintf(ptr, "2>&1 | %s/firejail/ftee %s", LIBDIR, outfile); - else - sprintf(ptr, " | %s/firejail/ftee %s", LIBDIR, outfile); + /* parent */ + if (dup2(pipefd[1], STDOUT_FILENO) == -1) { + errExit("dup2"); + } + if (enable_stderr && dup2(STDOUT_FILENO, STDERR_FILENO) == -1) { + errExit("dup2"); + } + close(pipefd[0]); + if (pipefd[1] != STDOUT_FILENO) { + close(pipefd[1]); + } - // run command - char *a[4]; - a[0] = "/bin/bash"; - a[1] = "-c"; - a[2] = cmd; - a[3] = NULL; - execvp(a[0], a); + char **args = calloc(argc + 1, sizeof(char *)); + if (!args) { + errExit("calloc"); + } + bool found_separator = false; + /* copy argv into args, but drop --output(-stderr) arguments */ + for (int i = 0, j = 0; i < argc; i++) { + if (!found_separator && i > 0) { + if (strncmp(argv[i], "--output=", 9) == 0) { + continue; + } + if (strncmp(argv[i], "--output-stderr=", 16) == 0) { + continue; + } + if (strncmp(argv[i], "--", 2) != 0 || strcmp(argv[i], "--") == 0) { + found_separator = true; + } + } + args[j++] = argv[i]; + } + execvp(args[0], args); perror("execvp"); exit(1);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor