From owner-doc-jp@jp.freebsd.org  Thu Jan 20 22:57:53 2000
Received: (from daemon@localhost)
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) id WAA39117;
	Thu, 20 Jan 2000 22:57:53 +0900 (JST)
	(envelope-from owner-doc-jp@jp.FreeBSD.org)
Received: from bilbo.micon.co.jp ([210.226.150.237])
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) with ESMTP id WAA39110
	for <doc-jp@jp.freebsd.org>; Thu, 20 Jan 2000 22:57:51 +0900 (JST)
	(envelope-from sakauchi@yamame.to)
Received: from guest1.myhome (p848763.kgci.ap.so-net.ne.jp [210.132.135.99])
	by bilbo.micon.co.jp (8.8.5/8.8.5) with ESMTP id WAA15225;
	Thu, 20 Jan 2000 22:57:41 +0900 (JST)
Message-Id: <200001201357.WAA15225@bilbo.micon.co.jp>
Date: Thu, 20 Jan 2000 23:01:07 +0900
From: Atushi Sakauchi <sakauchi@yamame.to>
To: doc-jp@jp.freebsd.org
In-Reply-To: In your message of "Wed, 19 Jan 2000 12:05:24 -0700 (MST)"
	<200001191905.MAA27712@harmony.village.org>
References: <200001191905.MAA27712@harmony.village.org>
User-Agent: Wanderlust/1.0.3 (Notorious) SEMI/1.13.4 (Terai) FLIM/1.12.7
 (=?ISO-8859-4?Q?Y=FEzaki?=) MULE XEmacs/21.1 (patch 6) (Big Bend)
 (i386--freebsd)
MIME-Version: 1.0 (generated by SEMI 1.13.4 - "Terai")
Content-Type: text/plain; charset=ISO-2022-JP
Reply-To: doc-jp@jp.freebsd.org
Precedence: list
X-Distribute: distribute version 2.1 (Alpha) patchlevel 24e+990727
X-Sequence: doc-jp 6979
Subject: [doc-jp 6979] Re: ANNOUNCE: FreeBSD Security Advisory: FreeBSD-SA-00:01.make
Errors-To: owner-doc-jp@jp.freebsd.org
Sender: owner-doc-jp@jp.freebsd.org
X-Originator: sakauchi@yamame.to

