|
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.
|