]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb: implement linux namespace support for fileio_lstat and vFile::lstat
authorFabian Kilger <kilger@sec.in.tum.de>
Wed, 11 Jun 2025 20:52:16 +0000 (22:52 +0200)
committerAndrew Burgess <aburgess@redhat.com>
Tue, 17 Jun 2025 20:37:11 +0000 (21:37 +0100)
The new algorithm to look for a build-id-based debug file
(introduced by commit 22836ca88591ac7efacf06d5b6db191763fd8aba)
makes use of fileio_lstat. As lstat was not supported by
linux-namespace.c, all lstat calls would be performed on the host
and not inside the namespace.  Fixed by adding namespace lstat
support.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32956

Approved-By: Andrew Burgess <aburgess@redhat.com>
gdb/linux-nat.c
gdb/linux-nat.h
gdb/nat/linux-namespaces.c
gdb/nat/linux-namespaces.h
gdbserver/hostio.cc
gdbserver/linux-low.cc
gdbserver/linux-low.h
gdbserver/target.cc
gdbserver/target.h

index 2f98060506bb7afb3e92bc4e4ce533a7db939c91..8f5f978074f017e0a043dc60dddbad1fe7163ea3 100644 (file)
@@ -4585,6 +4585,20 @@ linux_nat_target::fileio_open (struct inferior *inf, const char *filename,
   return fd;
 }
 
+/* Implementation of to_fileio_lstat.  */
+
+int
+linux_nat_target::fileio_lstat (struct inferior *inf, const char *filename,
+                               struct stat *sb, fileio_error *target_errno)
+{
+  int r = linux_mntns_lstat (linux_nat_fileio_pid_of (inf), filename, sb);
+
+  if (r == -1)
+    *target_errno = host_to_fileio_error (errno);
+
+  return r;
+}
+
 /* Implementation of to_fileio_readlink.  */
 
 std::optional<std::string>
index 6e539918ced0755840a1d8255bbcdf885ed3d4cc..21ec309dafb5ee3bfc4a58fb5592a0c382832826 100644 (file)
@@ -108,6 +108,9 @@ public:
                     const char *filename,
                     fileio_error *target_errno) override;
 
+  int fileio_lstat (struct inferior *inf, const char *filename,
+                  struct stat *sb, fileio_error *target_errno) override;
+
   int fileio_unlink (struct inferior *inf,
                     const char *filename,
                     fileio_error *target_errno) override;
index a3a38d82e647cdced7928b6dc20cf180ec1fe755..8fe320663f51b28ad9aec683e4165dceb959d276 100644 (file)
@@ -233,6 +233,12 @@ enum mnsh_msg_type
        MNSH_RET_INT.  */
     MNSH_REQ_SETNS,
 
+    /* A request that the helper call lstat.  The single
+       argument (the filename) should be passed in BUF, and
+       should include a terminating NUL character.  The helper
+       should respond with a MNSH_RET_INTSTR.  */
+    MNSH_REQ_LSTAT,
+
     /* A request that the helper call open.  Arguments should
        be passed in BUF, INT1 and INT2.  The filename (in BUF)
        should include a terminating NUL character.  The helper
@@ -284,6 +290,10 @@ mnsh_debug_print_message (enum mnsh_msg_type type,
       res += "ERROR";
       break;
 
+    case MNSH_REQ_LSTAT:
+      res += "LSTAT";
+      break;
+
     case MNSH_REQ_SETNS:
       res += "SETNS";
       break;
@@ -511,6 +521,20 @@ mnsh_handle_setns (int sock, int fd, int nstype)
   return mnsh_return_int (sock, result, errno);
 }
 
+
+/* Handle a MNSH_REQ_LSTAT message.  Must be async-signal-safe.  */
+
+static ssize_t
+mnsh_handle_lstat (int sock, const char *filename)
+{
+  struct stat sb;
+  int stat_ok = lstat (filename, &sb);
+
+  return mnsh_return_intstr (sock, stat_ok, &sb,
+                            stat_ok == -1 ? 0 : sizeof (sb),
+                            errno);
+}
+
 /* Handle a MNSH_REQ_OPEN message.  Must be async-signal-safe.  */
 
 static ssize_t
@@ -571,6 +595,11 @@ mnsh_main (int sock)
                response = mnsh_handle_setns (sock, fd, int1);
              break;
 
+           case MNSH_REQ_LSTAT:
+             if (size > 0 && buf[size - 1] == '\0')
+               response = mnsh_handle_lstat (sock, buf);
+             break;
+
            case MNSH_REQ_OPEN:
              if (size > 0 && buf[size - 1] == '\0')
                response = mnsh_handle_open (sock, buf, int1, int2);
@@ -761,6 +790,10 @@ mnsh_maybe_mourn_peer (void)
   mnsh_send_message (helper->sock, MNSH_REQ_OPEN, -1, flags, mode, \
                     filename, strlen (filename) + 1)
 
+#define mnsh_send_lstat(helper, filename) \
+  mnsh_send_message (helper->sock, MNSH_REQ_LSTAT, -1, 0, 0, \
+                    filename, strlen (filename) + 1)
+
 #define mnsh_send_unlink(helper, filename) \
   mnsh_send_message (helper->sock, MNSH_REQ_UNLINK, -1, 0, 0, \
                     filename, strlen (filename) + 1)
