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