diff options
-rw-r--r-- | newlib/ChangeLog | 5 | ||||
-rw-r--r-- | newlib/libc/stdio/tmpfile.c | 22 | ||||
-rw-r--r-- | newlib/libc/stdio64/tmpfile64.c | 23 |
3 files changed, 43 insertions, 7 deletions
diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 699dbd4..17a8a42 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,5 +1,10 @@ 2007-05-16 Eric Blake <ebb9@byu.net> + Close security hole in tmpfile. + * libc/stdio/tmpfile.c (_tmpfile_r): Avoid window between filename + generation and opening the fd. + * libc/stdio64/tmpfile64.c (_tmpfile64_r): Likewise. + * libc/include/math.h (INFINITY, NAN, FP_ILOGB0, FP_ILOGBNAN) (MATH_ERRNO, MATH_ERREXCEPT, math_errhandling): Add macros required by POSIX. diff --git a/newlib/libc/stdio/tmpfile.c b/newlib/libc/stdio/tmpfile.c index a6c2c91..902ef0b 100644 --- a/newlib/libc/stdio/tmpfile.c +++ b/newlib/libc/stdio/tmpfile.c @@ -49,6 +49,11 @@ Supporting OS subroutines required: <<close>>, <<fstat>>, <<getpid>>, #include <reent.h> #include <stdio.h> #include <errno.h> +#include <fcntl.h> + +#ifndef O_BINARY +# define O_BINARY 0 +#endif FILE * _DEFUN(_tmpfile_r, (ptr), @@ -58,11 +63,22 @@ _DEFUN(_tmpfile_r, (ptr), int e; char *f; char buf[L_tmpnam]; - - if ((f = _tmpnam_r (ptr, buf)) == NULL) + int fd; + + do + { + if ((f = _tmpnam_r (ptr, buf)) == NULL) + return NULL; + fd = _open_r (ptr, f, O_RDWR | O_CREAT | O_EXCL | O_BINARY, + S_IRUSR | S_IWUSR); + } + while (fd < 0 && ptr->_errno == EEXIST); + if (fd < 0) return NULL; - fp = _fopen_r (ptr, f, "wb+"); + fp = _fdopen_r (ptr, fd, "wb+"); e = ptr->_errno; + if (!fp) + _close_r (ptr, fd); _CAST_VOID _remove_r (ptr, f); ptr->_errno = e; return fp; diff --git a/newlib/libc/stdio64/tmpfile64.c b/newlib/libc/stdio64/tmpfile64.c index 9868963..e15f1c6 100644 --- a/newlib/libc/stdio64/tmpfile64.c +++ b/newlib/libc/stdio64/tmpfile64.c @@ -49,6 +49,11 @@ Supporting OS subroutines required: <<close>>, <<fstat>>, <<getpid>>, #include <stdio.h> #include <errno.h> +#include <fcntl.h> + +#ifndef O_BINARY +# define O_BINARY 0 +#endif #ifdef __LARGE64_FILES @@ -60,11 +65,22 @@ _DEFUN (_tmpfile64_r, (ptr), int e; char *f; char buf[L_tmpnam]; - - if ((f = _tmpnam_r (ptr, buf)) == NULL) + int fd; + + do + { + if ((f = _tmpnam_r (ptr, buf)) == NULL) + return NULL; + fd = _open64_r (ptr, f, O_RDWR | O_CREAT | O_EXCL | O_BINARY, + S_IRUSR | S_IWUSR); + } + while (fd < 0 && ptr->_errno == EEXIST); + if (fd < 0) return NULL; - fp = _fopen64_r (ptr, (const char *)f, "wb+"); + fp = _fdopen64_r (ptr, fd, "wb+"); e = ptr->_errno; + if (!fp) + _close_r (ptr, fd); _CAST_VOID _remove_r (ptr, f); ptr->_errno = e; return fp; @@ -81,4 +97,3 @@ _DEFUN_VOID (tmpfile64) #endif #endif /* __LARGE64_FILES */ - |