Hi, The people at Immunix recently scanned all of RedHat 7.0 for temp file problems and found some in CVS (among many others). I'm currently testing a patch for this problem; the current patch is attached. What the patch does is - define CVS_SAFE_FOPEN and safe_fopen to create temp files safely (i.e. using O_EXCL). This is still subject to denial of service, but at least it's safe :) - Checked all calls to cvs_temp_name(), and made sure that the resulting file is opened using safe_fopen() In most cases this was straightforward, but on several occasions RCS_checkout is called, and I went through RCS_checkout to make sure the file is created safely (this part of the patch may need special attention to make sure it's okay) Cheers Olaf -- Olaf Kirch | --- o --- Nous sommes du soleil we love when we play [EMAIL PROTECTED] | / | \ sol.dhoop.naytheet.ah kin.ir.samse.qurax [EMAIL PROTECTED] +-------------------- Why Not?! ----------------------- UNIX, n.: Spanish manufacturer of fire extinguishers.
diff -ur --new-file cvs-1.11.orig/lib/Makefile.in cvs-1.11/lib/Makefile.in --- cvs-1.11.orig/lib/Makefile.in Thu Dec 30 03:44:54 1999 +++ cvs-1.11/lib/Makefile.in Fri Jan 5 11:06:21 2001 @@ -39,6 +39,7 @@ mkdir.c \ regex.c \ rename.c \ + safe_fopen.c \ savecwd.c \ sighandle.c \ strstr.c \ @@ -50,7 +51,8 @@ xgetwd.c \ yesno.c -HEADERS = getline.h getopt.h fnmatch.h regex.h system.h wait.h md5.h savecwd.h +HEADERS = getline.h getopt.h fnmatch.h regex.h system.h wait.h md5.h savecwd.h \ + safe_fopen.h # Always use CVS's regular expression matcher regex.o, because of # variations in regular expression syntax - we want to be the same @@ -70,6 +72,7 @@ getopt1.o \ md5.o \ regex.o \ + safe_fopen.o \ savecwd.o \ sighandle.o \ stripslash.o \ diff -ur --new-file cvs-1.11.orig/lib/safe_fopen.c cvs-1.11/lib/safe_fopen.c --- cvs-1.11.orig/lib/safe_fopen.c Thu Jan 1 01:00:00 1970 +++ cvs-1.11/lib/safe_fopen.c Fri Jan 5 11:06:36 2001 @@ -0,0 +1,24 @@ +/* + * Safely open a temp file + * + */ + +#include <stdio.h> +#include "system.h" + +FILE * +safe_fopen(const char *name, const char *mode) +{ + int fd; + + /* Accept modes w w+ wb etc */ + if (mode[0] != 'w' && mode[0] != 'a') { + errno = EINVAL; + return NULL; + } + + if ((fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0) + return NULL; + + return fdopen(fd, mode); +} diff -ur --new-file cvs-1.11.orig/lib/safe_fopen.h cvs-1.11/lib/safe_fopen.h --- cvs-1.11.orig/lib/safe_fopen.h Thu Jan 1 01:00:00 1970 +++ cvs-1.11/lib/safe_fopen.h Fri Jan 5 11:06:36 2001 @@ -0,0 +1,14 @@ +#ifndef SAFE_FOPEN_H +#define SAFE_FOPEN_H + +#include <stdio.h> + +#if defined (__GNUC__) || (defined (__STDC__) && __STDC__) +#define __PROTO(args) args +#else +#define __PROTO(args) () +#endif /* GCC. */ + +extern FILE * safe_fopen __PROTO((const char *, const char *)); + +#endif /* SAFE_FOPEN_H */ Binary files cvs-1.11.orig/lib/safe_fopen.o and cvs-1.11/lib/safe_fopen.o differ diff -ur --new-file cvs-1.11.orig/lib/system.h cvs-1.11/lib/system.h --- cvs-1.11.orig/lib/system.h Mon Feb 16 19:55:18 1998 +++ cvs-1.11/lib/system.h Fri Jan 5 11:06:21 2001 @@ -429,6 +429,11 @@ #define CVS_FOPEN fopen #endif +#include "safe_fopen.h" +#ifndef CVS_SAFE_FOPEN +#define CVS_SAFE_FOPEN safe_fopen +#endif + #ifndef CVS_MKDIR #define CVS_MKDIR mkdir #endif diff -ur --new-file cvs-1.11.orig/src/commit.c cvs-1.11/src/commit.c --- cvs-1.11.orig/src/commit.c Wed Jul 26 21:29:01 2000 +++ cvs-1.11/src/commit.c Fri Jan 5 11:06:21 2001 @@ -592,7 +592,7 @@ FILE *fp; fname = cvs_temp_name (); - fp = CVS_FOPEN (fname, "w+"); + fp = CVS_SAFE_FOPEN (fname, "w+"); if (fp == NULL) error (1, 0, "cannot create temporary file %s", fname); if (fwrite (saved_message, 1, strlen (saved_message), fp) diff -ur --new-file cvs-1.11.orig/src/import.c cvs-1.11/src/import.c --- cvs-1.11.orig/src/import.c Tue Jul 11 22:32:02 2000 +++ cvs-1.11/src/import.c Fri Jan 5 11:06:21 2001 @@ -291,7 +291,7 @@ /* Create the logfile that will be logged upon completion */ tmpfile = cvs_temp_name (); - if ((logfp = CVS_FOPEN (tmpfile, "w+")) == NULL) + if ((logfp = CVS_SAFE_FOPEN (tmpfile, "w+")) == NULL) error (1, errno, "cannot create temporary file `%s'", tmpfile); /* On systems where we can unlink an open file, do so, so it will go away no matter how we exit. FIXME-maybe: Should be checking for diff -ur --new-file cvs-1.11.orig/src/login.c cvs-1.11/src/login.c --- cvs-1.11.orig/src/login.c Tue Aug 1 18:17:50 2000 +++ cvs-1.11/src/login.c Fri Jan 5 11:06:21 2001 @@ -215,7 +215,7 @@ FILE *tmp_fp; tmp_name = cvs_temp_name (); - if ((tmp_fp = CVS_FOPEN (tmp_name, "w")) == NULL) + if ((tmp_fp = CVS_SAFE_FOPEN (tmp_name, "w")) == NULL) { error (1, errno, "unable to open temp file %s", tmp_name); return 1; @@ -450,7 +450,7 @@ /* FIXME: This should not be in /tmp; that is almost surely a security hole. Probably should just keep it in memory. */ tmp_name = cvs_temp_name (); - if ((tmp_fp = CVS_FOPEN (tmp_name, "w")) == NULL) + if ((tmp_fp = CVS_SAFE_FOPEN (tmp_name, "w")) == NULL) { error (1, errno, "unable to open temp file %s", tmp_name); return 1; diff -ur --new-file cvs-1.11.orig/src/logmsg.c cvs-1.11/src/logmsg.c --- cvs-1.11.orig/src/logmsg.c Wed Mar 1 17:33:39 2000 +++ cvs-1.11/src/logmsg.c Fri Jan 5 11:06:21 2001 @@ -194,7 +194,11 @@ /* Create a temporary file */ fname = cvs_temp_name (); again: - if ((fp = CVS_FOPEN (fname, "w+")) == NULL) + /* need to remove file in case we jumped here after getting + * an error */ + unlink(fname); + + if ((fp = CVS_SAFE_FOPEN (fname, "w+")) == NULL) error (1, 0, "cannot create temporary file %s", fname); if (*messagep) @@ -419,7 +423,7 @@ fname = cvs_temp_name (); - fp = fopen (fname, "w"); + fp = CVS_SAFE_FOPEN (fname, "w"); if (fp == NULL) error (1, errno, "cannot create temporary file %s", fname); else diff -ur --new-file cvs-1.11.orig/src/patch.c cvs-1.11/src/patch.c --- cvs-1.11.orig/src/patch.c Thu Jul 6 19:30:42 2000 +++ cvs-1.11/src/patch.c Fri Jan 5 11:06:21 2001 @@ -504,7 +504,7 @@ /* Create 3 empty files. I'm not really sure there is any advantage to doing so now rather than just waiting until later. */ tmpfile1 = cvs_temp_name (); - fp1 = CVS_FOPEN (tmpfile1, "w+"); + fp1 = CVS_SAFE_FOPEN (tmpfile1, "w+"); if (fp1 == NULL) { error (0, errno, "cannot create temporary file %s", tmpfile1); @@ -515,7 +515,7 @@ if (fclose (fp1) < 0) error (0, errno, "warning: cannot close %s", tmpfile1); tmpfile2 = cvs_temp_name (); - fp2 = CVS_FOPEN (tmpfile2, "w+"); + fp2 = CVS_SAFE_FOPEN (tmpfile2, "w+"); if (fp2 == NULL) { error (0, errno, "cannot create temporary file %s", tmpfile2); @@ -526,7 +526,7 @@ if (fclose (fp2) < 0) error (0, errno, "warning: cannot close %s", tmpfile2); tmpfile3 = cvs_temp_name (); - fp3 = CVS_FOPEN (tmpfile3, "w+"); + fp3 = CVS_SAFE_FOPEN (tmpfile3, "w+"); if (fp3 == NULL) { error (0, errno, "cannot create temporary file %s", tmpfile3); diff -ur --new-file cvs-1.11.orig/src/rcs.c cvs-1.11/src/rcs.c --- cvs-1.11.orig/src/rcs.c Mon Aug 21 23:16:38 2000 +++ cvs-1.11/src/rcs.c Fri Jan 5 11:06:21 2001 @@ -4338,12 +4338,11 @@ ofp = stdout; else { - /* Symbolic links should be removed before replacement, so that - `fopen' doesn't follow the link and open the wrong file. */ - if (islink (sout)) - if (unlink_file (sout) < 0) - error (1, errno, "cannot remove %s", sout); - ofp = CVS_FOPEN (sout, expand == KFLAG_B ? "wb" : "w"); + /* Unconditionally remove the old file, so that safe_fopen + * can succeed */ + if (unlink_file (sout) < 0) + error (1, errno, "cannot remove %s", sout); + ofp = CVS_SAFE_FOPEN (sout, expand == KFLAG_B ? "wb" : "w"); if (ofp == NULL) error (1, errno, "cannot open %s", sout); } diff -ur --new-file cvs-1.11.orig/src/rcscmds.c cvs-1.11/src/rcscmds.c --- cvs-1.11.orig/src/rcscmds.c Sat Aug 15 22:47:46 1998 +++ cvs-1.11/src/rcscmds.c Fri Jan 5 11:06:21 2001 @@ -223,9 +223,17 @@ if (out == RUN_TTY) return diff3_run (call_diff_argc, call_diff_argv, NULL, &call_diff_stdout_callbacks); - else + else { + FILE *fp; + + /* Make sure the file is created safely */ + if (!(fp = CVS_SAFE_FOPEN(out, "w"))) + return 2; + fclose(fp); + return diff3_run (call_diff_argc, call_diff_argv, out, &call_diff_file_callbacks); + } } diff -ur --new-file cvs-1.11.orig/src/wrapper.c cvs-1.11/src/wrapper.c --- cvs-1.11.orig/src/wrapper.c Wed Dec 23 16:15:01 1998 +++ cvs-1.11/src/wrapper.c Fri Jan 5 11:06:21 2001 @@ -566,6 +566,15 @@ free (buf); buf = cvs_temp_name (); + /* Create temp file safely */ + { + FILE *fp; + + if (!(fp = CVS_SAFE_FOPEN(buf, "w"))) + return NULL; + fclose(fp); + } + args = xmalloc (strlen (e->tocvsFilter) + strlen (fileName) + strlen (buf));