Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH] gdb: linux-namespaces: enter user namespace when appropriate
@ 2025-06-10 16:57 Andrew Burgess
  2025-06-12 15:25 ` [PATCHv2] " Andrew Burgess
  0 siblings, 1 reply; 11+ messages in thread
From: Andrew Burgess @ 2025-06-10 16:57 UTC (permalink / raw)
  To: gdb-patches; +Cc: Benjamin Berg, Andrew Burgess

From: Benjamin Berg <benjamin@sipsolutions.net>

The use of user namespaces is required for normal users to use mount
namespaces.  Consider trying this as an unprivileged user:

  $ unshare --mount /bin/true
  unshare: unshare failed: Operation not permitted

The problem here is that an unprivileged user doesn't have the
required permissions to create a new mount namespace.  If, instead, we
do this:

  $ unshare --mount --map-root-user /bin/true

then this will succeed.  The new option causes unshare to create a
user namespace in which the unprivileged user is mapped to UID/GID 0,
and so gains all privileges (inside the namespace), the user is then
able to create the mount namespace as required.

So, how does this relate to GDB?

When a user attaches to a process running in a separate mount
namespace, GDB makes use of a separate helper process (see
linux_mntns_get_helper in nat/linux-namespaces.c), which will then use
the `setns` function to enter (or try to enter) the mount namespace of
the process GDB is attaching too.  The helper process will then handle
file I/O requests received from GDB, and return the results back to
GDB, this allows GDB to access files within the mount namespace.

The problem here is that, switching to a mount namespace requires that
a process hold CAP_SYS_CHROOT and CAP_SYS_ADMIN capabilities within
its user namespace (actually it's a little more complex, see 'man 2
setns').  Assuming GDB is running as an unprivileged user, then GDB
will not have the required permissions.

However, if GDB enters the user namespace that the `unshare` process
created, then the current user will be mapped to UID/GID 0, and will
have the required permissions.

And so, this patch extends linux_mntns_access_fs (in
nat/linux-namespace.c) to first try and switch to the user namespace
of the inferior before trying to switch to the mount namespace.  If
the inferior does have a user namespace, and does have elevated
privileges within that namespace, then this first switch by GDB will
mean that the second step, into the mount namespace, will succeed.

If there is no user namespace, or the inferior doesn't have elevated
privileges within the user namespace, then the switch into the mount
namespace will fail, just as it currently does, and the user will need
to give elevated privileges to GDB via some other mechanism (e.g. run
as root).

This work was originally posted here:

  https://inbox.sourceware.org/gdb-patches/20230321120126.1418012-1-benjamin@sipsolutions.net

I (Andrew Burgess) have made some cleanups to the code to comply with
GDB's coding standard, and the test is entirely mine.  This commit
message is also entirely mine -- the original message was very terse
and required the reader to understand how the various namespaces
work and interact.  The above is my attempt to document what I now
understand about the problem being fixed.

I've left the original author in place as the core of the GDB change
itself is largely as originally presented, but any inaccuracies in the
commit message, or problems with the test, are all mine.

Co-Authored-by: Andrew Burgess <aburgess@redhat.com>
---
 gdb/nat/linux-namespaces.c                    |  24 +++-
 .../gdb.base/user-namespace-attach.c          |  35 +++++
 .../gdb.base/user-namespace-attach.exp        | 130 ++++++++++++++++++
 3 files changed, 188 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.base/user-namespace-attach.c
 create mode 100644 gdb/testsuite/gdb.base/user-namespace-attach.exp

diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
index ea94fddcffa..f8afd75fe92 100644
--- a/gdb/nat/linux-namespaces.c
+++ b/gdb/nat/linux-namespaces.c
@@ -884,7 +884,7 @@ linux_mntns_access_fs (pid_t pid)
   struct stat sb;
   struct linux_mnsh *helper;
   ssize_t size;
-  int fd;
+  int fd, fd_user = -1;
 
   if (pid == getpid ())
     return MNSH_FS_DIRECT;
@@ -901,6 +901,8 @@ linux_mntns_access_fs (pid_t pid)
     {
       int save_errno = errno;
       close (fd);
+      if (fd_user >= 0)
+	close (fd_user);
       errno = save_errno;
     };
 
@@ -910,6 +912,13 @@ linux_mntns_access_fs (pid_t pid)
   if (sb.st_ino == ns->id)
     return MNSH_FS_DIRECT;
 
+  struct linux_ns *ns_user = linux_ns_get_namespace (LINUX_NS_USER);
+  if (ns_user != nullptr)
+    {
+      const char *ns_filename = linux_ns_filename (ns_user, pid);
+      fd_user = gdb_open_cloexec (ns_filename, O_RDONLY, 0).release ();
+    }
+
   helper = linux_mntns_get_helper ();
   if (helper == NULL)
     return MNSH_FS_ERROR;
@@ -918,6 +927,19 @@ linux_mntns_access_fs (pid_t pid)
     {
       int result, error;
 
+      /* Try to enter the user namespace first.  The current user might
+	 have elevated privileges within the user namespace, which would
+	 then allow the attempt to enter the mount namespace to succeed.  */
+      if (fd_user >= 0)
+	{
+	  size = mnsh_send_setns (helper, fd_user, 0);
+	  if (size < 0)
+	    return MNSH_FS_ERROR;
+
+	  if (mnsh_recv_int (helper, &result, &error) != 0)
+	    return MNSH_FS_ERROR;
+	}
+
       size = mnsh_send_setns (helper, fd, 0);
       if (size < 0)
 	return MNSH_FS_ERROR;
diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.c b/gdb/testsuite/gdb.base/user-namespace-attach.c
new file mode 100644
index 00000000000..684ce1cfc66
--- /dev/null
+++ b/gdb/testsuite/gdb.base/user-namespace-attach.c
@@ -0,0 +1,35 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2025 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+
+volatile int spin_p = 1;
+
+int
+main ()
+{
+  alarm (60);
+
+  printf ("pid = %lld\n", ((long long) getpid ()));
+
+  while (spin_p)
+    sleep (1);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.exp b/gdb/testsuite/gdb.base/user-namespace-attach.exp
new file mode 100644
index 00000000000..b817d74375a
--- /dev/null
+++ b/gdb/testsuite/gdb.base/user-namespace-attach.exp
@@ -0,0 +1,130 @@
+# Copyright 2025 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Check that GDB can attach to a process started using 'unshare'.  The
+# inferior is started in a separate mnt namespace.
+
+require can_spawn_for_attach
+
+standard_testfile
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile] == -1} {
+    return
+}
+
+# This test relies (at least in some parts) on the sysroot being
+# 'target:'.  Grab the current sysroot now so we can skip those tests
+# if the board file has changed the sysroot.
+set sysroot ""
+set test "show sysroot"
+gdb_test_multiple $test $test {
+    -re -wrap "The current system root is \"(.*)\"\\." {
+	set sysroot $expect_out(1,string)
+    }
+}
+
+# Start a process using 'unshare FLAGS', then attach to the process
+# from GDB.  Check that the attach worked as expected.
+proc run_test { flags } {
+
+    # If FLAGS contains '--mount' then a separate mnt namespace will
+    # be created, in which case the executable will have been read
+    # from the 'target:'.  Otherwise, the executable will have been
+    # read from the local filesystem, and there will be no prefix.
+    #
+    # Of course, this only applies if the sysroot is 'target:', some
+    # boards change this, so skip these tests on those boards.
+    if { [lsearch -exact [split $flags " "] "--mount"] != -1 } {
+	if { $::sysroot ne "target:" } {
+	    return
+	}
+
+	set prefix "target:"
+    } else {
+	set prefix ""
+    }
+
+
+
+    set inferior_spawn_id \
+	[spawn_wait_for_attach [list "unshare $flags $::binfile"]]
+    if { $inferior_spawn_id == -1 } {
+	unsupported "failed to spawn for attach"
+	return
+    }
+
+    set inferior_pid [spawn_id_get_pid $inferior_spawn_id]
+
+    clean_restart
+
+    set saw_bad_warning false
+    gdb_test_multiple "attach $inferior_pid" "attach to inferior" {
+	-re "^attach $::decimal\r\n" {
+	    exp_continue
+	}
+
+	-re "^warning: \[^\r\n\]+: could not open as an executable file: \[^\r\n\]+\r\n" {
+	    set saw_bad_warning true
+	    exp_continue
+	}
+
+	-re "^warning: \[^\r\n\]+: can't open to read symbols: \[^\r\n\]+\r\n" {
+	    set saw_bad_warning true
+	    exp_continue
+	}
+
+	-re "^warning: Could not load vsyscall page because no executable was specified\r\n" {
+	    # This warning is a secondary consequence of the above bad
+	    # warnings, so don't count this as a bad warnings, ignore
+	    # it instead.
+	    exp_continue
+    }
+
+	-re "^warning: \[^\r\n\]+\r\n" {
+	    # If we ignore "other" warnings then, should the above
+	    # warnings strings change we'll start ignoring the bad
+	    # warnings, and the test will appear to pass.
+	    #
+	    # If you are seeing a warning here that really has nothing
+	    # to do with the test failing, then the correct solution
+	    # is to add a new regexp to specifically match _that_
+	    # warning, and ignore it.
+	    set saw_bad_warning true
+	    exp_continue
+	}
+
+	-re "^$::gdb_prompt $" {
+	    gdb_assert { !$saw_bad_warning } $gdb_test_name
+	}
+
+	-re "^\[^\r\n\]*\r\n" {
+	    exp_continue
+	}
+    }
+
+    # Ensure GDB could access the executable.
+    set binfile_re [string_to_regexp $::binfile]
+    gdb_test "info inferiors" \
+	"\r\n\\*\\s+$::decimal\\s+\[^\r\n\]+\\s+${prefix}${binfile_re}\\s*"
+}
+
+set test_flags [list \
+		    "--mount --map-root-user" \
+		    "--user" \
+		    "--user --map-root-user"]
+
+foreach_with_prefix flags $test_flags {
+    run_test $flags
+}

base-commit: 3f8fc746d6bd837c082a41cbc37a2f8ec2325bf2
-- 
2.47.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv2] gdb: linux-namespaces: enter user namespace when appropriate
  2025-06-10 16:57 [PATCH] gdb: linux-namespaces: enter user namespace when appropriate Andrew Burgess
@ 2025-06-12 15:25 ` Andrew Burgess
  2025-06-13  9:17   ` [PATCHv3] " Andrew Burgess
  0 siblings, 1 reply; 11+ messages in thread
From: Andrew Burgess @ 2025-06-12 15:25 UTC (permalink / raw)
  To: gdb-patches; +Cc: Benjamin Berg, Andrew Burgess

From: Benjamin Berg <benjamin@sipsolutions.net>

In v2:

  - Update the test to ignore a warning seen when running the test on
    a machine with libc debug information installed, but without the
    libc source being available, e.g.:

    warning: 46     ../sysdeps/unix/sysv/linux/arm/libc-do-syscall.S: No such file or directory

    This was causing some CI failures to be reported from Linaro.

  - Rebased to current upstream/master.

--

The use of user namespaces is required for normal users to use mount
namespaces.  Consider trying this as an unprivileged user:

  $ unshare --mount /bin/true
  unshare: unshare failed: Operation not permitted

The problem here is that an unprivileged user doesn't have the
required permissions to create a new mount namespace.  If, instead, we
do this:

  $ unshare --mount --map-root-user /bin/true

then this will succeed.  The new option causes unshare to create a
user namespace in which the unprivileged user is mapped to UID/GID 0,
and so gains all privileges (inside the namespace), the user is then
able to create the mount namespace as required.

So, how does this relate to GDB?

When a user attaches to a process running in a separate mount
namespace, GDB makes use of a separate helper process (see
linux_mntns_get_helper in nat/linux-namespaces.c), which will then use
the `setns` function to enter (or try to enter) the mount namespace of
the process GDB is attaching too.  The helper process will then handle
file I/O requests received from GDB, and return the results back to
GDB, this allows GDB to access files within the mount namespace.

The problem here is that, switching to a mount namespace requires that
a process hold CAP_SYS_CHROOT and CAP_SYS_ADMIN capabilities within
its user namespace (actually it's a little more complex, see 'man 2
setns').  Assuming GDB is running as an unprivileged user, then GDB
will not have the required permissions.

However, if GDB enters the user namespace that the `unshare` process
created, then the current user will be mapped to UID/GID 0, and will
have the required permissions.

And so, this patch extends linux_mntns_access_fs (in
nat/linux-namespace.c) to first try and switch to the user namespace
of the inferior before trying to switch to the mount namespace.  If
the inferior does have a user namespace, and does have elevated
privileges within that namespace, then this first switch by GDB will
mean that the second step, into the mount namespace, will succeed.

If there is no user namespace, or the inferior doesn't have elevated
privileges within the user namespace, then the switch into the mount
namespace will fail, just as it currently does, and the user will need
to give elevated privileges to GDB via some other mechanism (e.g. run
as root).

This work was originally posted here:

  https://inbox.sourceware.org/gdb-patches/20230321120126.1418012-1-benjamin@sipsolutions.net

I (Andrew Burgess) have made some cleanups to the code to comply with
GDB's coding standard, and the test is entirely mine.  This commit
message is also entirely mine -- the original message was very terse
and required the reader to understand how the various namespaces
work and interact.  The above is my attempt to document what I now
understand about the problem being fixed.

I've left the original author in place as the core of the GDB change
itself is largely as originally presented, but any inaccuracies in the
commit message, or problems with the test, are all mine.

Co-Authored-by: Andrew Burgess <aburgess@redhat.com>
---
 gdb/nat/linux-namespaces.c                    |  24 +++-
 .../gdb.base/user-namespace-attach.c          |  35 +++++
 .../gdb.base/user-namespace-attach.exp        | 136 ++++++++++++++++++
 3 files changed, 194 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.base/user-namespace-attach.c
 create mode 100644 gdb/testsuite/gdb.base/user-namespace-attach.exp

diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
index a3a38d82e64..4b5cb373e7a 100644
--- a/gdb/nat/linux-namespaces.c
+++ b/gdb/nat/linux-namespaces.c
@@ -880,7 +880,7 @@ linux_mntns_access_fs (pid_t pid)
   struct stat sb;
   struct linux_mnsh *helper;
   ssize_t size;
-  int fd;
+  int fd, fd_user = -1;
 
   if (pid == getpid ())
     return MNSH_FS_DIRECT;
@@ -897,6 +897,8 @@ linux_mntns_access_fs (pid_t pid)
     {
       int save_errno = errno;
       close (fd);
+      if (fd_user >= 0)
+	close (fd_user);
       errno = save_errno;
     };
 
@@ -906,6 +908,13 @@ linux_mntns_access_fs (pid_t pid)
   if (sb.st_ino == ns->id)
     return MNSH_FS_DIRECT;
 
+  struct linux_ns *ns_user = linux_ns_get_namespace (LINUX_NS_USER);
+  if (ns_user != nullptr)
+    {
+      const char *ns_filename = linux_ns_filename (ns_user, pid);
+      fd_user = gdb_open_cloexec (ns_filename, O_RDONLY, 0).release ();
+    }
+
   helper = linux_mntns_get_helper ();
   if (helper == NULL)
     return MNSH_FS_ERROR;
@@ -914,6 +923,19 @@ linux_mntns_access_fs (pid_t pid)
     {
       int result, error;
 
+      /* Try to enter the user namespace first.  The current user might
+	 have elevated privileges within the user namespace, which would
+	 then allow the attempt to enter the mount namespace to succeed.  */
+      if (fd_user >= 0)
+	{
+	  size = mnsh_send_setns (helper, fd_user, 0);
+	  if (size < 0)
+	    return MNSH_FS_ERROR;
+
+	  if (mnsh_recv_int (helper, &result, &error) != 0)
+	    return MNSH_FS_ERROR;
+	}
+
       size = mnsh_send_setns (helper, fd, 0);
       if (size < 0)
 	return MNSH_FS_ERROR;
diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.c b/gdb/testsuite/gdb.base/user-namespace-attach.c
new file mode 100644
index 00000000000..684ce1cfc66
--- /dev/null
+++ b/gdb/testsuite/gdb.base/user-namespace-attach.c
@@ -0,0 +1,35 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2025 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+
+volatile int spin_p = 1;
+
+int
+main ()
+{
+  alarm (60);
+
+  printf ("pid = %lld\n", ((long long) getpid ()));
+
+  while (spin_p)
+    sleep (1);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.exp b/gdb/testsuite/gdb.base/user-namespace-attach.exp
new file mode 100644
index 00000000000..c01bc5ca583
--- /dev/null
+++ b/gdb/testsuite/gdb.base/user-namespace-attach.exp
@@ -0,0 +1,136 @@
+# Copyright 2025 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Check that GDB can attach to a process started using 'unshare'.  The
+# inferior is started in a separate mnt namespace.
+
+require can_spawn_for_attach
+
+standard_testfile
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile] == -1} {
+    return
+}
+
+# This test relies (at least in some parts) on the sysroot being
+# 'target:'.  Grab the current sysroot now so we can skip those tests
+# if the board file has changed the sysroot.
+set sysroot ""
+set test "show sysroot"
+gdb_test_multiple $test $test {
+    -re -wrap "The current system root is \"(.*)\"\\." {
+	set sysroot $expect_out(1,string)
+    }
+}
+
+# Start a process using 'unshare FLAGS', then attach to the process
+# from GDB.  Check that the attach worked as expected.
+proc run_test { flags } {
+
+    # If FLAGS contains '--mount' then a separate mnt namespace will
+    # be created, in which case the executable will have been read
+    # from the 'target:'.  Otherwise, the executable will have been
+    # read from the local filesystem, and there will be no prefix.
+    #
+    # Of course, this only applies if the sysroot is 'target:', some
+    # boards change this, so skip these tests on those boards.
+    if { [lsearch -exact [split $flags " "] "--mount"] != -1 } {
+	if { $::sysroot ne "target:" } {
+	    return
+	}
+
+	set prefix "target:"
+    } else {
+	set prefix ""
+    }
+
+
+
+    set inferior_spawn_id \
+	[spawn_wait_for_attach [list "unshare $flags $::binfile"]]
+    if { $inferior_spawn_id == -1 } {
+	unsupported "failed to spawn for attach"
+	return
+    }
+
+    set inferior_pid [spawn_id_get_pid $inferior_spawn_id]
+
+    clean_restart
+
+    set saw_bad_warning false
+    gdb_test_multiple "attach $inferior_pid" "attach to inferior" {
+	-re "^attach $::decimal\r\n" {
+	    exp_continue
+	}
+
+	-re "^warning: \[^\r\n\]+: could not open as an executable file: \[^\r\n\]+\r\n" {
+	    set saw_bad_warning true
+	    exp_continue
+	}
+
+	-re "^warning: \[^\r\n\]+: can't open to read symbols: \[^\r\n\]+\r\n" {
+	    set saw_bad_warning true
+	    exp_continue
+	}
+
+	-re "^warning: Could not load vsyscall page because no executable was specified\r\n" {
+	    # This warning is a secondary consequence of the above bad
+	    # warnings, so don't count this as a bad warnings, ignore
+	    # it instead.
+	    exp_continue
+	}
+
+	-re "^warning:\\s+$::decimal\\s*\[^\r\n\]: No such file or directory\r\n" {
+	    # This unrelated warning is seen when GDB stops in libc,
+	    # and the source code for libc is not available.
+	    exp_continue
+	}
+
+	-re "^warning: \[^\r\n\]+\r\n" {
+	    # If we ignore "other" warnings then, should the above
+	    # warnings strings change we'll start ignoring the bad
+	    # warnings, and the test will appear to pass.
+	    #
+	    # If you are seeing a warning here that really has nothing
+	    # to do with the test failing, then the correct solution
+	    # is to add a new regexp to specifically match _that_
+	    # warning, and ignore it.
+	    set saw_bad_warning true
+	    exp_continue
+	}
+
+	-re "^$::gdb_prompt $" {
+	    gdb_assert { !$saw_bad_warning } $gdb_test_name
+	}
+
+	-re "^\[^\r\n\]*\r\n" {
+	    exp_continue
+	}
+    }
+
+    # Ensure GDB could access the executable.
+    set binfile_re [string_to_regexp $::binfile]
+    gdb_test "info inferiors" \
+	"\r\n\\*\\s+$::decimal\\s+\[^\r\n\]+\\s+${prefix}${binfile_re}\\s*"
+}
+
+set test_flags [list \
+		    "--mount --map-root-user" \
+		    "--user" \
+		    "--user --map-root-user"]
+
+foreach_with_prefix flags $test_flags {
+    run_test $flags
+}

base-commit: add73a101f5e8225d4055563c52adaa64c8fb11d
-- 
2.47.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv3] gdb: linux-namespaces: enter user namespace when appropriate
  2025-06-12 15:25 ` [PATCHv2] " Andrew Burgess
