make -j creates temporary files for the purpose of storing shell commands - unfortunately, it just names them /tmp/makeXXXXX where XXXXX is the PID of the parent process. This leads to a potential DoS exploit wherein a user can guess the PID of the make process and create symlinks to, say /etc/passwd, which will be followed when root runs make -j, and overwritten (in practise it's necessary to 'mine' /tmp with a thousand or so consecutive symlinks to increase the chances of the PID landing in the range). This is of course only possible if root runs a parallel make on a system with a malicious user, but I still consider it a possibility.
The attached patches seem to rectify this problem - can someone please review them? Kris ----- "That suit's sharper than a page of Oscar Wilde witticisms that's been rolled up into a point, sprinkled with lemon juice and jabbed into someone's eye" "Wow, that's sharp!" - Ace Rimmer and the Cat, _Red Dwarf_
Index: job.c =================================================================== RCS file: /home/ncvs/src/usr.bin/make/job.c,v retrieving revision 1.12 diff -u -r1.12 job.c --- job.c 1999/02/14 22:22:42 1.12 +++ job.c 1999/05/15 12:24:19 @@ -161,13 +161,10 @@ /* * 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 XXXXX in - * the string are replaced by the pid of the make process in a 5-character - * field with leading zeroes. + * removed before the child shell is executed. */ static char tfile[] = TMPPAT; - /* * Descriptions for various shells. */ @@ -1664,7 +1661,6 @@ { register Job *job; /* new job descriptor */ char *argv[4]; /* Argument vector to shell */ - static int jobno = 0; /* job number of catching output in a file */ 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 */ @@ -1871,8 +1867,7 @@ /* * If we're using pipes to catch output, create the pipe by which we'll * get the shell's output. If we're using files, print out that we're - * starting a job and then set up its temporary-file name. This is just - * tfile with two extra digits tacked on -- jobno. + * starting a job and then set up its temporary-file name. */ if (!compatMake || (job->flags & JOB_FIRST)) { if (usePipes) { @@ -1886,9 +1881,8 @@ } else { (void) fprintf(stdout, "Remaking `%s'\n", gn->name); (void) fflush(stdout); - sprintf(job->outFile, "%s%02d", tfile, jobno); - jobno = (jobno + 1) % 100; - job->outFd = open(job->outFile,O_WRONLY|O_CREAT|O_APPEND,0600); + strcpy(job->outFile, TMPPAT); + job->outFd = mkstemp(job->outFile); (void) fcntl(job->outFd, F_SETFD, 1); } } @@ -2405,7 +2399,7 @@ { GNode *begin; /* node for commands to do at the very start */ - (void) sprintf(tfile, "/tmp/make%05d", getpid()); + (void) mktemp(tfile); jobs = Lst_Init(FALSE); stoppedJobs = Lst_Init(FALSE); Index: job.h =================================================================== RCS file: /home/ncvs/src/usr.bin/make/job.h,v retrieving revision 1.8 diff -u -r1.8 job.h --- job.h 1997/04/21 20:32:11 1.8 +++ job.h 1999/05/15 10:44:41 @@ -47,7 +47,7 @@ #ifndef _JOB_H_ #define _JOB_H_ -#define TMPPAT "/tmp/makeXXXXX" +#define TMPPAT "/tmp/makeXXXXXXXX" /* * The SEL_ constants determine the maximum amount of time spent in select @@ -128,7 +128,7 @@ } o_pipe; /* data used when catching the output via * a pipe */ struct { - char of_outFile[sizeof(TMPPAT)+2]; + char of_outFile[sizeof(TMPPAT)]; /* Name of file to which shell output * was rerouted */ int of_outFd; /* Stream open to the output Index: main.c =================================================================== RCS file: /home/ncvs/src/usr.bin/make/main.c,v retrieving revision 1.30 diff -u -r1.30 main.c --- main.c 1999/03/01 06:01:05 1.30 +++ main.c 1999/05/15 07:53:18 @@ -1253,7 +1253,7 @@ } /* - * enunlink -- + * eunlink -- * Remove a file carefully, avoiding directories. */ int