nat: linux-namespaces: Also enter user namespace

Message ID 20230321120126.1418012-1-benjamin@sipsolutions.net
State New
Headers
Series nat: linux-namespaces: Also enter user namespace |

Commit Message

Terekhov, Mikhail via Gdb-patches March 21, 2023, 12:01 p.m. UTC
  From: Benjamin Berg <benjamin@sipsolutions.net>

The use of user namespaces is required for normal users to use mount
namespaces. Also entering the user namespace means that a normal user
can debug processes created that way.
---
 gdb/nat/linux-namespaces.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)
  

Comments

Tom Tromey Sept. 19, 2023, 6:45 p.m. UTC | #1
>>>>> benjamin--- via Gdb-patches <gdb-patches@sourceware.org> writes:

> From: Benjamin Berg <benjamin@sipsolutions.net>
> The use of user namespaces is required for normal users to use mount
> namespaces. Also entering the user namespace means that a normal user
> can debug processes created that way.

I was going through my email backlog and didn't see a reply to this.

I don't know anything about mount namespaces.  How would one test this
patch?  Is it possible to modify some existing test to exercise the new
code?

Tom
  
Benjamin Berg Sept. 20, 2023, 8:15 a.m. UTC | #2
On Tue, 2023-09-19 at 12:45 -0600, Tom Tromey wrote:
> > > > > 
> > From: Benjamin Berg <benjamin@sipsolutions.net>
> > The use of user namespaces is required for normal users to use mount
> > namespaces. Also entering the user namespace means that a normal user
> > can debug processes created that way.
> 
> I was going through my email backlog and didn't see a reply to this.
> 
> I don't know anything about mount namespaces.  How would one test this
> patch?  Is it possible to modify some existing test to exercise the new
> code?

You can easily reproduce it by starting a target process as normal user
using:

$ unshare --mount -r target-process

Then, simply try to attach GDB to i. Without the patch, GDB will not be
able to enter the mount namespace unless it is run using e.g. "sudo"
instead of the original user (in the same way as "unshare --mount"
without "-r" will not work for the normal user). With the patch it will
succeed.

The patch works great for me solving my namespaces problem, but I never
checked if there is a test case that could be modified/extended. If
there is a test case, then it would likely already exercise the new
code path and I would also expect such a test to fail already if run as
a non-root user.

Benjamin
  
Benjamin Berg Dec. 20, 2023, 11:42 a.m. UTC | #3
Hi Tom,

is there something I can do to unblock this patch?

I need it internally, and it is kind of annoying that I need to rebuild
GDB for this simple fix so that I don't need to run the debugger with
sudo.

Benjamin

On Tue, 2023-09-19 at 12:45 -0600, Tom Tromey wrote:
> > > > > > benjamin--- via Gdb-patches <gdb-patches@sourceware.org>
> > > > > > writes:
> 
> > From: Benjamin Berg <benjamin@sipsolutions.net>
> > The use of user namespaces is required for normal users to use
> > mount
> > namespaces. Also entering the user namespace means that a normal
> > user
> > can debug processes created that way.
> 
> I was going through my email backlog and didn't see a reply to this.
> 
> I don't know anything about mount namespaces.  How would one test
> this
> patch?  Is it possible to modify some existing test to exercise the
> new
> code?
> 
> Tom
>
  

Patch

diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c
index 4b1fee18425..95277b403d7 100644
--- a/gdb/nat/linux-namespaces.c
+++ b/gdb/nat/linux-namespaces.c
@@ -880,11 +880,12 @@  enum mnsh_fs_code
 static enum mnsh_fs_code
 linux_mntns_access_fs (pid_t pid)
 {
-  struct linux_ns *ns;
+  struct linux_ns *ns, *ns_user;
   struct stat sb;
   struct linux_mnsh *helper;
   ssize_t size;
-  int fd;
+  int fd, fd_user = -1;
+  int result, error;
 
   if (pid == getpid ())
     return MNSH_FS_DIRECT;
@@ -901,6 +902,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,13 +913,23 @@  linux_mntns_access_fs (pid_t pid)
   if (sb.st_ino == ns->id)
     return MNSH_FS_DIRECT;
 
+  ns_user = linux_ns_get_namespace (LINUX_NS_USER);
+  if (ns_user != NULL)
+    fd_user = gdb_open_cloexec (linux_ns_filename (ns_user, pid), O_RDONLY, 0).release ();
+
   helper = linux_mntns_get_helper ();
   if (helper == NULL)
     return MNSH_FS_ERROR;
 
   if (sb.st_ino != helper->nsid)
     {
-      int result, error;
+      /* Try to enter user namespace */
+      if (fd_user >= 0)
+	{
+	  mnsh_send_setns (helper, fd_user, 0);
+	  if (mnsh_recv_int (helper, &result, &error) != 0)
+	    warning (_("Could not enter user namespace"));
+	}
 
       size = mnsh_send_setns (helper, fd, 0);
       if (size < 0)