patches for easier mirroring, to eliminate a special copy, to make www.freebsd.org/security a full copy of security.freebsd.org and be eventually be the same. For now files are just sitting there. The symlinks are missing. Discussed on: www (repository location) Discussed with: simon (so)
243 lines
7.8 KiB
Text
243 lines
7.8 KiB
Text
-----BEGIN PGP SIGNED MESSAGE-----
|
|
|
|
=============================================================================
|
|
FreeBSD-SA-00:01 Security Advisory
|
|
FreeBSD, Inc.
|
|
|
|
Topic: Insecure temporary file handling in make(1)
|
|
|
|
Category: core
|
|
Module: make
|
|
Announced: 2000-01-19
|
|
Affects: All versions before the correction date.
|
|
Corrected: 2000-01-16
|
|
FreeBSD only: NO
|
|
|
|
Patches: ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-00:01/make.patch
|
|
|
|
I. Background
|
|
|
|
The make(1) program is typically used to schedule building of source
|
|
code. It has a switch ('-j') to allow parallel building by spawning
|
|
multiple child processes.
|
|
|
|
II. Problem Description
|
|
|
|
The -j option to make(1) uses temporary files in /tmp to communicate
|
|
with its child processes by storing the shell command the child should
|
|
execute. This is useful on multi-processor architectures for making
|
|
use of all of the available CPUs, and is also widely used on
|
|
uniprocessor systems to minimize the scheduling latency of the build
|
|
process.
|
|
|
|
However make(1) uses the temporary file in an insecure way, repeatedly
|
|
deleting and reusing the same file name for the entire life of the
|
|
program. This makes it vulnerable to a race condition wherein a
|
|
malicious user could observe the name of the temporary file being
|
|
used, and replace the contents of a later instance of the file with
|
|
her desired commands after the legitimate commands have been written.
|
|
|
|
This vulnerability was discovered as part of the FreeBSD Auditing
|
|
Project, an ongoing effort to identify and correct security
|
|
vulnerabilities in the FreeBSD operating system.
|
|
|
|
All versions of NetBSD and OpenBSD are also believed to be vulnerable
|
|
to this problem. Other systems using a BSD-derived make(1) binary may
|
|
also be vulnerable.
|
|
|
|
III. Impact
|
|
|
|
Local users could execute arbitrary shell commands as part of the
|
|
build process scheduled by "make -j" by another user.
|
|
|
|
IV. Workaround
|
|
|
|
Avoid using the '-j' flag to make(1).
|
|
|
|
V. Solution
|
|
|
|
Upgrade your system to one that is listed above as having the problem
|
|
resolved, or patch your present system.
|
|
|
|
To patch your present system: save the patch below into a file, and
|
|
execute the following commands as root:
|
|
|
|
cd /usr/src/usr.bin/make
|
|
patch < /path/to/patch/file
|
|
make all
|
|
make install
|
|
|
|
Patches for 3.4-STABLE and 4.0-CURRENT systems before the resolution date:
|
|
|
|
Index: job.c
|
|
===================================================================
|
|
RCS file: /home/ncvs/src/usr.bin/make/job.c,v
|
|
retrieving revision 1.16
|
|
diff -u -r1.16 job.c
|
|
--- job.c 1999/09/11 13:08:01 1.16
|
|
+++ job.c 2000/01/17 01:42:57
|
|
@@ -163,14 +163,6 @@
|
|
#define JOB_STOPPED 3 /* The job is stopped */
|
|
|
|
/*
|
|
- * tfile is the name of a file into which all shell commands are put. It is
|
|
- * used over by removing it before the child shell is executed. The XXXXXXXXXX
|
|
- * in the string are replaced by mkstemp(3).
|
|
- */
|
|
-static char tfile[sizeof(TMPPAT)];
|
|
-
|
|
-
|
|
-/*
|
|
* Descriptions for various shells.
|
|
*/
|
|
static Shell shells[] = {
|
|
@@ -993,7 +985,7 @@
|
|
/*
|
|
* If we are aborting and the job table is now empty, we finish.
|
|
*/
|
|
- (void) eunlink(tfile);
|
|
+ (void) eunlink(job->tfile);
|
|
Finish(errors);
|
|
}
|
|
}
|
|
@@ -1668,6 +1660,7 @@
|
|
Boolean cmdsOK; /* true if the nodes commands were all right */
|
|
Boolean local; /* Set true if the job was run locally */
|
|
Boolean noExec; /* Set true if we decide not to run the job */
|
|
+ int tfd; /* File descriptor for temp file */
|
|
|
|
if (previous != NULL) {
|
|
previous->flags &= ~(JOB_FIRST|JOB_IGNERR|JOB_SILENT|JOB_REMOTE);
|
|
@@ -1697,6 +1690,12 @@
|
|
}
|
|
job->flags |= flags;
|
|
|
|
+ (void) strcpy(job->tfile, TMPPAT);
|
|
+ if ((tfd = mkstemp(job->tfile)) == -1)
|
|
+ Punt("cannot create temp file: %s", strerror(errno));
|
|
+ else
|
|
+ (void) close(tfd);
|
|
+
|
|
/*
|
|
* Check the commands now so any attributes from .DEFAULT have a chance
|
|
* to migrate to the node
|
|
@@ -1722,9 +1721,9 @@
|
|
DieHorribly();
|
|
}
|
|
|
|
- job->cmdFILE = fopen(tfile, "w+");
|
|
+ job->cmdFILE = fopen(job->tfile, "w+");
|
|
if (job->cmdFILE == NULL) {
|
|
- Punt("Could not open %s", tfile);
|
|
+ Punt("Could not open %s", job->tfile);
|
|
}
|
|
(void) fcntl(FILENO(job->cmdFILE), F_SETFD, 1);
|
|
/*
|
|
@@ -1830,7 +1829,7 @@
|
|
* Unlink and close the command file if we opened one
|
|
*/
|
|
if (job->cmdFILE != stdout) {
|
|
- (void) eunlink(tfile);
|
|
+ (void) eunlink(job->tfile);
|
|
if (job->cmdFILE != NULL)
|
|
(void) fclose(job->cmdFILE);
|
|
} else {
|
|
@@ -1859,7 +1858,7 @@
|
|
}
|
|
} else {
|
|
(void) fflush(job->cmdFILE);
|
|
- (void) eunlink(tfile);
|
|
+ (void) eunlink(job->tfile);
|
|
}
|
|
|
|
/*
|
|
@@ -2403,13 +2402,6 @@
|
|
* be running at once. */
|
|
{
|
|
GNode *begin; /* node for commands to do at the very start */
|
|
- int tfd;
|
|
-
|
|
- (void) strcpy(tfile, TMPPAT);
|
|
- if ((tfd = mkstemp(tfile)) == -1)
|
|
- Punt("cannot create temp file: %s", strerror(errno));
|
|
- else
|
|
- (void) close(tfd);
|
|
|
|
jobs = Lst_Init(FALSE);
|
|
stoppedJobs = Lst_Init(FALSE);
|
|
@@ -2914,7 +2906,7 @@
|
|
}
|
|
}
|
|
}
|
|
- (void) eunlink(tfile);
|
|
+ (void) eunlink(job->tfile);
|
|
}
|
|
|
|
/*
|
|
@@ -2948,7 +2940,6 @@
|
|
}
|
|
}
|
|
}
|
|
- (void) eunlink(tfile);
|
|
return(errors);
|
|
}
|
|
|
|
@@ -3024,6 +3015,7 @@
|
|
KILL(job->pid, SIGINT);
|
|
KILL(job->pid, SIGKILL);
|
|
#endif /* RMT_WANTS_SIGNALS */
|
|
+ (void) eunlink(job->tfile);
|
|
}
|
|
}
|
|
|
|
@@ -3032,7 +3024,6 @@
|
|
*/
|
|
while (waitpid((pid_t) -1, &foo, WNOHANG) > 0)
|
|
continue;
|
|
- (void) eunlink(tfile);
|
|
}
|
|
|
|
#ifdef REMOTE
|
|
Index: job.h
|
|
===================================================================
|
|
RCS file: /home/ncvs/src/usr.bin/make/job.h,v
|
|
retrieving revision 1.10
|
|
diff -u -r1.10 job.h
|
|
--- job.h 1999/08/28 01:03:31 1.10
|
|
+++ job.h 2000/01/17 01:42:31
|
|
@@ -93,6 +93,8 @@
|
|
#define JOB_BUFSIZE 1024
|
|
typedef struct Job {
|
|
int pid; /* The child's process ID */
|
|
+ char tfile[sizeof(TMPPAT)];
|
|
+ /* Temporary file to use for job */
|
|
GNode *node; /* The target the child is making */
|
|
LstNode tailCmds; /* The node of the first command to be
|
|
* saved when the job has been run */
|
|
|
|
=============================================================================
|
|
FreeBSD, Inc.
|
|
|
|
Web Site: http://www.freebsd.org/
|
|
Confidential contacts: security-officer@freebsd.org
|
|
Security notifications: security-notifications@freebsd.org
|
|
Security public discussion: freebsd-security@freebsd.org
|
|
PGP Key: ftp://ftp.freebsd.org/pub/FreeBSD/CERT/public_key.asc
|
|
|
|
Notice: Any patches in this document may not apply cleanly due to
|
|
modifications caused by digital signature or mailer software.
|
|
Please reference the URL listed at the top of this document
|
|
for original copies of all patches if necessary.
|
|
=============================================================================
|
|
|
|
-----BEGIN PGP SIGNATURE-----
|
|
Version: 2.6.3ia
|
|
Charset: noconv
|
|
Comment: Processed by Mailcrypt 3.4, an Emacs/PGP interface
|
|
|
|
iQCVAwUBOIVvCFUuHi5z0oilAQF7nQP+No1n5Rl2g0ltvu+Vrx2ImMZreOwz04zZ
|
|
a6MM+bQQ0q/pXgupzSQ3xcfpzZzHjQx2+ajMg4P+l7+OsBvjBvrVFrc021rRW18W
|
|
Ds3A/Vlm8seaWOe4Q4u5qSTdp2PO9HXJrEQWL37xAQtqVyT3J2E37MQyEfENWg4d
|
|
FeIUCiTIMuA=
|
|
=86yT
|
|
-----END PGP SIGNATURE-----
|