@ 2025-06-13  9:17   ` Andrew Burgess
  2025-06-23 13:56     ` Andrew Burgess
  0 siblings, 1 reply; 11+ messages in thread
From: Andrew Burgess @ 2025-06-13  9:17 UTC (permalink / raw)
  To: gdb-patches; +Cc: Benjamin Berg, Andrew Burgess

From: Benjamin Berg <benjamin@sipsolutions.net>

In v2:

  - Update the test to ignore a warning seen when running the test on
    a machine with libc debug information installed, but without the
    libc source being available, e.g.:

    warning: 46     ../sysdeps/unix/sysv/linux/arm/libc-do-syscall.S: No such file or directory

    This was causing some CI failures to be reported from Linaro.

  - Rebased to current upstream/master.

In v3:

  - Same as V2, but fix the test pattern correctly this time.

--

The use of user namespaces is required for normal users to use mount
namespaces.  Consider trying this as an unprivileged user:

  $ unshare --mount /bin/true
  unshare: unshare failed: Operation not permitted

The problem here is that an unprivileged user doesn't have the
required permissions to create a new mount namespace.  If, instead, we
do this:

  $ unshare --mount --map-root-user /bin/true

then this will succeed.  The new option causes unshare to create a
user namespace in which the unprivileged user is mapped to UID/GID 0,
and so gains all privileges (inside the namespace), the user is then
able to create the mount namespace as required.

So, how does this relate to GDB?

When a user attaches to a process running in a separate mount
namespace, GDB makes use of a separate helper process (see
linux_mntns_get_helper in nat/linux-namespaces.c), which will then use
the `setns` function to enter (or try to enter) the mount namespace of
the process GDB is attaching too.  The helper process will then handle
file I/O requests received from GDB, and return the results back to
GDB, this allows GDB to access files within the mount namespace.

