From 9e257a5713c872183026af854586bc511dc23287 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Fri, 7 Feb 2025 18:36:29 +0000
Subject: [PATCH] pv-wrap: Have a file descriptor for $HOME in the
 PvWrapContext

This will allow the LD_PRELOAD handling code to use a real or mock
home directory, as appropriate.

Signed-off-by: Simon McVittie <smcv@collabora.com>
---
 pressure-vessel/wrap-context.c     | 18 ++++++++++++++++++
 pressure-vessel/wrap-context.h     |  1 +
 pressure-vessel/wrap.c             |  3 ++-
 tests/pressure-vessel/wrap-setup.c |  5 +++++
 4 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/pressure-vessel/wrap-context.c b/pressure-vessel/wrap-context.c
index 8216431fa..102c1f8e5 100644
--- a/pressure-vessel/wrap-context.c
+++ b/pressure-vessel/wrap-context.c
@@ -117,6 +117,7 @@ pv_wrap_context_init (PvWrapContext *self)
 {
   self->is_flatpak_env = g_file_test ("/.flatpak-info", G_FILE_TEST_IS_REGULAR);
   self->original_environ = g_get_environ ();
+  self->current_home_fd = -1;
 
   pv_wrap_options_init (&self->options);
 
@@ -178,11 +179,27 @@ static void
 pv_wrap_context_constructed (GObject *object)
 {
   PvWrapContext *self = PV_WRAP_CONTEXT (object);
+  g_autoptr(GError) local_error = NULL;
 
   G_OBJECT_CLASS (pv_wrap_context_parent_class)->constructed (object);
 
   if (self->current_home == NULL)
     self->current_home = g_strdup (g_get_home_dir ());
+
+  self->current_home_fd = _srt_sysroot_open (self->current_root,
+                                             self->current_home,
+                                             (SRT_RESOLVE_FLAGS_READABLE
+                                              | SRT_RESOLVE_FLAGS_MUST_BE_DIRECTORY),
+                                             NULL,
+                                             &local_error);
+
+
+  if (self->current_home_fd < 0)
+    {
+      g_warning ("Cannot open current home directory \"%s\": %s",
+                 self->current_home, local_error->message);
+      g_clear_error (&local_error);
+    }
 }
 
 static void
@@ -208,6 +225,7 @@ pv_wrap_context_finalize (GObject *object)
   g_strfreev (self->original_argv);
   g_strfreev (self->original_environ);
   g_free (self->current_home);
+  glnx_close_fd (&self->current_home_fd);
 
   G_OBJECT_CLASS (pv_wrap_context_parent_class)->finalize (object);
 }
diff --git a/pressure-vessel/wrap-context.h b/pressure-vessel/wrap-context.h
index 68cc601a1..8538ce6f2 100644
--- a/pressure-vessel/wrap-context.h
+++ b/pressure-vessel/wrap-context.h
@@ -105,6 +105,7 @@ struct _PvWrapContext
 
   gboolean is_flatpak_env;
   int original_argc;
+  int current_home_fd;
 };
 
 #define PV_TYPE_WRAP_CONTEXT \
diff --git a/pressure-vessel/wrap.c b/pressure-vessel/wrap.c
index de714d16c..8729b85df 100644
--- a/pressure-vessel/wrap.c
+++ b/pressure-vessel/wrap.c
@@ -915,7 +915,8 @@ main (int argc,
 
       cwd_p_host = pv_current_namespace_path_to_host_path (cwd_p);
 
-      if (_srt_is_same_file (self->current_home, cwd_p))
+      if (self->current_home_fd >= 0
+          && _srt_fstatat_is_same_file (self->current_home_fd, "", AT_FDCWD, cwd_p))
         {
           g_info ("Not making physical working directory \"%s\" available to "
                   "container because it is the home directory",
diff --git a/tests/pressure-vessel/wrap-setup.c b/tests/pressure-vessel/wrap-setup.c
index 0dfada919..177509c2f 100644
--- a/tests/pressure-vessel/wrap-setup.c
+++ b/tests/pressure-vessel/wrap-setup.c
@@ -80,6 +80,7 @@ typedef struct
   PvWrapContext *context;
   SrtSysroot *mock_host;
   FlatpakBwrap *bwrap;
+  gchar *home;
   gchar *tmpdir;
   gchar *mock_runtime;
   gchar *var;
@@ -242,6 +243,9 @@ setup (Fixture *f,
   glnx_opendirat (AT_FDCWD, f->var, TRUE, &f->var_fd, &local_error);
   g_assert_no_error (local_error);
 
+  f->home = g_build_filename (f->mock_host->path, "home", "me", NULL);
+  glnx_shutil_mkdir_p_at (AT_FDCWD, f->home, 0755, NULL, &local_error);
+  g_assert_no_error (local_error);
   f->context = pv_wrap_context_new (f->mock_host, "/home/me", &local_error);
   g_assert_no_error (local_error);
   f->bwrap = flatpak_bwrap_new (flatpak_bwrap_empty_env);
@@ -311,6 +315,7 @@ teardown (Fixture *f,
   g_clear_object (&f->context);
   g_clear_object (&f->mock_host);
   g_clear_pointer (&f->mock_runtime, g_free);
+  g_clear_pointer (&f->home, g_free);
   g_clear_pointer (&f->tmpdir, g_free);
   g_clear_pointer (&f->var, g_free);
   g_clear_pointer (&f->bwrap, flatpak_bwrap_free);
-- 
GitLab