Casinos Not On GamstopNon Gamstop CasinosCasinos Not On GamstopOnline Casinos UKNon Gamstop Casino
20th Jan 2000 [SBWID-163]
COMMAND
	    make
SYSTEMS AFFECTED
	    All  FreeBSD  versions  before  the  correction date (2000-01-16),
	    NetBSD, OpenBSD
PROBLEM
	    Following is based on FreeBSD-SA-00:01 Security Advisory  FreeBSD.
	    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.
	    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.  Local users could  execute
	    arbitrary shell commands as part of the build process scheduled by
	    "make -j" by another user.
SOLUTION
	    Avoid using the '-j' flag to make(1).  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 */
	
	

Internet highlights