Published:
20 January 2000
Protect yourself against future threats.
-----BEGIN PGP SIGNED MESSAGE----- =========================================================================== AUSCERT External Security Bulletin Redistribution ESB-2000.013 -- FreeBSD-SA-00:01 Insecure temporary file handling in make(1) 21 January 2000 =========================================================================== The FreeBSD Security Team has released the following advisory concerning a /tmp race condition vulnerability. This vulnerability may allow local users to execute commands with the privileges of another user. - --------------------------BEGIN INCLUDED 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----- - --------------------------END INCLUDED TEXT-------------------- This security bulletin is provided as a service to AusCERT's members. As AusCERT did not write the document quoted above, AusCERT has had no control over its content. The decision to use any or all of this information is the responsibility of each user or organisation, and should be done so in accordance with site policies and procedures. NOTE: This is only the original release of the security bulletin. It may not be updated when updates to the original are made. If downloading at a later date, it is recommended that the bulletin is retrieved directly from the original authors to ensure that the information is still current. Contact information for the authors of the original document is included in the Security Bulletin above. If you have any questions or need further information, please contact them directly. Previous advisories and external security bulletins can be retrieved from: http://www.auscert.org.au/Information/advisories.html If you believe that your system has been compromised, contact AusCERT or your representative in FIRST (Forum of Incident Response and Security Teams). Internet Email: auscert@auscert.org.au Facsimile: (07) 3365 7031 Telephone: (07) 3365 4417 (International: +61 7 3365 4417) AusCERT personnel answer during Queensland business hours which are GMT+10:00 (AEST). On call after hours for emergencies. -----BEGIN PGP SIGNATURE----- Version: 2.6.3i Charset: noconv Comment: ftp://ftp.auscert.org.au/pub/auscert/AUSCERT_PGP.key iQCVAwUBOIhFuSh9+71yA2DNAQHTNAQAlPIZ8ip1geeI6Z+IIJEW5YbCRZgFWmwK pywW1FRYVcUmqUsUSEUjurz+Ruftg38xfCmBLnc7TSs86am1oqpic8StXcmPGQ8u qIVMrBO13fOfGt30xd/TvG7Rd+d6uh4A3mCmNRh9RunzLkWr88HWcL7jqpPJTNpR XIGHxZzkvNQ= =PrDr -----END PGP SIGNATURE-----