From: <and...@us...> - 2013-11-14 23:04:59
|
Revision: 12699 http://sourceforge.net/p/plplot/code/12699 Author: andrewross Date: 2013-11-14 23:04:56 +0000 (Thu, 14 Nov 2013) Log Message: ----------- Update the way the tk driver creates fifos to avoid GNU linker complaining about use of the insecure tmpnam. Instead we now use mkdtemp to securely create a private temporary directory, then create the fifo in that. This avoids potential race conditions. Modified Paths: -------------- trunk/cmake/modules/plplot.cmake trunk/config.h.in trunk/drivers/tk.c trunk/include/plplotP.h trunk/src/plstdio.c Modified: trunk/cmake/modules/plplot.cmake =================================================================== --- trunk/cmake/modules/plplot.cmake 2013-11-14 21:32:36 UTC (rev 12698) +++ trunk/cmake/modules/plplot.cmake 2013-11-14 23:04:56 UTC (rev 12699) @@ -253,6 +253,8 @@ check_function_exists(popen HAVE_POPEN) check_function_exists(usleep PL_HAVE_USLEEP) check_function_exists(mkstemp PL_HAVE_MKSTEMP) +check_function_exists(mkdtemp PL_HAVE_MKDTEMP) +check_function_exists(mkfifo PL_HAVE_MKFIFO) check_function_exists(unlink PL_HAVE_UNLINK) check_function_exists(_NSGetArgc HAVE_NSGETARGC) Modified: trunk/config.h.in =================================================================== --- trunk/config.h.in 2013-11-14 21:32:36 UTC (rev 12698) +++ trunk/config.h.in 2013-11-14 23:04:56 UTC (rev 12699) @@ -109,6 +109,12 @@ // Define to 1 if the function mkstemp is available. #cmakedefine PL_HAVE_MKSTEMP 1 +// Define to 1 if the function mkdtemp is available. +#cmakedefine PL_HAVE_MKDTEMP 1 + +// Define to 1 if the function mkfifo is available. +#cmakedefine PL_HAVE_MKFIFO 1 + // Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. #cmakedefine HAVE_NDIR_H 1 Modified: trunk/drivers/tk.c =================================================================== --- trunk/drivers/tk.c 2013-11-14 21:32:36 UTC (rev 12698) +++ trunk/drivers/tk.c 2013-11-14 23:04:56 UTC (rev 12699) @@ -1521,6 +1521,7 @@ TkDev *dev = (TkDev *) pls->dev; PLiodev *iodev = (PLiodev *) dev->iodev; size_t bufmax = (size_t) ( pls->bufmax * 1.2 ); + char *dirname = NULL; dbug_enter( "link_init" ); @@ -1528,11 +1529,11 @@ if ( !pls->dp ) { - // This of tmpnam should (?) be safe since mkfifo - // will fail if the filename already exists - iodev->fileName = (char *) tmpnam( NULL ); - if ( mkfifo( iodev->fileName, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) < 0 ) + // This uses the pl_create_tempfifo function to create + // the fifo in a safe manner by first creating a private + // temporary directory. + iodev->fileName = pl_create_tempfifo( (char **) &iodev->fileName, &dirname ); + if ( dirname == NULL || iodev->fileName == NULL ) abort_session( pls, "mkfifo error" ); // Tell plframe widget to open FIFO (for reading). @@ -1555,8 +1556,10 @@ // Unlink FIFO so that it isn't left around if program crashes. // This also ensures no other program can mess with it. - if ( unlink( iodev->fileName ) == -1 ) + if ( unlink( iodev->fileName) == -1 ) abort_session( pls, "Error removing fifo" ); + if ( rmdir( dirname ) == -1 ) + abort_session( pls, "Error removing temporary directory" ); } // Create socket for data transfer to the plframe widget Modified: trunk/include/plplotP.h =================================================================== --- trunk/include/plplotP.h 2013-11-14 21:32:36 UTC (rev 12698) +++ trunk/include/plplotP.h 2013-11-14 23:04:56 UTC (rev 12699) @@ -1227,6 +1227,10 @@ PLDLLIMPEXP FILE * pl_create_tempfile( char **fname ); +// Create a temporary fifo securely +PLDLLIMPEXP char * +pl_create_tempfifo( char **p_fifoname, char **p_dirname ); + #ifdef __cplusplus } #endif Modified: trunk/src/plstdio.c =================================================================== --- trunk/src/plstdio.c 2013-11-14 21:32:36 UTC (rev 12698) +++ trunk/src/plstdio.c 2013-11-14 23:04:56 UTC (rev 12699) @@ -27,10 +27,12 @@ #if defined ( MSDOS ) || defined ( WIN32 ) #include <sys/types.h> -#include <sys/stat.h> #include <fcntl.h> #endif +// This is needed for mode flags for mkfifo as well sa for MSDOS / WIN32 +#include <sys/stat.h> + // For Visual C++ 2005 and later mktemp() and open() are deprecated (see // http://msdn.microsoft.com/en-us/library/ms235413.aspx and // http://msdn.microsoft.com/en-us/library/ms235491.aspx). mktemp() @@ -254,3 +256,91 @@ return fd; } +// +// pl_create_tempfifo() +// +// Securely create a temporary fifo and return the file name. +// This only works on POSIX compliant platforms at the moment. +// It creates a secure directory first using mkdtemp, then +// creates the named fifo in this directory. The combination of +// a private directory and mkfifo failing if the file name already exists +// makes this secure against race conditions / DoS attacks. This function +// includes additional functionality over mkdtemp in that it honours the +// TMP / TMPDIR / TEMP environment variables. +// +// The function returns the file name of the fifo. +// +char * +pl_create_tempfifo( char **p_fifoname, char **p_dirname ) +{ +#if !defined PL_HAVE_MKDTEMP || !defined PL_HAVE_MKFIFO + plwarn("Creating fifos not supported on this platform"); + return NULL; +#else + FILE *fd; + const char *tmpdir; + char *template; + char *dirname; + const char *tmpname = "plplot_dir_XXXXXX"; + const char *fifoname = "plplot_fifo"; + int flags; + +#if defined ( MSDOS ) || defined ( WIN32 ) + tmpdir = getenv( "TEMP" ); +#else + tmpdir = getenv( "TMPDIR" ); +#endif + +// The P_TMPDIR macro is defined in stdio.h on many UNIX systems - try that +#ifdef P_TMPDIR + if ( tmpdir == NULL ) + tmpdir = P_TMPDIR; +#endif + + if ( tmpdir == NULL ) + { +#if defined ( MSDOS ) || defined ( WIN32 ) + tmpdir = "c:\\windows\\Temp"; +#else + tmpdir = "/tmp"; +#endif + } + + // N.B. Malloc ensures template is long enough so strcpy and strcat are safe here + dirname = (char *) malloc( sizeof ( char ) * ( strlen( tmpdir ) + strlen( tmpname ) + 2 ) ); + strcpy( dirname, tmpdir ); +#if defined ( MSDOS ) || defined ( WIN32 ) + strcat( dirname, "\\" ); +#else + strcat( dirname, "/" ); +#endif + strcat( dirname, tmpname ); + // Create the temporary directory + dirname = mkdtemp( dirname ); + *p_dirname = dirname; + + // Now create the fifo in the directory + template = (char *) malloc( sizeof ( char ) * ( strlen( tmpdir ) + strlen( tmpname ) + strlen(fifoname) + 4 ) ); + strcpy( template, dirname ); +#if defined ( MSDOS ) || defined ( WIN32 ) + strcat( template, "\\" ); +#else + strcat( template, "/" ); +#endif + strcat( template, fifoname ); + *p_fifoname = template; + + // Check that mkfifo succeeds safely + if ( mkfifo( template, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) < 0 ) { + plwarn( "mkfifo error" ); + free( template ); + *p_fifoname = NULL; + free( dirname ); + *p_dirname = NULL; + return NULL; + } + + return template; +#endif +} + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |