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