[ostree] checkout: Only fchown/fchmod directories after we're done populating them



commit b6704f8346c8f7392c69f30f0053800abc36fbc3
Author: Colin Walters <walters verbum org>
Date:   Thu Feb 27 11:19:33 2014 -0500

    checkout: Only fchown/fchmod directories after we're done populating them
    
    See https://mail.gnome.org/archives/ostree-list/2014-February/msg00020.html

 src/libostree/ostree-repo-checkout.c |   46 ++++++++++++++++++++++++---------
 1 files changed, 33 insertions(+), 13 deletions(-)
---
diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c
index eb7cf6e..a2a8b52 100644
--- a/src/libostree/ostree-repo-checkout.c
+++ b/src/libostree/ostree-repo-checkout.c
@@ -550,9 +550,12 @@ checkout_tree_at (OstreeRepo                        *self,
   gs_unref_variant GVariant *xattrs = NULL;
   gs_unref_object GFileEnumerator *dir_enum = NULL;
 
+  /* Create initially with mode 0700, then chown/chmod only when we're
+   * done.  This avoids anyone else being able to operate on partially
+   * constructed dirs.
+   */
   do
-    res = mkdirat (destination_parent_fd, destination_name,
-                   g_file_info_get_attribute_uint32 (source_info, "unix::mode"));
+    res = mkdirat (destination_parent_fd, destination_name, 0700);
   while (G_UNLIKELY (res == -1 && errno == EINTR));
   if (res == -1)
     {
@@ -569,19 +572,9 @@ checkout_tree_at (OstreeRepo                        *self,
                             cancellable, error))
     goto out;
 
+  /* Set the xattrs now, so any derived labeling works */
   if (!did_exist && mode != OSTREE_REPO_CHECKOUT_MODE_USER)
     {
-      do
-        res = fchown (destination_dfd,
-                      g_file_info_get_attribute_uint32 (source_info, "unix::uid"),
-                      g_file_info_get_attribute_uint32 (source_info, "unix::gid"));
-      while (G_UNLIKELY (res == -1 && errno == EINTR));
-      if (G_UNLIKELY (res == -1))
-        {
-          ot_util_set_error_from_errno (error, errno);
-          goto out;
-        }
-
       if (!ostree_repo_file_get_xattrs (source, &xattrs, NULL, error))
         goto out;
 
@@ -633,6 +626,33 @@ checkout_tree_at (OstreeRepo                        *self,
         }
     }
 
+  /* We do fchmod/fchown last so that no one else could access the
+   * partially created directory and change content we're laying out.
+   */
+  if (!did_exist && mode != OSTREE_REPO_CHECKOUT_MODE_USER)
+    {
+      do
+        res = fchmod (destination_dfd,
+                      g_file_info_get_attribute_uint32 (source_info, "unix::mode"));
+      while (G_UNLIKELY (res == -1 && errno == EINTR));
+      if (G_UNLIKELY (res == -1))
+        {
+          ot_util_set_error_from_errno (error, errno);
+          goto out;
+        }
+
+      do
+        res = fchown (destination_dfd,
+                      g_file_info_get_attribute_uint32 (source_info, "unix::uid"),
+                      g_file_info_get_attribute_uint32 (source_info, "unix::gid"));
+      while (G_UNLIKELY (res == -1 && errno == EINTR));
+      if (G_UNLIKELY (res == -1))
+        {
+          ot_util_set_error_from_errno (error, errno);
+          goto out;
+        }
+    }
+
   ret = TRUE;
  out:
   if (destination_dfd != -1)


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