summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMickaël Salaün <mic@digikod.net>2014-05-11 22:54:58 +0200
committerMickaël Salaün <mic@digikod.net>2014-05-19 23:11:33 +0200
commit8daeed9570af72eb135c8ded460d2888f05b2e68 (patch)
tree58cd5ee246f071d45c8e16a255f18bd6d9455674
parent0403f332b1f478696c30d3d8a0e2f6eef24aaf88 (diff)
downloadlibffi-8daeed9570af72eb135c8ded460d2888f05b2e68.tar.gz
closures: Create temporary file with O_TMPFILE and O_CLOEXEC when available
The open_temp_exec_file_dir function can create a temporary file without file system accessible link. If the O_TMPFILE flag is not defined (old Linux kernel or libc) the behavior is unchanged. The open_temp_exec_file_name function now need a new argument "flags" (like O_CLOEXEC) used for temporary file creation. The O_TMPFILE flag allow temporary file creation without race condition. This feature/fix prevent another process to access the (future) executable file from the file system. The O_CLOEXEC flag automatically close the temporary file for any execve. This avoid transmitting (executable) file descriptor to a child process.
-rw-r--r--src/closures.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/src/closures.c b/src/closures.c
index c7863f3..9799ce6 100644
--- a/src/closures.c
+++ b/src/closures.c
@@ -265,9 +265,9 @@ static size_t execsize = 0;
/* Open a temporary file name, and immediately unlink it. */
static int
-open_temp_exec_file_name (char *name)
+open_temp_exec_file_name (char *name, int flags)
{
- int fd = mkstemp (name);
+ int fd = mkostemp (name, flags);
if (fd != -1)
unlink (name);
@@ -280,8 +280,27 @@ static int
open_temp_exec_file_dir (const char *dir)
{
static const char suffix[] = "/ffiXXXXXX";
- size_t lendir = strlen (dir);
- char *tempname = __builtin_alloca (lendir + sizeof (suffix));
+ int lendir, flags, fd;
+ char *tempname;
+
+#ifdef O_CLOEXEC
+ flags = O_CLOEXEC;
+#else
+ flags = 0;
+#endif
+
+#ifdef O_TMPFILE
+ fd = open (dir, flags | O_RDWR | O_EXCL | O_TMPFILE, 0700);
+ /* If the running system does not support the O_TMPFILE flag then retry without it. */
+ if (fd != -1 || (errno != EINVAL && errno != EISDIR && errno != EOPNOTSUPP)) {
+ return fd;
+ } else {
+ errno = 0;
+ }
+#endif
+
+ lendir = strlen (dir);
+ tempname = __builtin_alloca (lendir + sizeof (suffix));
if (!tempname)
return -1;
@@ -289,7 +308,7 @@ open_temp_exec_file_dir (const char *dir)
memcpy (tempname, dir, lendir);
memcpy (tempname + lendir, suffix, sizeof (suffix));
- return open_temp_exec_file_name (tempname);
+ return open_temp_exec_file_name (tempname, flags);
}
/* Open a temporary file in the directory in the named environment