From a291e3b6538a0697986d1a7d22aa220829998bab Mon Sep 17 00:00:00 2001 From: jb Date: Sat, 5 May 2012 06:30:51 +0000 Subject: [PATCH] Fix handling of temporary files. 2012-05-05 Janne Blomqvist * gfortran.texi (GFORTRAN_TMPDIR): Rename to TMPDIR, explain algorithm for choosing temp directory. 2012-05-05 Janne Blomqvist * config.h.in: Regenerated. * configure: Regenerated. * configure.ac: Add checks for getegid and __secure_getenv. * io/unix.c (P_tmpdir): Fallback definition for macro. (tempfile_open): New function. (tempfile): Use secure_getenv, call tempfile_open to try each directory in turn. * libgfortran.h (DEFAULT_TMPDIR): Remove macro. (secure_getenv): New macro/prototype. * runtime/environ.c (secure_getenv): New function. (variable_table): Rename GFORTRAN_TMPDIR to TMPDIR. * runtime/main.c (find_addr2line): Use secure_getenv. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@187190 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/fortran/ChangeLog | 5 ++ gcc/fortran/gfortran.texi | 31 ++++++++--- libgfortran/ChangeLog | 15 +++++ libgfortran/config.h.in | 6 ++ libgfortran/configure | 10 +++- libgfortran/configure.ac | 2 +- libgfortran/io/unix.c | 125 ++++++++++++++++++++++++++---------------- libgfortran/libgfortran.h | 16 ++++-- libgfortran/runtime/environ.c | 18 +++++- libgfortran/runtime/main.c | 2 +- 10 files changed, 163 insertions(+), 67 deletions(-) diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index bb4c22d49bc..d1cb4294be6 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,8 @@ +2012-05-05 Janne Blomqvist + + * gfortran.texi (GFORTRAN_TMPDIR): Rename to TMPDIR, explain + algorithm for choosing temp directory. + 2012-05-04 Tobias Burnus PR fortran/53175 diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi index b1790c6ad5f..96662c49423 100644 --- a/gcc/fortran/gfortran.texi +++ b/gcc/fortran/gfortran.texi @@ -576,10 +576,10 @@ environment variables. Malformed environment variables are silently ignored. @menu +* TMPDIR:: Directory for scratch files * GFORTRAN_STDIN_UNIT:: Unit number for standard input * GFORTRAN_STDOUT_UNIT:: Unit number for standard output * GFORTRAN_STDERR_UNIT:: Unit number for standard error -* GFORTRAN_TMPDIR:: Directory for scratch files * GFORTRAN_UNBUFFERED_ALL:: Do not buffer I/O for all units. * GFORTRAN_UNBUFFERED_PRECONNECTED:: Do not buffer I/O for preconnected units. * GFORTRAN_SHOW_LOCUS:: Show location for runtime errors @@ -590,6 +590,27 @@ Malformed environment variables are silently ignored. * GFORTRAN_ERROR_BACKTRACE:: Show backtrace on run-time errors @end menu +@node TMPDIR +@section @env{TMPDIR}---Directory for scratch files + +When opening a file with @code{STATUS='SCRATCH'}, GNU Fortran tries to +create the file in one of the potential directories by testing each +directory in the order below. + +@enumerate +@item +The environment variable @env{TMPDIR}, if it exists. + +@item +On the MinGW target, the directory returned by the @code{GetTempPath} +function. Alternatively, on the Cygwin target, the @env{TMP} and +@env{TEMP} environment variables, if they exist, in that order. + +@item +The @code{P_tmpdir} macro if it is defined, otherwise the directory +@file{/tmp}. +@end enumerate + @node GFORTRAN_STDIN_UNIT @section @env{GFORTRAN_STDIN_UNIT}---Unit number for standard input @@ -611,14 +632,6 @@ This environment variable can be used to select the unit number preconnected to standard error. This must be a positive integer. The default value is 0. -@node GFORTRAN_TMPDIR -@section @env{GFORTRAN_TMPDIR}---Directory for scratch files - -This environment variable controls where scratch files are -created. If this environment variable is missing, -GNU Fortran searches for the environment variable @env{TMP}, then @env{TEMP}. -If these are missing, the default is @file{/tmp}. - @node GFORTRAN_UNBUFFERED_ALL @section @env{GFORTRAN_UNBUFFERED_ALL}---Do not buffer I/O on all units diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index ec662841ee2..46f2cf41853 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,18 @@ +2012-05-05 Janne Blomqvist + + * config.h.in: Regenerated. + * configure: Regenerated. + * configure.ac: Add checks for getegid and __secure_getenv. + * io/unix.c (P_tmpdir): Fallback definition for macro. + (tempfile_open): New function. + (tempfile): Use secure_getenv, call tempfile_open to try each + directory in turn. + * libgfortran.h (DEFAULT_TMPDIR): Remove macro. + (secure_getenv): New macro/prototype. + * runtime/environ.c (secure_getenv): New function. + (variable_table): Rename GFORTRAN_TMPDIR to TMPDIR. + * runtime/main.c (find_addr2line): Use secure_getenv. + 2012-04-22 Tobias Burnus PR fortran/53051 diff --git a/libgfortran/config.h.in b/libgfortran/config.h.in index 30a7e121325..b75fa968023 100644 --- a/libgfortran/config.h.in +++ b/libgfortran/config.h.in @@ -426,6 +426,9 @@ /* Define to 1 if you have the `getcwd' function. */ #undef HAVE_GETCWD +/* Define to 1 if you have the `getegid' function. */ +#undef HAVE_GETEGID + /* Define to 1 if you have the `geteuid' function. */ #undef HAVE_GETEUID @@ -834,6 +837,9 @@ /* Define to 1 if you have the `ynl' function. */ #undef HAVE_YNL +/* Define to 1 if you have the `__secure_getenv' function. */ +#undef HAVE___SECURE_GETENV + /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR diff --git a/libgfortran/configure b/libgfortran/configure index b80f5453d00..e2db9ea2537 100755 --- a/libgfortran/configure +++ b/libgfortran/configure @@ -2592,6 +2592,8 @@ as_fn_append ac_func_list " getppid" as_fn_append ac_func_list " getuid" as_fn_append ac_func_list " geteuid" as_fn_append ac_func_list " umask" +as_fn_append ac_func_list " getegid" +as_fn_append ac_func_list " __secure_getenv" as_fn_append ac_header_list " math.h" # Check that the precious variables saved in the cache have kept the same # value. @@ -12319,7 +12321,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12322 "configure" +#line 12324 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12425,7 +12427,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12428 "configure" +#line 12430 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -16536,6 +16538,10 @@ done + + + + # Check for C99 (and other IEEE) math functions { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sin in -lm" >&5 $as_echo_n "checking for sin in -lm... " >&6; } diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac index d70924e8fcf..41bef720234 100644 --- a/libgfortran/configure.ac +++ b/libgfortran/configure.ac @@ -266,7 +266,7 @@ ftruncate chsize chdir getlogin gethostname kill link symlink sleep ttyname \ alarm access fork execl wait setmode execve pipe dup2 close \ strcasestr getrlimit gettimeofday stat fstat lstat getpwuid vsnprintf dup \ getcwd localtime_r gmtime_r strerror_r getpwuid_r ttyname_r clock_gettime \ -readlink getgid getpid getppid getuid geteuid umask) +readlink getgid getpid getppid getuid geteuid umask getegid __secure_getenv) # Check for C99 (and other IEEE) math functions GCC_CHECK_MATH_FUNC([acosf]) diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c index 185936f109d..c81163f2563 100644 --- a/libgfortran/io/unix.c +++ b/libgfortran/io/unix.c @@ -176,6 +176,17 @@ fallback_access (const char *path, int mode) #endif +/* Fallback directory for creating temporary files. P_tmpdir is + defined on many POSIX platforms. */ +#ifndef P_tmpdir +#ifdef _P_tmpdir +#define P_tmpdir _P_tmpdir /* MinGW */ +#else +#define P_tmpdir "/tmp" +#endif +#endif + + /* Unix and internal stream I/O module */ static const int BUFFER_SIZE = 8192; @@ -1026,54 +1037,23 @@ unpack_filename (char *cstring, const char *fstring, int len) } -/* tempfile()-- Generate a temporary filename for a scratch file and - * open it. mkstemp() opens the file for reading and writing, but the - * library mode prevents anything that is not allowed. The descriptor - * is returned, which is -1 on error. The template is pointed to by - * opp->file, which is copied into the unit structure - * and freed later. */ +/* Helper function for tempfile(). Tries to open a temporary file in + the directory specified by tempdir. If successful, the file name is + stored in fname and the descriptor returned. Returns -1 on + failure. */ static int -tempfile (st_parameter_open *opp) +tempfile_open (const char *tempdir, char **fname) { - const char *tempdir; - char *template; - const char *slash = "/"; int fd; - size_t tempdirlen; - -#ifndef HAVE_MKSTEMP - int count; - size_t slashlen; -#endif + const char *slash = "/"; - tempdir = getenv ("GFORTRAN_TMPDIR"); -#ifdef __MINGW32__ - if (tempdir == NULL) - { - char buffer[MAX_PATH + 1]; - DWORD ret; - ret = GetTempPath (MAX_PATH, buffer); - /* If we are not able to get a temp-directory, we use - current directory. */ - if (ret > MAX_PATH || !ret) - buffer[0] = 0; - else - buffer[ret] = 0; - tempdir = strdup (buffer); - } -#else - if (tempdir == NULL) - tempdir = getenv ("TMP"); - if (tempdir == NULL) - tempdir = getenv ("TEMP"); - if (tempdir == NULL) - tempdir = DEFAULT_TEMPDIR; -#endif + if (!tempdir) + return -1; - /* Check for special case that tempdir contains slash - or backslash at end. */ - tempdirlen = strlen (tempdir); + /* Check for the special case that tempdir ends with a slash or + backslash. */ + size_t tempdirlen = strlen (tempdir); if (*tempdir == 0 || tempdir[tempdirlen - 1] == '/' #ifdef __MINGW32__ || tempdir[tempdirlen - 1] == '\\' @@ -1082,7 +1062,7 @@ tempfile (st_parameter_open *opp) slash = ""; // Take care that the template is longer in the mktemp() branch. - template = xmalloc (tempdirlen + 23); + char * template = xmalloc (tempdirlen + 23); #ifdef HAVE_MKSTEMP snprintf (template, tempdirlen + 23, "%s%sgfortrantmpXXXXXX", @@ -1092,8 +1072,8 @@ tempfile (st_parameter_open *opp) #else /* HAVE_MKSTEMP */ fd = -1; - count = 0; - slashlen = strlen (slash); + int count = 0; + size_t slashlen = strlen (slash); do { snprintf (template, tempdirlen + 23, "%s%sgfortrantmpaaaXXXXXX", @@ -1127,8 +1107,59 @@ tempfile (st_parameter_open *opp) while (fd == -1 && errno == EEXIST); #endif /* HAVE_MKSTEMP */ - opp->file = template; - opp->file_len = strlen (template); /* Don't include trailing nul */ + *fname = template; + return fd; +} + + +/* tempfile()-- Generate a temporary filename for a scratch file and + * open it. mkstemp() opens the file for reading and writing, but the + * library mode prevents anything that is not allowed. The descriptor + * is returned, which is -1 on error. The template is pointed to by + * opp->file, which is copied into the unit structure + * and freed later. */ + +static int +tempfile (st_parameter_open *opp) +{ + const char *tempdir; + char *fname; + int fd = -1; + + tempdir = secure_getenv ("TMPDIR"); + fd = tempfile_open (tempdir, &fname); +#ifdef __MINGW32__ + if (fd == -1) + { + char buffer[MAX_PATH + 1]; + DWORD ret; + ret = GetTempPath (MAX_PATH, buffer); + /* If we are not able to get a temp-directory, we use + current directory. */ + if (ret > MAX_PATH || !ret) + buffer[0] = 0; + else + buffer[ret] = 0; + tempdir = strdup (buffer); + fd = tempfile_open (tempdir, &fname); + } +#elif defined(__CYGWIN__) + if (fd == -1) + { + tempdir = secure_getenv ("TMP"); + fd = tempfile_open (tempdir, &fname); + } + if (fd == -1) + { + tempdir = secure_getenv ("TEMP"); + fd = tempfile_open (tempdir, &fname); + } +#endif + if (fd == -1) + fd = tempfile_open (P_tmpdir, &fname); + + opp->file = fname; + opp->file_len = strlen (fname); /* Don't include trailing nul */ return fd; } diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h index e7f5b711a51..051e2e85a1e 100644 --- a/libgfortran/libgfortran.h +++ b/libgfortran/libgfortran.h @@ -584,10 +584,6 @@ iexport_data_proto(filename); #define gfc_alloca(x) __builtin_alloca(x) -/* Directory for creating temporary files. Only used when none of the - following environment variables exist: GFORTRAN_TMPDIR, TMP and TEMP. */ -#define DEFAULT_TEMPDIR "/tmp" - /* The default value of record length for preconnected units is defined here. This value can be overriden by an environment variable. Default value is 1 Gb. */ @@ -776,6 +772,18 @@ internal_proto(show_variables); unit_convert get_unformatted_convert (int); internal_proto(get_unformatted_convert); +/* Secure getenv() which returns NULL if running as SUID/SGID. */ +#ifdef HAVE___SECURE_GETENV +#define secure_getenv __secure_getenv +#elif defined(HAVE_GETUID) && defined(HAVE_GETEUID) \ + && defined(HAVE_GETGID) && defined(HAVE_GETEGID) +#define FALLBACK_SECURE_GETENV +extern char *secure_getenv (const char *); +internal_proto(secure_getenv); +#else +#define secure_getenv getenv +#endif + /* string.c */ extern int find_option (st_parameter_common *, const char *, gfc_charlen_type, diff --git a/libgfortran/runtime/environ.c b/libgfortran/runtime/environ.c index 7782cee044c..bcb91f44613 100644 --- a/libgfortran/runtime/environ.c +++ b/libgfortran/runtime/environ.c @@ -56,6 +56,19 @@ variable; static void init_unformatted (variable *); + +#ifdef FALLBACK_SECURE_GETENV +char * +secure_getenv (const char *name) +{ + if ((getuid () == geteuid ()) && (getgid () == getegid ())) + return getenv (name); + else + return NULL; +} +#endif + + /* print_spaces()-- Print a particular number of spaces. */ static void @@ -285,9 +298,8 @@ static variable variable_table[] = { "Unit number that will be preconnected to standard error\n" "(No preconnection if negative)", 0}, - {"GFORTRAN_TMPDIR", 0, NULL, init_string, show_string, - "Directory for scratch files. Overrides the TMP environment variable\n" - "If TMP is not set " DEFAULT_TEMPDIR " is used.", 0}, + {"TMPDIR", 0, NULL, init_string, show_string, + "Directory for scratch files.", 0}, {"GFORTRAN_UNBUFFERED_ALL", 0, &options.all_unbuffered, init_boolean, show_boolean, diff --git a/libgfortran/runtime/main.c b/libgfortran/runtime/main.c index 79659e52bcd..72c32fc2e1b 100644 --- a/libgfortran/runtime/main.c +++ b/libgfortran/runtime/main.c @@ -163,7 +163,7 @@ find_addr2line (void) { #ifdef HAVE_ACCESS #define A2L_LEN 10 - char *path = getenv ("PATH"); + char *path = secure_getenv ("PATH"); if (!path) return; size_t n = strlen (path); -- 2.11.4.GIT