diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 68cff05d..f76dcd66 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 ad512f98..e893c4f8 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 4887e8d1..98617552 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)) {