$B:dFb$G$9!%(B

FreeBSD-SA-00:01.make $B$r(B announce-jp $B8~$1$KLu$7$F$_$^$7$?!%(B
$B$h$m$7$/$*4j$$$7$^$9!%(B
patch $B$NItJ,$N(B indent $B$r<h$C$F$_$^$7$?!%(B
$B$3$NE@$K$D$$$F$b$40U8+$$$?$@$1$l$P$H;W$$$^$9!%(B 

  $B$3$N%a!<%k$O(B announce-jp $B$KN.$l$?(B

Subject: ANNOUNCE: FreeBSD Security Advisory: FreeBSD-SA-00:01.make
From: FreeBSD Security Officer <security-officer@FreeBSD.ORG>
Date: Wed, 19 Jan 2000 12:05:24 -0700 (MST)
Message-Id: <200001191905.MAA27712@harmony.village.org>

$B$rF|K\8lLu$7$?$b$N$G$9(B.
  $B86J8$O(B PGP $B=pL>$5$l$F$$$^$9$,(B, $B$3$NF|K\8lLu$O(B PGP $B=pL>$5$l$F$$$^$;$s(B. 
$B%Q%C%AEy$NFbMF$,2~cb$5$l$F$$$J$$$3$H$r3NG'$9$k$?$a$K(B PGP $B$N%A%'%C%/$r9T(B
$B$J$&$K$O86J8$r;2>H$7$F$/$@$5$$(B. 
  $BF|K\8lLu$O(B FreeBSD $BF|K\8l%I%-%e%a%s%F!<%7%g%s%W%m%8%'%/%H(B (doc-jp) $B$,(B
$B;29M$N$?$a$KDs6!$9$k$b$N$G(B, $BK]Lu<T$*$h$S(B doc-jp $B$O(B $B$=$NFbMF$K$D$$$F(B
$B$$$+$J$kJ]>Z$b$$$?$7$^$;$s(B. 
  $BF|K\8lLu$K$D$$$F$N$*Ld$$9g$o$;$O(B doc-jp@jp.freebsd.org $B$^$G(B
$B$*4j$$$7$^$9(B. 

=============================================================================
FreeBSD-SA-00:01                                            Security Advisory
                                                                FreeBSD, Inc.

$B%H%T%C%/(B:       Insecure temporary file handling in make(1)

$B%+%F%4%j!<(B:     core
$B%b%8%e!<%k(B:     make
$B9pCNF|(B:         2000-01-19
$B1F6ABP>](B:       $B=$@5$5$l$k0JA0$N$9$Y$F$N%P!<%8%g%s(B
$B=$@5F|(B:         2000-01-16
FreeBSD $B$@$1$NLdBj$+(B:   NO

$B%Q%C%A(B:         ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-00:01/make.patch

I.   $BGX7J(B

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.

make(1) $B%W%m%0%i%`$O!$%=!<%9%3!<%I$N%S%k%I$N%9%1%8%e!<%j%s%0$K(B
$BE57?E*$K;HMQ$5$l$k%W%m%0%i%`$G$9!%%9%$%C%A(B(-j) $B$K$h$j!$J#?t$N(B
$B;R%W%m%;%9$r5/F0$9$k$3$H$G!$JB9T%S%k%I$r9T$J$&$3$H$,$G$-$^$9!%(B

II.  $B2r@b(B

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.

make(1) $B$N(B -j $B%*%W%7%g%s$O(B /tmp $BFb$N0l;~%U%!%$%k$K!$;R%W%m%;%9$,<B9T$9$Y(B 
$B$-%7%'%k%3%^%s%I$r3JG<$9$k$3$H$G!$;R%W%m%;%9$HDL?.$7$^$9!%$3$l$O%^%k%A!&(B
$B%W%m%;%C%5!&%"!<%-%F%/%A%c$G$O!$;HMQ$G$-$kA4$F%W%m%;%C%5$r;HMQ$9$k$?$a$K(B 
$BM-8z$G$"$j!$%7%s%0%k%W%m%;%C%5!&%7%9%F%`$K$*$$$F$b!$%S%k%I:n6H$N!$BT$A;~(B
$B4V$r:G>.$K$9$k$?$a$K!$9-$/;H$o$l$F$$$^$9!%(B

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.

$B$7$+$7(B make(1) $B$O!$?F%W%m%;%9$N@8B84|4VCf!$F1$8%U%!%$%kL>$r7+JV$7>C5n$7(B
$B:F;HMQ$9$k$H$$$&0BA4$G$J$$J}K!$r$H$C$F$$$^$9!%0-0U$r;}$D%f!<%6$,!$;H$o$l(B
$B$k0l;~%U%!%$%k$NL>A0$r4Q;!$G$-$^$9$+$i!$@55,$N%3%^%s%I$,=q$-9~$^$l$?8e$K!$(B
$B%U%!%$%k$NFbMF$rG$0U$N%3%^%s%I$K=q$-49$($k$3$H$,2DG=$G$"$k$H$$$&6%9g>uBV(B
$B$,@8$8$k$H$$$&LdBj$,$"$j$^$9!%(B 

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.

$B$3$NLdBj$O!$(BFreeBSD $B%*%Z%l!<%F%#%s%0%7%9%F%`$N%;%-%e%j%F%#>e$NLdBj$r(B
$BH/8+$7!$=$@5$9$k:n6H$rB3$1$F$$$k(B, FreeBSD Auditing Project $B$N(B $B@.2L$N(B
$B$R$H$D$H$7$FH/8+$5$l$^$7$?!%(B 

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.

NetBSD $B$H(B OpenBSD $B$NA4$F$N%P!<%8%g%s$K$bF1MM$NLdBj$,$"$k$H3N?.$5$l$F$$$^(B
$B$9!%(BBSD $B5/8;$N(B make(1) $B%P%$%J%j$r:NMQ$7$F$$$k!$B>$NA4$F$N%7%9%F%`$K$b!$(B
$B$3$NLdBj$,$"$k2DG=@-$,$"$j$^$9!%(B

III. $B1F6A(B

Local users could execute arbitrary shell commands as part of the
build process scheduled by "make -j" by another user.

$B%m!<%+%k%f!<%6!<$,!$B>$N%f!<%6$N(B "make -j" $B$+$i<B9T$5$l$k%S%k%I%W%m%;%9(B
$B$N0lIt$H$7$FG$0U$N%7%'%k%3%^%s%I$r<B9T$9$k$3$H$,2DG=$G$9!%(B 

IV.  $BBP1~:v(B

Avoid using the '-j' flag to make(1).

make(1) $B$N(B '-j' $B%U%i%0$r;HMQ$7$J$$$G2<$5$$!%(B

V.   $B2r7h:v(B

Upgrade your system to one that is listed above as having the problem
resolved, or patch your present system.

$B!V=$@5F|!W0J9_$N%P!<%8%g%s$K!$%7%9%F%`$r%"%C%W%0%l!<%I$9$k$+!$%Q%C%A$r(B
$BE,MQ$7$F$/$@$5$$!%(B

To patch your present system: save the patch below into a file, and
execute the following commands as root:

$B%Q%C%A$NE,MQ$9$k$K$O!$0J2<$N%Q%C%A$r%U%!%$%k$K%;!<%V$7!$(Broot $B8"8B$G0J2<(B
$B$N%3%^%s%I$r<B9T$7$^$9!%(B

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:

$B=$@5F|0JA0$N(B 3.4-STABLE $B$*$h$S(B 4.0-CURRENT $B$KBP$9$k%Q%C%A$G$9!%(B

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

$BCm0U(B: $BK\J8=qCf$K%Q%C%A$,4^$^$l$F$$$k>l9g(B, $BEE;R=pL>$d%a%$%i$N=hM}$GJQ99(B
      $B$5$l$k$?$a(B, $B$=$N$^$^$G$O$-$A$s$HE,MQ$G$-$J$$$+$b$7$l$^$;$s(B. $BI,MW(B
      $B$G$"$l$P(B, $BK\J8=q$NKAF,$K5-:\$7$F$"$k(B URL $B$r;2>H$7$F%*%j%8%J%k$N(B
      $B%3%T!<$rF~<j$7$F$/$@$5$$(B.
=============================================================================
