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