diff --git a/pressure-vessel/runtime.c b/pressure-vessel/runtime.c
index 62fb34ef2fdd41f2b2c39249cd48802d8770d22f..443bd05f5280bb4d2f186257f13603d488f06027 100644
--- a/pressure-vessel/runtime.c
+++ b/pressure-vessel/runtime.c
@@ -5751,3 +5751,103 @@ pv_runtime_get_modified_app (PvRuntime *self)
   else
     return NULL;
 }
+
+/*
+ * Return %TRUE if the runtime provides @library, either directly or
+ * via the graphics-stack provider.
+ */
+gboolean
+pv_runtime_has_library (PvRuntime *self,
+                        const char *library)
+{
+  glnx_autofd int source_files_fd = -1;
+  gsize i;
+
+  g_return_val_if_fail (PV_IS_RUNTIME (self), FALSE);
+  g_return_val_if_fail (library != NULL, FALSE);
+
+  g_debug ("Checking whether runtime has library: %s", library);
+
+  for (i = 0; i < PV_N_SUPPORTED_ARCHITECTURES; i++)
+    {
+      const PvMultiarchDetails *details = &pv_multiarch_details[i];
+      g_autoptr(GPtrArray) dirs = NULL;
+      gsize j;
+
+      dirs = pv_multiarch_details_get_libdirs (details,
+                                               PV_MULTIARCH_LIBDIRS_FLAGS_NONE);
+
+      for (j = 0; j < dirs->len; j++)
+        {
+          const char *libdir = g_ptr_array_index (dirs, j);
+          g_autofree gchar *path = g_build_filename (libdir, library, NULL);
+
+          if (self->mutable_sysroot_fd >= 0)
+            {
+              glnx_autofd int fd = -1;
+
+              fd = _srt_resolve_in_sysroot (self->mutable_sysroot_fd, path,
+                                            SRT_RESOLVE_FLAGS_NONE,
+                                            NULL, NULL);
+
+              if (fd >= 0)
+                {
+                  g_debug ("-> yes, ${mutable_sysroot}/%s", path);
+                  return TRUE;
+                }
+            }
+          else
+            {
+              glnx_autofd int fd = -1;
+
+              /* The runtime isn't necessarily a sysroot (it might just be a
+               * merged /usr) but in practice it'll be close enough: we look
+               * up each library in /usr/foo and /foo anyway. */
+              if (source_files_fd < 0)
+                {
+                  if (!glnx_opendirat (AT_FDCWD, self->source_files, TRUE,
+                                       &source_files_fd, NULL))
+                    continue;
+                }
+
+              fd = _srt_resolve_in_sysroot (source_files_fd, path,
+                                            SRT_RESOLVE_FLAGS_NONE,
+                                            NULL, NULL);
+
+              if (fd >= 0)
+                {
+                  g_debug ("-> yes, ${source_files}/%s", path);
+                  return TRUE;
+                }
+            }
+
+          /* If the graphics stack provider is not the same as the current
+           * namespace (in practice this rarely/never happens), we also
+           * want to steer clear of libraries that only exist in the
+           * graphics stack provider.
+           *
+           * If the graphics stack provider *is* the current namespace,
+           * and the library doesn't exist in the container runtime, then
+           * it's OK to use libraries from it in LD_PRELOAD, because there
+           * is no other version that might have been meant. */
+          if (self->provider != NULL
+              && g_strcmp0 (self->provider->path_in_current_ns, "/") != 0)
+            {
+              glnx_autofd int fd = -1;
+
+              fd = _srt_resolve_in_sysroot (self->provider->fd, path,
+                                            SRT_RESOLVE_FLAGS_NONE,
+                                            NULL, NULL);
+
+              if (fd >= 0)
+                {
+                  g_debug ("-> yes, ${provider}/%s", path);
+                  return TRUE;
+                }
+            }
+        }
+    }
+
+  g_debug ("-> no");
+  return FALSE;
+}
diff --git a/pressure-vessel/runtime.h b/pressure-vessel/runtime.h
index dfb9f19f47ba299fe111763bdf8cdc04dd570985..6370deea3b411809feeed5bc61f6b7ca6004d93b 100644
--- a/pressure-vessel/runtime.h
+++ b/pressure-vessel/runtime.h
@@ -113,4 +113,7 @@ gboolean pv_runtime_use_shared_sockets (PvRuntime *self,
                                         PvEnviron *container_env,
                                         GError **error);
 
