From 695771667c7736f3c69b74a6a3f344b36aff1e41 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 12 Jun 2017 13:20:42 -0400 Subject: [PATCH] lib/repo: Skip import via hardlink if repo owners don't match MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this, if one had repos of matching mode but different owners, which could happen if one e.g. makes a `bare` non-root repo in `/ostree/deploy/$stateroot/var/tmp`, every time we tried to call `linkat()` we'd get `EPERM` and fall back to a copy. Fix this by saving the repo owner uid, and avoid trying to call `linkat()` if we know it's going to fail. Of course most commonly in this scenario we'll immediately fail trying to `chown` the files to `0`, but this is prep for a future patch to improve `bare-user` → `bare-user-only` imports where we'll be a bit more sophisticated. Closes: #922 Approved by: alexlarsson --- src/libostree/ostree-repo-private.h | 1 + src/libostree/ostree-repo.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 55602940..6cbf9ebe 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -116,6 +116,7 @@ struct OstreeRepo { GHashTable *updated_uncompressed_dirs; GHashTable *object_sizes; + uid_t owner_uid; uid_t target_owner_uid; gid_t target_owner_gid; diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 1da06217..e43d4dcd 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -2092,6 +2092,7 @@ ostree_repo_open (OstreeRepo *self, if (fstat (self->objects_dir_fd, &stbuf) != 0) return glnx_throw_errno (error); + self->owner_uid = stbuf.st_uid; if (stbuf.st_uid != getuid () || stbuf.st_gid != getgid ()) { @@ -3168,8 +3169,14 @@ ostree_repo_import_object_from_with_trust (OstreeRepo *self, GCancellable *cancellable, GError **error) { - if (trusted && /* Don't hardlink into untrusted remotes */ - self->mode == source->mode) + /* We try to import via hardlink. If the remote is explicitly not trusted + * (i.e.) their checksums may be incorrect, we skip that. Also, we require the + * repository modes to match, as well as the owner uid (since we need to be + * able to make hardlinks). + */ + if (trusted && + self->mode == source->mode && + self->owner_uid == source->owner_uid) { gboolean hardlink_was_supported = FALSE;