A minor security bug has been found in Exim which applies to both Exim 3 and
Exim 4.
It is a minor bug because it can be exploited only by a local Exim admin user.
Such users are normally sysadmins who have root on the machine anyway. In order
to exploit the bug, you have to
(a) Change Exim's configuration file by setting the pid_file_path option.
This requires write access to the file, or the use of -C by someone
running as root or exim.
(b) Run an exploit that starts up an Exim daemon - this requires the starter
to be an admin user.
The exploit relies on the fact that, in Exim 3, the specification of the value
of pid_file_path requires it to contain "%s" somewhere. This is replaced by the
value of a non-standard port number.
In Exim 4, for backwards compatibility, I arranged that any "%s" in the value
of pid_file_path was just ignored, because in Exim 4, a pid file is no longer
written for daemons with non-standard options (it got too difficult to
specify).
In case anybody is really worried about this problem, there are two patches
below.
In the Exim 4 patch, I have abandoned the backwards compatibility. Anybody who
has a setting of pid_file_path that still contains "%s" should remove the "%s"
from their setting. In fact, this should be done anyway, even if you don't
apply the patch, because you'll need to have done this before the next release.
In the Exim 3 patch, I have abandoned the facility for inserting a non-standard
port number as part of the file name. Again, you should remove "%s" from any
pid_file_path setting after applying the patch.
- --
Philip Hazel University of Cambridge Computing Service,
ph10@??? Cambridge, England. Phone: +44 1223 334714.
- ------------------------------ Exim 4.10 patch -------------------------------
*** exim-4.10/src/daemon.c Mon Jul 22 09:59:48 2002
- --- daemon.c Wed Dec 4 10:52:04 2002
***************
*** 960,991 ****
(b) When -bd is used and -oX is not used, or
(c) When -oP is used to supply a path.
! The variable daemon_write_pid is used to control this.
- - Note re use of sprintf: spool_directory and pid_file_path are checked on
- - input to be < 200 characters. */
- -
if (running_in_test_harness || daemon_write_pid)
{
FILE *f;
- - uschar buff[256];
- -
if (pid_file_path[0] == 0)
! sprintf(CS buff, "%s/exim-daemon.pid", spool_directory);
! else
! sprintf(CS buff, CS pid_file_path, ""); /* Backward compatibility */
! f = Ufopen(buff, "wb");
if (f != NULL)
{
fprintf(f, "%d\n", (int)getpid());
fchmod(fileno(f), 0644);
fclose(f);
! DEBUG(D_any) debug_printf("pid written to %s\n", buff);
}
else
DEBUG(D_any)
! debug_printf("%s\n", string_open_failed(errno, "pid file %s", buff));
}
/* Set up the handler for SIGHUP, which causes a restart of the daemon. */
- --- 960,987 ----
(b) When -bd is used and -oX is not used, or
(c) When -oP is used to supply a path.
! The variable daemon_write_pid is used to control this. */
if (running_in_test_harness || daemon_write_pid)
{
FILE *f;
if (pid_file_path[0] == 0)
! pid_file_path = string_sprintf("%s/exim-daemon.pid", spool_directory);
! f = Ufopen(pid_file_path, "wb");
if (f != NULL)
{
fprintf(f, "%d\n", (int)getpid());
fchmod(fileno(f), 0644);
fclose(f);
! DEBUG(D_any) debug_printf("pid written to %s\n", pid_file_path);
}
else
+ {
DEBUG(D_any)
! debug_printf("%s\n", string_open_failed(errno, "pid file %s",
! pid_file_path));
! }
}
/* Set up the handler for SIGHUP, which causes a restart of the daemon. */
- ------------------------------ End of Exim 4.10 patch ------------------------
- ------------------------------ Exim 3.36 patch -------------------------------
*** exim-3.36/src/daemon.c Thu Apr 4 13:56:16 2002
- --- daemon.c Wed Dec 4 11:01:39 2002
***************
*** 590,596 ****
if (pid_file_path[0] == 0)
sprintf(buff, "%s/exim-daemon.pid", spool_directory);
else
! sprintf(buff, pid_file_path, "");
}
else
{
- --- 590,596 ----
if (pid_file_path[0] == 0)
sprintf(buff, "%s/exim-daemon.pid", spool_directory);
else
! strcpy(buff, pid_file_path);
}
else
{
***************
*** 598,606 ****
sprintf(buff, "%s/exim-daemon.%d.pid", spool_directory, smtp_port);
else
{
! char dbuff[12];
! sprintf(dbuff, ".%d", smtp_port);
! sprintf(buff, pid_file_path, dbuff);
}
}
- --- 598,604 ----
sprintf(buff, "%s/exim-daemon.%d.pid", spool_directory, smtp_port);
else
{
! strcpy(buff, pid_file_path);
}
}
- ------------------------------ End of Exim 3.36 patch ------------------------