[ostree] repo: When writing to a non-root owned repo, chown() objects to match



commit 5fb8bb955e2b762e0d462d0acd0924cb842f88ab
Author: Colin Walters <walters verbum org>
Date:   Tue Oct 21 14:34:04 2014 -0400

    repo: When writing to a non-root owned repo, chown() objects to match
    
    Some package systems need to be run as root, so the process linking to
    libostree may also be root.  However, it's reasonable to have the
    target repository be owned by a uid other than root.
    
    This patch makes it Just Work by chowning the file content to match.
    
    Note this only operates on archive-z2 repositories, because you can't
    usefully serve bare repositories via HTTP.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=738954

 src/libostree/ostree-repo-commit.c  |   16 ++++++++++++++++
 src/libostree/ostree-repo-private.h |    3 +++
 src/libostree/ostree-repo.c         |   17 +++++++++++++++++
 3 files changed, 36 insertions(+), 0 deletions(-)
---
diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c
index 68cff05..f76dcd6 100644
--- a/src/libostree/ostree-repo-commit.c
+++ b/src/libostree/ostree-repo-commit.c
@@ -72,6 +72,22 @@ commit_loose_object_trusted (OstreeRepo        *self,
 {
   gboolean ret = FALSE;
 
+  /* We may be writing as root to a non-root-owned repository; if so,
+   * automatically inherit the non-root ownership.
+   */
+  if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2
+      && self->target_owner_uid != -1) 
+    {
+      if (G_UNLIKELY (fchownat (self->tmp_dir_fd, temp_filename,
+                                self->target_owner_uid,
+                                self->target_owner_gid,
+                                AT_SYMLINK_NOFOLLOW) == -1))
+        {
+          ot_util_set_error_from_errno (error, errno);
+          goto out;
+        }
+    }
+
   /* Special handling for symlinks in bare repositories */
   if (is_symlink && self->mode == OSTREE_REPO_MODE_BARE)
     {
diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h
index ad512f9..e893c4f 100644
--- a/src/libostree/ostree-repo-private.h
+++ b/src/libostree/ostree-repo-private.h
@@ -65,6 +65,9 @@ struct OstreeRepo {
   GHashTable *updated_uncompressed_dirs;
   GHashTable *object_sizes;
 
+  uid_t target_owner_uid;
+  gid_t target_owner_gid;
+
   GKeyFile *config;
   OstreeRepoMode mode;
   gboolean enable_uncompressed_cache;
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 4887e8d..9861755 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -819,6 +819,7 @@ ostree_repo_open (OstreeRepo    *self,
 {
   gboolean ret = FALSE;
   gboolean is_archive;
+  struct stat stbuf;
   gs_free char *version = NULL;
   gs_free char *mode = NULL;
   gs_free char *parent_repo_path = NULL;
@@ -836,6 +837,22 @@ ostree_repo_open (OstreeRepo    *self,
 
   self->writable = faccessat (AT_FDCWD, gs_file_get_path_cached (self->objects_dir), W_OK, 0) == 0;
 
+  if (fstat (self->objects_dir_fd, &stbuf) != 0)
+    {
+      ot_util_set_error_from_errno (error, errno);
+      goto out;
+    }
+
+  if (stbuf.st_uid != getuid () || stbuf.st_gid != getgid ())
+    {
+      self->target_owner_uid = stbuf.st_uid;
+      self->target_owner_gid = stbuf.st_gid;
+    }
+  else
+    {
+      self->target_owner_uid = self->target_owner_gid = -1;
+    }
+
   self->config = g_key_file_new ();
   if (!g_key_file_load_from_file (self->config, gs_file_get_path_cached (self->config_file), 0, error))
     {


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