+gboolean pv_runtime_has_library (PvRuntime *self,
+                                 const char *library);
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (PvRuntime, g_object_unref)
diff --git a/pressure-vessel/wrap-setup.c b/pressure-vessel/wrap-setup.c
index fdcaef856f75687745f849e77daacee1819f35b7..c9982426e1d374c7938dcf5784e0851aea7ee05a 100644
--- a/pressure-vessel/wrap-setup.c
+++ b/pressure-vessel/wrap-setup.c
@@ -502,9 +502,6 @@ append_preload_per_architecture (GPtrArray *argv,
   g_autoptr(SrtSystemInfo) system_info = srt_system_info_new (NULL);
   gsize i;
 
-  g_debug ("Found $LIB or $PLATFORM in \"%s\", splitting architectures",
-           preload);
-
   if (system_info == NULL)
     system_info = srt_system_info_new (NULL);
 
@@ -537,10 +534,19 @@ append_preload_per_architecture (GPtrArray *argv,
           platform = pv_multiarch_details[i].platforms[0];
 
           mock_path = g_string_new (preload);
-          g_string_replace (mock_path, "$LIB", lib, 0);
-          g_string_replace (mock_path, "${LIB}", lib, 0);
-          g_string_replace (mock_path, "$PLATFORM", platform, 0);
-          g_string_replace (mock_path, "${PLATFORM}", platform, 0);
+
+          if (strchr (preload, '/') == NULL)
+            {
+              g_string_printf (mock_path, "/path/to/%s/%s", lib, preload);
+            }
+          else
+            {
+              g_string_replace (mock_path, "$LIB", lib, 0);
+              g_string_replace (mock_path, "${LIB}", lib, 0);
+              g_string_replace (mock_path, "$PLATFORM", platform, 0);
+              g_string_replace (mock_path, "${PLATFORM}", platform, 0);
+            }
+
           path = mock_path->str;
 
           /* As a special case, pretend one 64-bit library failed to load,
@@ -575,6 +581,73 @@ append_preload_per_architecture (GPtrArray *argv,
     }
 }
 
+static void
+append_preload_basename (GPtrArray *argv,
+                         const char *option,
+                         const char *preload,
+                         GStrv env,
+                         PvAppendPreloadFlags flags,
+                         PvRuntime *runtime,
+                         FlatpakExports *exports)
+{
+  gboolean runtime_has_library = FALSE;
+
+  if (runtime != NULL)
+    runtime_has_library = pv_runtime_has_library (runtime, preload);
+
+  if (flags & PV_APPEND_PRELOAD_FLAGS_IN_UNIT_TESTS)
+    {
+      /* Mock implementation for unit tests: behave as though the
+       * container has everything except libfakeroot/libfakechroot. */
+      if (g_str_has_prefix (preload, "libfake"))
+        runtime_has_library = FALSE;
+      else
+        runtime_has_library = TRUE;
+    }
+
+  if (runtime_has_library)
+    {
+      /* If the library exists in the container runtime or in the
+       * stack we imported from the graphics provider, e.g.
+       * LD_PRELOAD=libpthread.so.0, then we certainly don't want
+       * to be loading it from the current namespace: that would
+       * bypass our logic for comparing library versions and picking
+       * the newest. Just pass through the LD_PRELOAD item into the
+       * container, and let the dynamic linker in the container choose
+       * what it means (container runtime or graphics provider as
+       * appropriate). */
+      g_debug ("Found \"%s\" in runtime or graphics stack provider, "
+               "passing %s through as-is",
+               preload, option);
+      append_preload_internal (argv,
+                               option,
+                               NULL,
+                               NULL,
+                               preload,
+                               env,
+                               flags,
+                               runtime,
+                               NULL);
+    }
+  else
+    {
+      /* There's no such library in the container runtime or in the
+       * graphics provider, so it's OK to inject the version from the
+       * current namespace. Use the same trick as for ${PLATFORM} to
+       * turn it into (up to) one absolute path per ABI. */
+      g_debug ("Did not find \"%s\" in runtime or graphics stack provider, "
+               "splitting architectures",
+               preload);
+      append_preload_per_architecture (argv,
+                                       option,
+                                       preload,
+                                       env,
+                                       flags,
+                                       runtime,
+                                       exports);
+    }
+}
+
 /**
  * pv_wrap_append_preload:
  * @argv: (element-type filename): Array of command-line options to populate
@@ -635,19 +708,13 @@ pv_wrap_append_preload (GPtrArray *argv,
       case SRT_LOADABLE_KIND_BASENAME:
         /* Basenames can't have dynamic string tokens. */
         g_warn_if_fail ((loadable_flags & SRT_LOADABLE_FLAGS_DYNAMIC_TOKENS) == 0);
-        /* Ideally we would handle this more cleverly, but for now,
-         * pass preload through to the container without adjustment.
-         * It isn't useful to add it to the FlatpakExports, because it
-         * isn't an absolute filename. */
-        append_preload_internal (argv,
+        append_preload_basename (argv,
                                  option,
-                                 NULL,
-                                 NULL,
                                  preload,
                                  env,
                                  flags,
                                  runtime,
-                                 NULL);
+                                 exports);
         break;
 
       case SRT_LOADABLE_KIND_PATH:
@@ -665,6 +732,8 @@ pv_wrap_append_preload (GPtrArray *argv,
           }
         else if (loadable_flags & SRT_LOADABLE_FLAGS_ABI_DEPENDENT)
           {
+            g_debug ("Found $LIB or $PLATFORM in \"%s\", splitting architectures",
+                     preload);
             append_preload_per_architecture (argv,
                                              option,
                                              preload,