lib/pull: Extend BAREUSERONLY_FILES flag to HTTP requests
authorColin Walters <walters@verbum.org>
Wed, 14 Jun 2017 21:55:11 +0000 (17:55 -0400)
committerAtomic Bot <atomic-devel@projectatomic.io>
Thu, 15 Jun 2017 07:10:22 +0000 (07:10 +0000)
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
tests/pull-test.sh

index 2e93f90b77f219b10c0938486689a8f287e2d9b1..704a68d22fc954a822bee19772fa6b7cc682e5fb 100644 (file)
@@ -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)
index f1ebca4cbafed02ccfa6f3572ae1e7c53e980ed8..9f74c0d8c0285c5605c71e658192203b66066435 100644 (file)
@@ -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 <<EOF
+2048 /some-setuid
+EOF
+echo asetuid > 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