xref: /netbsd-src/external/gpl3/gdb/dist/gdb/nat/linux-namespaces.c (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
1 /* Linux namespaces(7) support.
2 
3    Copyright (C) 2015-2019 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 #include "common/common-defs.h"
21 #include "nat/linux-namespaces.h"
22 #include "common/filestuff.h"
23 #include <fcntl.h>
24 #include <sys/syscall.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <sys/socket.h>
28 #include "common/gdb_wait.h"
29 #include <signal.h>
30 #include <sched.h>
31 
32 /* See nat/linux-namespaces.h.  */
33 int debug_linux_namespaces;
34 
35 /* Handle systems without fork.  */
36 
37 static inline pid_t
38 do_fork (void)
39 {
40 #ifdef HAVE_FORK
41   return fork ();
42 #else
43   errno = ENOSYS;
44   return -1;
45 #endif
46 }
47 
48 /* Handle systems without setns.  */
49 
50 static inline int
51 do_setns (int fd, int nstype)
52 {
53 #ifdef HAVE_SETNS
54   return setns (fd, nstype);
55 #elif defined __NR_setns
56   return syscall (__NR_setns, fd, nstype);
57 #else
58   errno = ENOSYS;
59   return -1;
60 #endif
61 }
62 
63 /* Handle systems without MSG_CMSG_CLOEXEC.  */
64 
65 #ifndef MSG_CMSG_CLOEXEC
66 #define MSG_CMSG_CLOEXEC 0
67 #endif
68 
69 /* A Linux namespace.  */
70 
71 struct linux_ns
72 {
73   /* Filename of this namespace's entries in /proc/PID/ns.  */
74   const char *filename;
75 
76   /* Nonzero if this object has been initialized.  */
77   int initialized;
78 
79   /* Nonzero if this namespace is supported on this system.  */
80   int supported;
81 
82   /* ID of the namespace the calling process is in, used to
83      see if other processes share the namespace.  The code in
84      this file assumes that the calling process never changes
85      namespace.  */
86   ino_t id;
87 };
88 
89 /* Return the absolute filename of process PID's /proc/PID/ns
90    entry for namespace NS.  The returned value persists until
91    this function is next called.  */
92 
93 static const char *
94 linux_ns_filename (struct linux_ns *ns, int pid)
95 {
96   static char filename[PATH_MAX];
97 
98   gdb_assert (pid > 0);
99   xsnprintf (filename, sizeof (filename), "/proc/%d/ns/%s", pid,
100 	     ns->filename);
101 
102   return filename;
103 }
104 
105 /* Return a representation of the caller's TYPE namespace, or
106    NULL if TYPE namespaces are not supported on this system.  */
107 
108 static struct linux_ns *
109 linux_ns_get_namespace (enum linux_ns_type type)
110 {
111   static struct linux_ns namespaces[NUM_LINUX_NS_TYPES] =
112     {
113       { "ipc" },
114       { "mnt" },
115       { "net" },
116       { "pid" },
117       { "user" },
118       { "uts" },
119     };
120   struct linux_ns *ns;
121 
122   gdb_assert (type >= 0 && type < NUM_LINUX_NS_TYPES);
123   ns = &namespaces[type];
124 
125   if (!ns->initialized)
126     {
127       struct stat sb;
128 
129       if (stat (linux_ns_filename (ns, getpid ()), &sb) == 0)
130 	{
131 	  ns->id = sb.st_ino;
132 
133 	  ns->supported = 1;
134 	}
135 
136       ns->initialized = 1;
137     }
138 
139   return ns->supported ? ns : NULL;
140 }
141 
142 /* See nat/linux-namespaces.h.  */
143 
144 int
145 linux_ns_same (pid_t pid, enum linux_ns_type type)
146 {
147   struct linux_ns *ns = linux_ns_get_namespace (type);
148   const char *filename;
149   struct stat sb;
150 
151   /* If the kernel does not support TYPE namespaces then there's
152      effectively only one TYPE namespace that all processes on
153      the system share.  */
154   if (ns == NULL)
155     return 1;
156 
157   /* Stat PID's TYPE namespace entry to get the namespace ID.  This
158      might fail if the process died, or if we don't have the right
159      permissions (though we should be attached by this time so this
160      seems unlikely).  In any event, we can't make any decisions and
161      must throw.  */
162   filename = linux_ns_filename (ns, pid);
163   if (stat (filename, &sb) != 0)
164     perror_with_name (filename);
165 
166   return sb.st_ino == ns->id;
167 }
168 
169 /* We need to use setns(2) to handle filesystem access in mount
170    namespaces other than our own, but this isn't permitted for
171    multithreaded processes.  GDB is multithreaded when compiled
172    with Guile support, and may become multithreaded if compiled
173    with Python support.  We deal with this by spawning a single-
174    threaded helper process to access mount namespaces other than
175    our own.
176 
177    The helper process is started the first time a call to setns
178    is required.  The main process (GDB or gdbserver) communicates
179    with the helper via sockets, passing file descriptors where
180    necessary using SCM_RIGHTS.  Once started the helper process
181    runs until the main process terminates; when this happens the
182    helper will receive socket errors, notice that its parent died,
183    and exit accordingly (see mnsh_maybe_mourn_peer).
184 
185    The protocol is that the main process sends a request in a
186    single message, and the helper replies to every message it
187    receives with a single-message response.  If the helper
188    receives a message it does not understand it will reply with
189    a MNSH_MSG_ERROR message.  The main process checks all
190    responses it receives with gdb_assert, so if the main process
191    receives something unexpected (which includes MNSH_MSG_ERROR)
192    the main process will call internal_error.
193 
194    For avoidance of doubt, if the helper process receives a
195    message it doesn't handle it will reply with MNSH_MSG_ERROR.
196    If the main process receives MNSH_MSG_ERROR at any time then
197    it will call internal_error.  If internal_error causes the
198    main process to exit, the helper will notice this and also
199    exit.  The helper will not exit until the main process
200    terminates, so if the user continues through internal_error
201    the helper will still be there awaiting requests from the
202    main process.
203 
204    Messages in both directions have the following payload:
205 
206    - TYPE (enum mnsh_msg_type, always sent) - the message type.
207    - INT1 and
208    - INT2 (int, always sent, though not always used) - two
209            values whose meaning is message-type-dependent.
210 	   See enum mnsh_msg_type documentation below.
211    - FD (int, optional, sent using SCM_RIGHTS) - an open file
212          descriptor.
213    - BUF (unstructured data, optional) - some data with message-
214           type-dependent meaning.
215 
216    Note that the helper process is the child of a call to fork,
217    so all code in the helper must be async-signal-safe.  */
218 
219 /* Mount namespace helper message types.  */
220 
221 enum mnsh_msg_type
222   {
223     /* A communication error occurred.  Receipt of this message
224        by either end will cause an assertion failure in the main
225        process.  */
226     MNSH_MSG_ERROR,
227 
228     /* Requests, sent from the main process to the helper.  */
229 
230     /* A request that the helper call setns.  Arguments should
231        be passed in FD and INT1.  Helper should respond with a
232        MNSH_RET_INT.  */
233     MNSH_REQ_SETNS,
234 
235     /* A request that the helper call open.  Arguments should
236        be passed in BUF, INT1 and INT2.  The filename (in BUF)
237        should include a terminating NUL character.  The helper
238        should respond with a MNSH_RET_FD.  */
239     MNSH_REQ_OPEN,
240 
241     /* A request that the helper call unlink.  The single
242        argument (the filename) should be passed in BUF, and
243        should include a terminating NUL character.  The helper
244        should respond with a MNSH_RET_INT.  */
245     MNSH_REQ_UNLINK,
246 
247     /* A request that the helper call readlink.  The single
248        argument (the filename) should be passed in BUF, and
249        should include a terminating NUL character.  The helper
250        should respond with a MNSH_RET_INTSTR.  */
251     MNSH_REQ_READLINK,
252 
253     /* Responses, sent to the main process from the helper.  */
254 
255     /* Return an integer in INT1 and errno in INT2.  */
256     MNSH_RET_INT,
257 
258     /* Return a file descriptor in FD if one was opened or an
259        integer in INT1 otherwise.  Return errno in INT2.  */
260     MNSH_RET_FD,
261 
262     /* Return an integer in INT1, errno in INT2, and optionally
263        some data in BUF.  */
264     MNSH_RET_INTSTR,
265   };
266 
267 /* Print a string representation of a message using debug_printf.
268    This function is not async-signal-safe so should never be
269    called from the helper.  */
270 
271 static void
272 mnsh_debug_print_message (enum mnsh_msg_type type,
273 			  int fd, int int1, int int2,
274 			  const void *buf, int bufsiz)
275 {
276   gdb_byte *c = (gdb_byte *) buf;
277   gdb_byte *cl = c + bufsiz;
278 
279   switch (type)
280     {
281     case MNSH_MSG_ERROR:
282       debug_printf ("ERROR");
283       break;
284 
285     case MNSH_REQ_SETNS:
286       debug_printf ("SETNS");
287       break;
288 
289     case MNSH_REQ_OPEN:
290       debug_printf ("OPEN");
291       break;
292 
293     case MNSH_REQ_UNLINK:
294       debug_printf ("UNLINK");
295       break;
296 
297     case MNSH_REQ_READLINK:
298       debug_printf ("READLINK");
299       break;
300 
301     case MNSH_RET_INT:
302       debug_printf ("INT");
303       break;
304 
305     case MNSH_RET_FD:
306       debug_printf ("FD");
307       break;
308 
309     case MNSH_RET_INTSTR:
310       debug_printf ("INTSTR");
311       break;
312 
313     default:
314       debug_printf ("unknown-packet-%d", type);
315     }
316 
317   debug_printf (" %d %d %d \"", fd, int1, int2);
318 
319   for (; c < cl; c++)
320     debug_printf (*c >= ' ' && *c <= '~' ? "%c" : "\\%o", *c);
321 
322   debug_printf ("\"");
323 }
324 
325 /* Forward declaration.  */
326 
327 static void mnsh_maybe_mourn_peer (void);
328 
329 /* Send a message.  The argument SOCK is the file descriptor of the
330    sending socket, the other arguments are the payload to send.
331    Return the number of bytes sent on success.  Return -1 on failure
332    and set errno appropriately.  This function is called by both the
333    main process and the helper so must be async-signal-safe.  */
334 
335 static ssize_t
336 mnsh_send_message (int sock, enum mnsh_msg_type type,
337 		   int fd, int int1, int int2,
338 		   const void *buf, int bufsiz)
339 {
340   struct msghdr msg;
341   struct iovec iov[4];
342   char fdbuf[CMSG_SPACE (sizeof (fd))];
343   ssize_t size;
344 
345   /* Build the basic TYPE, INT1, INT2 message.  */
346   memset (&msg, 0, sizeof (msg));
347   msg.msg_iov = iov;
348 
349   iov[0].iov_base = &type;
350   iov[0].iov_len = sizeof (type);
351   iov[1].iov_base = &int1;
352   iov[1].iov_len = sizeof (int1);
353   iov[2].iov_base = &int2;
354   iov[2].iov_len = sizeof (int2);
355 
356   msg.msg_iovlen = 3;
357 
358   /* Append BUF if supplied.  */
359   if (buf != NULL && bufsiz > 0)
360     {
361       iov[3].iov_base = alloca (bufsiz);
362       memcpy (iov[3].iov_base, buf, bufsiz);
363       iov[3].iov_len = bufsiz;
364 
365       msg.msg_iovlen ++;
366     }
367 
368   /* Attach FD if supplied.  */
369   if (fd >= 0)
370     {
371       struct cmsghdr *cmsg;
372 
373       msg.msg_control = fdbuf;
374       msg.msg_controllen = sizeof (fdbuf);
375 
376       cmsg = CMSG_FIRSTHDR (&msg);
377       cmsg->cmsg_level = SOL_SOCKET;
378       cmsg->cmsg_type = SCM_RIGHTS;
379       cmsg->cmsg_len = CMSG_LEN (sizeof (int));
380 
381       memcpy (CMSG_DATA (cmsg), &fd, sizeof (int));
382 
383       msg.msg_controllen = cmsg->cmsg_len;
384     }
385 
386   /* Send the message.  */
387   size = sendmsg (sock, &msg, 0);
388 
389   if (size < 0)
390     mnsh_maybe_mourn_peer ();
391 
392   if (debug_linux_namespaces)
393     {
394       debug_printf ("mnsh: send: ");
395       mnsh_debug_print_message (type, fd, int1, int2, buf, bufsiz);
396       debug_printf (" -> %s\n", pulongest (size));
397     }
398 
399   return size;
400 }
401 
402 /* Receive a message.  The argument SOCK is the file descriptor of
403    the receiving socket, the other arguments point to storage for
404    the received payload.  Returns the number of bytes stored into
405    BUF on success, which may be zero in the event no BUF was sent.
406    Return -1 on failure and set errno appropriately.  This function
407    is called from both the main process and the helper and must be
408    async-signal-safe.  */
409 
410 static ssize_t
411 mnsh_recv_message (int sock, enum mnsh_msg_type *type,
412 		   int *fd, int *int1, int *int2,
413 		   void *buf, int bufsiz)
414 {
415   struct msghdr msg;
416   struct iovec iov[4];
417   char fdbuf[CMSG_SPACE (sizeof (*fd))];
418   struct cmsghdr *cmsg;
419   ssize_t size, fixed_size;
420   int i;
421 
422   /* Build the message to receive data into.  */
423   memset (&msg, 0, sizeof (msg));
424   msg.msg_iov = iov;
425 
426   iov[0].iov_base = type;
427   iov[0].iov_len = sizeof (*type);
428   iov[1].iov_base = int1;
429   iov[1].iov_len = sizeof (*int1);
430   iov[2].iov_base = int2;
431   iov[2].iov_len = sizeof (*int2);
432   iov[3].iov_base = buf;
433   iov[3].iov_len = bufsiz;
434 
435   msg.msg_iovlen = 4;
436 
437   for (fixed_size = i = 0; i < msg.msg_iovlen - 1; i++)
438     fixed_size += iov[i].iov_len;
439 
440   msg.msg_control = fdbuf;
441   msg.msg_controllen = sizeof (fdbuf);
442 
443   /* Receive the message.  */
444   size = recvmsg (sock, &msg, MSG_CMSG_CLOEXEC);
445   if (size < 0)
446     {
447       if (debug_linux_namespaces)
448 	debug_printf ("namespace-helper: recv failed (%s)\n",
449 		      pulongest (size));
450 
451       mnsh_maybe_mourn_peer ();
452 
453       return size;
454     }
455 
456   /* Check for truncation.  */
457   if (size < fixed_size || (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)))
458     {
459       if (debug_linux_namespaces)
460 	debug_printf ("namespace-helper: recv truncated (%s 0x%x)\n",
461 		      pulongest (size), msg.msg_flags);
462 
463       mnsh_maybe_mourn_peer ();
464 
465       errno = EBADMSG;
466       return -1;
467     }
468 
469   /* Unpack the file descriptor if supplied.  */
470   cmsg = CMSG_FIRSTHDR (&msg);
471   if (cmsg != NULL
472       && cmsg->cmsg_len == CMSG_LEN (sizeof (int))
473       && cmsg->cmsg_level == SOL_SOCKET
474       && cmsg->cmsg_type == SCM_RIGHTS)
475     memcpy (fd, CMSG_DATA (cmsg), sizeof (int));
476   else
477     *fd = -1;
478 
479   if (debug_linux_namespaces)
480     {
481       debug_printf ("mnsh: recv: ");
482       mnsh_debug_print_message (*type, *fd, *int1, *int2, buf,
483 				size - fixed_size);
484       debug_printf ("\n");
485     }
486 
487   /* Return the number of bytes of data in BUF.  */
488   return size - fixed_size;
489 }
490 
491 /* Shortcuts for returning results from the helper.  */
492 
493 #define mnsh_return_int(sock, result, error) \
494   mnsh_send_message (sock, MNSH_RET_INT, -1, result, error, NULL, 0)
495 
496 #define mnsh_return_fd(sock, fd, error) \
497   mnsh_send_message (sock, MNSH_RET_FD, \
498 		     (fd) < 0 ? -1 : (fd), \
499 		     (fd) < 0 ? (fd) : 0, \
500 		     error, NULL, 0)
501 
502 #define mnsh_return_intstr(sock, result, buf, bufsiz, error) \
503   mnsh_send_message (sock, MNSH_RET_INTSTR, -1, result, error, \
504 		     buf, bufsiz)
505 
506 /* Handle a MNSH_REQ_SETNS message.  Must be async-signal-safe.  */
507 
508 static ssize_t
509 mnsh_handle_setns (int sock, int fd, int nstype)
510 {
511   int result = do_setns (fd, nstype);
512 
513   return mnsh_return_int (sock, result, errno);
514 }
515 
516 /* Handle a MNSH_REQ_OPEN message.  Must be async-signal-safe.  */
517 
518 static ssize_t
519 mnsh_handle_open (int sock, const char *filename,
520 		  int flags, mode_t mode)
521 {
522   int fd = gdb_open_cloexec (filename, flags, mode);
523   ssize_t result = mnsh_return_fd (sock, fd, errno);
524 
525   if (fd >= 0)
526     close (fd);
527 
528   return result;
529 }
530 
531 /* Handle a MNSH_REQ_UNLINK message.  Must be async-signal-safe.  */
532 
533 static ssize_t
534 mnsh_handle_unlink (int sock, const char *filename)
535 {
536   int result = unlink (filename);
537 
538   return mnsh_return_int (sock, result, errno);
539 }
540 
541 /* Handle a MNSH_REQ_READLINK message.  Must be async-signal-safe.  */
542 
543 static ssize_t
544 mnsh_handle_readlink (int sock, const char *filename)
545 {
546   char buf[PATH_MAX];
547   int len = readlink (filename, buf, sizeof (buf));
548 
549   return mnsh_return_intstr (sock, len,
550 			     buf, len < 0 ? 0 : len,
551 			     errno);
552 }
553 
554 /* The helper process.  Never returns.  Must be async-signal-safe.  */
555 
556 static void mnsh_main (int sock) ATTRIBUTE_NORETURN;
557 
558 static void
559 mnsh_main (int sock)
560 {
561   while (1)
562     {
563       enum mnsh_msg_type type;
564       int fd, int1, int2;
565       char buf[PATH_MAX];
566       ssize_t size, response = -1;
567 
568       size = mnsh_recv_message (sock, &type,
569 				&fd, &int1, &int2,
570 				buf, sizeof (buf));
571 
572       if (size >= 0 && size < sizeof (buf))
573 	{
574 	  switch (type)
575 	    {
576 	    case MNSH_REQ_SETNS:
577 	      if (fd > 0)
578 		response = mnsh_handle_setns (sock, fd, int1);
579 	      break;
580 
581 	    case MNSH_REQ_OPEN:
582 	      if (size > 0 && buf[size - 1] == '\0')
583 		response = mnsh_handle_open (sock, buf, int1, int2);
584 	      break;
585 
586 	    case MNSH_REQ_UNLINK:
587 	      if (size > 0 && buf[size - 1] == '\0')
588 		response = mnsh_handle_unlink (sock, buf);
589 	      break;
590 
591 	    case MNSH_REQ_READLINK:
592 	      if (size > 0 && buf[size - 1] == '\0')
593 		response = mnsh_handle_readlink (sock, buf);
594 	      break;
595 
596 	    default:
597 	      break; /* Handled below.  */
598 	    }
599 	}
600 
601       /* Close any file descriptors we were passed.  */
602       if (fd >= 0)
603 	close (fd);
604 
605       /* Can't handle this message, bounce it back.  */
606       if (response < 0)
607 	{
608 	  if (size < 0)
609 	    size = 0;
610 
611 	  mnsh_send_message (sock, MNSH_MSG_ERROR,
612 			     -1, int1, int2, buf, size);
613 	}
614     }
615 }
616 
617 /* The mount namespace helper process.  */
618 
619 struct linux_mnsh
620 {
621   /* PID of helper.  */
622   pid_t pid;
623 
624   /* Socket for communication.  */
625   int sock;
626 
627   /* ID of the mount namespace the helper is currently in.  */
628   ino_t nsid;
629 };
630 
631 /* In the helper process this is set to the PID of the process that
632    created the helper (i.e. GDB or gdbserver).  In the main process
633    this is set to zero.  Used by mnsh_maybe_mourn_peer.  */
634 static int mnsh_creator_pid = 0;
635 
636 /* Return an object representing the mount namespace helper process.
637    If no mount namespace helper process has been started then start
638    one.  Return NULL if no mount namespace helper process could be
639    started.  */
640 
641 static struct linux_mnsh *
642 linux_mntns_get_helper (void)
643 {
644   static struct linux_mnsh *helper = NULL;
645 
646   if (helper == NULL)
647     {
648       static struct linux_mnsh h;
649       struct linux_ns *ns;
650       pid_t helper_creator = getpid ();
651       int sv[2];
652 
653       ns = linux_ns_get_namespace (LINUX_NS_MNT);
654       if (ns == NULL)
655 	return NULL;
656 
657       if (gdb_socketpair_cloexec (AF_UNIX, SOCK_STREAM, 0, sv) < 0)
658 	return NULL;
659 
660       h.pid = do_fork ();
661       if (h.pid < 0)
662 	{
663 	  int saved_errno = errno;
664 
665 	  close (sv[0]);
666 	  close (sv[1]);
667 
668 	  errno = saved_errno;
669 	  return NULL;
670 	}
671 
672       if (h.pid == 0)
673 	{
674 	  /* Child process.  */
675 	  close (sv[0]);
676 
677 	  mnsh_creator_pid = helper_creator;
678 
679 	  /* Debug printing isn't async-signal-safe.  */
680 	  debug_linux_namespaces = 0;
681 
682 	  mnsh_main (sv[1]);
683 	}
684 
685       /* Parent process.  */
686       close (sv[1]);
687 
688       helper = &h;
689       helper->sock = sv[0];
690       helper->nsid = ns->id;
691 
692       if (debug_linux_namespaces)
693 	debug_printf ("Started mount namespace helper process %d\n",
694 		      helper->pid);
695     }
696 
697   return helper;
698 }
699 
700 /* Check whether the other process died and act accordingly.  Called
701    whenever a socket error occurs, from both the main process and the
702    helper.  Must be async-signal-safe when called from the helper.  */
703 
704 static void
705 mnsh_maybe_mourn_peer (void)
706 {
707   if (mnsh_creator_pid != 0)
708     {
709       /* We're in the helper.  Check if our current parent is the
710 	 process that started us.  If it isn't, then our original
711 	 parent died and we've been reparented.  Exit immediately
712 	 if that's the case.  */
713       if (getppid () != mnsh_creator_pid)
714 	_exit (0);
715     }
716   else
717     {
718       /* We're in the main process.  */
719 
720       struct linux_mnsh *helper = linux_mntns_get_helper ();
721       int status;
722       pid_t pid;
723 
724       if (helper->pid < 0)
725 	{
726 	  /* We already mourned it.  */
727 	  return;
728 	}
729 
730       pid = waitpid (helper->pid, &status, WNOHANG);
731       if (pid == 0)
732 	{
733 	  /* The helper is still alive.  */
734 	  return;
735 	}
736       else if (pid == -1)
737 	{
738 	  if (errno == ECHILD)
739 	    warning (_("mount namespace helper vanished?"));
740 	  else
741 	    internal_warning (__FILE__, __LINE__,
742 			      _("unhandled error %d"), errno);
743 	}
744       else if (pid == helper->pid)
745 	{
746 	  if (WIFEXITED (status))
747 	    warning (_("mount namespace helper exited with status %d"),
748 		     WEXITSTATUS (status));
749 	  else if (WIFSIGNALED (status))
750 	    warning (_("mount namespace helper killed by signal %d"),
751 		     WTERMSIG (status));
752 	  else
753 	    internal_warning (__FILE__, __LINE__,
754 			      _("unhandled status %d"), status);
755 	}
756       else
757 	internal_warning (__FILE__, __LINE__,
758 			  _("unknown pid %d"), pid);
759 
760       /* Something unrecoverable happened.  */
761       helper->pid = -1;
762     }
763 }
764 
765 /* Shortcuts for sending messages to the helper.  */
766 
767 #define mnsh_send_setns(helper, fd, nstype) \
768   mnsh_send_message (helper->sock, MNSH_REQ_SETNS, fd, nstype, 0, \
769 		     NULL, 0)
770 
771 #define mnsh_send_open(helper, filename, flags, mode) \
772   mnsh_send_message (helper->sock, MNSH_REQ_OPEN, -1, flags, mode, \
773     		     filename, strlen (filename) + 1)
774 
775 #define mnsh_send_unlink(helper, filename) \
776   mnsh_send_message (helper->sock, MNSH_REQ_UNLINK, -1, 0, 0, \
777     		     filename, strlen (filename) + 1)
778 
779 #define mnsh_send_readlink(helper, filename) \
780   mnsh_send_message (helper->sock, MNSH_REQ_READLINK, -1, 0, 0, \
781     		     filename, strlen (filename) + 1)
782 
783 /* Receive a message from the helper.  Issue an assertion failure if
784    the message isn't a correctly-formatted MNSH_RET_INT.  Set RESULT
785    and ERROR and return 0 on success.  Set errno and return -1 on
786    failure.  */
787 
788 static int
789 mnsh_recv_int (struct linux_mnsh *helper, int *result, int *error)
790 {
791   enum mnsh_msg_type type;
792   char buf[PATH_MAX];
793   ssize_t size;
794   int fd;
795 
796   size = mnsh_recv_message (helper->sock, &type, &fd,
797 			    result, error,
798 			    buf, sizeof (buf));
799   if (size < 0)
800     return -1;
801 
802   gdb_assert (type == MNSH_RET_INT);
803   gdb_assert (fd == -1);
804   gdb_assert (size == 0);
805 
806   return 0;
807 }
808 
809 /* Receive a message from the helper.  Issue an assertion failure if
810    the message isn't a correctly-formatted MNSH_RET_FD.  Set FD and
811    ERROR and return 0 on success.  Set errno and return -1 on
812    failure.  */
813 
814 static int
815 mnsh_recv_fd (struct linux_mnsh *helper, int *fd, int *error)
816 {
817   enum mnsh_msg_type type;
818   char buf[PATH_MAX];
819   ssize_t size;
820   int result;
821 
822   size = mnsh_recv_message (helper->sock, &type, fd,
823 			    &result, error,
824 			    buf, sizeof (buf));
825   if (size < 0)
826     return -1;
827 
828   gdb_assert (type == MNSH_RET_FD);
829   gdb_assert (size == 0);
830 
831   if (*fd < 0)
832     {
833       gdb_assert (result < 0);
834       *fd = result;
835     }
836 
837   return 0;
838 }
839 
840 /* Receive a message from the helper.  Issue an assertion failure if
841    the message isn't a correctly-formatted MNSH_RET_INTSTR.  Set
842    RESULT and ERROR and optionally store data in BUF, then return
843    the number of bytes stored in BUF on success (this may be zero).
844    Set errno and return -1 on error.  */
845 
846 static ssize_t
847 mnsh_recv_intstr (struct linux_mnsh *helper,
848 		  int *result, int *error,
849 		  void *buf, int bufsiz)
850 {
851   enum mnsh_msg_type type;
852   ssize_t size;
853   int fd;
854 
855   size = mnsh_recv_message (helper->sock, &type, &fd,
856 			    result, error,
857 			    buf, bufsiz);
858 
859   if (size < 0)
860     return -1;
861 
862   gdb_assert (type == MNSH_RET_INTSTR);
863   gdb_assert (fd == -1);
864 
865   return size;
866 }
867 
868 /* Return values for linux_mntns_access_fs.  */
869 
870 enum mnsh_fs_code
871   {
872     /* Something went wrong, errno is set.  */
873     MNSH_FS_ERROR = -1,
874 
875     /* The main process is in the correct mount namespace.
876        The caller should access the filesystem directly.  */
877     MNSH_FS_DIRECT,
878 
879     /* The helper is in the correct mount namespace.
880        The caller should access the filesystem via the helper.  */
881     MNSH_FS_HELPER
882   };
883 
884 /* Return a value indicating how the caller should access the
885    mount namespace of process PID.  */
886 
887 static enum mnsh_fs_code
888 linux_mntns_access_fs (pid_t pid)
889 {
890   struct cleanup *old_chain;
891   struct linux_ns *ns;
892   struct stat sb;
893   struct linux_mnsh *helper;
894   ssize_t size;
895   int fd, saved_errno;
896 
897   if (pid == getpid ())
898     return MNSH_FS_DIRECT;
899 
900   ns = linux_ns_get_namespace (LINUX_NS_MNT);
901   if (ns == NULL)
902     return MNSH_FS_DIRECT;
903 
904   old_chain = make_cleanup (null_cleanup, NULL);
905 
906   fd = gdb_open_cloexec (linux_ns_filename (ns, pid), O_RDONLY, 0);
907   if (fd < 0)
908     goto error;
909 
910   make_cleanup_close (fd);
911 
912   if (fstat (fd, &sb) != 0)
913     goto error;
914 
915   if (sb.st_ino == ns->id)
916     {
917       do_cleanups (old_chain);
918 
919       return MNSH_FS_DIRECT;
920     }
921 
922   helper = linux_mntns_get_helper ();
923   if (helper == NULL)
924     goto error;
925 
926   if (sb.st_ino != helper->nsid)
927     {
928       int result, error;
929 
930       size = mnsh_send_setns (helper, fd, 0);
931       if (size < 0)
932 	goto error;
933 
934       if (mnsh_recv_int (helper, &result, &error) != 0)
935 	goto error;
936 
937       if (result != 0)
938 	{
939 	  /* ENOSYS indicates that an entire function is unsupported
940 	     (it's not appropriate for our versions of open/unlink/
941 	     readlink to sometimes return with ENOSYS depending on how
942 	     they're called) so we convert ENOSYS to ENOTSUP if setns
943 	     fails.  */
944 	  if (error == ENOSYS)
945 	    error = ENOTSUP;
946 
947 	  errno = error;
948 	  goto error;
949 	}
950 
951       helper->nsid = sb.st_ino;
952     }
953 
954   do_cleanups (old_chain);
955 
956   return MNSH_FS_HELPER;
957 
958 error:
959   saved_errno = errno;
960 
961   do_cleanups (old_chain);
962 
963   errno = saved_errno;
964   return MNSH_FS_ERROR;
965 }
966 
967 /* See nat/linux-namespaces.h.  */
968 
969 int
970 linux_mntns_open_cloexec (pid_t pid, const char *filename,
971 			  int flags, mode_t mode)
972 {
973   enum mnsh_fs_code access = linux_mntns_access_fs (pid);
974   struct linux_mnsh *helper;
975   int fd, error;
976   ssize_t size;
977 
978   if (access == MNSH_FS_ERROR)
979     return -1;
980 
981   if (access == MNSH_FS_DIRECT)
982     return gdb_open_cloexec (filename, flags, mode);
983 
984   gdb_assert (access == MNSH_FS_HELPER);
985 
986   helper = linux_mntns_get_helper ();
987 
988   size = mnsh_send_open (helper, filename, flags, mode);
989   if (size < 0)
990     return -1;
991 
992   if (mnsh_recv_fd (helper, &fd, &error) != 0)
993     return -1;
994 
995   if (fd < 0)
996     errno = error;
997 
998   return fd;
999 }
1000 
1001 /* See nat/linux-namespaces.h.  */
1002 
1003 int
1004 linux_mntns_unlink (pid_t pid, const char *filename)
1005 {
1006   enum mnsh_fs_code access = linux_mntns_access_fs (pid);
1007   struct linux_mnsh *helper;
1008   int ret, error;
1009   ssize_t size;
1010 
1011   if (access == MNSH_FS_ERROR)
1012     return -1;
1013 
1014   if (access == MNSH_FS_DIRECT)
1015     return unlink (filename);
1016 
1017   gdb_assert (access == MNSH_FS_HELPER);
1018 
1019   helper = linux_mntns_get_helper ();
1020 
1021   size = mnsh_send_unlink (helper, filename);
1022   if (size < 0)
1023     return -1;
1024 
1025   if (mnsh_recv_int (helper, &ret, &error) != 0)
1026     return -1;
1027 
1028   if (ret != 0)
1029     errno = error;
1030 
1031   return ret;
1032 }
1033 
1034 /* See nat/linux-namespaces.h.  */
1035 
1036 ssize_t
1037 linux_mntns_readlink (pid_t pid, const char *filename,
1038 		      char *buf, size_t bufsiz)
1039 {
1040   enum mnsh_fs_code access = linux_mntns_access_fs (pid);
1041   struct linux_mnsh *helper;
1042   int ret, error;
1043   ssize_t size;
1044 
1045   if (access == MNSH_FS_ERROR)
1046     return -1;
1047 
1048   if (access == MNSH_FS_DIRECT)
1049     return readlink (filename, buf, bufsiz);
1050 
1051   gdb_assert (access == MNSH_FS_HELPER);
1052 
1053   helper = linux_mntns_get_helper ();
1054 
1055   size = mnsh_send_readlink (helper, filename);
1056   if (size < 0)
1057     return -1;
1058 
1059   size = mnsh_recv_intstr (helper, &ret, &error, buf, bufsiz);
1060 
1061   if (size < 0)
1062     {
1063       ret = -1;
1064       errno = error;
1065     }
1066   else
1067     gdb_assert (size == ret);
1068 
1069   return ret;
1070 }
1071