diff --git a/pressure-vessel/runtime.c b/pressure-vessel/runtime.c
index 24288f09fd405b0f9dc9229b189f4e3a8ebb1d46..90ed82324f594c9be3c87923bf9fe09c1faedd1e 100644
--- a/pressure-vessel/runtime.c
+++ b/pressure-vessel/runtime.c
@@ -2084,8 +2084,8 @@ pv_runtime_take_from_provider (PvRuntime *self,
           if (flags & TAKE_FROM_PROVIDER_FLAGS_COPY_FALLBACK)
             {
               glnx_autofd int file_fd = -1;
+              glnx_autofd int dest_fd = -1;
               glnx_autofd int sysroot_fd = -1;
-              struct stat stat_buf;
 
               if (!glnx_opendirat (-1, self->provider_in_current_namespace,
                                    FALSE, &sysroot_fd, error))
@@ -2095,22 +2095,36 @@ pv_runtime_take_from_provider (PvRuntime *self,
                                                  SRT_RESOLVE_FLAGS_READABLE,
                                                  NULL, error);
               if (file_fd < 0)
-                return FALSE;
-
-              if (fstat (file_fd, &stat_buf) != 0)
                 {
-                  return glnx_throw_errno_prefix (error,
-                                                  "An error occurred using fstat for %s",
-                                                  source_in_provider);
+                  g_prefix_error (error,
+                                  "Unable to make \"%s\" available in container: ",
+                                  source_in_provider);
+                  return FALSE;
                 }
 
-              g_autofree gchar *proc_fd = g_strdup_printf ("/proc/self/fd/%d", file_fd);
+              /* We already deleted ${parent_dirfd}/${base}, and we don't
+               * care about atomicity or durability here, so we can just
+               * write in-place. The permissions are uninteresting because
+               * we're not expecting other users to read this temporary
+               * sysroot anyway, so use 0600 just in case the source file
+               * has restrictive permissions. */
+              dest_fd = TEMP_FAILURE_RETRY (openat (parent_dirfd, base,
+                                                    O_WRONLY|O_CLOEXEC|O_NOCTTY|O_CREAT|O_EXCL,
+                                                    0600));
+
+              if (dest_fd < 0)
+                return glnx_throw_errno_prefix (error,
+                                                "Unable to open \"%s\" for writing",
+                                                dest_in_container);
 
+              if (glnx_regfile_copy_bytes (file_fd, dest_fd, (off_t) -1) < 0)
+                return glnx_throw_errno_prefix (error,
+                                                "Unable to copy contents of \"%s/%s\" to \"%s\"",
+                                                self->provider_in_current_namespace,
+                                                source_in_provider,
+                                                dest_in_container);
 
-              return glnx_file_copy_at (AT_FDCWD, proc_fd, &stat_buf,
-                                        parent_dirfd, base,
-                                        GLNX_FILE_COPY_OVERWRITE,
-                                        NULL, error);
+              return TRUE;
             }
           else
             {
@@ -2461,9 +2475,11 @@ pv_runtime_take_ld_so_from_provider (PvRuntime *self,
                                      &ld_so_relative_to_provider, error);
 
   if (path_fd < 0)
-    return glnx_throw_errno_prefix (error,
-                                    "Unable to determine provider path to %s",
-                                    arch->ld_so);
+    {
+      g_prefix_error (error, "Unable to determine provider path to %s: ",
+                      arch->ld_so);
+      return FALSE;
+    }
 
   ld_so_in_provider = g_build_filename (self->provider_in_host_namespace,
                                         ld_so_relative_to_provider, NULL);
diff --git a/steam-runtime-tools/resolve-in-sysroot.c b/steam-runtime-tools/resolve-in-sysroot.c
index 21965157ee34bc16262527ab77dfc6487fe2496e..c4dbb581d213483b9f20993ba2e05e7870ecbdba 100644
--- a/steam-runtime-tools/resolve-in-sysroot.c
+++ b/steam-runtime-tools/resolve-in-sysroot.c
@@ -313,12 +313,20 @@ _srt_resolve_in_sysroot (int sysroot,
       if (flags & SRT_RESOLVE_FLAGS_DIRECTORY)
         {
           if (!glnx_opendirat (-1, proc_fd_name, TRUE, &fd, error))
-            return -1;
+            {
+              g_prefix_error (error, "Unable to open \"%s\" as directory: ",
+                              current_path->str);
+              return -1;
+            }
         }
       else
         {
           if (!glnx_openat_rdonly (-1, proc_fd_name, TRUE, &fd, error))
-            return -1;
+            {
+              g_prefix_error (error, "Unable to open \"%s\": ",
+                              current_path->str);
+              return -1;
+            }
         }
 
       if (real_path_out != NULL)
diff --git a/tests/pressure-vessel/resolve-in-sysroot.c b/tests/pressure-vessel/resolve-in-sysroot.c
index b578399961d2f49bb6e2c7ad90b76a71c042243c..ec6e928a9ef5f7984be554c1a6bb5833115864db 100644
--- a/tests/pressure-vessel/resolve-in-sysroot.c
+++ b/tests/pressure-vessel/resolve-in-sysroot.c
@@ -120,6 +120,7 @@ test_resolve_in_sysroot (Fixture *f,
     { "a/b/symlink_to_c", "c" },
     { "a/b/symlink_to_b2", "../b2" },
     { "a/b/symlink_to_c2", "../../a/b2/c2" },
+    { "a/b/symlink_to_itself", "." },
     { "a/b/abs_symlink_to_run", "/run" },
     { "a/b/long_symlink_to_dev", "../../../../../../../../../../../dev" },
     { "x", "create_me" },
@@ -178,6 +179,15 @@ test_resolve_in_sysroot (Fixture *f,
     { { "a/b/symlink_to_b2" }, { "a/b2" } },
     { { "a/b/symlink_to_c2" }, { "a/b2/c2" } },
     { { "a/b/abs_symlink_to_run" }, { NULL, G_IO_ERROR_NOT_FOUND } },
+    {
+      { "a/b/symlink_to_itself", SRT_RESOLVE_FLAGS_KEEP_FINAL_SYMLINK },
+      { "a/b/symlink_to_itself" },
+    },
+    {
+      { "a/b/symlink_to_itself",
+        SRT_RESOLVE_FLAGS_KEEP_FINAL_SYMLINK|SRT_RESOLVE_FLAGS_READABLE },
+      { NULL, G_IO_ERROR_TOO_MANY_LINKS },
+    },
     {
       { "a/b/abs_symlink_to_run", SRT_RESOLVE_FLAGS_KEEP_FINAL_SYMLINK },
       { "a/b/abs_symlink_to_run" }
@@ -282,6 +292,7 @@ test_resolve_in_sysroot (Fixture *f,
       else
         {
           g_assert_error (error, G_IO_ERROR, it->expect.code);
+          g_test_message ("Got error as expected: %s", error->message);
           g_assert_cmpint (fd, ==, -1);
 
           if (out_path != NULL)