The problem here is that, switching to a mount namespace requires that
a process hold CAP_SYS_CHROOT and CAP_SYS_ADMIN capabilities within
its user namespace (actually it's a little more complex, see 'man 2
setns').  Assuming GDB is running as an unprivileged user, then GDB
will not have the required permissions.

However, if GDB enters the user namespace that the `unshare` process
created, then the current user will be mapped to UID/GID 0, and will
have the required permissions.

And so, this patch extends linux_mntns_access_fs (in
nat/linux-namespace.c) to first try and switch to the user namespace
of the inferior before trying to switch to the mount namespace.  If
the inferior does have a user namespace, and does have elevated
privileges within that namespace, then this first switch by GDB will
mean that the second step, into the mount namespace, will succeed.

If there is no user namespace, or the inferior doesn't have elevated
privileges within the user namespace, then the switch into the mount
namespace will fail, just as it currently does, and the user will need
to give elevated privileges to GDB via some other mechanism (e.g. run
as root).

This work was originally posted here:

  https://inbox.sourceware.org/gdb-patches/20230321120126.1418012-1-benjamin@sipsolutions.net

I (Andrew Burgess) have made some cleanups to the code to comply with
GDB's coding standard, and the test is entirely mine.  This commit
message is also entirely mine -- the original message was very terse
and required the reader to understand how the various namespaces
work and interact.  The above is my attempt to document what I now
understand about the problem being fixed.

I've left the original author in place as the core of the GDB change
itself is largely as originally presented, but any inaccuracies in the
commit message, or problems with the test, are all mine.

Co-Authored-by: Andrew Burgess <aburgess@redhat.com>
---
 gdb/nat/linux-namespaces.c                    |  24 +++-
 .../gdb.base/user-namespace-attach.c          |  35 +++++
 .../gdb.base/user-namespace-attach.exp        | 136 ++++++++++++++++++
 3 files changed, 194 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.base/user-namespace-attach.c
 create mode 100644 gdb/testsuite/gdb.base/user-namespace-attach.exp

diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
index a3a38d82e64..4b5cb373e7a 100644
--- a/gdb/nat/linux-namespaces.c
+++ b/gdb/nat/linux-namespaces.c
@@ -880,7 +880,7 @@ linux_mntns_access_fs (pid_t pid)
   struct stat sb;
   struct linux_mnsh *helper;
   ssize_t size;
-  int fd;
+  int fd, fd_user = -1;
 
   if (pid == getpid ())
     return MNSH_FS_DIRECT;
@@ -897,6 +897,8 @@ linux_mntns_access_fs (pid_t pid)
     {
       int save_errno = errno;
       close (fd);
+      if (fd_user >= 0)
+	close (fd_user);
       errno = save_errno;
     };
 
@@ -906,6 +908,13 @@ linux_mntns_access_fs (pid_t pid)
   if (sb.st_ino == ns->id)
     return MNSH_FS_DIRECT;
 
+  struct linux_ns *ns_user = linux_ns_get_namespace (LINUX_NS_USER);
+  if (ns_user != nullptr)
+    {
+      const char *ns_filename = linux_ns_filename (ns_user, pid);
+      fd_user = gdb_open_cloexec (ns_filename, O_RDONLY, 0).release ();
+    }
+
   helper = linux_mntns_get_helper ();
   if (helper == NULL)
     return MNSH_FS_ERROR;
@@ -914,6 +923,19 @@ linux_mntns_access_fs (pid_t pid)
     {
       int result, error;
 
+      /* Try to enter the user namespace first.  The current user might
+	 have elevated privileges within the user namespace, which would
+	 then allow the attempt to enter the mount namespace to succeed.  */
+      if (fd_user >= 0)
+	{
+	  size = mnsh_send_setns (helper, fd_user, 0);
+	  if (size < 0)
+	    return MNSH_FS_ERROR;
+
+	  if (mnsh_recv_int (helper, &result, &error) != 0)
+	    return MNSH_FS_ERROR;
+	}
+
       size = mnsh_send_setns (helper, fd, 0);
       if (size < 0)
 	return MNSH_FS_ERROR;
diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.c b/gdb/testsuite/gdb.base/user-namespace-attach.c
new file mode 100644
index 00000000000..684ce1cfc66
--- /dev/null
+++ b/gdb/testsuite/gdb.base/user-namespace-attach.c
@@ -0,0 +1,35 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2025 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+
+volatile int spin_p = 1;
+
+int
+main ()
+{
+  alarm (60);
+
+  printf ("pid = %lld\n", ((long long) getpid ()));
+
+  while (spin_p)
+    sleep (1);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.exp b/gdb/testsuite/gdb.base/user-namespace-attach.exp
new file mode 100644
index 00000000000..9936bb998eb
--- /dev/null
+++ b/gdb/testsuite/gdb.base/user-namespace-attach.exp
@@ -0,0 +1,136 @@
+# Copyright 2025 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Check that GDB can attach to a process started using 'unshare'.  The
+# inferior is started in a separate mnt namespace.
+
+require can_spawn_for_attach
+
+standard_testfile
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile] == -1} {
+    return
+}
+
+# This test relies (at least in some parts) on the sysroot being
+# 'target:'.  Grab the current sysroot now so we can skip those tests
+# if the board file has changed the sysroot.
+set sysroot ""
+set test "show sysroot"
+gdb_test_multiple $test $test {
+    -re -wrap "The current system root is \"(.*)\"\\." {
+	set sysroot $expect_out(1,string)
+    }
+}
+
+# Start a process using 'unshare FLAGS', then attach to the process
+# from GDB.  Check that the attach worked as expected.
+proc run_test { flags } {
+
+    # If FLAGS contains '--mount' then a separate mnt namespace will
+    # be created, in which case the executable will have been read
+    # from the 'target:'.  Otherwise, the executable will have been
+    # read from the local filesystem, and there will be no prefix.
+    #
+    # Of course, this only applies if the sysroot is 'target:', some
+    # boards change this, so skip these tests on those boards.
+    if { [lsearch -exact [split $flags " "] "--mount"] != -1 } {
+	if { $::sysroot ne "target:" } {
+	    return
+	}
+
+	set prefix "target:"
+    } else {
+	set prefix ""
+    }
+
+
+
+    set inferior_spawn_id \
+	[spawn_wait_for_attach [list "unshare $flags $::binfile"]]
+    if { $inferior_spawn_id == -1 } {
+	unsupported "failed to spawn for attach"
+	return
+    }
+
+    set inferior_pid [spawn_id_get_pid $inferior_spawn_id]
+
+    clean_restart
+
+    set saw_bad_warning false
+    gdb_test_multiple "attach $inferior_pid" "attach to inferior" {
+	-re "^attach $::decimal\r\n" {
+	    exp_continue
+	}
+
+	-re "^warning: \[^\r\n\]+: could not open as an executable file: \[^\r\n\]+\r\n" {
+	    set saw_bad_warning true
+	    exp_continue
+	}
+
+	-re "^warning: \[^\r\n\]+: can't open to read symbols: \[^\r\n\]+\r\n" {
+	    set saw_bad_warning true
+	    exp_continue
+	}
+
+	-re "^warning: Could not load vsyscall page because no executable was specified\r\n" {
+	    # This warning is a secondary consequence of the above bad
+	    # warnings, so don't count this as a bad warnings, ignore
+	    # it instead.
+	    exp_continue
+	}
+
+	-re "^warning:\\s+$::decimal\\s*\[^\r\n\]+: No such file or directory\r\n" {
+	    # This unrelated warning is seen when GDB stops in libc,
+	    # and the source code for libc is not available.
+	    exp_continue
+	}
+
+	-re "^warning: \[^\r\n\]+\r\n" {
+	    # If we ignore "other" warnings then, should the above
+	    # warnings strings change we'll start ignoring the bad
+	    # warnings, and the test will appear to pass.
+	    #
+	    # If you are seeing a warning here that really has nothing
+	    # to do with the test failing, then the correct solution
+	    # is to add a new regexp to specifically match _that_
+	    # warning, and ignore it.
+	    set saw_bad_warning true
+	    exp_continue
+	}
+
+	-re "^$::gdb_prompt $" {
+	    gdb_assert { !$saw_bad_warning } $gdb_test_name
+	}
+
+	-re "^\[^\r\n\]*\r\n" {
+	    exp_continue
+	}
+    }
+
+    # Ensure GDB could access the executable.
+    set binfile_re [string_to_regexp $::binfile]
+    gdb_test "info inferiors" \
+	"\r\n\\*\\s+$::decimal\\s+\[^\r\n\]+\\s+${prefix}${binfile_re}\\s*"
+}
+
+set test_flags [list \
+		    "--mount --map-root-user" \
+		    "--user" \
+		    "--user --map-root-user"]
+
+foreach_with_prefix flags $test_flags {
+    run_test $flags
+}

base-commit: add73a101f5e8225d4055563c52adaa64c8fb11d
-- 
2.47.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] gdb: linux-namespaces: enter user namespace when appropriate
  2025-06-13  9:17   ` [PATCHv3] " Andrew Burgess
@ 2025-06-23 13:56     ` Andrew Burgess
  2025-06-25  9:48       ` Tom de Vries
  0 siblings, 1 reply; 11+ messages in thread
From: Andrew Burgess @ 2025-06-23 13:56 UTC (permalink / raw)
  To: gdb-patches; +Cc: Benjamin Berg

Andrew Burgess <aburgess@redhat.com> writes:

> From: Benjamin Berg <benjamin@sipsolutions.net>
>
> In v2:
>
>   - Update the test to ignore a warning seen when running the test on
>     a machine with libc debug information installed, but without the
>     libc source being available, e.g.:
>
>     warning: 46     ../sysdeps/unix/sysv/linux/arm/libc-do-syscall.S: No such file or directory
>
>     This was causing some CI failures to be reported from Linaro.
>
>   - Rebased to current upstream/master.
>
> In v3:
>
>   - Same as V2, but fix the test pattern correctly this time.
>
> --
>
> The use of user namespaces is required for normal users to use mount
> namespaces.  Consider trying this as an unprivileged user:
>
>   $ unshare --mount /bin/true
>   unshare: unshare failed: Operation not permitted
>
> The problem here is that an unprivileged user doesn't have the
> required permissions to create a new mount namespace.  If, instead, we
> do this:
>
>   $ unshare --mount --map-root-user /bin/true
>
> then this will succeed.  The new option causes unshare to create a
> user namespace in which the unprivileged user is mapped to UID/GID 0,
> and so gains all privileges (inside the namespace), the user is then
> able to create the mount namespace as required.
>
> So, how does this relate to GDB?
>
> When a user attaches to a process running in a separate mount
> namespace, GDB makes use of a separate helper process (see
> linux_mntns_get_helper in nat/linux-namespaces.c), which will then use
> the `setns` function to enter (or try to enter) the mount namespace of
> the process GDB is attaching too.  The helper process will then handle
> file I/O requests received from GDB, and return the results back to
> GDB, this allows GDB to access files within the mount namespace.
>
> The problem here is that, switching to a mount namespace requires that
> a process hold CAP_SYS_CHROOT and CAP_SYS_ADMIN capabilities within
> its user namespace (actually it's a little more complex, see 'man 2
> setns').  Assuming GDB is running as an unprivileged user, then GDB
> will not have the required permissions.
>
> However, if GDB enters the user namespace that the `unshare` process
> created, then the current user will be mapped to UID/GID 0, and will
> have the required permissions.
>
> And so, this patch extends linux_mntns_access_fs (in
> nat/linux-namespace.c) to first try and switch to the user namespace
> of the inferior before trying to switch to the mount namespace.  If
> the inferior does have a user namespace, and does have elevated
> privileges within that namespace, then this first switch by GDB will
> mean that the second step, into the mount namespace, will succeed.
>
> If there is no user namespace, or the inferior doesn't have elevated
> privileges within the user namespace, then the switch into the mount
> namespace will fail, just as it currently does, and the user will need
> to give elevated privileges to GDB via some other mechanism (e.g. run
> as root).
>
> This work was originally posted here:
>
>   https://inbox.sourceware.org/gdb-patches/20230321120126.1418012-1-benjamin@sipsolutions.net
>
> I (Andrew Burgess) have made some cleanups to the code to comply with
> GDB's coding standard, and the test is entirely mine.  This commit
> message is also entirely mine -- the original message was very terse
> and required the reader to understand how the various namespaces
> work and interact.  The above is my attempt to document what I now
> understand about the problem being fixed.
>
> I've left the original author in place as the core of the GDB change
> itself is largely as originally presented, but any inaccuracies in the
> commit message, or problems with the test, are all mine.
>
> Co-Authored-by: Andrew Burgess <aburgess@redhat.com>

I've pushed this patch.

The GDB changes have been on the list for a couple of years now, and
(except for some comments and formating) are mostly unchanged in my
version.

My contributions to this work are the test and the commit message.

Thanks,
Andrew


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] gdb: linux-namespaces: enter user namespace when appropriate
  2025-06-23 13:56     ` Andrew Burgess
@ 2025-06-25  9:48       ` Tom de Vries
  2025-06-25 10:34         ` Andrew Burgess
  0 siblings, 1 reply; 11+ messages in thread
From: Tom de Vries @ 2025-06-25  9:48 UTC (permalink / raw)
  To: Andrew Burgess, gdb-patches; +Cc: Benjamin Berg

