diff --git a/pressure-vessel/wrap-setup.c b/pressure-vessel/wrap-setup.c
index 08c710134adf2040cd27f20dbc7c691e5eeb60cf..edda14e40b410168a275c5d53668e389b70c328d 100644
--- a/pressure-vessel/wrap-setup.c
+++ b/pressure-vessel/wrap-setup.c
@@ -545,6 +545,63 @@ pv_wrap_move_into_scope (const char *steam_app_id)
     g_debug ("Cannot move into a systemd scope: %s", local_error->message);
 }
 
+/*
+ * export_path_for_preload:
+ * @context: Context we are running in
+ * @path: Absolute path to a LD_PRELOAD or LD_AUDIT module
+ *
+ * Return the path that we would need to add to `context->exports`
+ * to make this module available to the container, or %NULL if no path
+ * should be added.
+ *
+ * Returns: (transfer full) (nullable): Path to export, or %NULL
+ */
+static gchar *
+export_path_for_preload (PvWrapContext *context,
+                         const char *path)
+{
+  g_autofree gchar *parent = NULL;
+  glnx_autofd int parent_fd = -1;
+  FlatpakExports *exports = context->exports;
+
+  if (exports == NULL)
+    return NULL;
+
+  /* Normally we export the directory containing the LD_PRELOAD module,
+   * and not the module itself. For example, if we're going to load
+   * /home/me/.local/lib64/mangohud/libMangoHud_shim.so,
+   * we want to share /home/me/.local/lib64/mangohud with the
+   * container, so that libMangoHud_shim.so can dlopen
+   * libMangoHud_opengl.so in the same directory, as expected.
+   * This is a compromise between exporting too much (which we
+   * could easily do if we walked further up the directory tree,
+   * for example undoing the effect of --unshare-home)
+   * and exporting too little (just libMangoHud_shim.so, which
+   * doesn't do anything useful on its own). */
+  parent = g_path_get_dirname (path);
+  parent_fd = _srt_sysroot_open (context->current_root,
+                                 parent,
+                                 SRT_RESOLVE_FLAGS_MUST_BE_DIRECTORY,
+                                 NULL,
+                                 NULL);
+
+  /* Special case: we don't want to export all of $HOME if we are doing
+   * --unshare-home, so override that to only exporting the minimum
+   *  that we can: the module itself. */
+  if (context->current_home_fd >= 0
+      && parent_fd >= 0
+      && _srt_fstatat_is_same_file (context->current_home_fd, "",
+                                    parent_fd, ""))
+    {
+      g_debug ("Not exporting parent of \"%s\" because it is $HOME",
+               path);
+      return g_strdup (path);
+    }
+
+  g_debug ("Exporting parent of \"%s\" -> \"%s\"", path, parent);
+  return g_steal_pointer (&parent);
+}
+
 static void
 append_preload_internal (PvWrapContext *context,
                          GPtrArray *argv,
@@ -765,13 +822,15 @@ append_preload_per_architecture (PvWrapContext *context,
 
       if (path != NULL)
         {
+          g_autofree gchar *export_path = export_path_for_preload (context, path);
+
           g_debug ("Found %s version of %s at %s",
                    multiarch_tuple, preload, path);
           append_preload_internal (context,
                                    argv,
                                    which,
                                    i,
-                                   path,
+                                   export_path,
                                    path,
                                    flags);
         }
@@ -824,7 +883,7 @@ append_preload_basename (PvWrapContext *context,
                                argv,
                                which,
                                PV_UNSPECIFIED_ABI,
-                               NULL,
+                               NULL,  /* don't export anything */
                                preload,
                                flags);
     }
@@ -929,6 +988,8 @@ pv_wrap_append_preload (PvWrapContext *context,
           }
         else
           {
+            g_autofree gchar *export_path = export_path_for_preload (context, preload);
+
             /* All dynamic tokens should be handled above, so we can
              * assume that preload is a concrete filename */
             g_warn_if_fail ((loadable_flags & SRT_LOADABLE_FLAGS_DYNAMIC_TOKENS) == 0);
@@ -936,7 +997,7 @@ pv_wrap_append_preload (PvWrapContext *context,
                                      argv,
                                      which,
                                      PV_UNSPECIFIED_ABI,
-                                     preload,
+                                     export_path,
                                      preload,
                                      flags);
           }