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