On 6/23/25 15:56, Andrew Burgess wrote:
> Andrew Burgess <aburgess@redhat.com> writes:
> 
>> From: Benjamin Berg <benjamin@sipsolutions.net>
>>
>> In v2:
>>
>>    - Update the test to ignore a warning seen when running the test on
>>      a machine with libc debug information installed, but without the
>>      libc source being available, e.g.:
>>
>>      warning: 46     ../sysdeps/unix/sysv/linux/arm/libc-do-syscall.S: No such file or directory
>>
>>      This was causing some CI failures to be reported from Linaro.
>>
>>    - Rebased to current upstream/master.
>>
>> In v3:
>>
>>    - Same as V2, but fix the test pattern correctly this time.
>>
>> --
>>
>> The use of user namespaces is required for normal users to use mount
>> namespaces.  Consider trying this as an unprivileged user:
>>
>>    $ unshare --mount /bin/true
>>    unshare: unshare failed: Operation not permitted
>>
>> The problem here is that an unprivileged user doesn't have the
>> required permissions to create a new mount namespace.  If, instead, we
>> do this:
>>
>>    $ unshare --mount --map-root-user /bin/true
>>
>> then this will succeed.  The new option causes unshare to create a
>> user namespace in which the unprivileged user is mapped to UID/GID 0,
>> and so gains all privileges (inside the namespace), the user is then
>> able to create the mount namespace as required.
>>
>> So, how does this relate to GDB?
>>
>> When a user attaches to a process running in a separate mount
>> namespace, GDB makes use of a separate helper process (see
>> linux_mntns_get_helper in nat/linux-namespaces.c), which will then use
>> the `setns` function to enter (or try to enter) the mount namespace of
>> the process GDB is attaching too.  The helper process will then handle
>> file I/O requests received from GDB, and return the results back to
>> GDB, this allows GDB to access files within the mount namespace.
>>
>> The problem here is that, switching to a mount namespace requires that
>> a process hold CAP_SYS_CHROOT and CAP_SYS_ADMIN capabilities within
>> its user namespace (actually it's a little more complex, see 'man 2
>> setns').  Assuming GDB is running as an unprivileged user, then GDB
>> will not have the required permissions.
>>
>> However, if GDB enters the user namespace that the `unshare` process
>> created, then the current user will be mapped to UID/GID 0, and will
>> have the required permissions.
>>
>> And so, this patch extends linux_mntns_access_fs (in
>> nat/linux-namespace.c) to first try and switch to the user namespace
>> of the inferior before trying to switch to the mount namespace.  If
>> the inferior does have a user namespace, and does have elevated
>> privileges within that namespace, then this first switch by GDB will
>> mean that the second step, into the mount namespace, will succeed.
>>
>> If there is no user namespace, or the inferior doesn't have elevated
>> privileges within the user namespace, then the switch into the mount
>> namespace will fail, just as it currently does, and the user will need
>> to give elevated privileges to GDB via some other mechanism (e.g. run
>> as root).
>>
>> This work was originally posted here:
>>
>>    https://inbox.sourceware.org/gdb-patches/20230321120126.1418012-1-benjamin@sipsolutions.net
>>
>> I (Andrew Burgess) have made some cleanups to the code to comply with
>> GDB's coding standard, and the test is entirely mine.  This commit
>> message is also entirely mine -- the original message was very terse
>> and required the reader to understand how the various namespaces
>> work and interact.  The above is my attempt to document what I now
>> understand about the problem being fixed.
>>
>> I've left the original author in place as the core of the GDB change
>> itself is largely as originally presented, but any inaccuracies in the
>> commit message, or problems with the test, are all mine.
>>
>> Co-Authored-by: Andrew Burgess <aburgess@redhat.com>
> 
> I've pushed this patch.
> 

The new test-case fails on arm32 (Linaro CI reported this, and I was 
able to reproduce) due to insufficient permissions:
...
(gdb) attach 184732
Attaching to process 184732
warning: process 184732 is a zombie - the process has already terminated
ptrace: Operation not permitted.
(gdb) FAIL: gdb.base/user-namespace-attach.exp: flags=--mount 
--map-root-user: attach to inferior
...

In essence, the test-case assumes:
...
$ unshare --mount --map-root-user /bin/true; echo $?
0
...
but we get instead:
...
$ unshare --mount --map-root-user /bin/true; echo $?
unshare: unshare failed: Operation not permitted
1
...

Filed here ( https://sourceware.org/bugzilla/show_bug.cgi?id=33108 ).

Thanks,
- Tom

> The GDB changes have been on the list for a couple of years now, and
> (except for some comments and formating) are mostly unchanged in my
> version.
> 
> My contributions to this work are the test and the commit message.
> 
> Thanks,
> Andrew
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] gdb: linux-namespaces: enter user namespace when appropriate
  2025-06-25  9:48       ` Tom de Vries
@ 2025-06-25 10:34         ` Andrew Burgess
  2025-06-25 11:01           ` Tom de Vries
  0 siblings, 1 reply; 11+ messages in thread
From: Andrew Burgess @ 2025-06-25 10:34 UTC (permalink / raw)
  To: Tom de Vries, gdb-patches; +Cc: Benjamin Berg

Tom de Vries <tdevries@suse.de> writes:

> On 6/23/25 15:56, Andrew Burgess wrote:
>> Andrew Burgess <aburgess@redhat.com> writes:
>> 
>>> From: Benjamin Berg <benjamin@sipsolutions.net>
>>>
>>> In v2:
>>>
>>>    - Update the test to ignore a warning seen when running the test on
>>>      a machine with libc debug information installed, but without the
>>>      libc source being available, e.g.:
>>>
>>>      warning: 46     ../sysdeps/unix/sysv/linux/arm/libc-do-syscall.S: No such file or directory
>>>
>>>      This was causing some CI failures to be reported from Linaro.
>>>
>>>    - Rebased to current upstream/master.
>>>
>>> In v3:
>>>
>>>    - Same as V2, but fix the test pattern correctly this time.
>>>
>>> --
>>>
>>> The use of user namespaces is required for normal users to use mount
>>> namespaces.  Consider trying this as an unprivileged user:
>>>
>>>    $ unshare --mount /bin/true
>>>    unshare: unshare failed: Operation not permitted
>>>
>>> The problem here is that an unprivileged user doesn't have the
>>> required permissions to create a new mount namespace.  If, instead, we
>>> do this:
>>>
>>>    $ unshare --mount --map-root-user /bin/true
>>>
>>> then this will succeed.  The new option causes unshare to create a
>>> user namespace in which the unprivileged user is mapped to UID/GID 0,
>>> and so gains all privileges (inside the namespace), the user is then
>>> able to create the mount namespace as required.
>>>
>>> So, how does this relate to GDB?
>>>
>>> When a user attaches to a process running in a separate mount
>>> namespace, GDB makes use of a separate helper process (see
>>> linux_mntns_get_helper in nat/linux-namespaces.c), which will then use
>>> the `setns` function to enter (or try to enter) the mount namespace of
>>> the process GDB is attaching too.  The helper process will then handle
>>> file I/O requests received from GDB, and return the results back to
>>> GDB, this allows GDB to access files within the mount namespace.
>>>
>>> The problem here is that, switching to a mount namespace requires that
>>> a process hold CAP_SYS_CHROOT and CAP_SYS_ADMIN capabilities within
>>> its user namespace (actually it's a little more complex, see 'man 2
>>> setns').  Assuming GDB is running as an unprivileged user, then GDB
>>> will not have the required permissions.
>>>
>>> However, if GDB enters the user namespace that the `unshare` process
>>> created, then the current user will be mapped to UID/GID 0, and will
>>> have the required permissions.
>>>
>>> And so, this patch extends linux_mntns_access_fs (in
>>> nat/linux-namespace.c) to first try and switch to the user namespace
>>> of the inferior before trying to switch to the mount namespace.  If
>>> the inferior does have a user namespace, and does have elevated
>>> privileges within that namespace, then this first switch by GDB will
>>> mean that the second step, into the mount namespace, will succeed.
>>>
>>> If there is no user namespace, or the inferior doesn't have elevated
>>> privileges within the user namespace, then the switch into the mount
>>> namespace will fail, just as it currently does, and the user will need
>>> to give elevated privileges to GDB via some other mechanism (e.g. run
>>> as root).
>>>
>>> This work was originally posted here:
>>>
>>>    https://inbox.sourceware.org/gdb-patches/20230321120126.1418012-1-benjamin@sipsolutions.net
>>>
>>> I (Andrew Burgess) have made some cleanups to the code to comply with
>>> GDB's coding standard, and the test is entirely mine.  This commit
>>> message is also entirely mine -- the original message was very terse
>>> and required the reader to understand how the various namespaces
>>> work and interact.  The above is my attempt to document what I now
>>> understand about the problem being fixed.
>>>
>>> I've left the original author in place as the core of the GDB change
>>> itself is largely as originally presented, but any inaccuracies in the
>>> commit message, or problems with the test, are all mine.
>>>
>>> Co-Authored-by: Andrew Burgess <aburgess@redhat.com>
>> 
>> I've pushed this patch.
>> 
>
> The new test-case fails on arm32 (Linaro CI reported this, and I was 
> able to reproduce) due to insufficient permissions:
> ...
> (gdb) attach 184732
> Attaching to process 184732
> warning: process 184732 is a zombie - the process has already terminated
> ptrace: Operation not permitted.
> (gdb) FAIL: gdb.base/user-namespace-attach.exp: flags=--mount 
> --map-root-user: attach to inferior
> ...
>
> In essence, the test-case assumes:
> ...
> $ unshare --mount --map-root-user /bin/true; echo $?
> 0
> ...
> but we get instead:
> ...
> $ unshare --mount --map-root-user /bin/true; echo $?
> unshare: unshare failed: Operation not permitted
> 1
> ...
>
> Filed here ( https://sourceware.org/bugzilla/show_bug.cgi?id=33108 ).

Hi!

Thanks for raising this issue.

What do you think to the patch below?

I've tested this by passing a bogus flag to `unshare`, e.g. "unshare
-blahblah", which has the same effect of causing the `unshare` process
to exit immediately with an exit code of 1.  I now see the test reported
as unsupported.

Thanks,
Andrew

---

commit 1c61ee90c22666a6f33a474c27a901d03bbc5da9
Author: Andrew Burgess <aburgess@redhat.com>
Date:   Wed Jun 25 11:24:30 2025 +0100

    gdb/testsuite: handle failure to start process to later attach to
    
    Commit:
    
      commit b23903836007d1acaf7f8c059ab000ee83fcebfa
      Date:   Tue Mar 21 13:01:26 2023 +0100
    
          gdb: linux-namespaces: enter user namespace when appropriate
    
    added a new test gdb.base/user-namespace-attach.exp.  It has been
    reported that this test will sometimes fail, like this:
    
      (gdb) attach 184732
      Attaching to process 184732
      warning: process 184732 is a zombie - the process has already terminated
      ptrace: Operation not permitted.
      (gdb) FAIL: gdb.base/user-namespace-attach.exp: flags=--mount --map-root-user: attach to inferior
    
    the test tries to run the 'unshare' application.  Sometimes though,
    the application is present, but the set of flags used is not
    supported (maybe due to restrictions on the local machine), so we see
    behaviour like this:
    
      $ unshare --mount --map-root-user /bin/true; echo $?
      unshare: unshare failed: Operation not permitted
      1
    
    Handle this case by checking for the warning:
    
      warning: process 184732 is a zombie - the process has already terminated
    
    when GDB tries to attach.  If we see this warning then we assume the
    'unshare' process failed to start correctly, in which case we report
    the test as unsupported and perform an early return.
    
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33108

diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.exp b/gdb/testsuite/gdb.base/user-namespace-attach.exp
index 9936bb998eb..01f3dae1693 100644
--- a/gdb/testsuite/gdb.base/user-namespace-attach.exp
+++ b/gdb/testsuite/gdb.base/user-namespace-attach.exp
@@ -69,12 +69,18 @@ proc run_test { flags } {
 
     clean_restart
 
+    set saw_failure_to_start false
     set saw_bad_warning false
     gdb_test_multiple "attach $inferior_pid" "attach to inferior" {
 	-re "^attach $::decimal\r\n" {
 	    exp_continue
 	}
 
+	-re "^warning: process $::decimal is a zombie - the process has already terminated\r\n" {
+	    set saw_failure_to_start true
+	    exp_continue
+	}
+
 	-re "^warning: \[^\r\n\]+: could not open as an executable file: \[^\r\n\]+\r\n" {
 	    set saw_bad_warning true
 	    exp_continue
@@ -112,6 +118,11 @@ proc run_test { flags } {
 	}
 
 	-re "^$::gdb_prompt $" {
+	    if { $saw_failure_to_start } {
+		unsupported "unshare process failed to start"
+		return
+	    }
+
 	    gdb_assert { !$saw_bad_warning } $gdb_test_name
 	}
 


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] gdb: linux-namespaces: enter user namespace when appropriate
  2025-06-25 10:34         ` Andrew Burgess
@ 2025-06-25 11:01           ` Tom de Vries
  2025-06-25 14:15             ` Andrew Burgess
  0 siblings, 1 reply; 11+ messages in thread
From: Tom de Vries @ 2025-06-25 11:01 UTC (permalink / raw)
  To: Andrew Burgess, gdb-patches; +Cc: Benjamin Berg

On 6/25/25 12:34, Andrew Burgess wrote:
> Tom de Vries <tdevries@suse.de> writes:
> 
>> On 6/23/25 15:56, Andrew Burgess wrote:
>>> Andrew Burgess <aburgess@redhat.com> writes:
>>>
>>>> From: Benjamin Berg <benjamin@sipsolutions.net>
>>>>
>>>> In v2:
>>>>
>>>>     - Update the test to ignore a warning seen when running the test on
>>>>       a machine with libc debug information installed, but without the
>>>>       libc source being available, e.g.:
>>>>
>>>>       warning: 46     ../sysdeps/unix/sysv/linux/arm/libc-do-syscall.S: No such file or directory
>>>>
>>>>       This was causing some CI failures to be reported from Linaro.
>>>>
>>>>     - Rebased to current upstream/master.
>>>>
>>>> In v3:
>>>>
>>>>     - Same as V2, but fix the test pattern correctly this time.
>>>>
>>>> --
>>>>
>>>> The use of user namespaces is required for normal users to use mount
>>>> namespaces.  Consider trying this as an unprivileged user:
>>>>
>>>>     $ unshare --mount /bin/true
>>>>     unshare: unshare failed: Operation not permitted
>>>>
>>>> The problem here is that an unprivileged user doesn't have the
>>>> required permissions to create a new mount namespace.  If, instead, we
>>>> do this:
>>>>
>>>>     $ unshare --mount --map-root-user /bin/true
>>>>
>>>> then this will succeed.  The new option causes unshare to create a
>>>> user namespace in which the unprivileged user is mapped to UID/GID 0,
>>>> and so gains all privileges (inside the namespace), the user is then
>>>> able to create the mount namespace as required.
>>>>
>>>> So, how does this relate to GDB?
>>>>
>>>> When a user attaches to a process running in a separate mount
>>>> namespace, GDB makes use of a separate helper process (see
>>>> linux_mntns_get_helper in nat/linux-namespaces.c), which will then use
>>>> the `setns` function to enter (or try to enter) the mount namespace of
>>>> the process GDB is attaching too.  The helper process will then handle
>>>> file I/O requests received from GDB, and return the results back to
>>>> GDB, this allows GDB to access files within the mount namespace.
>>>>
>>>> The problem here is that, switching to a mount namespace requires that
>>>> a process hold CAP_SYS_CHROOT and CAP_SYS_ADMIN capabilities within
>>>> its user namespace (actually it's a little more complex, see 'man 2
>>>> setns').  Assuming GDB is running as an unprivileged user, then GDB
>>>> will not have the required permissions.
>>>>
>>>> However, if GDB enters the user namespace that the `unshare` process
>>>> created, then the current user will be mapped to UID/GID 0, and will
>>>> have the required permissions.
>>>>
>>>> And so, this patch extends linux_mntns_access_fs (in
>>>> nat/linux-namespace.c) to first try and switch to the user namespace
>>>> of the inferior before trying to switch to the mount namespace.  If
>>>> the inferior does have a user namespace, and does have elevated
>>>> privileges within that namespace, then this first switch by GDB will
>>>> mean that the second step, into the mount namespace, will succeed.
>>>>
>>>> If there is no user namespace, or the inferior doesn't have elevated
>>>> privileges within the user namespace, then the switch into the mount
>>>> namespace will fail, just as it currently does, and the user will need
>>>> to give elevated privileges to GDB via some other mechanism (e.g. run
>>>> as root).
>>>>
>>>> This work was originally posted here:
>>>>
>>>>     https://inbox.sourceware.org/gdb-patches/20230321120126.1418012-1-benjamin@sipsolutions.net
>>>>
>>>> I (Andrew Burgess) have made some cleanups to the code to comply with
>>>> GDB's coding standard, and the test is entirely mine.  This commit
>>>> message is also entirely mine -- the original message was very terse
>>>> and required the reader to understand how the various namespaces
>>>> work and interact.  The above is my attempt to document what I now
>>>> understand about the problem being fixed.
>>>>
>>>> I've left the original author in place as the core of the GDB change
>>>> itself is largely as originally presented, but any inaccuracies in the
>>>> commit message, or problems with the test, are all mine.
>>>>
>>>> Co-Authored-by: Andrew Burgess <aburgess@redhat.com>
>>>
>>> I've pushed this patch.
>>>
>>
>> The new test-case fails on arm32 (Linaro CI reported this, and I was
>> able to reproduce) due to insufficient permissions:
>> ...
>> (gdb) attach 184732
>> Attaching to process 184732
>> warning: process 184732 is a zombie - the process has already terminated
>> ptrace: Operation not permitted.
>> (gdb) FAIL: gdb.base/user-namespace-attach.exp: flags=--mount
>> --map-root-user: attach to inferior
>> ...
>>
>> In essence, the test-case assumes:
>> ...
>> $ unshare --mount --map-root-user /bin/true; echo $?
>> 0
>> ...
>> but we get instead:
>> ...
>> $ unshare --mount --map-root-user /bin/true; echo $?
>> unshare: unshare failed: Operation not permitted
>> 1
>> ...
>>
>> Filed here ( https://sourceware.org/bugzilla/show_bug.cgi?id=33108 ).
> 
> Hi!
> 
> Thanks for raising this issue.
> 
> What do you think to the patch below?
> 
> I've tested this by passing a bogus flag to `unshare`, e.g. "unshare
> -blahblah", which has the same effect of causing the `unshare` process
> to exit immediately with an exit code of 1.  I now see the test reported
> as unsupported.
> 

Hi Andrew,

thanks for picking this up.

FWIW, the problem with this solution is that a timeout now looks like 
unsupported.

More concretely, by doing this (on x86_64-linux, where the test-case 
passes for me):
...
diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.exp 
b/gdb/testsuite/gdb.base/user
-namespace-attach.exp
index 01f3dae1693..c5ec5ef6369 100644
--- a/gdb/testsuite/gdb.base/user-namespace-attach.exp
+++ b/gdb/testsuite/gdb.base/user-namespace-attach.exp
@@ -66,6 +66,7 @@ proc run_test { flags } {
      }

      set inferior_pid [spawn_id_get_pid $inferior_spawn_id]
+    sleep 90

      clean_restart

...
I trigger the timeout of 60 seconds in the exec, and with your patch get:
...
		=== gdb Summary ===

# of unsupported tests		3
...
but without your patch I get:
...
# of unexpected failures	6
...

I don't think it's terribly important though.

You could try the approach I proposed in the PR, or you could pursue 
this one.

In the latter case, please add a comment that a timeout may trigger the 
same message.

Thanks,
- Tom

> Thanks,
> Andrew
> 
> ---
> 
> commit 1c61ee90c22666a6f33a474c27a901d03bbc5da9
> Author: Andrew Burgess <aburgess@redhat.com>
> Date:   Wed Jun 25 11:24:30 2025 +0100
> 
>      gdb/testsuite: handle failure to start process to later attach to
>      
>      Commit:
>      
>        commit b23903836007d1acaf7f8c059ab000ee83fcebfa
>        Date:   Tue Mar 21 13:01:26 2023 +0100
>      
>            gdb: linux-namespaces: enter user namespace when appropriate
>      
>      added a new test gdb.base/user-namespace-attach.exp.  It has been
>      reported that this test will sometimes fail, like this:
>      
>        (gdb) attach 184732
>        Attaching to process 184732
>        warning: process 184732 is a zombie - the process has already terminated
>        ptrace: Operation not permitted.
>        (gdb) FAIL: gdb.base/user-namespace-attach.exp: flags=--mount --map-root-user: attach to inferior
>      
>      the test tries to run the 'unshare' application.  Sometimes though,
>      the application is present, but the set of flags used is not
>      supported (maybe due to restrictions on the local machine), so we see
>      behaviour like this:
>      
>        $ unshare --mount --map-root-user /bin/true; echo $?
>        unshare: unshare failed: Operation not permitted
>        1
>      
>      Handle this case by checking for the warning:
>      
>        warning: process 184732 is a zombie - the process has already terminated
>      
>      when GDB tries to attach.  If we see this warning then we assume the
>      'unshare' process failed to start correctly, in which case we report
>      the test as unsupported and perform an early return.
>      
>      Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33108
> 
> diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.exp b/gdb/testsuite/gdb.base/user-namespace-attach.exp
> index 9936bb998eb..01f3dae1693 100644
> --- a/gdb/testsuite/gdb.base/user-namespace-attach.exp
> +++ b/gdb/testsuite/gdb.base/user-namespace-attach.exp
> @@ -69,12 +69,18 @@ proc run_test { flags } {
>   
>       clean_restart
>   
> +    set saw_failure_to_start false
>       set saw_bad_warning false
>       gdb_test_multiple "attach $inferior_pid" "attach to inferior" {
>   	-re "^attach $::decimal\r\n" {
>   	    exp_continue
>   	}
>   
> +	-re "^warning: process $::decimal is a zombie - the process has already terminated\r\n" {
> +	    set saw_failure_to_start true
> +	    exp_continue
> +	}
> +
>   	-re "^warning: \[^\r\n\]+: could not open as an executable file: \[^\r\n\]+\r\n" {
>   	    set saw_bad_warning true
>   	    exp_continue
> @@ -112,6 +118,11 @@ proc run_test { flags } {
>   	}
>   
>   	-re "^$::gdb_prompt $" {
> +	    if { $saw_failure_to_start } {
> +		unsupported "unshare process failed to start"
> +		return
> +	    }
> +
>   	    gdb_assert { !$saw_bad_warning } $gdb_test_name
>   	}
>   
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] gdb: linux-namespaces: enter user namespace when appropriate
  2025-06-25 11:01           ` Tom de Vries
@ 2025-06-25 14:15             ` Andrew Burgess
  2025-06-25 14:43               ` Tom de Vries
  2025-06-25 14:43               ` Tom de Vries
  0 siblings, 2 replies; 11+ messages in thread
From: Andrew Burgess @ 2025-06-25 14:15 UTC (permalink / raw)
  To: Tom de Vries, gdb-patches; +Cc: Benjamin Berg

Tom de Vries <tdevries@suse.de> writes:

> On 6/25/25 12:34, Andrew Burgess wrote:
>> Tom de Vries <tdevries@suse.de> writes:
>> 
>>> On 6/23/25 15:56, Andrew Burgess wrote:
>>>> Andrew Burgess <aburgess@redhat.com> writes:
>>>>
>>>>> From: Benjamin Berg <benjamin@sipsolutions.net>
>>>>>
>>>>> In v2:
>>>>>
>>>>>     - Update the test to ignore a warning seen when running the test on
>>>>>       a machine with libc debug information installed, but without the
>>>>>       libc source being available, e.g.:
>>>>>
>>>>>       warning: 46     ../sysdeps/unix/sysv/linux/arm/libc-do-syscall.S: No such file or directory
>>>>>
>>>>>       This was causing some CI failures to be reported from Linaro.
>>>>>
>>>>>     - Rebased to current upstream/master.
>>>>>
>>>>> In v3:
>>>>>
>>>>>     - Same as V2, but fix the test pattern correctly this time.
>>>>>
>>>>> --
>>>>>
>>>>> The use of user namespaces is required for normal users to use mount
>>>>> namespaces.  Consider trying this as an unprivileged user:
>>>>>
>>>>>     $ unshare --mount /bin/true
>>>>>     unshare: unshare failed: Operation not permitted
>>>>>
>>>>> The problem here is that an unprivileged user doesn't have the
>>>>> required permissions to create a new mount namespace.  If, instead, we
>>>>> do this:
>>>>>
>>>>>     $ unshare --mount --map-root-user /bin/true
>>>>>
>>>>> then this will succeed.  The new option causes unshare to create a
>>>>> user namespace in which the unprivileged user is mapped to UID/GID 0,
>>>>> and so gains all privileges (inside the namespace), the user is then
>>>>> able to create the mount namespace as required.
>>>>>
>>>>> So, how does this relate to GDB?
>>>>>
>>>>> When a user attaches to a process running in a separate mount
>>>>> namespace, GDB makes use of a separate helper process (see
>>>>> linux_mntns_get_helper in nat/linux-namespaces.c), which will then use
>>>>> the `setns` function to enter (or try to enter) the mount namespace of
>>>>> the process GDB is attaching too.  The helper process will then handle
>>>>> file I/O requests received from GDB, and return the results back to
>>>>> GDB, this allows GDB to access files within the mount namespace.
>>>>>
>>>>> The problem here is that, switching to a mount namespace requires that
>>>>> a process hold CAP_SYS_CHROOT and CAP_SYS_ADMIN capabilities within
>>>>> its user namespace (actually it's a little more complex, see 'man 2
>>>>> setns').  Assuming GDB is running as an unprivileged user, then GDB
>>>>> will not have the required permissions.
>>>>>
>>>>> However, if GDB enters the user namespace that the `unshare` process
>>>>> created, then the current user will be mapped to UID/GID 0, and will
>>>>> have the required permissions.
>>>>>
>>>>> And so, this patch extends linux_mntns_access_fs (in
>>>>> nat/linux-namespace.c) to first try and switch to the user namespace
>>>>> of the inferior before trying to switch to the mount namespace.  If
>>>>> the inferior does have a user namespace, and does have elevated
>>>>> privileges within that namespace, then this first switch by GDB will
>>>>> mean that the second step, into the mount namespace, will succeed.
>>>>>
>>>>> If there is no user namespace, or the inferior doesn't have elevated
>>>>> privileges within the user namespace, then the switch into the mount
>>>>> namespace will fail, just as it currently does, and the user will need
>>>>> to give elevated privileges to GDB via some other mechanism (e.g. run
>>>>> as root).
>>>>>
>>>>> This work was originally posted here:
>>>>>
>>>>>     https://inbox.sourceware.org/gdb-patches/20230321120126.1418012-1-benjamin@sipsolutions.net
>>>>>
>>>>> I (Andrew Burgess) have made some cleanups to the code to comply with
>>>>> GDB's coding standard, and the test is entirely mine.  This commit
>>>>> message is also entirely mine -- the original message was very terse
>>>>> and required the reader to understand how the various namespaces
>>>>> work and interact.  The above is my attempt to document what I now
>>>>> understand about the problem being fixed.
>>>>>
>>>>> I've left the original author in place as the core of the GDB change
>>>>> itself is largely as originally presented, but any inaccuracies in the
>>>>> commit message, or problems with the test, are all mine.
>>>>>
>>>>> Co-Authored-by: Andrew Burgess <aburgess@redhat.com>
>>>>
>>>> I've pushed this patch.
>>>>
>>>
>>> The new test-case fails on arm32 (Linaro CI reported this, and I was
>>> able to reproduce) due to insufficient permissions:
>>> ...
>>> (gdb) attach 184732
>>> Attaching to process 184732
>>> warning: process 184732 is a zombie - the process has already terminated
>>> ptrace: Operation not permitted.
>>> (gdb) FAIL: gdb.base/user-namespace-attach.exp: flags=--mount
>>> --map-root-user: attach to inferior
>>> ...
>>>
>>> In essence, the test-case assumes:
>>> ...
>>> $ unshare --mount --map-root-user /bin/true; echo $?
>>> 0
>>> ...
>>> but we get instead:
>>> ...
>>> $ unshare --mount --map-root-user /bin/true; echo $?
>>> unshare: unshare failed: Operation not permitted
>>> 1
>>> ...
>>>
>>> Filed here ( https://sourceware.org/bugzilla/show_bug.cgi?id=33108 ).
>> 
>> Hi!
>> 
>> Thanks for raising this issue.
>> 
>> What do you think to the patch below?
>> 
>> I've tested this by passing a bogus flag to `unshare`, e.g. "unshare
>> -blahblah", which has the same effect of causing the `unshare` process
>> to exit immediately with an exit code of 1.  I now see the test reported
>> as unsupported.
>> 
>
> Hi Andrew,
>
> thanks for picking this up.
>
> FWIW, the problem with this solution is that a timeout now looks like 
> unsupported.
>
> More concretely, by doing this (on x86_64-linux, where the test-case 
> passes for me):
> ...
> diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.exp 
> b/gdb/testsuite/gdb.base/user
> -namespace-attach.exp
> index 01f3dae1693..c5ec5ef6369 100644
> --- a/gdb/testsuite/gdb.base/user-namespace-attach.exp
> +++ b/gdb/testsuite/gdb.base/user-namespace-attach.exp
> @@ -66,6 +66,7 @@ proc run_test { flags } {
>       }
>
>       set inferior_pid [spawn_id_get_pid $inferior_spawn_id]
> +    sleep 90
>
>       clean_restart
>
> ...
> I trigger the timeout of 60 seconds in the exec, and with your patch get:
> ...
> 		=== gdb Summary ===
>
> # of unsupported tests		3
> ...
> but without your patch I get:
> ...
> # of unexpected failures	6
> ...
>
> I don't think it's terribly important though.
>
> You could try the approach I proposed in the PR, or you could pursue 
> this one.
>
> In the latter case, please add a comment that a timeout may trigger the 
> same message.

You make a good point.  I think your suggestion is probably the best
approach then.  How about the patch below?

Thanks,
Andrew

---

4d0265f72da gdb/testsuite: handle failure to start process for later attach test [Andrew Burgess (2 minutes ago)]

diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.exp b/gdb/testsuite/gdb.base/user-namespace-attach.exp
index 9936bb998eb..741093c2c14 100644
--- a/gdb/testsuite/gdb.base/user-namespace-attach.exp
+++ b/gdb/testsuite/gdb.base/user-namespace-attach.exp
@@ -56,10 +56,22 @@ proc run_test { flags } {
 	set prefix ""
     }
 
+    set unshare_cmd "unshare $flags"
 
+    # Run '/bin/true' using UNSHARE_CMD.  If the flags in UNSHARE_CMD
+    # aren't supported then this will fail, this means we shouldn't
+    # spawn the command with our test executable and try attaching.
+    #
+    # This will also fail if /bin/true isn't present, or doesn't work
+    # as we expect.  But this should be fine for many targets.
+    set res [remote_exec target "$unshare_cmd /bin/true"]
+    if { [lindex $res 0] != 0 } {
+	unsupported "unshare flags not supported"
+	return
+    }
 
     set inferior_spawn_id \
-	[spawn_wait_for_attach [list "unshare $flags $::binfile"]]
+	[spawn_wait_for_attach [list "$unshare_cmd $::binfile"]]
     if { $inferior_spawn_id == -1 } {
 	unsupported "failed to spawn for attach"
 	return


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] gdb: linux-namespaces: enter user namespace when appropriate
  2025-06-25 14:15             ` Andrew Burgess
@ 2025-06-25 14:43               ` Tom de Vries
  2025-06-26 12:40                 ` Andrew Burgess
  2025-06-25 14:43               ` Tom de Vries
  1 sibling, 1 reply; 11+ messages in thread
From: Tom de Vries @ 2025-06-25 14:43 UTC (permalink / raw)
  To: Andrew Burgess, gdb-patches; +Cc: Benjamin Berg

On 6/25/25 16:15, Andrew Burgess wrote:
> Tom de Vries <tdevries@suse.de> writes:
> 
>> On 6/25/25 12:34, Andrew Burgess wrote:
>>> Tom de Vries <tdevries@suse.de> writes:
>>>
>>>> On 6/23/25 15:56, Andrew Burgess wrote:
>>>>> Andrew Burgess <aburgess@redhat.com> writes:
>>>>>
>>>>>> From: Benjamin Berg <benjamin@sipsolutions.net>
>>>>>>
>>>>>> In v2:
>>>>>>
>>>>>>      - Update the test to ignore a warning seen when running the test on
>>>>>>        a machine with libc debug information installed, but without the
>>>>>>        libc source being available, e.g.:
>>>>>>
>>>>>>        warning: 46     ../sysdeps/unix/sysv/linux/arm/libc-do-syscall.S: No such file or directory
>>>>>>
>>>>>>        This was causing some CI failures to be reported from Linaro.
>>>>>>
>>>>>>      - Rebased to current upstream/master.
>>>>>>
>>>>>> In v3:
>>>>>>
>>>>>>      - Same as V2, but fix the test pattern correctly this time.
>>>>>>
>>>>>> --
>>>>>>
>>>>>> The use of user namespaces is required for normal users to use mount
>>>>>> namespaces.  Consider trying this as an unprivileged user:
>>>>>>
>>>>>>      $ unshare --mount /bin/true
>>>>>>      unshare: unshare failed: Operation not permitted
>>>>>>
>>>>>> The problem here is that an unprivileged user doesn't have the
>>>>>> required permissions to create a new mount namespace.  If, instead, we
>>>>>> do this:
>>>>>>
>>>>>>      $ unshare --mount --map-root-user /bin/true
>>>>>>
>>>>>> then this will succeed.  The new option causes unshare to create a
>>>>>> user namespace in which the unprivileged user is mapped to UID/GID 0,
>>>>>> and so gains all privileges (inside the namespace), the user is then
>>>>>> able to create the mount namespace as required.
>>>>>>
>>>>>> So, how does this relate to GDB?
>>>>>>
>>>>>> When a user attaches to a process running in a separate mount
>>>>>> namespace, GDB makes use of a separate helper process (see
>>>>>> linux_mntns_get_helper in nat/linux-namespaces.c), which will then use
>>>>>> the `setns` function to enter (or try to enter) the mount namespace of
>>>>>> the process GDB is attaching too.  The helper process will then handle
>>>>>> file I/O requests received from GDB, and return the results back to
>>>>>> GDB, this allows GDB to access files within the mount namespace.
>>>>>>
>>>>>> The problem here is that, switching to a mount namespace requires that
>>>>>> a process hold CAP_SYS_CHROOT and CAP_SYS_ADMIN capabilities within
>>>>>> its user namespace (actually it's a little more complex, see 'man 2
>>>>>> setns').  Assuming GDB is running as an unprivileged user, then GDB
>>>>>> will not have the required permissions.
>>>>>>
>>>>>> However, if GDB enters the user namespace that the `unshare` process
>>>>>> created, then the current user will be mapped to UID/GID 0, and will
>>>>>> have the required permissions.
>>>>>>
>>>>>> And so, this patch extends linux_mntns_access_fs (in
>>>>>> nat/linux-namespace.c) to first try and switch to the user namespace
>>>>>> of the inferior before trying to switch to the mount namespace.  If
>>>>>> the inferior does have a user namespace, and does have elevated
>>>>>> privileges within that namespace, then this first switch by GDB will
>>>>>> mean that the second step, into the mount namespace, will succeed.
>>>>>>
>>>>>> If there is no user namespace, or the inferior doesn't have elevated
>>>>>> privileges within the user namespace, then the switch into the mount
>>>>>> namespace will fail, just as it currently does, and the user will need
>>>>>> to give elevated privileges to GDB via some other mechanism (e.g. run
>>>>>> as root).
>>>>>>
>>>>>> This work was originally posted here:
>>>>>>
>>>>>>      https://inbox.sourceware.org/gdb-patches/20230321120126.1418012-1-benjamin@sipsolutions.net
>>>>>>
>>>>>> I (Andrew Burgess) have made some cleanups to the code to comply with
>>>>>> GDB's coding standard, and the test is entirely mine.  This commit
>>>>>> message is also entirely mine -- the original message was very terse
>>>>>> and required the reader to understand how the various namespaces
>>>>>> work and interact.  The above is my attempt to document what I now
>>>>>> understand about the problem being fixed.
>>>>>>
>>>>>> I've left the original author in place as the core of the GDB change
>>>>>> itself is largely as originally presented, but any inaccuracies in the
>>>>>> commit message, or problems with the test, are all mine.
>>>>>>
>>>>>> Co-Authored-by: Andrew Burgess <aburgess@redhat.com>
>>>>>
>>>>> I've pushed this patch.
>>>>>
>>>>
>>>> The new test-case fails on arm32 (Linaro CI reported this, and I was
>>>> able to reproduce) due to insufficient permissions:
>>>> ...
>>>> (gdb) attach 184732
>>>> Attaching to process 184732
>>>> warning: process 184732 is a zombie - the process has already terminated
>>>> ptrace: Operation not permitted.
>>>> (gdb) FAIL: gdb.base/user-namespace-attach.exp: flags=--mount
>>>> --map-root-user: attach to inferior
>>>> ...
>>>>
>>>> In essence, the test-case assumes:
>>>> ...
>>>> $ unshare --mount --map-root-user /bin/true; echo $?
>>>> 0
>>>> ...
>>>> but we get instead:
>>>> ...
>>>> $ unshare --mount --map-root-user /bin/true; echo $?
>>>> unshare: unshare failed: Operation not permitted
>>>> 1
>>>> ...
>>>>
>>>> Filed here ( https://sourceware.org/bugzilla/show_bug.cgi?id=33108 ).
>>>
>>> Hi!
>>>
>>> Thanks for raising this issue.
>>>
>>> What do you think to the patch below?
>>>
>>> I've tested this by passing a bogus flag to `unshare`, e.g. "unshare
>>> -blahblah", which has the same effect of causing the `unshare` process
>>> to exit immediately with an exit code of 1.  I now see the test reported
>>> as unsupported.
>>>
>>
>> Hi Andrew,
>>
>> thanks for picking this up.
>>
>> FWIW, the problem with this solution is that a timeout now looks like
>> unsupported.
>>
>> More concretely, by doing this (on x86_64-linux, where the test-case
>> passes for me):
>> ...
>> diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.exp
>> b/gdb/testsuite/gdb.base/user
>> -namespace-attach.exp
>> index 01f3dae1693..c5ec5ef6369 100644
>> --- a/gdb/testsuite/gdb.base/user-namespace-attach.exp
>> +++ b/gdb/testsuite/gdb.base/user-namespace-attach.exp
>> @@ -66,6 +66,7 @@ proc run_test { flags } {
>>        }
>>
>>        set inferior_pid [spawn_id_get_pid $inferior_spawn_id]
>> +    sleep 90
>>
>>        clean_restart
>>
>> ...
>> I trigger the timeout of 60 seconds in the exec, and with your patch get:
>> ...
>> 		=== gdb Summary ===
>>
>> # of unsupported tests		3
>> ...
>> but without your patch I get:
>> ...
>> # of unexpected failures	6
>> ...
>>
>> I don't think it's terribly important though.
>>
>> You could try the approach I proposed in the PR, or you could pursue
>> this one.
>>
>> In the latter case, please add a comment that a timeout may trigger the
>> same message.
> 
> You make a good point.  I think your suggestion is probably the best
> approach then.  How about the patch below?
> 

LGTM.

I've also tested it on x86_64-linux, where the test-case still passes, 
and on arm-linux, where the test-case now results in 3 times unsupported.

Thanks,
- Tom

> Thanks,
> Andrew
> 
> ---
> 
> 4d0265f72da gdb/testsuite: handle failure to start process for later attach test [Andrew Burgess (2 minutes ago)]
> 
> diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.exp b/gdb/testsuite/gdb.base/user-namespace-attach.exp
> index 9936bb998eb..741093c2c14 100644
> --- a/gdb/testsuite/gdb.base/user-namespace-attach.exp
> +++ b/gdb/testsuite/gdb.base/user-namespace-attach.exp
> @@ -56,10 +56,22 @@ proc run_test { flags } {
>   	set prefix ""
>       }
>   
> +    set unshare_cmd "unshare $flags"
>   
> +    # Run '/bin/true' using UNSHARE_CMD.  If the flags in UNSHARE_CMD
> +    # aren't supported then this will fail, this means we shouldn't
> +    # spawn the command with our test executable and try attaching.
> +    #
> +    # This will also fail if /bin/true isn't present, or doesn't work
> +    # as we expect.  But this should be fine for many targets.
> +    set res [remote_exec target "$unshare_cmd /bin/true"]
> +    if { [lindex $res 0] != 0 } {
> +	unsupported "unshare flags not supported"
> +	return
> +    }
>   
>       set inferior_spawn_id \
> -	[spawn_wait_for_attach [list "unshare $flags $::binfile"]]
> +	[spawn_wait_for_attach [list "$unshare_cmd $::binfile"]]
>       if { $inferior_spawn_id == -1 } {
>   	unsupported "failed to spawn for attach"
>   	return
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] gdb: linux-namespaces: enter user namespace when appropriate
  2025-06-25 14:15             ` Andrew Burgess
  2025-06-25 14:43               ` Tom de Vries
@ 2025-06-25 14:43               ` Tom de Vries
  1 sibling, 0 replies; 11+ messages in thread
From: Tom de Vries @ 2025-06-25 14:43 UTC (permalink / raw)
  To: Andrew Burgess, gdb-patches; +Cc: Benjamin Berg

On 6/25/25 16:15, Andrew Burgess wrote:
> Tom de Vries <tdevries@suse.de> writes:
> 
>> On 6/25/25 12:34, Andrew Burgess wrote:
>>> Tom de Vries <tdevries@suse.de> writes:
>>>
>>>> On 6/23/25 15:56, Andrew Burgess wrote:
>>>>> Andrew Burgess <aburgess@redhat.com> writes:
>>>>>
>>>>>> From: Benjamin Berg <benjamin@sipsolutions.net>
>>>>>>
>>>>>> In v2:
>>>>>>
>>>>>>      - Update the test to ignore a warning seen when running the test on
>>>>>>        a machine with libc debug information installed, but without the
>>>>>>        libc source being available, e.g.:
>>>>>>
>>>>>>        warning: 46     ../sysdeps/unix/sysv/linux/arm/libc-do-syscall.S: No such file or directory
>>>>>>
>>>>>>        This was causing some CI failures to be reported from Linaro.
>>>>>>
>>>>>>      - Rebased to current upstream/master.
>>>>>>
>>>>>> In v3:
>>>>>>
>>>>>>      - Same as V2, but fix the test pattern correctly this time.
>>>>>>
>>>>>> --
>>>>>>
>>>>>> The use of user namespaces is required for normal users to use mount
>>>>>> namespaces.  Consider trying this as an unprivileged user:
>>>>>>
>>>>>>      $ unshare --mount /bin/true
>>>>>>      unshare: unshare failed: Operation not permitted
>>>>>>
>>>>>> The problem here is that an unprivileged user doesn't have the
>>>>>> required permissions to create a new mount namespace.  If, instead, we
>>>>>> do this:
>>>>>>
>>>>>>      $ unshare --mount --map-root-user /bin/true
>>>>>>
>>>>>> then this will succeed.  The new option causes unshare to create a
>>>>>> user namespace in which the unprivileged user is mapped to UID/GID 0,
>>>>>> and so gains all privileges (inside the namespace), the user is then
>>>>>> able to create the mount namespace as required.
>>>>>>
>>>>>> So, how does this relate to GDB?
>>>>>>
>>>>>> When a user attaches to a process running in a separate mount
>>>>>> namespace, GDB makes use of a separate helper process (see
>>>>>> linux_mntns_get_helper in nat/linux-namespaces.c), which will then use
>>>>>> the `setns` function to enter (or try to enter) the mount namespace of
>>>>>> the process GDB is attaching too.  The helper process will then handle
>>>>>> file I/O requests received from GDB, and return the results back to
>>>>>> GDB, this allows GDB to access files within the mount namespace.
>>>>>>
>>>>>> The problem here is that, switching to a mount namespace requires that
>>>>>> a process hold CAP_SYS_CHROOT and CAP_SYS_ADMIN capabilities within
>>>>>> its user namespace (actually it's a little more complex, see 'man 2
>>>>>> setns').  Assuming GDB is running as an unprivileged user, then GDB
>>>>>> will not have the required permissions.
>>>>>>
>>>>>> However, if GDB enters the user namespace that the `unshare` process
>>>>>> created, then the current user will be mapped to UID/GID 0, and will
>>>>>> have the required permissions.
>>>>>>
>>>>>> And so, this patch extends linux_mntns_access_fs (in
>>>>>> nat/linux-namespace.c) to first try and switch to the user namespace
>>>>>> of the inferior before trying to switch to the mount namespace.  If
>>>>>> the inferior does have a user namespace, and does have elevated
>>>>>> privileges within that namespace, then this first switch by GDB will
>>>>>> mean that the second step, into the mount namespace, will succeed.
>>>>>>
>>>>>> If there is no user namespace, or the inferior doesn't have elevated
>>>>>> privileges within the user namespace, then the switch into the mount
>>>>>> namespace will fail, just as it currently does, and the user will need
>>>>>> to give elevated privileges to GDB via some other mechanism (e.g. run
>>>>>> as root).
>>>>>>
>>>>>> This work was originally posted here:
>>>>>>
>>>>>>      https://inbox.sourceware.org/gdb-patches/20230321120126.1418012-1-benjamin@sipsolutions.net
>>>>>>
>>>>>> I (Andrew Burgess) have made some cleanups to the code to comply with
>>>>>> GDB's coding standard, and the test is entirely mine.  This commit
>>>>>> message is also entirely mine -- the original message was very terse
>>>>>> and required the reader to understand how the various namespaces
>>>>>> work and interact.  The above is my attempt to document what I now
>>>>>> understand about the problem being fixed.
>>>>>>
>>>>>> I've left the original author in place as the core of the GDB change
>>>>>> itself is largely as originally presented, but any inaccuracies in the
>>>>>> commit message, or problems with the test, are all mine.
>>>>>>
>>>>>> Co-Authored-by: Andrew Burgess <aburgess@redhat.com>
>>>>>
>>>>> I've pushed this patch.
>>>>>
>>>>
>>>> The new test-case fails on arm32 (Linaro CI reported this, and I was
>>>> able to reproduce) due to insufficient permissions:
>>>> ...
>>>> (gdb) attach 184732
>>>> Attaching to process 184732
>>>> warning: process 184732 is a zombie - the process has already terminated
>>>> ptrace: Operation not permitted.
>>>> (gdb) FAIL: gdb.base/user-namespace-attach.exp: flags=--mount
>>>> --map-root-user: attach to inferior
>>>> ...
>>>>
>>>> In essence, the test-case assumes:
>>>> ...
>>>> $ unshare --mount --map-root-user /bin/true; echo $?
>>>> 0
>>>> ...
>>>> but we get instead:
>>>> ...
>>>> $ unshare --mount --map-root-user /bin/true; echo $?
>>>> unshare: unshare failed: Operation not permitted
>>>> 1
>>>> ...
>>>>
>>>> Filed here ( https://sourceware.org/bugzilla/show_bug.cgi?id=33108 ).
>>>
>>> Hi!
>>>
>>> Thanks for raising this issue.
>>>
>>> What do you think to the patch below?
>>>
>>> I've tested this by passing a bogus flag to `unshare`, e.g. "unshare
>>> -blahblah", which has the same effect of causing the `unshare` process
>>> to exit immediately with an exit code of 1.  I now see the test reported
>>> as unsupported.
>>>
>>
>> Hi Andrew,
>>
>> thanks for picking this up.
>>
>> FWIW, the problem with this solution is that a timeout now looks like
>> unsupported.
>>
>> More concretely, by doing this (on x86_64-linux, where the test-case
>> passes for me):
>> ...
>> diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.exp
>> b/gdb/testsuite/gdb.base/user
>> -namespace-attach.exp
>> index 01f3dae1693..c5ec5ef6369 100644
>> --- a/gdb/testsuite/gdb.base/user-namespace-attach.exp
>> +++ b/gdb/testsuite/gdb.base/user-namespace-attach.exp
>> @@ -66,6 +66,7 @@ proc run_test { flags } {
>>        }
>>
>>        set inferior_pid [spawn_id_get_pid $inferior_spawn_id]
>> +    sleep 90
>>
>>        clean_restart
>>
>> ...
>> I trigger the timeout of 60 seconds in the exec, and with your patch get:
>> ...
>> 		=== gdb Summary ===
>>
>> # of unsupported tests		3
>> ...
>> but without your patch I get:
>> ...
>> # of unexpected failures	6
>> ...
>>
>> I don't think it's terribly important though.
>>
>> You could try the approach I proposed in the PR, or you could pursue
>> this one.
>>
>> In the latter case, please add a comment that a timeout may trigger the
>> same message.
> 
> You make a good point.  I think your suggestion is probably the best
> approach then.  How about the patch below?
> 
> Thanks,
> Andrew
> 
> ---
> 
> 4d0265f72da gdb/testsuite: handle failure to start process for later attach test [Andrew Burgess (2 minutes ago)]
> 
> diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.exp b/gdb/testsuite/gdb.base/user-namespace-attach.exp
> index 9936bb998eb..741093c2c14 100644
> --- a/gdb/testsuite/gdb.base/user-namespace-attach.exp
> +++ b/gdb/testsuite/gdb.base/user-namespace-attach.exp
> @@ -56,10 +56,22 @@ proc run_test { flags } {
>   	set prefix ""
>       }
>   
> +    set unshare_cmd "unshare $flags"
>   
> +    # Run '/bin/true' using UNSHARE_CMD.  If the flags in UNSHARE_CMD
> +    # aren't supported then this will fail, this means we shouldn't
> +    # spawn the command with our test executable and try attaching.
> +    #
> +    # This will also fail if /bin/true isn't present, or doesn't work
> +    # as we expect.  But this should be fine for many targets.
> +    set res [remote_exec target "$unshare_cmd /bin/true"]
> +    if { [lindex $res 0] != 0 } {
> +	unsupported "unshare flags not supported"
> +	return
> +    }
>   
>       set inferior_spawn_id \
> -	[spawn_wait_for_attach [list "unshare $flags $::binfile"]]
> +	[spawn_wait_for_attach [list "$unshare_cmd $::binfile"]]
>       if { $inferior_spawn_id == -1 } {
>   	unsupported "failed to spawn for attach"
>   	return
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCHv3] gdb: linux-namespaces: enter user namespace when appropriate
  2025-06-25 14:43               ` Tom de Vries
@ 2025-06-26 12:40                 ` Andrew Burgess
  0 siblings, 0 replies; 11+ messages in thread
From: Andrew Burgess @ 2025-06-26 12:40 UTC (permalink / raw)
  To: Tom de Vries, gdb-patches; +Cc: Benjamin Berg

Tom de Vries <tdevries@suse.de> writes:

> On 6/25/25 16:15, Andrew Burgess wrote:
>> Tom de Vries <tdevries@suse.de> writes:
>> 
>>> On 6/25/25 12:34, Andrew Burgess wrote:
>>>> Tom de Vries <tdevries@suse.de> writes:
>>>>
>>>>> On 6/23/25 15:56, Andrew Burgess wrote:
>>>>>> Andrew Burgess <aburgess@redhat.com> writes:
>>>>>>
>>>>>>> From: Benjamin Berg <benjamin@sipsolutions.net>
>>>>>>>
>>>>>>> In v2:
>>>>>>>
>>>>>>>      - Update the test to ignore a warning seen when running the test on
>>>>>>>        a machine with libc debug information installed, but without the
>>>>>>>        libc source being available, e.g.:
>>>>>>>
>>>>>>>        warning: 46     ../sysdeps/unix/sysv/linux/arm/libc-do-syscall.S: No such file or directory
>>>>>>>
>>>>>>>        This was causing some CI failures to be reported from Linaro.
>>>>>>>
>>>>>>>      - Rebased to current upstream/master.
>>>>>>>
>>>>>>> In v3:
>>>>>>>
>>>>>>>      - Same as V2, but fix the test pattern correctly this time.
>>>>>>>
>>>>>>> --
>>>>>>>
>>>>>>> The use of user namespaces is required for normal users to use mount
>>>>>>> namespaces.  Consider trying this as an unprivileged user:
>>>>>>>
>>>>>>>      $ unshare --mount /bin/true
>>>>>>>      unshare: unshare failed: Operation not permitted
>>>>>>>
>>>>>>> The problem here is that an unprivileged user doesn't have the
>>>>>>> required permissions to create a new mount namespace.  If, instead, we
>>>>>>> do this:
>>>>>>>
>>>>>>>      $ unshare --mount --map-root-user /bin/true
>>>>>>>
>>>>>>> then this will succeed.  The new option causes unshare to create a
>>>>>>> user namespace in which the unprivileged user is mapped to UID/GID 0,
>>>>>>> and so gains all privileges (inside the namespace), the user is then
>>>>>>> able to create the mount namespace as required.
>>>>>>>
>>>>>>> So, how does this relate to GDB?
>>>>>>>
>>>>>>> When a user attaches to a process running in a separate mount
>>>>>>> namespace, GDB makes use of a separate helper process (see
>>>>>>> linux_mntns_get_helper in nat/linux-namespaces.c), which will then use
>>>>>>> the `setns` function to enter (or try to enter) the mount namespace of
>>>>>>> the process GDB is attaching too.  The helper process will then handle
>>>>>>> file I/O requests received from GDB, and return the results back to
>>>>>>> GDB, this allows GDB to access files within the mount namespace.
>>>>>>>
>>>>>>> The problem here is that, switching to a mount namespace requires that
>>>>>>> a process hold CAP_SYS_CHROOT and CAP_SYS_ADMIN capabilities within
>>>>>>> its user namespace (actually it's a little more complex, see 'man 2
>>>>>>> setns').  Assuming GDB is running as an unprivileged user, then GDB
>>>>>>> will not have the required permissions.
>>>>>>>
>>>>>>> However, if GDB enters the user namespace that the `unshare` process
>>>>>>> created, then the current user will be mapped to UID/GID 0, and will
>>>>>>> have the required permissions.
>>>>>>>
>>>>>>> And so, this patch extends linux_mntns_access_fs (in
>>>>>>> nat/linux-namespace.c) to first try and switch to the user namespace
>>>>>>> of the inferior before trying to switch to the mount namespace.  If
>>>>>>> the inferior does have a user namespace, and does have elevated
>>>>>>> privileges within that namespace, then this first switch by GDB will
>>>>>>> mean that the second step, into the mount namespace, will succeed.
>>>>>>>
>>>>>>> If there is no user namespace, or the inferior doesn't have elevated
>>>>>>> privileges within the user namespace, then the switch into the mount
>>>>>>> namespace will fail, just as it currently does, and the user will need
>>>>>>> to give elevated privileges to GDB via some other mechanism (e.g. run
>>>>>>> as root).
>>>>>>>
>>>>>>> This work was originally posted here:
>>>>>>>
>>>>>>>      https://inbox.sourceware.org/gdb-patches/20230321120126.1418012-1-benjamin@sipsolutions.net
>>>>>>>
>>>>>>> I (Andrew Burgess) have made some cleanups to the code to comply with
>>>>>>> GDB's coding standard, and the test is entirely mine.  This commit
>>>>>>> message is also entirely mine -- the original message was very terse
>>>>>>> and required the reader to understand how the various namespaces
>>>>>>> work and interact.  The above is my attempt to document what I now
>>>>>>> understand about the problem being fixed.
>>>>>>>
>>>>>>> I've left the original author in place as the core of the GDB change
>>>>>>> itself is largely as originally presented, but any inaccuracies in the
>>>>>>> commit message, or problems with the test, are all mine.
>>>>>>>
>>>>>>> Co-Authored-by: Andrew Burgess <aburgess@redhat.com>
>>>>>>
>>>>>> I've pushed this patch.
>>>>>>
>>>>>
>>>>> The new test-case fails on arm32 (Linaro CI reported this, and I was
>>>>> able to reproduce) due to insufficient permissions:
>>>>> ...
>>>>> (gdb) attach 184732
>>>>> Attaching to process 184732
>>>>> warning: process 184732 is a zombie - the process has already terminated
>>>>> ptrace: Operation not permitted.
>>>>> (gdb) FAIL: gdb.base/user-namespace-attach.exp: flags=--mount
>>>>> --map-root-user: attach to inferior
>>>>> ...
>>>>>
>>>>> In essence, the test-case assumes:
>>>>> ...
>>>>> $ unshare --mount --map-root-user /bin/true; echo $?
>>>>> 0
>>>>> ...
>>>>> but we get instead:
>>>>> ...
>>>>> $ unshare --mount --map-root-user /bin/true; echo $?
>>>>> unshare: unshare failed: Operation not permitted
>>>>> 1
>>>>> ...
>>>>>
>>>>> Filed here ( https://sourceware.org/bugzilla/show_bug.cgi?id=33108 ).
>>>>
>>>> Hi!
>>>>
>>>> Thanks for raising this issue.
>>>>
>>>> What do you think to the patch below?
>>>>
>>>> I've tested this by passing a bogus flag to `unshare`, e.g. "unshare
>>>> -blahblah", which has the same effect of causing the `unshare` process
>>>> to exit immediately with an exit code of 1.  I now see the test reported
>>>> as unsupported.
>>>>
>>>
>>> Hi Andrew,
>>>
>>> thanks for picking this up.
>>>
>>> FWIW, the problem with this solution is that a timeout now looks like
>>> unsupported.
>>>
>>> More concretely, by doing this (on x86_64-linux, where the test-case
>>> passes for me):
>>> ...
>>> diff --git a/gdb/testsuite/gdb.base/user-namespace-attach.exp
>>> b/gdb/testsuite/gdb.base/user
>>> -namespace-attach.exp
>>> index 01f3dae1693..c5ec5ef6369 100644
>>> --- a/gdb/testsuite/gdb.base/user-namespace-attach.exp
>>> +++ b/gdb/testsuite/gdb.base/user-namespace-attach.exp
>>> @@ -66,6 +66,7 @@ proc run_test { flags } {
>>>        }
>>>
>>>        set inferior_pid [spawn_id_get_pid $inferior_spawn_id]
>>> +    sleep 90
>>>
>>>        clean_restart
>>>
>>> ...
>>> I trigger the timeout of 60 seconds in the exec, and with your patch get:
>>> ...
>>> 		=== gdb Summary ===
>>>
>>> # of unsupported tests		3
>>> ...
>>> but without your patch I get:
>>> ...
>>> # of unexpected failures	6
>>> ...
>>>
>>> I don't think it's terribly important though.
>>>
>>> You could try the approach I proposed in the PR, or you could pursue
>>> this one.
>>>
>>> In the latter case, please add a comment that a timeout may trigger the
>>> same message.
>> 
>> You make a good point.  I think your suggestion is probably the best
>> approach then.  How about the patch below?
>> 
>
> LGTM.
>
> I've also tested it on x86_64-linux, where the test-case still passes, 
> and on arm-linux, where the test-case now results in 3 times unsupported.
>

I pushed this patch.

Thanks,
Andrew


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2025-06-26 12:41 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-06-10 16:57 [PATCH] gdb: linux-namespaces: enter user namespace when appropriate Andrew Burgess
2025-06-12 15:25 ` [PATCHv2] " Andrew Burgess
2025-06-13  9:17   ` [PATCHv3] " Andrew Burgess
2025-06-23 13:56     ` Andrew Burgess
2025-06-25  9:48       ` Tom de Vries
2025-06-25 10:34         ` Andrew Burgess
2025-06-25 11:01           ` Tom de Vries
2025-06-25 14:15             ` Andrew Burgess
2025-06-25 14:43               ` Tom de Vries
2025-06-26 12:40                 ` Andrew Burgess
2025-06-25 14:43               ` Tom de Vries

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox