From 9529e8d43579aaf6f6ebb90516385a89aaff34ff Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 14 Jun 2017 17:55:11 -0400 Subject: [PATCH] lib/pull: Extend BAREUSERONLY_FILES flag to HTTP requests For the flatpak PR: https://github.com/flatpak/flatpak/pull/849 It's really more convenient if this works for HTTP pulls as well, since flatpak does various types of pulling, and we can just set the flag everywhere. Further, we might as well reject the content as early as possible. Closes: #930 Approved by: alexlarsson --- src/libostree/ostree-repo-pull.c | 23 ++++++++++++-------- tests/pull-test.sh | 36 +++++++++++++++++++++++++------- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 2e93f90b..704a68d2 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -871,7 +871,12 @@ content_fetch_on_complete (GObject *object, checksum_obj = ostree_object_to_string (checksum, objtype); g_debug ("fetch of %s complete", checksum_obj); - if (pull_data->is_mirror && pull_data->repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2) + /* If we're mirroring and writing into an archive repo, we can directly copy + * the content rather than paying the cost of exploding it, checksumming, and + * re-gzip. + */ + if (pull_data->is_mirror && pull_data->repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 + && !pull_data->is_bareuseronly_files) { gboolean have_object; if (!ostree_repo_has_object (pull_data->repo, OSTREE_OBJECT_TYPE_FILE, checksum, @@ -903,16 +908,22 @@ content_fetch_on_complete (GObject *object, } /* Also, delete it now that we've opened it, we'll hold - * a reference to the fd. If we fail to write later, then + * a reference to the fd. If we fail to validate or write, then * the temp space will be cleaned up. */ (void) unlinkat (_ostree_fetcher_get_dfd (fetcher), temp_path, 0); + if (!validate_bareuseronly_mode (pull_data, + checksum, + g_file_info_get_attribute_uint32 (file_info, "unix::mode"), + error)) + goto out; + if (!ostree_raw_file_to_content_stream (file_in, file_info, xattrs, &object_input, &length, cancellable, error)) goto out; - + pull_data->n_outstanding_content_write_requests++; ostree_repo_write_content_async (pull_data->repo, checksum, object_input, length, @@ -3145,12 +3156,6 @@ ostree_repo_pull_with_options (OstreeRepo *self, pull_data->disable_static_deltas = TRUE; } - else if (pull_data->is_bareuseronly_files) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Can't use bareuseronly-files with non-local origin repo"); - goto out; - } /* We can't use static deltas if pulling into an archive-z2 repo. */ if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2) diff --git a/tests/pull-test.sh b/tests/pull-test.sh index f1ebca4c..9f74c0d8 100644 --- a/tests/pull-test.sh +++ b/tests/pull-test.sh @@ -35,7 +35,7 @@ function verify_initial_contents() { assert_file_has_content baz/cow '^moo$' } -echo "1..21" +echo "1..23" # Try both syntaxes repo_init --no-gpg-verify @@ -79,12 +79,34 @@ ${CMD_PREFIX} ostree --repo=mirrorrepo pull origin main ${CMD_PREFIX} ostree --repo=mirrorrepo fsck echo "ok pull (refuses deltas)" -if ${CMD_PREFIX} ostree --repo=mirrorrepo \ - pull origin main --bareuseronly-files 2>err.txt; then - assert_not_reached "--bareuseronly-files unexpectedly succeeded" -fi -assert_file_has_content err.txt 'bareuseronly-files with non-local' -echo "ok pull (refuses bareuseronly)" +cd ${test_tmpdir} +rm mirrorrepo/refs/remotes/* -rf +${CMD_PREFIX} ostree --repo=mirrorrepo prune --refs-only +${CMD_PREFIX} ostree --repo=mirrorrepo pull --bareuseronly-files origin main +echo "ok pull (bareuseronly, safe)" + +rm checkout-origin-main -rf +$OSTREE --repo=ostree-srv/gnomerepo checkout main checkout-origin-main +cat > statoverride.txt < checkout-origin-main/some-setuid +${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo commit -b content-with-suid --statoverride=statoverride.txt --tree=dir=checkout-origin-main +${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo summary -u +# Verify we reject it both when unpacking and when mirroring +for flag in "" "--mirror"; do + if ${CMD_PREFIX} ostree --repo=mirrorrepo pull ${flag} --bareuseronly-files origin content-with-suid 2>err.txt; then + assert_not_reached "pulled unsafe bareuseronly" + fi + assert_file_has_content err.txt 'object.*\.file: invalid mode.*with bits 040.*' +done +echo "ok pull (bareuseronly, unsafe)" + +cd ${test_tmpdir} +rm mirrorrepo/refs/remotes/* -rf +${CMD_PREFIX} ostree --repo=mirrorrepo prune --refs-only +${CMD_PREFIX} ostree --repo=mirrorrepo pull --mirror --bareuseronly-files origin main +echo "ok pull (bareuseronly mirror)" cd ${test_tmpdir} rm mirrorrepo/refs/remotes/* -rf