[libglnx] fdio: Ensure O_TMPFILE is mode 0600



commit 452c371ff30e9c54cf9a0bcee421d4415085e8d9
Author: Colin Walters <walters verbum org>
Date:   Sun Jul 9 21:30:14 2017 -0400

    fdio: Ensure O_TMPFILE is mode 0600
    
    Work around an older glibc bug.

 glnx-fdio.c               |   17 +++++++++++------
 tests/test-libglnx-fdio.c |   24 ++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 6 deletions(-)
---
diff --git a/glnx-fdio.c b/glnx-fdio.c
index c8da35e..09aa87f 100644
--- a/glnx-fdio.c
+++ b/glnx-fdio.c
@@ -169,13 +169,12 @@ glnx_tmpfile_clear (GLnxTmpfile *tmpf)
   tmpf->initialized = FALSE;
 }
 
-/* Allocate a temporary file, using Linux O_TMPFILE if available.
+/* Allocate a temporary file, using Linux O_TMPFILE if available. The file mode
+ * will be 0600.
+ *
  * The result will be stored in @out_tmpf, which is caller allocated
  * so you can store it on the stack in common scenarios.
  *
- * Note that with O_TMPFILE, the file mode will be `000`; you likely
- * want to chmod it before calling glnx_link_tmpfile_at().
- *
  * The directory fd @dfd must live at least as long as the output @out_tmpf.
  */
 gboolean
@@ -185,6 +184,7 @@ glnx_open_tmpfile_linkable_at (int dfd,
                                GLnxTmpfile *out_tmpf,
                                GError **error)
 {
+  const guint mode = 0600;
   glnx_fd_close int fd = -1;
   int count;
 
@@ -200,11 +200,16 @@ glnx_open_tmpfile_linkable_at (int dfd,
    * link_tmpfile() below to rename the result after writing the file
    * in full. */
 #if defined(O_TMPFILE) && !defined(DISABLE_OTMPFILE) && !defined(ENABLE_WRPSEUDO_COMPAT)
-  fd = openat (dfd, subpath, O_TMPFILE|flags, 0600);
+  fd = openat (dfd, subpath, O_TMPFILE|flags, mode);
   if (fd == -1 && !(G_IN_SET(errno, ENOSYS, EISDIR, EOPNOTSUPP)))
     return glnx_throw_errno_prefix (error, "open(O_TMPFILE)");
   if (fd != -1)
     {
+      /* Workaround for https://sourceware.org/bugzilla/show_bug.cgi?id=17523
+       * See also https://github.com/ostreedev/ostree/issues/991
+       */
+      if (fchmod (fd, mode) < 0)
+        return glnx_throw_errno_prefix (error, "fchmod");
       out_tmpf->initialized = TRUE;
       out_tmpf->src_dfd = dfd; /* Copied; caller must keep open */
       out_tmpf->fd = glnx_steal_fd (&fd);
@@ -221,7 +226,7 @@ glnx_open_tmpfile_linkable_at (int dfd,
       {
         glnx_gen_temp_name (tmp);
 
-        fd = openat (dfd, tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, 0600);
+        fd = openat (dfd, tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, mode);
         if (fd < 0)
           {
             if (errno == EEXIST)
diff --git a/tests/test-libglnx-fdio.c b/tests/test-libglnx-fdio.c
index 311e7f0..cee7cb6 100644
--- a/tests/test-libglnx-fdio.c
+++ b/tests/test-libglnx-fdio.c
@@ -137,12 +137,36 @@ test_renameat2_exchange (void)
   g_assert_no_error (local_error);
 }
 
+static void
+test_tmpfile (void)
+{
+  g_autoptr(GError) local_error = NULL;
+  GError **error = &local_error;
+  g_auto(GLnxTmpfile) tmpf = { 0, };
+
+  if (!glnx_open_tmpfile_linkable_at (AT_FDCWD, ".", O_WRONLY|O_CLOEXEC, &tmpf, error))
+    goto out;
+
+  if (glnx_loop_write (tmpf.fd, "foo", strlen ("foo")) < 0)
+    {
+      (void)glnx_throw_errno_prefix (error, "write");
+      goto out;
+    }
+
+  if (glnx_link_tmpfile_at (&tmpf, GLNX_LINK_TMPFILE_NOREPLACE, AT_FDCWD, "foo", error))
+    goto out;
+
+ out:
+  g_assert_no_error (local_error);
+}
+
 int main (int argc, char **argv)
 {
   int ret;
 
   g_test_init (&argc, &argv, NULL);
 
+  g_test_add_func ("/tmpfile", test_tmpfile);
   g_test_add_func ("/renameat2-noreplace", test_renameat2_noreplace);
   g_test_add_func ("/renameat2-exchange", test_renameat2_exchange);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]