GDBserver
linux-namespaces.c
Go to the documentation of this file.
1 /* Linux namespaces(7) support.
2 
3  Copyright (C) 2015-2018 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 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. */
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 *
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 
222  {
223  /* A communication error occurred. Receipt of this message
224  by either end will cause an assertion failure in the main
225  process. */
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. */
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. */
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. */
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. */
252 
253  /* Responses, sent to the main process from the helper. */
254 
255  /* Return an integer in INT1 and errno in INT2. */
257 
258  /* Return a file descriptor in FD if one was opened or an
259  integer in INT1 otherwise. Return errno in INT2. */
261 
262  /* Return an integer in INT1, errno in INT2, and optionally
263  some data in BUF. */
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
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)
391 
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  {
448  debug_printf ("namespace-helper: recv failed (%s)\n",
449  pulongest (size));
450 
452 
453  return size;
454  }
455 
456  /* Check for truncation. */
457  if (size < fixed_size || (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)))
458  {
460  debug_printf ("namespace-helper: recv truncated (%s 0x%x)\n",
461  pulongest (size), msg.msg_flags);
462 
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 
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 
612  -1, int1, int2, buf, size);
613  }
614  }
615 }
616 
617 /* The mount namespace helper process. */
618 
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 *
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 
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. */
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 
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
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 
871  {
872  /* Something went wrong, errno is set. */
874 
875  /* The main process is in the correct mount namespace.
876  The caller should access the filesystem directly. */
878 
879  /* The helper is in the correct mount namespace.
880  The caller should access the filesystem via the 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
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 
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 }
static ssize_t mnsh_handle_unlink(int sock, const char *filename)
int gdb_socketpair_cloexec(int domain, int style, int protocol, int filedes[2])
#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)
static ssize_t mnsh_handle_readlink(int sock, const char *filename)
linux_ns_type
void warning(const char *fmt,...)
Definition: errors.c:26
void * memset(T *s, int c, size_t n)=delete
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:35
#define mnsh_send_readlink(helper, filename)
#define mnsh_send_unlink(helper, filename)
int debug_linux_namespaces
void null_cleanup(void *arg)
Definition: cleanups.c:294
static ssize_t mnsh_handle_open(int sock, const char *filename, int flags, mode_t mode)
static pid_t do_fork(void)
#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
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:116
struct cleanup * make_cleanup_close(int fd)
Definition: filestuff.c:413
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)
#define errno
Definition: wincecompat.h:24
#define gdb_assert(expr)
Definition: gdb_assert.h:32
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)
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
void * alloca(size_t)
#define MSG_CMSG_CLOEXEC
static int do_setns(int fd, int nstype)
void perror_with_name(const char *string)
Definition: utils.c:57
int gdb_open_cloexec(const char *filename, int flags, unsigned long mode)
Definition: filestuff.c:283
#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
void do_cleanups(struct cleanup *old_chain)
Definition: cleanups.c:174