From ca973f1732d93684d6f47f14362bc27f9b0a4197 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 18 May 2011 21:58:25 +0200 Subject: [PATCH] CVE backports, first pass --- exim-4.72-0001-div-by-zero.patch | 35 ++++++ exim-4.72-0002-eval-sigfpe.patch | 49 ++++++++ exim-4.72-0003-CVE-2011-1407.patch | 34 ++++++ exim-4.72-0004-CVE-2011-0017.patch | 119 +++++++++++++++++++ exim-4.72-0005-CVE-2010-4345.patch | 94 +++++++++++++++ exim-4.72-0006-CVE-2010-4345.patch | 97 ++++++++++++++++ exim-4.72-0007-CVE-2010-4345.patch | 160 +++++++++++++++++++++++++ exim-4.72-0008-CVE-2010-4345.patch | 180 +++++++++++++++++++++++++++++ exim-4.72-0009-CVE-2010-4345.patch | 33 ++++++ exim.spec | 26 ++++- 10 files changed, 826 insertions(+), 1 deletion(-) create mode 100644 exim-4.72-0001-div-by-zero.patch create mode 100644 exim-4.72-0002-eval-sigfpe.patch create mode 100644 exim-4.72-0003-CVE-2011-1407.patch create mode 100644 exim-4.72-0004-CVE-2011-0017.patch create mode 100644 exim-4.72-0005-CVE-2010-4345.patch create mode 100644 exim-4.72-0006-CVE-2010-4345.patch create mode 100644 exim-4.72-0007-CVE-2010-4345.patch create mode 100644 exim-4.72-0008-CVE-2010-4345.patch create mode 100644 exim-4.72-0009-CVE-2010-4345.patch diff --git a/exim-4.72-0001-div-by-zero.patch b/exim-4.72-0001-div-by-zero.patch new file mode 100644 index 0000000..d57a979 --- /dev/null +++ b/exim-4.72-0001-div-by-zero.patch @@ -0,0 +1,35 @@ +From 519e7d3b8bef1e1de255c5926e49d03545c3f0bb Mon Sep 17 00:00:00 2001 +From: Phil Pennock +Date: Tue, 12 Apr 2011 04:24:12 -0400 +Subject: [PATCH 01/13] Catch divide-by-zero in ${eval:...}. + +Fixes 1102 +--- + src/src/expand.c | 11 ++++++++++- + 1 files changed, 10 insertions(+), 1 deletions(-) + +diff --git a/src/src/expand.c b/src/src/expand.c +index 6e47125..a0d967d 100644 +--- a/src/src/expand.c ++++ b/src/src/expand.c +@@ -3074,7 +3074,16 @@ if (*error == NULL) + int y = eval_op_unary(&s, decimal, error); + if (*error != NULL) break; + if (op == '*') x *= y; +- else if (op == '/') x /= y; ++ else if (op == '/') ++ { ++ if (y == 0) ++ { ++ *error = US"divide by zero"; ++ x = 0; ++ break; ++ } ++ x /= y; ++ } + else x %= y; + } + } +-- +1.7.1 + diff --git a/exim-4.72-0002-eval-sigfpe.patch b/exim-4.72-0002-eval-sigfpe.patch new file mode 100644 index 0000000..415d2ff --- /dev/null +++ b/exim-4.72-0002-eval-sigfpe.patch @@ -0,0 +1,49 @@ +From d84c166641a5c0a460a53cbbb117c7fe3f41e9c2 Mon Sep 17 00:00:00 2001 +From: Phil Pennock +Date: Tue, 12 Apr 2011 16:26:44 -0400 +Subject: [PATCH 02/13] Also ${eval:x % 0} fixed to not SIGFPE. + +Pointed out by: Steven A. Reisman +--- + src/src/expand.c | 23 +++++++++++++---------- + 1 files changed, 13 insertions(+), 10 deletions(-) + +diff --git a/src/src/expand.c b/src/src/expand.c +index a0d967d..a96da27 100644 +--- a/src/src/expand.c ++++ b/src/src/expand.c +@@ -3073,18 +3073,21 @@ if (*error == NULL) + int op = *s++; + int y = eval_op_unary(&s, decimal, error); + if (*error != NULL) break; +- if (op == '*') x *= y; +- else if (op == '/') ++ if (op == '*') ++ x *= y; ++ else ++ { ++ if (y == 0) + { +- if (y == 0) +- { +- *error = US"divide by zero"; +- x = 0; +- break; +- } +- x /= y; ++ *error = (op == '/') ? US"divide by zero" : US"modulo by zero"; ++ x = 0; ++ break; + } +- else x %= y; ++ if (op == '/') ++ x /= y; ++ else ++ x %= y; ++ } + } + } + *sptr = s; +-- +1.7.1 + diff --git a/exim-4.72-0003-CVE-2011-1407.patch b/exim-4.72-0003-CVE-2011-1407.patch new file mode 100644 index 0000000..0e99e07 --- /dev/null +++ b/exim-4.72-0003-CVE-2011-1407.patch @@ -0,0 +1,34 @@ +From cca8361d074b4d1f1a24143ee79a3bf045781062 Mon Sep 17 00:00:00 2001 +From: Tom Kistner +Date: Sat, 30 Apr 2011 13:20:17 +0100 +Subject: [PATCH 03/13] Bugzilla #1106: Don't pass DKIM compound log line as format string + +--- + src/src/dkim.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/src/dkim.c b/src/src/dkim.c +index ca46805..94fbaa5 100644 +--- a/src/src/dkim.c ++++ b/src/src/dkim.c +@@ -108,7 +108,7 @@ void dkim_exim_verify_finish(void) { + /* Log a line for each signature */ + uschar *logmsg = string_append(NULL, &size, &ptr, 5, + +- string_sprintf( "DKIM: d=%s s=%s c=%s/%s a=%s ", ++ string_sprintf( "d=%s s=%s c=%s/%s a=%s ", + sig->domain, + sig->selector, + (sig->canon_headers == PDKIM_CANON_SIMPLE)?"simple":"relaxed", +@@ -176,7 +176,7 @@ void dkim_exim_verify_finish(void) { + } + + logmsg[ptr] = '\0'; +- log_write(0, LOG_MAIN, (char *)logmsg); ++ log_write(0, LOG_MAIN, "DKIM: %s", logmsg); + + /* Build a colon-separated list of signing domains (and identities, if present) in dkim_signers */ + dkim_signers = string_append(dkim_signers, +-- +1.7.1 + diff --git a/exim-4.72-0004-CVE-2011-0017.patch b/exim-4.72-0004-CVE-2011-0017.patch new file mode 100644 index 0000000..3fc18e6 --- /dev/null +++ b/exim-4.72-0004-CVE-2011-0017.patch @@ -0,0 +1,119 @@ +From c69806dd901049cd7828baff79cc0a5d96490e6d Mon Sep 17 00:00:00 2001 +From: Phil Pennock +Date: Fri, 21 Jan 2011 03:56:02 -0500 +Subject: [PATCH 04/13] Check return values of setgid/setuid. + +CVE-2011-0017 + +One assertion of the unimportance of checking the return value was wrong, +in the event of a compromised exim run-time user. +--- + src/src/exim.c | 41 +++++++++++++++++++++++++++++++++++++---- + src/src/log.c | 19 ++++++++++++++----- + 2 files changed, 51 insertions(+), 9 deletions(-) + +diff --git a/src/src/exim.c b/src/src/exim.c +index 12916e8..bb39438 100644 +--- a/src/src/exim.c ++++ b/src/src/exim.c +@@ -1309,7 +1309,7 @@ int arg_error_handling = error_handling; + int filter_sfd = -1; + int filter_ufd = -1; + int group_count; +-int i; ++int i, rv; + int list_queue_option = 0; + int msg_action = 0; + int msg_action_arg = -1; +@@ -1628,8 +1628,20 @@ real_gid = getgid(); + + if (real_uid == root_uid) + { +- setgid(real_gid); +- setuid(real_uid); ++ rv = setgid(real_gid); ++ if (rv) ++ { ++ fprintf(stderr, "exim: setgid(%ld) failed: %s\n", ++ (long int)real_gid, strerror(errno)); ++ exit(EXIT_FAILURE); ++ } ++ rv = setuid(real_uid); ++ if (rv) ++ { ++ fprintf(stderr, "exim: setuid(%ld) failed: %s\n", ++ (long int)real_uid, strerror(errno)); ++ exit(EXIT_FAILURE); ++ } + } + + /* If neither the original real uid nor the original euid was root, Exim is +@@ -3746,7 +3758,28 @@ if (!unprivileged && /* originally had root AND */ + + /* When we are retaining a privileged uid, we still change to the exim gid. */ + +-else setgid(exim_gid); ++else ++ { ++ int rv; ++ rv = setgid(exim_gid); ++ /* Impact of failure is that some stuff might end up with an incorrect group. ++ We track this for failures from root, since any attempt to change privilege ++ by root should succeed and failures should be examined. For non-root, ++ there's no security risk. For me, it's { exim -bV } on a just-built binary, ++ no need to complain then. */ ++ if (rv == -1) ++ { ++ if (!unprivileged) ++ { ++ fprintf(stderr, ++ "exim: changing group failed: %s\n", strerror(errno)); ++ exit(EXIT_FAILURE); ++ } ++ else ++ debug_printf("changing group to %ld failed: %s\n", ++ (long int)exim_gid, strerror(errno)); ++ } ++ } + + /* Handle a request to list the delivery queue */ + +diff --git a/src/src/log.c b/src/src/log.c +index a5cd100..ff8f9dd 100644 +--- a/src/src/log.c ++++ b/src/src/log.c +@@ -343,17 +343,26 @@ are neither exim nor root, creation is not attempted. */ + + else if (euid == root_uid) + { +- int status; ++ int status, rv; + pid_t pid = fork(); + + /* In the subprocess, change uid/gid and do the creation. Return 0 from the +- subprocess on success. There doesn't seem much point in testing for setgid +- and setuid errors. */ ++ subprocess on success. If we don't check for setuid failures, then the file ++ can be created as root, so vulnerabilities which cause setuid to fail mean ++ that the Exim user can use symlinks to cause a file to be opened/created as ++ root. We always open for append, so can't nuke existing content but it would ++ still be Rather Bad. */ + + if (pid == 0) + { +- (void)setgid(exim_gid); +- (void)setuid(exim_uid); ++ rv = setgid(exim_gid); ++ if (rv) ++ die(US"exim: setgid for log-file creation failed, aborting", ++ US"Unexpected log failure, please try later"); ++ rv = setuid(exim_uid); ++ if (rv) ++ die(US"exim: setuid for log-file creation failed, aborting", ++ US"Unexpected log failure, please try later"); + _exit((create_log(buffer) < 0)? 1 : 0); + } + +-- +1.7.1 + diff --git a/exim-4.72-0005-CVE-2010-4345.patch b/exim-4.72-0005-CVE-2010-4345.patch new file mode 100644 index 0000000..f5b7342 --- /dev/null +++ b/exim-4.72-0005-CVE-2010-4345.patch @@ -0,0 +1,94 @@ +From c0d4b16d16983569141de9052b8c3567f5839a1e Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Sat, 11 Dec 2010 13:44:55 +0000 +Subject: [PATCH 05/13] Don't allow a configure file which is writeable by the Exim user or group + +(Bug 1044, CVE-2010-4345) +--- + src/src/EDITME | 7 +++---- + src/src/config.h.defaults | 1 + + src/src/globals.c | 1 + + src/src/globals.h | 1 + + src/src/readconf.c | 5 ++--- + 6 files changed, 18 insertions(+), 13 deletions(-) + +diff --git a/src/src/EDITME b/src/src/EDITME +index 3ee1663..368290c 100644 +--- a/src/src/EDITME ++++ b/src/src/EDITME +@@ -412,14 +412,13 @@ FIXED_NEVER_USERS=root + + + #------------------------------------------------------------------------------ +-# By default, Exim insists that its configuration file be owned either by root +-# or by the Exim user. You can specify one additional permitted owner here. ++# By default, Exim insists that its configuration file be owned by root. You ++# can specify one additional permitted owner here. + + # CONFIGURE_OWNER= + + # If the configuration file is group-writeable, Exim insists by default that it +-# is owned by root or the Exim user. You can specify one additional permitted +-# group owner here. ++# is owned by root. You can specify one additional permitted group owner here. + + # CONFIGURE_GROUP= + +diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults +index 8bae17b..20ecf0b 100644 +--- a/src/src/config.h.defaults ++++ b/src/src/config.h.defaults +@@ -159,5 +159,6 @@ just in case. */ + #define DNS_MAXNAME 1024 + #define EXPAND_MAXN 20 + #define ROOT_UID 0 ++#define ROOT_GID 0 + + /* End of config.h.defaults */ +diff --git a/src/src/globals.c b/src/src/globals.c +index 3e1e76c..7a09b08 100644 +--- a/src/src/globals.c ++++ b/src/src/globals.c +@@ -945,6 +945,7 @@ int rewrite_existflags = 0; + uschar *rfc1413_hosts = US"*"; + int rfc1413_query_timeout = 5; + /* BOOL rfc821_domains = FALSE; <<< on the way out */ ++uid_t root_gid = ROOT_GID; + uid_t root_uid = ROOT_UID; + + router_instance *routers = NULL; +diff --git a/src/src/globals.h b/src/src/globals.h +index cc5d601..70635c0 100644 +--- a/src/src/globals.h ++++ b/src/src/globals.h +@@ -609,6 +609,7 @@ extern int rewrite_existflags; /* Indicate which headers have rewrites * + extern uschar *rfc1413_hosts; /* RFC hosts */ + extern int rfc1413_query_timeout; /* Timeout on RFC 1413 calls */ + /* extern BOOL rfc821_domains; */ /* If set, syntax is 821, not 822 => being abolished */ ++extern uid_t root_gid; /* The gid for root */ + extern uid_t root_uid; /* The uid for root */ + extern router_info routers_available[];/* Vector of available routers */ + extern router_instance *routers; /* Chain of instantiated routers */ +diff --git a/src/src/readconf.c b/src/src/readconf.c +index 41fb9f7..a5f32bf 100644 +--- a/src/src/readconf.c ++++ b/src/src/readconf.c +@@ -2838,13 +2838,12 @@ if (!config_changed) + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to stat configuration file %s", + big_buffer); + +- if ((statbuf.st_uid != root_uid && /* owner not root */ +- statbuf.st_uid != exim_uid /* owner not exim */ ++ if ((statbuf.st_uid != root_uid /* owner not root */ + #ifdef CONFIGURE_OWNER + && statbuf.st_uid != config_uid /* owner not the special one */ + #endif + ) || /* or */ +- (statbuf.st_gid != exim_gid /* group not exim & */ ++ (statbuf.st_gid != root_gid /* group not root & */ + #ifdef CONFIGURE_GROUP + && statbuf.st_gid != config_gid /* group not the special one */ + #endif +-- +1.7.1 + diff --git a/exim-4.72-0006-CVE-2010-4345.patch b/exim-4.72-0006-CVE-2010-4345.patch new file mode 100644 index 0000000..6403d9a --- /dev/null +++ b/exim-4.72-0006-CVE-2010-4345.patch @@ -0,0 +1,97 @@ +From 8145e5489cd02197b156efd8fefeae986747e05a Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Sat, 11 Dec 2010 14:09:17 +0000 +Subject: [PATCH 06/13] Check configure file permissions even for non-default files if still privileged + +(Bug 1044, CVE-2010-4345) +--- + src/src/exim.c | 7 ++++--- + src/src/globals.c | 1 + + src/src/globals.h | 1 + + src/src/readconf.c | 6 +++--- + 4 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/src/src/exim.c b/src/src/exim.c +index bb39438..a3af9db 100644 +--- a/src/src/exim.c ++++ b/src/src/exim.c +@@ -1989,6 +1989,7 @@ for (i = 1; i < argc; i++) + + config_main_filelist = argrest; + config_changed = TRUE; ++ trusted_config = FALSE; + } + break; + +@@ -3187,7 +3188,7 @@ values (such as the path name). If running in the test harness, pretend that + configuration file changes and macro definitions haven't happened. */ + + if (( /* EITHER */ +- (config_changed || macros != NULL) && /* Config changed, and */ ++ (!trusted_config || macros != NULL) && /* Config changed, and */ + real_uid != root_uid && /* Not root, and */ + #ifndef ALT_CONFIG_ROOT_ONLY /* (when not locked out) */ + real_uid != exim_uid && /* Not exim, and */ +@@ -3406,7 +3407,7 @@ If ALT_CONFIG_ROOT_ONLY is defined, we don't know whether we were called by the + built-in exim user or one defined in the configuration. In either event, + re-enable log processing, assuming the sysadmin knows what they are doing. */ + +-if (removed_privilege && (config_changed || macros != NULL) && ++if (removed_privilege && (!trusted_config || macros != NULL) && + real_uid == exim_uid) + { + #ifdef ALT_CONFIG_ROOT_ONLY +@@ -3418,7 +3419,7 @@ if (removed_privilege && (config_changed || macros != NULL) && + else + log_write(0, LOG_MAIN|LOG_PANIC, + "exim user (uid=%d) is defined only at runtime; privilege lost for %s", +- (int)exim_uid, config_changed? "-C" : "-D"); ++ (int)exim_uid, trusted_config? "-D" : "-C"); + #endif + } + +diff --git a/src/src/globals.c b/src/src/globals.c +index 7a09b08..211b1cd 100644 +--- a/src/src/globals.c ++++ b/src/src/globals.c +@@ -1264,6 +1264,7 @@ tree_node *tree_nonrecipients = NULL; + tree_node *tree_unusable = NULL; + + BOOL trusted_caller = FALSE; ++BOOL trusted_config = TRUE; + gid_t *trusted_groups = NULL; + uid_t *trusted_users = NULL; + uschar *timezone_string = US TIMEZONE_DEFAULT; +diff --git a/src/src/globals.h b/src/src/globals.h +index 70635c0..fe5b7c3 100644 +--- a/src/src/globals.h ++++ b/src/src/globals.h +@@ -779,6 +779,7 @@ extern tree_node *tree_nonrecipients; /* Tree of nonrecipient addresses */ + extern tree_node *tree_unusable; /* Tree of unusable addresses */ + + extern BOOL trusted_caller; /* Caller is trusted */ ++extern BOOL trusted_config; /* Configuration file is trusted */ + extern gid_t *trusted_groups; /* List of trusted groups */ + extern uid_t *trusted_users; /* List of trusted users */ + extern uschar *timezone_string; /* Required timezone setting */ +diff --git a/src/src/readconf.c b/src/src/readconf.c +index a5f32bf..d6416c8 100644 +--- a/src/src/readconf.c ++++ b/src/src/readconf.c +@@ -2829,10 +2829,10 @@ else + "configuration file %s", filename)); + } + +-/* Check the status of the file we have opened, unless it was specified on +-the command line, in which case privilege was given away at the start. */ ++/* Check the status of the file we have opened, if we have retained root ++privileges. */ + +-if (!config_changed) ++if (trusted_config) + { + if (fstat(fileno(config_file), &statbuf) != 0) + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to stat configuration file %s", +-- +1.7.1 + diff --git a/exim-4.72-0007-CVE-2010-4345.patch b/exim-4.72-0007-CVE-2010-4345.patch new file mode 100644 index 0000000..607e275 --- /dev/null +++ b/exim-4.72-0007-CVE-2010-4345.patch @@ -0,0 +1,160 @@ +From 18a77559b0921016e18e80670171d10e3b04e9da Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Sat, 11 Dec 2010 23:39:54 +0000 +Subject: [PATCH 07/13] Remove ALT_CONFIG_ROOT_ONLY build option, effectively making it always true. + +We *never* want the Exim user to be able to specify arbitrary configuration +files. Don't let them build it that way. + +(Bug 1044, CVE-2010-4345) +--- + src/src/config.h.defaults | 1 - + src/src/exim.c | 39 +++++++--------------- + 4 files changed, 56 insertions(+), 96 deletions(-) + +diff --git a/src/src/EDITME b/src/src/EDITME +index 368290c..4175b97 100644 +--- a/src/src/EDITME ++++ b/src/src/EDITME +@@ -440,35 +440,21 @@ FIXED_NEVER_USERS=root + + #------------------------------------------------------------------------------ + # The -C option allows Exim to be run with an alternate runtime configuration +-# file. When this is used by root or the Exim user, root privilege is retained +-# by the binary (for any other caller, it is dropped). You can restrict the +-# location of alternate configurations by defining a prefix below. Any file +-# used with -C must then start with this prefix (except that /dev/null is also +-# permitted if the caller is root, because that is used in the install script). +-# If the prefix specifies a directory that is owned by root, a compromise of +-# the Exim account does not permit arbitrary alternate configurations to be +-# used. The prefix can be more restrictive than just a directory (the second +-# example). ++# file. When this is used by root, root privilege is retained by the binary ++# (for any other caller including the Exim user, it is dropped). You can ++# restrict the location of alternate configurations by defining a prefix below. ++# Any file used with -C must then start with this prefix (except that /dev/null ++# is also permitted if the caller is root, because that is used in the install ++# script). If the prefix specifies a directory that is owned by root, a ++# compromise of the Exim account does not permit arbitrary alternate ++# configurations to be used. The prefix can be more restrictive than just a ++# directory (the second example). + + # ALT_CONFIG_PREFIX=/some/directory/ + # ALT_CONFIG_PREFIX=/some/directory/exim.conf- + + + #------------------------------------------------------------------------------ +-# If you uncomment the following line, only root may use the -C or -D options +-# without losing root privilege. The -C option specifies an alternate runtime +-# configuration file, and the -D option changes macro values in the runtime +-# configuration. Uncommenting this line restricts what can be done with these +-# options. A call to receive a message (either one-off or via a daemon) cannot +-# successfully continue to deliver it, because the re-exec of Exim to regain +-# root privilege will fail, owing to the use of -C or -D by the Exim user. +-# However, you can still use -C for testing (as root) if you do separate Exim +-# calls for receiving a message and subsequently delivering it. +- +-# ALT_CONFIG_ROOT_ONLY=yes +- +- +-#------------------------------------------------------------------------------ + # Uncommenting this option disables the use of the -D command line option, + # which changes the values of macros in the runtime configuration file. + # This is another protection against somebody breaking into the Exim account. +diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults +index 20ecf0b..f72c292 100644 +--- a/src/src/config.h.defaults ++++ b/src/src/config.h.defaults +@@ -13,7 +13,6 @@ in config.h unless some value is defined in Local/Makefile. If there is data, + it's a default value. */ + + #define ALT_CONFIG_PREFIX +-#define ALT_CONFIG_ROOT_ONLY + + #define APPENDFILE_MODE 0600 + #define APPENDFILE_DIRECTORY_MODE 0700 +diff --git a/src/src/exim.c b/src/src/exim.c +index a3af9db..93f27b7 100644 +--- a/src/src/exim.c ++++ b/src/src/exim.c +@@ -3172,11 +3172,11 @@ if (setgroups(0, NULL) != 0) + + /* If the configuration file name has been altered by an argument on the + command line (either a new file name or a macro definition) and the caller is +-not root or the exim user, or if this is a filter testing run, remove any +-setuid privilege the program has, and run as the underlying user. ++not root, or if this is a filter testing run, remove any setuid privilege the ++program has and run as the underlying user. + +-If ALT_CONFIG_ROOT_ONLY is defined, the exim user is locked out of this, which +-severely restricts the use of -C for some purposes. ++The exim user is locked out of this, which severely restricts the use of -C ++for some purposes. + + Otherwise, set the real ids to the effective values (should be root unless run + from inetd, which it can either be root or the exim uid, if one is configured). +@@ -3190,9 +3190,6 @@ configuration file changes and macro definitions haven't happened. */ + if (( /* EITHER */ + (!trusted_config || macros != NULL) && /* Config changed, and */ + real_uid != root_uid && /* Not root, and */ +- #ifndef ALT_CONFIG_ROOT_ONLY /* (when not locked out) */ +- real_uid != exim_uid && /* Not exim, and */ +- #endif + !running_in_test_harness /* Not fudged */ + ) || /* OR */ + expansion_test /* expansion testing */ +@@ -3380,15 +3377,12 @@ else + } + + /* Handle the case when we have removed the setuid privilege because of -C or +--D. This means that the caller of Exim was not root, and, provided that +-ALT_CONFIG_ROOT_ONLY is not defined, was not the Exim user that is built into +-the binary. ++-D. This means that the caller of Exim was not root. + +-If ALT_CONFIG_ROOT_ONLY is not defined, there is a problem if it turns out we +-were running as the exim user defined in the configuration file (different to +-the one in the binary). The sysadmin may expect this case to retain privilege +-because "the binary was called by the Exim user", but it hasn't, because of the +-order in which it handles this stuff. There are two possibilities: ++There is a problem if we were running as the Exim user. The sysadmin may ++expect this case to retain privilege because "the binary was called by the ++Exim user", but it hasn't, because either the -D option set macros, or the ++-C option set a non-default configuration file. There are two possibilities: + + (1) If deliver_drop_privilege is set, Exim is not going to re-exec in order + to do message deliveries. Thus, the fact that it is running as a +@@ -3400,27 +3394,18 @@ order in which it handles this stuff. There are two possibilities: + + (2) If deliver_drop_privilege is not set, the configuration won't work as + apparently intended, and so we log a panic message. In order to retain +- root for -C or -D, the caller must either be root or the Exim user +- defined in the binary (when deliver_drop_ privilege is false). +- +-If ALT_CONFIG_ROOT_ONLY is defined, we don't know whether we were called by the +-built-in exim user or one defined in the configuration. In either event, +-re-enable log processing, assuming the sysadmin knows what they are doing. */ ++ root for -C or -D, the caller must be root (when deliver_drop_privilege ++ is false). */ + + if (removed_privilege && (!trusted_config || macros != NULL) && + real_uid == exim_uid) + { +- #ifdef ALT_CONFIG_ROOT_ONLY +- really_exim = TRUE; /* let logging work normally */ +- #else +- + if (deliver_drop_privilege) + really_exim = TRUE; /* let logging work normally */ + else + log_write(0, LOG_MAIN|LOG_PANIC, +- "exim user (uid=%d) is defined only at runtime; privilege lost for %s", ++ "exim user lost privilege for using %s option", + (int)exim_uid, trusted_config? "-D" : "-C"); +- #endif + } + + /* Start up Perl interpreter if Perl support is configured and there is a +-- +1.7.1 + diff --git a/exim-4.72-0008-CVE-2010-4345.patch b/exim-4.72-0008-CVE-2010-4345.patch new file mode 100644 index 0000000..9b8e7d4 --- /dev/null +++ b/exim-4.72-0008-CVE-2010-4345.patch @@ -0,0 +1,180 @@ +From a47c55346c719d8f1f71f0849b1b4f87a55e3541 Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Sun, 12 Dec 2010 02:41:37 +0000 +Subject: [PATCH 08/13] Add TRUSTED_CONFIG_PREFIX_FILE option + +(Bug 1044, CVE-2010-4345) +-- + src/src/EDITME | 13 +++ + src/src/config.h.defaults | 1 + + src/src/exim.c | 101 ++++++++++++++++++++++- + 6 files changed, 299 insertions(+), 102 deletions(-) + +diff --git a/src/src/EDITME b/src/src/EDITME +index 4175b97..6bfdb7c 100644 +--- a/src/src/EDITME ++++ b/src/src/EDITME +@@ -455,6 +455,19 @@ FIXED_NEVER_USERS=root + + + #------------------------------------------------------------------------------ ++# When a user other than root uses the -C option to override the configuration ++# file (including the Exim user when re-executing Exim to regain root ++# privileges for local message delivery), this will normally cause Exim to ++# drop root privileges. The TRUSTED_CONFIG_PREFIX_LIST option, specifies ++# a file which contains a list of trusted configuration prefixes (like the ++# ALT_CONFIG_PREFIX above), one per line. If the -C option is used to specify ++# a configuration file which matches a trusted prefix, root privileges are not ++# dropped by Exim. ++ ++# TRUSTED_CONFIG_PREFIX_LIST=/usr/exim/trusted_configs ++ ++ ++#------------------------------------------------------------------------------ + # Uncommenting this option disables the use of the -D command line option, + # which changes the values of macros in the runtime configuration file. + # This is another protection against somebody breaking into the Exim account. +diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults +index f72c292..a160fef 100644 +--- a/src/src/config.h.defaults ++++ b/src/src/config.h.defaults +@@ -13,6 +13,7 @@ in config.h unless some value is defined in Local/Makefile. If there is data, + it's a default value. */ + + #define ALT_CONFIG_PREFIX ++#define TRUSTED_CONFIG_PREFIX_LIST + + #define APPENDFILE_MODE 0600 + #define APPENDFILE_DIRECTORY_MODE 0700 +diff --git a/src/src/exim.c b/src/src/exim.c +index 93f27b7..1f43898 100644 +--- a/src/src/exim.c ++++ b/src/src/exim.c +@@ -1986,10 +1986,103 @@ for (i = 1; i < argc; i++) + } + } + #endif ++ if (real_uid != root_uid) ++ { ++ #ifdef TRUSTED_CONFIG_PREFIX_LIST ++ ++ if (Ustrstr(argrest, "/../")) ++ trusted_config = FALSE; ++ else ++ { ++ FILE *trust_list = Ufopen(TRUSTED_CONFIG_PREFIX_LIST, "rb"); ++ if (trust_list) ++ { ++ struct stat statbuf; ++ ++ if (fstat(fileno(trust_list), &statbuf) != 0 || ++ (statbuf.st_uid != root_uid /* owner not root */ ++ #ifdef CONFIGURE_OWNER ++ && statbuf.st_uid != config_uid /* owner not the special one */ ++ #endif ++ ) || /* or */ ++ (statbuf.st_gid != root_gid /* group not root */ ++ #ifdef CONFIGURE_GROUP ++ && statbuf.st_gid != config_gid /* group not the special one */ ++ #endif ++ && (statbuf.st_mode & 020) != 0 /* group writeable */ ++ ) || /* or */ ++ (statbuf.st_mode & 2) != 0) /* world writeable */ ++ { ++ trusted_config = FALSE; ++ fclose(trust_list); ++ } ++ else ++ { ++ /* Well, the trust list at least is up to scratch... */ ++ void *reset_point = store_get(0); ++ uschar *trusted_prefixes[32]; ++ int nr_prefixes = 0; ++ int i = 0; ++ ++ while (Ufgets(big_buffer, big_buffer_size, trust_list)) ++ { ++ uschar *start = big_buffer, *nl; ++ while (*start && isspace(*start)) ++ start++; ++ if (*start == '#') ++ continue; ++ nl = Ustrchr(start, '\n'); ++ if (nl) ++ *nl = 0; ++ trusted_prefixes[nr_prefixes++] = string_copy(start); ++ if (nr_prefixes == 32) ++ break; ++ } ++ fclose(trust_list); ++ ++ if (nr_prefixes) ++ { ++ int sep = 0; ++ uschar *list = argrest; ++ uschar *filename; ++ while (trusted_config && (filename = string_nextinlist(&list, ++ &sep, big_buffer, big_buffer_size)) != NULL) ++ { ++ for (i=0; i < nr_prefixes; i++) ++ { ++ int len = Ustrlen(trusted_prefixes[i]); ++ if (Ustrlen(filename) >= len && ++ Ustrncmp(filename, trusted_prefixes[i], len) == 0) ++ break; ++ } ++ if (i == nr_prefixes) ++ { ++ trusted_config = FALSE; ++ break; ++ } ++ } ++ } ++ else ++ { ++ /* No valid prefixes found in trust_list file. */ ++ trusted_config = FALSE; ++ } ++ } ++ } ++ else ++ { ++ /* Could not open trust_list file. */ ++ trusted_config = FALSE; ++ } ++ } ++ #else ++ /* Not root; don't trust config */ ++ trusted_config = FALSE; ++ #endif ++ } + + config_main_filelist = argrest; + config_changed = TRUE; +- trusted_config = FALSE; + } + break; + +@@ -3382,7 +3475,7 @@ else + There is a problem if we were running as the Exim user. The sysadmin may + expect this case to retain privilege because "the binary was called by the + Exim user", but it hasn't, because either the -D option set macros, or the +--C option set a non-default configuration file. There are two possibilities: ++-C option set a non-trusted configuration file. There are two possibilities: + + (1) If deliver_drop_privilege is set, Exim is not going to re-exec in order + to do message deliveries. Thus, the fact that it is running as a +@@ -3394,8 +3487,8 @@ Exim user", but it hasn't, because either the -D option set macros, or the + + (2) If deliver_drop_privilege is not set, the configuration won't work as + apparently intended, and so we log a panic message. In order to retain +- root for -C or -D, the caller must be root (when deliver_drop_privilege +- is false). */ ++ root for -C or -D, the caller must either be root or be invoking a ++ trusted configuration file (when deliver_drop_privilege is false). */ + + if (removed_privilege && (!trusted_config || macros != NULL) && + real_uid == exim_uid) +-- +1.7.1 + diff --git a/exim-4.72-0009-CVE-2010-4345.patch b/exim-4.72-0009-CVE-2010-4345.patch new file mode 100644 index 0000000..181be60 --- /dev/null +++ b/exim-4.72-0009-CVE-2010-4345.patch @@ -0,0 +1,33 @@ +From 44badec262804bd3d309de902f1724ef40a79847 Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Sun, 12 Dec 2010 10:18:48 +0000 +Subject: [PATCH 09/13] Allow only absolute paths in TRUSTED_CONFIG_PREFIX_LIST, fix store leak + +--- + src/src/exim.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/src/src/exim.c b/src/src/exim.c +index 1f43898..cfb85b0 100644 +--- a/src/src/exim.c ++++ b/src/src/exim.c +@@ -2029,7 +2029,7 @@ for (i = 1; i < argc; i++) + uschar *start = big_buffer, *nl; + while (*start && isspace(*start)) + start++; +- if (*start == '#') ++ if (*start != '/') + continue; + nl = Ustrchr(start, '\n'); + if (nl) +@@ -2061,6 +2061,7 @@ for (i = 1; i < argc; i++) + break; + } + } ++ store_reset(reset_point); + } + else + { +-- +1.7.1 + diff --git a/exim.spec b/exim.spec index ccd7af9..8f492a5 100644 --- a/exim.spec +++ b/exim.spec @@ -12,7 +12,7 @@ Summary: The exim mail transfer agent Name: exim Version: 4.72 -Release: 1%{?dist} +Release: 2%{?dist} License: GPLv2+ Url: http://www.exim.org/ Group: System Environment/Daemons @@ -52,6 +52,16 @@ Patch23: exim-4.67-smarthost-config.patch Patch24: exim-4.71-dynlookup.patch Patch25: exim-4.69-dynlookup-config.patch Patch26: exim-4.69-strictaliasing.patch +Patch31: exim-4.72-0001-div-by-zero.patch +Patch32: exim-4.72-0002-eval-sigfpe.patch +Patch33: exim-4.72-0003-CVE-2011-1407.patch +Patch34: exim-4.72-0004-CVE-2011-0017.patch +Patch35: exim-4.72-0005-CVE-2010-4345.patch +Patch36: exim-4.72-0006-CVE-2010-4345.patch +Patch37: exim-4.72-0007-CVE-2010-4345.patch +Patch38: exim-4.72-0008-CVE-2010-4345.patch +Patch39: exim-4.72-0009-CVE-2010-4345.patch + Requires: /etc/pki/tls/certs /etc/pki/tls/private Requires: /etc/aliases @@ -183,6 +193,16 @@ greylisting unconditional. %patch25 -p1 -b .dynconfig %patch26 -p1 -b .strictaliasing +%patch31 -p2 -b .0001 +%patch32 -p2 -b .0002 +%patch33 -p2 -b .0003 +%patch34 -p2 -b .0004 +%patch35 -p2 -b .0005 +%patch36 -p2 -b .0006 +%patch37 -p2 -b .0007 +%patch38 -p2 -b .0008 +%patch39 -p2 -b .0009 + cp src/EDITME Local/Makefile sed -i 's@^# LOOKUP_MODULE_DIR=.*@LOOKUP_MODULE_DIR=%{_libdir}/exim/%{version}-%{release}/lookups@' Local/Makefile sed -i 's@^# AUTH_LIBS=-lsasl2@AUTH_LIBS=-lsasl2@' Local/Makefile @@ -501,6 +521,10 @@ test "$1" = 0 || %{_initrddir}/clamd.exim condrestart >/dev/null || : %{_sysconfdir}/cron.daily/greylist-tidy.sh %changelog +* Wed May 18 2011 Mark Chappell 4.72-2 +- Backport various security fixes +- (CVE-2011-1407 CVE-2011-0017 CVE-2010-4345) + * Thu Jun 03 2010 David Woodhouse - 4.72-1 - Update to 4.72 (fixes CVE-2010-2023, CVS-2010-2024)