merge branch 'pr-1982'

nsexec (CVE-2019-5736): avoid parsing environ

LGTMs: @cyphar @crosbymichael
Closes #1982
This commit is contained in:
Aleksa Sarai 2019-02-15 18:40:33 +11:00
commit 751f18de2a
No known key found for this signature in database
GPG Key ID: 9E18AA267DDB8DB4
1 changed files with 10 additions and 13 deletions

View File

@ -169,31 +169,25 @@ static int parse_xargs(char *data, int data_length, char ***output)
} }
/* /*
* "Parse" out argv and envp from /proc/self/cmdline and /proc/self/environ. * "Parse" out argv from /proc/self/cmdline.
* This is necessary because we are running in a context where we don't have a * This is necessary because we are running in a context where we don't have a
* main() that we can just get the arguments from. * main() that we can just get the arguments from.
*/ */
static int fetchve(char ***argv, char ***envp) static int fetchve(char ***argv)
{ {
char *cmdline = NULL, *environ = NULL; char *cmdline = NULL;
size_t cmdline_size, environ_size; size_t cmdline_size;
cmdline = read_file("/proc/self/cmdline", &cmdline_size); cmdline = read_file("/proc/self/cmdline", &cmdline_size);
if (!cmdline) if (!cmdline)
goto error; goto error;
environ = read_file("/proc/self/environ", &environ_size);
if (!environ)
goto error;
if (parse_xargs(cmdline, cmdline_size, argv) <= 0) if (parse_xargs(cmdline, cmdline_size, argv) <= 0)
goto error; goto error;
if (parse_xargs(environ, environ_size, envp) <= 0)
goto error;
return 0; return 0;
error: error:
free(environ);
free(cmdline); free(cmdline);
return -EINVAL; return -EINVAL;
} }
@ -246,23 +240,26 @@ error:
return -EIO; return -EIO;
} }
/* Get cheap access to the environment. */
extern char **environ;
int ensure_cloned_binary(void) int ensure_cloned_binary(void)
{ {
int execfd; int execfd;
char **argv = NULL, **envp = NULL; char **argv = NULL;
/* Check that we're not self-cloned, and if we are then bail. */ /* Check that we're not self-cloned, and if we are then bail. */
int cloned = is_self_cloned(); int cloned = is_self_cloned();
if (cloned > 0 || cloned == -ENOTRECOVERABLE) if (cloned > 0 || cloned == -ENOTRECOVERABLE)
return cloned; return cloned;
if (fetchve(&argv, &envp) < 0) if (fetchve(&argv) < 0)
return -EINVAL; return -EINVAL;
execfd = clone_binary(); execfd = clone_binary();
if (execfd < 0) if (execfd < 0)
return -EIO; return -EIO;
fexecve(execfd, argv, envp); fexecve(execfd, argv, environ);
return -ENOEXEC; return -ENOEXEC;
} }