From 6364b03729c2cdec8d7e6bf2b389b3385770b8ac Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 29 Jun 2023 02:42:04 -0400 Subject: [PATCH] fetcher: Always open tmpfiles in repo (except on FUSE) This reverts commit 4e61e6f7d0d6aebd6abcdc455ec53164afe39e8d and re-instates the fix for ensuring that we download temporary files into the repository location. However in order to ensure we don't re-introduce https://github.com/ostreedev/ostree/issues/2900 we detect the case where we're writing to a FUSE mount and keep the prior behavior. I've verified that this works with flatpak. Note a downside of this is the change needs to be triplicated across the 3 http backends. This then again Closes: https://github.com/ostreedev/ostree/issues/2571 --- src/libostree/ostree-fetcher-curl.c | 21 ++++++++++++++------- src/libostree/ostree-fetcher-soup.c | 18 +++++++++++++++--- src/libostree/ostree-fetcher-soup3.c | 16 ++++++++++++++-- src/libostree/ostree-fetcher-util.h | 11 ++--------- src/libostree/ostree-fetcher.h | 2 ++ src/libostree/ostree-repo-private.h | 1 + src/libostree/ostree-repo-pull.c | 2 ++ src/libostree/ostree-repo.c | 11 +++++++++++ 8 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/libostree/ostree-fetcher-curl.c b/src/libostree/ostree-fetcher-curl.c index 9d07e5e10c..be88c4ef9f 100644 --- a/src/libostree/ostree-fetcher-curl.c +++ b/src/libostree/ostree-fetcher-curl.c @@ -24,6 +24,7 @@ #include #include #include +#include /* These macros came from 7.43.0, but we want to check * for versions a bit earlier than that (to work on CentOS 7), @@ -76,6 +77,7 @@ struct OstreeFetcher char *proxy; struct curl_slist *extra_headers; int tmpdir_dfd; + bool force_anonymous; char *custom_user_agent; GMainContext *mainctx; @@ -250,6 +252,12 @@ _ostree_fetcher_new (int tmpdir_dfd, const char *remote_name, OstreeFetcherConfi return fetcher; } +void +_ostree_fetcher_set_force_anonymous_tmpfiles (OstreeFetcher *self) +{ + self->force_anonymous = true; +} + static void destroy_and_unref_source (GSource *source) { @@ -271,13 +279,12 @@ request_get_uri (FetcherRequest *req, GUri *baseuri) static gboolean ensure_tmpfile (FetcherRequest *req, GError **error) { - if (!req->tmpf.initialized) - { - if (!_ostree_fetcher_tmpf_from_flags (req->flags, req->fetcher->tmpdir_dfd, &req->tmpf, - error)) - return FALSE; - } - return TRUE; + if (req->tmpf.initialized) + return TRUE; + if (req->fetcher->force_anonymous) + return glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, &req->tmpf, error); + else + return _ostree_fetcher_tmpf (req->fetcher->tmpdir_dfd, &req->tmpf, error); } /* Check for completed transfers, and remove their easy handles */ diff --git a/src/libostree/ostree-fetcher-soup.c b/src/libostree/ostree-fetcher-soup.c index dbba2f002c..629065fffe 100644 --- a/src/libostree/ostree-fetcher-soup.c +++ b/src/libostree/ostree-fetcher-soup.c @@ -25,6 +25,7 @@ #include #include #include +#include #define LIBSOUP_USE_UNSTABLE_REQUEST_API #include #include @@ -59,6 +60,7 @@ typedef struct char *remote_name; int base_tmpdir_dfd; + bool force_anonymous; GVariant *extra_headers; gboolean transfer_gzip; @@ -681,6 +683,12 @@ _ostree_fetcher_new (int tmpdir_dfd, const char *remote_name, OstreeFetcherConfi return self; } +void +_ostree_fetcher_set_force_anonymous_tmpfiles (OstreeFetcher *self) +{ + self->thread_closure->force_anonymous = true; +} + int _ostree_fetcher_get_dfd (OstreeFetcher *fetcher) { @@ -888,9 +896,13 @@ on_stream_read (GObject *object, GAsyncResult *result, gpointer user_data) { if (!pending->is_membuf) { - if (!_ostree_fetcher_tmpf_from_flags (pending->flags, - pending->thread_closure->base_tmpdir_dfd, - &pending->tmpf, &local_error)) + if (pending->thread_closure->force_anonymous) + { + if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, &pending->tmpf, &local_error)) + goto out; + } + else if (!_ostree_fetcher_tmpf (pending->thread_closure->base_tmpdir_dfd, &pending->tmpf, + &local_error)) goto out; pending->out_stream = g_unix_output_stream_new (pending->tmpf.fd, FALSE); } diff --git a/src/libostree/ostree-fetcher-soup3.c b/src/libostree/ostree-fetcher-soup3.c index f6ada17abf..e7a9ab05b3 100644 --- a/src/libostree/ostree-fetcher-soup3.c +++ b/src/libostree/ostree-fetcher-soup3.c @@ -72,6 +72,7 @@ struct OstreeFetcher OstreeFetcherConfigFlags config_flags; char *remote_name; int tmpdir_dfd; + bool force_anonymous; GHashTable *sessions; /* (element-type GMainContext SoupSession ) */ GProxyResolver *proxy_resolver; @@ -292,6 +293,12 @@ _ostree_fetcher_new (int tmpdir_dfd, const char *remote_name, OstreeFetcherConfi return self; } +void +_ostree_fetcher_set_force_anonymous_tmpfiles (OstreeFetcher *self) +{ + self->thread_closure->force_anonymous = true; +} + int _ostree_fetcher_get_dfd (OstreeFetcher *self) { @@ -448,8 +455,13 @@ on_stream_read (GObject *object, GAsyncResult *result, gpointer user_data) { if (!request->is_membuf) { - if (!_ostree_fetcher_tmpf_from_flags (request->flags, request->fetcher->tmpdir_dfd, - &request->tmpf, &local_error)) + if (pending->thread_closure->force_anonymous) + { + if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, &pending->tmpf, &local_error)) + goto out; + } + else if (!_ostree_fetcher_tmpf (request->fetcher->tmpdir_dfd, &request->tmpf, + &local_error)) { g_task_return_error (task, local_error); return; diff --git a/src/libostree/ostree-fetcher-util.h b/src/libostree/ostree-fetcher-util.h index c3243801ce..97233e1f33 100644 --- a/src/libostree/ostree-fetcher-util.h +++ b/src/libostree/ostree-fetcher-util.h @@ -32,17 +32,10 @@ G_BEGIN_DECLS #define OSTREE_FETCHER_USERAGENT_STRING (PACKAGE_NAME "/" PACKAGE_VERSION) static inline gboolean -_ostree_fetcher_tmpf_from_flags (OstreeFetcherRequestFlags flags, int dfd, GLnxTmpfile *tmpf, - GError **error) +_ostree_fetcher_tmpf (int dfd, GLnxTmpfile *tmpf, GError **error) { - if ((flags & OSTREE_FETCHER_REQUEST_LINKABLE) > 0) - { - if (!glnx_open_tmpfile_linkable_at (dfd, ".", O_RDWR | O_CLOEXEC, tmpf, error)) - return FALSE; - } - else if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, tmpf, error)) + if (!glnx_open_tmpfile_linkable_at (dfd, ".", O_RDWR | O_CLOEXEC, tmpf, error)) return FALSE; - if (!glnx_fchmod (tmpf->fd, 0644, error)) return FALSE; return TRUE; diff --git a/src/libostree/ostree-fetcher.h b/src/libostree/ostree-fetcher.h index 42ff3a17d3..6a555e0962 100644 --- a/src/libostree/ostree-fetcher.h +++ b/src/libostree/ostree-fetcher.h @@ -88,6 +88,8 @@ GType _ostree_fetcher_get_type (void) G_GNUC_CONST; OstreeFetcher *_ostree_fetcher_new (int tmpdir_dfd, const char *remote_name, OstreeFetcherConfigFlags flags); +void _ostree_fetcher_set_force_anonymous_tmpfiles (OstreeFetcher *fetcher); + int _ostree_fetcher_get_dfd (OstreeFetcher *fetcher); void _ostree_fetcher_set_cookie_jar (OstreeFetcher *self, const char *jar_path); diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 6d3f21e61f..d8ca057ddb 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -193,6 +193,7 @@ struct OstreeRepo gboolean inited; gboolean writable; + gboolean is_on_fuse; /* TRUE if the repository is on a FUSE filesystem */ OstreeRepoSysrootKind sysroot_kind; GError *writable_error; gboolean in_transaction; diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 6d69d79ee5..2ad9215aa2 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -2966,6 +2966,8 @@ _ostree_repo_remote_new_fetcher (OstreeRepo *self, const char *remote_name, gboo } fetcher = _ostree_fetcher_new (self->tmp_dir_fd, remote_name, fetcher_flags); + if (self->is_on_fuse) + _ostree_fetcher_set_force_anonymous_tmpfiles (fetcher); { g_autofree char *tls_client_cert_path = NULL; diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 8633701f40..fc15cb7873 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -3426,6 +3426,17 @@ ostree_repo_open (OstreeRepo *self, GCancellable *cancellable, GError **error) /* Note - we don't return this error yet! */ } + { + struct statfs fsstbuf; + if (fstatfs (self->repo_dir_fd, &fsstbuf) < 0) + return glnx_throw_errno_prefix (error, "fstatfs"); +#ifndef FUSE_SUPER_MAGIC +#define FUSE_SUPER_MAGIC 0x65735546 +#endif + self->is_on_fuse = (fsstbuf.f_type == FUSE_SUPER_MAGIC); + g_debug ("using fuse: %d", self->is_on_fuse); + } + if (!glnx_fstat (self->objects_dir_fd, &stbuf, error)) return FALSE; self->owner_uid = stbuf.st_uid;