@@ -943,6 +976,42 @@ linux_mntns_access_fs (pid_t pid)
 
 /* See nat/linux-namespaces.h.  */
 
+int
+linux_mntns_lstat (pid_t pid, const char *filename,
+                  struct stat *sb)
+{
+  enum mnsh_fs_code access = linux_mntns_access_fs (pid);
+
+  if (access == MNSH_FS_ERROR)
+    return -1;
+
+  if (access == MNSH_FS_DIRECT)
+    return lstat (filename, sb);
+
+  gdb_assert (access == MNSH_FS_HELPER);
+
+  struct linux_mnsh *helper = linux_mntns_get_helper ();
+
+  ssize_t size = mnsh_send_lstat (helper, filename);
+  if (size < 0)
+    return -1;
+
+  int stat_ok, error;
+  size = mnsh_recv_intstr (helper, &stat_ok, &error, sb, sizeof (*sb));
+
+  if (size < 0)
+    {
+      stat_ok = -1;
+      errno = error;
+    }
+  else
+    gdb_assert (stat_ok == -1 || size == sizeof (*sb));
+
+  return stat_ok;
+}
+
+/* See nat/linux-namespaces.h.  */
+
 int
 linux_mntns_open_cloexec (pid_t pid, const char *filename,
                          int flags, mode_t mode)
index cfaccde91e96ef2df22642f8fc9bd29bc1fe3dda..a9a99f164e02c2a0d1cd964dae720d2f74251bd0 100644 (file)
@@ -64,6 +64,11 @@ enum linux_ns_type
 
 extern int linux_ns_same (pid_t pid, enum linux_ns_type type);
 
+/* Like lstat(2), but in the mount namespace of process PID.  */
+
+extern int linux_mntns_lstat (pid_t pid, const char *filename,
+                             struct stat *sb);
+
 /* Like gdb_open_cloexec, but in the mount namespace of process
    PID.  */
 
index 8b4d74d5942c82f461b831b367d39acc04702477..ca8e4918e476ff87e65aebd4fa5f913fdef8dc35 100644 (file)
@@ -525,7 +525,7 @@ handle_stat (char *own_buf, int *new_packet_len)
 static void
 handle_lstat (char *own_buf, int *new_packet_len)
 {
-  int bytes_sent;
+  int ret, bytes_sent;
   char *p;
   struct stat st;
   struct fio_stat fst;
@@ -540,7 +540,12 @@ handle_lstat (char *own_buf, int *new_packet_len)
       return;
     }
 
-  if (lstat (filename, &st) == -1)
+  if (hostio_fs_pid != 0)
+    ret = the_target->multifs_lstat (hostio_fs_pid, filename, &st);
+  else
+    ret = lstat (filename, &st);
+
+  if (ret == -1)
     {
       hostio_error (own_buf);
       return;
index 1d223c11db9f270de03eab9d9a94afa94454e25d..e507558c64e73581cee23ae8c594fd7f4838c220 100644 (file)
@@ -6049,6 +6049,12 @@ linux_process_target::multifs_open (int pid, const char *filename,
   return linux_mntns_open_cloexec (pid, filename, flags, mode);
 }
 
+int
+linux_process_target::multifs_lstat (int pid, const char *filename, struct stat *sb)
+{
+  return linux_mntns_lstat (pid, filename, sb);
+}
+
 int
 linux_process_target::multifs_unlink (int pid, const char *filename)
 {
index 7d3e35fa9b098483847a30f244cf1274640f7059..e1c88ee0bb2cb64f7f1400f926e45e901d977333 100644 (file)
@@ -304,6 +304,8 @@ public:
   int multifs_open (int pid, const char *filename, int flags,
                    mode_t mode) override;
 
+  int multifs_lstat (int pid, const char *filename, struct stat *st) override;
+
   int multifs_unlink (int pid, const char *filename) override;
 
   ssize_t multifs_readlink (int pid, const char *filename, char *buf,
index e812785d39709eee593497048f809ac3b86fa6b6..c400174c47cfd0e2ad218fbcd95abfd5b468be60 100644 (file)
@@ -772,6 +772,13 @@ process_stratum_target::multifs_open (int pid, const char *filename,
   return open (filename, flags, mode);
 }
 
+int
+process_stratum_target::multifs_lstat (int pid, const char *filename,
+                                      struct stat *sb)
+{
+  return lstat (filename, sb);
+}
+
 int
 process_stratum_target::multifs_unlink (int pid, const char *filename)
 {
index af788e256eb3abb49dd927b235df56435883c6e8..4d3f80f736d9d43c6e8b2fffc2e0a7f1fca56c56 100644 (file)
@@ -441,6 +441,12 @@ public:
   virtual int multifs_open (int pid, const char *filename,
                            int flags, mode_t mode);
 
+  /* Multiple-filesystem-aware lstat.  Like lstat(2), but operating in
+     the filesystem as it appears to process PID.  Systems where all
+     processes share a common filesystem should not override this.
+     The default behavior is to use lstat(2).  */
+  virtual int multifs_lstat (int pid, const char *filename, struct stat *sb);
+
   /* Multiple-filesystem-aware unlink.  Like unlink(2), but operates
      in the filesystem as it appears to process PID.  Systems where
      all processes share a common filesystem should not override this.