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