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