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