summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2022-03-09 14:11:50 +0000
committerJeremy Harris <jgh146exb@wizmail.org>2022-03-09 14:11:50 +0000
commit7596f24296bffbb02eeb7e13b6580d67ccaf798e (patch)
treee37a0ad30a5441d3f7edbee1926d5efd5e1f7d4d
parent6e48a63849cd3f1dfb3555fe57094954b3f7f092 (diff)
downloadexim4-7596f24296bffbb02eeb7e13b6580d67ccaf798e.tar.gz
Add backstop check for taint of executable name when calling exec()
-rw-r--r--src/src/child.c8
-rw-r--r--src/src/exim.c2
-rw-r--r--src/src/smtp_in.c1
-rw-r--r--src/src/transport.c1
4 files changed, 10 insertions, 2 deletions
diff --git a/src/src/child.c b/src/src/child.c
index 267306ee3..4c0dbabd1 100644
--- a/src/src/child.c
+++ b/src/src/child.c
@@ -81,7 +81,7 @@ argv = store_get((extra + acount + MAX_CLMACROS + 24) * sizeof(char *), GET_UNTA
/* In all case, the list starts out with the path, any macros, and a changed
config file. */
-argv[n++] = exim_path;
+argv[n++] = exim_path; /* assume untainted */
if (clmacro_count > 0)
{
memcpy(argv + n, clmacros, clmacro_count * sizeof(uschar *));
@@ -343,6 +343,12 @@ int save_errno;
int inpfd[2], outpfd[2];
pid_t pid;
+if (is_tainted(argv[0]))
+ {
+ log_write(0, LOG_MAIN | LOG_PANIC, "Attempt to exec tainted path: '%s'", argv[0]);
+ return (pid_t)(-1);
+ }
+
/* Create the pipes. */
if (pipe(inpfd) != 0) return (pid_t)(-1);
diff --git a/src/src/exim.c b/src/src/exim.c
index eada6bbf8..ade96fe20 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -4397,7 +4397,7 @@ if (bi_option)
{
int i = 0;
uschar *argv[3];
- argv[i++] = bi_command;
+ argv[i++] = bi_command; /* nonexpanded option so assume untainted */
if (alias_arg) argv[i++] = alias_arg;
argv[i++] = NULL;
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index 852148fcf..3fe3dab82 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -5911,6 +5911,7 @@ while (done <= 0)
{
DEBUG(D_exec) debug_print_argv(argv);
exim_nullstd(); /* Ensure std{in,out,err} exist */
+ /* argv[0] should be untainted, from child_exec_exim() */
execv(CS argv[0], (char *const *)argv);
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "exec of \"%s\" (ETRN) failed: %s",
etrn_command, strerror(errno));
diff --git a/src/src/transport.c b/src/src/transport.c
index 8b320ecc2..37623ea1a 100644
--- a/src/src/transport.c
+++ b/src/src/transport.c
@@ -1972,6 +1972,7 @@ if (socket_fd != 0)
DEBUG(D_exec) debug_print_argv(argv);
exim_nullstd(); /* Ensure std{out,err} exist */
+/* argv[0] should be untainted, from child_exec_exim() */
execv(CS argv[0], (char *const *)argv);
DEBUG(D_any) debug_printf("execv failed: %s\n", strerror(errno));