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