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
This commit is contained in:
Colin Walters 2014-10-21 14:34:04 -04:00
parent a4d904ee38
commit 5fb8bb955e
3 changed files with 36 additions and 0 deletions

View File

@ -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)
{

View File

@ -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;

View File

@ -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))
{