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