f710c03bf499d309a26874fdc3ee55c26415403e
[deliverable/binutils-gdb.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 <sys/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 (" -> %ld\n", 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 (%ld)\n", size);
430
431 mnsh_maybe_mourn_peer ();
432
433 return size;
434 }
435
436 /* Check for truncation. */
437 if (size < fixed_size || (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)))
438 {
439 if (debug_linux_namespaces)
440 debug_printf ("namespace-helper: recv truncated (%ld 0x%x)\n",
441 size, msg.msg_flags);
442
443 mnsh_maybe_mourn_peer ();
444
445 errno = EBADMSG;
446 return -1;
447 }
448
449 /* Unpack the file descriptor if supplied. */
450 cmsg = CMSG_FIRSTHDR (&msg);
451 if (cmsg != NULL
452 && cmsg->cmsg_len == CMSG_LEN (sizeof (int))
453 && cmsg->cmsg_level == SOL_SOCKET
454 && cmsg->cmsg_type == SCM_RIGHTS)
455 memcpy (fd, CMSG_DATA (cmsg), sizeof (int));
456 else
457 *fd = -1;
458
459 if (debug_linux_namespaces)
460 {
461 debug_printf ("mnsh: recv: ");
462 mnsh_debug_print_message (*type, *fd, *int1, *int2, buf,
463 size - fixed_size);
464 debug_printf ("\n");
465 }
466
467 /* Return the number of bytes of data in BUF. */
468 return size - fixed_size;
469 }
470
471 /* Shortcuts for returning results from the helper. */
472
473 #define mnsh_return_int(sock, result, error) \
474 mnsh_send_message (sock, MNSH_RET_INT, -1, result, error, NULL, 0)
475
476 #define mnsh_return_fd(sock, fd, error) \
477 mnsh_send_message (sock, MNSH_RET_FD, \
478 (fd) < 0 ? -1 : (fd), \
479 (fd) < 0 ? (fd) : 0, \
480 error, NULL, 0)
481
482 #define mnsh_return_intstr(sock, result, buf, bufsiz, error) \
483 mnsh_send_message (sock, MNSH_RET_INTSTR, -1, result, error, \
484 buf, bufsiz)
485
486 /* Handle a MNSH_REQ_SETNS message. Must be async-signal-safe. */
487
488 static ssize_t
489 mnsh_handle_setns (int sock, int fd, int nstype)
490 {
491 int result = setns (fd, nstype);
492
493 return mnsh_return_int (sock, result, errno);
494 }
495
496 /* Handle a MNSH_REQ_OPEN message. Must be async-signal-safe. */
497
498 static ssize_t
499 mnsh_handle_open (int sock, const char *filename,
500 int flags, mode_t mode)
501 {
502 int fd = gdb_open_cloexec (filename, flags, mode);
503 ssize_t result = mnsh_return_fd (sock, fd, errno);
504
505 if (fd >= 0)
506 close (fd);
507
508 return result;
509 }
510
511 /* Handle a MNSH_REQ_UNLINK message. Must be async-signal-safe. */
512
513 static ssize_t
514 mnsh_handle_unlink (int sock, const char *filename)
515 {
516 int result = unlink (filename);
517
518 return mnsh_return_int (sock, result, errno);
519 }
520
521 /* Handle a MNSH_REQ_READLINK message. Must be async-signal-safe. */
522
523 static ssize_t
524 mnsh_handle_readlink (int sock, const char *filename)
525 {
526 char buf[PATH_MAX];
527 int len = readlink (filename, buf, sizeof (buf));
528
529 return mnsh_return_intstr (sock, len,
530 buf, len < 0 ? 0 : len,
531 errno);
532 }
533
534 /* The helper process. Never returns. Must be async-signal-safe. */
535
536 static void mnsh_main (int sock) ATTRIBUTE_NORETURN;
537
538 static void
539 mnsh_main (int sock)
540 {
541 while (1)
542 {
543 enum mnsh_msg_type type;
544 int fd, int1, int2;
545 char buf[PATH_MAX];
546 ssize_t size, response = -1;
547
548 size = mnsh_recv_message (sock, &type,
549 &fd, &int1, &int2,
550 buf, sizeof (buf));
551
552 if (size >= 0 && size < sizeof (buf))
553 {
554 switch (type)
555 {
556 case MNSH_REQ_SETNS:
557 if (fd > 0)
558 response = mnsh_handle_setns (sock, fd, int1);
559 break;
560
561 case MNSH_REQ_OPEN:
562 if (size > 0 && buf[size - 1] == '\0')
563 response = mnsh_handle_open (sock, buf, int1, int2);
564 break;
565
566 case MNSH_REQ_UNLINK:
567 if (size > 0 && buf[size - 1] == '\0')
568 response = mnsh_handle_unlink (sock, buf);
569 break;
570
571 case MNSH_REQ_READLINK:
572 if (size > 0 && buf[size - 1] == '\0')
573 response = mnsh_handle_readlink (sock, buf);
574 break;
575
576 default:
577 break; /* Handled below. */
578 }
579 }
580
581 /* Close any file descriptors we were passed. */
582 if (fd >= 0)
583 close (fd);
584
585 /* Can't handle this message, bounce it back. */
586 if (response < 0)
587 {
588 if (size < 0)
589 size = 0;
590
591 mnsh_send_message (sock, MNSH_MSG_ERROR,
592 -1, int1, int2, buf, size);
593 }
594 }
595 }
596
597 /* The mount namespace helper process. */
598
599 struct linux_mnsh
600 {
601 /* PID of helper. */
602 pid_t pid;
603
604 /* Socket for communication. */
605 int sock;
606
607 /* ID of the mount namespace the helper is currently in. */
608 ino_t nsid;
609 };
610
611 /* In the helper process this is set to the PID of the process that
612 created the helper (i.e. GDB or gdbserver). In the main process
613 this is set to zero. Used by mnsh_maybe_mourn_peer. */
614 static int mnsh_creator_pid = 0;
615
616 /* Return an object representing the mount namespace helper process.
617 If no mount namespace helper process has been started then start
618 one. Return NULL if no mount namespace helper process could be
619 started. */
620
621 static struct linux_mnsh *
622 linux_mntns_get_helper (void)
623 {
624 static struct linux_mnsh *helper = NULL;
625
626 if (helper == NULL)
627 {
628 static struct linux_mnsh h;
629 struct linux_ns *ns;
630 pid_t helper_creator = getpid ();
631 int sv[2];
632
633 ns = linux_ns_get_namespace (LINUX_NS_MNT);
634 if (ns == NULL)
635 return NULL;
636
637 if (gdb_socketpair_cloexec (AF_UNIX, SOCK_STREAM, 0, sv) < 0)
638 return NULL;
639
640 h.pid = fork ();
641 if (h.pid < 0)
642 {
643 int saved_errno = errno;
644
645 close (sv[0]);
646 close (sv[1]);
647
648 errno = saved_errno;
649 return NULL;
650 }
651
652 if (h.pid == 0)
653 {
654 /* Child process. */
655 close (sv[0]);
656
657 mnsh_creator_pid = helper_creator;
658
659 /* Debug printing isn't async-signal-safe. */
660 debug_linux_namespaces = 0;
661
662 mnsh_main (sv[1]);
663 }
664
665 /* Parent process. */
666 close (sv[1]);
667
668 helper = &h;
669 helper->sock = sv[0];
670 helper->nsid = ns->id;
671
672 if (debug_linux_namespaces)
673 debug_printf ("Started mount namespace helper process %d\n",
674 helper->pid);
675 }
676
677 return helper;
678 }
679
680 /* Check whether the other process died and act accordingly. Called
681 whenever a socket error occurs, from both the main process and the
682 helper. Must be async-signal-safe when called from the helper. */
683
684 static void
685 mnsh_maybe_mourn_peer (void)
686 {
687 if (mnsh_creator_pid != 0)
688 {
689 /* We're in the helper. Check if our current parent is the
690 process that started us. If it isn't, then our original
691 parent died and we've been reparented. Exit immediately
692 if that's the case. */
693 if (getppid () != mnsh_creator_pid)
694 _exit (0);
695 }
696 else
697 {
698 /* We're in the main process. */
699
700 struct linux_mnsh *helper = linux_mntns_get_helper ();
701 int status;
702 pid_t pid;
703
704 if (helper->pid < 0)
705 {
706 /* We already mourned it. */
707 return;
708 }
709
710 pid = waitpid (helper->pid, &status, WNOHANG);
711 if (pid == 0)
712 {
713 /* The helper is still alive. */
714 return;
715 }
716 else if (pid == -1)
717 {
718 if (errno == ECHILD)
719 warning (_("mount namespace helper vanished?"));
720 else
721 internal_warning (__FILE__, __LINE__,
722 _("unhandled error %d"), errno);
723 }
724 else if (pid == helper->pid)
725 {
726 if (WIFEXITED (status))
727 warning (_("mount namespace helper exited with status %d"),
728 WEXITSTATUS (status));
729 else if (WIFSIGNALED (status))
730 warning (_("mount namespace helper killed by signal %d"),
731 WTERMSIG (status));
732 else
733 internal_warning (__FILE__, __LINE__,
734 _("unhandled status %d"), status);
735 }
736 else
737 internal_warning (__FILE__, __LINE__,
738 _("unknown pid %d"), pid);
739
740 /* Something unrecoverable happened. */
741 helper->pid = -1;
742 }
743 }
744
745 /* Shortcuts for sending messages to the helper. */
746
747 #define mnsh_send_setns(helper, fd, nstype) \
748 mnsh_send_message (helper->sock, MNSH_REQ_SETNS, fd, nstype, 0, \
749 NULL, 0)
750
751 #define mnsh_send_open(helper, filename, flags, mode) \
752 mnsh_send_message (helper->sock, MNSH_REQ_OPEN, -1, flags, mode, \
753 filename, strlen (filename) + 1)
754
755 #define mnsh_send_unlink(helper, filename) \
756 mnsh_send_message (helper->sock, MNSH_REQ_UNLINK, -1, 0, 0, \
757 filename, strlen (filename) + 1)
758
759 #define mnsh_send_readlink(helper, filename) \
760 mnsh_send_message (helper->sock, MNSH_REQ_READLINK, -1, 0, 0, \
761 filename, strlen (filename) + 1)
762
763 /* Receive a message from the helper. Issue an assertion failure if
764 the message isn't a correctly-formatted MNSH_RET_INT. Set RESULT
765 and ERROR and return 0 on success. Set errno and return -1 on
766 failure. */
767
768 static int
769 mnsh_recv_int (struct linux_mnsh *helper, int *result, int *error)
770 {
771 enum mnsh_msg_type type;
772 char buf[PATH_MAX];
773 ssize_t size;
774 int fd;
775
776 size = mnsh_recv_message (helper->sock, &type, &fd,
777 result, error,
778 buf, sizeof (buf));
779 if (size < 0)
780 return -1;
781
782 gdb_assert (type == MNSH_RET_INT);
783 gdb_assert (fd == -1);
784 gdb_assert (size == 0);
785
786 return 0;
787 }
788
789 /* Receive a message from the helper. Issue an assertion failure if
790 the message isn't a correctly-formatted MNSH_RET_FD. Set FD and
791 ERROR and return 0 on success. Set errno and return -1 on
792 failure. */
793
794 static int
795 mnsh_recv_fd (struct linux_mnsh *helper, int *fd, int *error)
796 {
797 enum mnsh_msg_type type;
798 char buf[PATH_MAX];
799 ssize_t size;
800 int result;
801
802 size = mnsh_recv_message (helper->sock, &type, fd,
803 &result, error,
804 buf, sizeof (buf));
805 if (size < 0)
806 return -1;
807
808 gdb_assert (type == MNSH_RET_FD);
809 gdb_assert (size == 0);
810
811 if (*fd < 0)
812 {
813 gdb_assert (result < 0);
814 *fd = result;
815 }
816
817 return 0;
818 }
819
820 /* Receive a message from the helper. Issue an assertion failure if
821 the message isn't a correctly-formatted MNSH_RET_INTSTR. Set
822 RESULT and ERROR and optionally store data in BUF, then return
823 the number of bytes stored in BUF on success (this may be zero).
824 Set errno and return -1 on error. */
825
826 static ssize_t
827 mnsh_recv_intstr (struct linux_mnsh *helper,
828 int *result, int *error,
829 void *buf, int bufsiz)
830 {
831 enum mnsh_msg_type type;
832 ssize_t size;
833 int fd;
834
835 size = mnsh_recv_message (helper->sock, &type, &fd,
836 result, error,
837 buf, bufsiz);
838
839 if (size < 0)
840 return -1;
841
842 gdb_assert (type == MNSH_RET_INTSTR);
843 gdb_assert (fd == -1);
844
845 return size;
846 }
847
848 /* Return values for linux_mntns_access_fs. */
849
850 enum mnsh_fs_code
851 {
852 /* Something went wrong, errno is set. */
853 MNSH_FS_ERROR = -1,
854
855 /* The main process is in the correct mount namespace.
856 The caller should access the filesystem directly. */
857 MNSH_FS_DIRECT,
858
859 /* The helper is in the correct mount namespace.
860 The caller should access the filesystem via the helper. */
861 MNSH_FS_HELPER
862 };
863
864 /* Return a value indicating how the caller should access the
865 mount namespace of process PID. */
866
867 static enum mnsh_fs_code
868 linux_mntns_access_fs (pid_t pid)
869 {
870 struct cleanup *old_chain;
871 struct linux_ns *ns;
872 struct stat sb;
873 struct linux_mnsh *helper;
874 ssize_t size;
875 int fd, saved_errno;
876
877 if (pid == getpid ())
878 return MNSH_FS_DIRECT;
879
880 ns = linux_ns_get_namespace (LINUX_NS_MNT);
881 if (ns == NULL)
882 return MNSH_FS_DIRECT;
883
884 old_chain = make_cleanup (null_cleanup, NULL);
885
886 fd = gdb_open_cloexec (linux_ns_filename (ns, pid), O_RDONLY, 0);
887 if (fd < 0)
888 goto error;
889
890 old_chain = make_cleanup_close (fd);
891
892 if (fstat (fd, &sb) != 0)
893 goto error;
894
895 if (sb.st_ino == ns->id)
896 {
897 do_cleanups (old_chain);
898
899 return MNSH_FS_DIRECT;
900 }
901
902 helper = linux_mntns_get_helper ();
903 if (helper == NULL)
904 goto error;
905
906 if (sb.st_ino != helper->nsid)
907 {
908 int result, error;
909
910 size = mnsh_send_setns (helper, fd, 0);
911 if (size < 0)
912 goto error;
913
914 if (mnsh_recv_int (helper, &result, &error) != 0)
915 goto error;
916
917 if (result != 0)
918 {
919 /* ENOSYS indicates that an entire function is unsupported
920 (it's not appropriate for our versions of open/unlink/
921 readlink to sometimes return with ENOSYS depending on how
922 they're called) so we convert ENOSYS to ENOTSUP if setns
923 fails. */
924 if (error == ENOSYS)
925 error = ENOTSUP;
926
927 errno = error;
928 goto error;
929 }
930
931 helper->nsid = sb.st_ino;
932 }
933
934 do_cleanups (old_chain);
935
936 return MNSH_FS_HELPER;
937
938 error:
939 saved_errno = errno;
940
941 do_cleanups (old_chain);
942
943 errno = saved_errno;
944 return MNSH_FS_ERROR;
945 }
946
947 /* See nat/linux-namespaces.h. */
948
949 int
950 linux_mntns_open_cloexec (pid_t pid, const char *filename,
951 int flags, mode_t mode)
952 {
953 enum mnsh_fs_code access = linux_mntns_access_fs (pid);
954 struct linux_mnsh *helper;
955 int fd, error;
956 ssize_t size;
957
958 if (access == MNSH_FS_ERROR)
959 return -1;
960
961 if (access == MNSH_FS_DIRECT)
962 return gdb_open_cloexec (filename, flags, mode);
963
964 gdb_assert (access == MNSH_FS_HELPER);
965
966 helper = linux_mntns_get_helper ();
967
968 size = mnsh_send_open (helper, filename, flags, mode);
969 if (size < 0)
970 return -1;
971
972 if (mnsh_recv_fd (helper, &fd, &error) != 0)
973 return -1;
974
975 if (fd < 0)
976 errno = error;
977
978 return fd;
979 }
980
981 /* See nat/linux-namespaces.h. */
982
983 int
984 linux_mntns_unlink (pid_t pid, const char *filename)
985 {
986 enum mnsh_fs_code access = linux_mntns_access_fs (pid);
987 struct linux_mnsh *helper;
988 int ret, error;
989 ssize_t size;
990
991 if (access == MNSH_FS_ERROR)
992 return -1;
993
994 if (access == MNSH_FS_DIRECT)
995 return unlink (filename);
996
997 gdb_assert (access == MNSH_FS_HELPER);
998
999 helper = linux_mntns_get_helper ();
1000
1001 size = mnsh_send_unlink (helper, filename);
1002 if (size < 0)
1003 return -1;
1004
1005 if (mnsh_recv_int (helper, &ret, &error) != 0)
1006 return -1;
1007
1008 if (ret != 0)
1009 errno = error;
1010
1011 return ret;
1012 }
1013
1014 /* See nat/linux-namespaces.h. */
1015
1016 ssize_t
1017 linux_mntns_readlink (pid_t pid, const char *filename,
1018 char *buf, size_t bufsiz)
1019 {
1020 enum mnsh_fs_code access = linux_mntns_access_fs (pid);
1021 struct linux_mnsh *helper;
1022 int ret, error;
1023 ssize_t size;
1024
1025 if (access == MNSH_FS_ERROR)
1026 return -1;
1027
1028 if (access == MNSH_FS_DIRECT)
1029 return readlink (filename, buf, bufsiz);
1030
1031 gdb_assert (access == MNSH_FS_HELPER);
1032
1033 helper = linux_mntns_get_helper ();
1034
1035 size = mnsh_send_readlink (helper, filename);
1036 if (size < 0)
1037 return -1;
1038
1039 size = mnsh_recv_intstr (helper, &ret, &error, buf, bufsiz);
1040
1041 if (size < 0)
1042 {
1043 ret = -1;
1044 errno = error;
1045 }
1046 else
1047 gdb_assert (size == ret);
1048
1049 return ret;
1050 }
This page took 0.050206 seconds and 3 git commands to generate.