1 /* $OpenBSD: monitor.c,v 1.83 2023/02/08 08:03:11 tb Exp $ */ 2 3 /* 4 * Copyright (c) 2003 H�kan Olsson. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/socket.h> 29 #include <sys/ioctl.h> 30 #include <sys/stat.h> 31 #include <sys/wait.h> 32 #include <netinet/in.h> 33 34 #include <dirent.h> 35 #include <errno.h> 36 #include <fcntl.h> 37 #include <pwd.h> 38 #include <signal.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 #include <limits.h> 43 44 #include <regex.h> 45 #include <keynote.h> 46 47 #include "conf.h" 48 #include "log.h" 49 #include "monitor.h" 50 #include "policy.h" 51 #include "ui.h" 52 #include "util.h" 53 #include "pf_key_v2.h" 54 55 struct monitor_state { 56 pid_t pid; 57 int s; 58 char root[PATH_MAX]; 59 } m_state; 60 61 extern char *pid_file; 62 63 extern void set_slave_signals(void); 64 65 /* Private functions. */ 66 static void must_read(void *, size_t); 67 static void must_write(const void *, size_t); 68 69 static void m_priv_getfd(void); 70 static void m_priv_setsockopt(void); 71 static void m_priv_req_readdir(void); 72 static void m_priv_bind(void); 73 static void m_priv_pfkey_open(void); 74 static int m_priv_local_sanitize_path(const char *, size_t, int); 75 static int m_priv_check_sockopt(int, int); 76 static int m_priv_check_bind(const struct sockaddr *, socklen_t); 77 78 static void set_monitor_signals(void); 79 static void sig_pass_to_chld(int); 80 81 /* 82 * Public functions, unprivileged. 83 */ 84 85 /* Setup monitor context, fork, drop child privs. */ 86 pid_t 87 monitor_init(int debug) 88 { 89 struct passwd *pw; 90 int p[2]; 91 92 bzero(&m_state, sizeof m_state); 93 94 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, p) != 0) 95 log_fatal("monitor_init: socketpair() failed"); 96 97 pw = getpwnam(ISAKMPD_PRIVSEP_USER); 98 if (pw == NULL) 99 log_fatalx("monitor_init: getpwnam(\"%s\") failed", 100 ISAKMPD_PRIVSEP_USER); 101 strlcpy(m_state.root, pw->pw_dir, sizeof m_state.root); 102 103 set_monitor_signals(); 104 m_state.pid = fork(); 105 106 if (m_state.pid == -1) 107 log_fatal("monitor_init: fork of unprivileged child failed"); 108 if (m_state.pid == 0) { 109 /* The child process drops privileges. */ 110 set_slave_signals(); 111 112 if (chroot(pw->pw_dir) != 0 || chdir("/") != 0) 113 log_fatal("monitor_init: chroot failed"); 114 115 if (setgroups(1, &pw->pw_gid) == -1 || 116 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 117 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 118 log_fatal("monitor_init: can't drop privileges"); 119 120 m_state.s = p[0]; 121 close(p[1]); 122 123 LOG_DBG((LOG_MISC, 10, 124 "monitor_init: privileges dropped for child process")); 125 } else { 126 /* Privileged monitor. */ 127 setproctitle("monitor [priv]"); 128 129 m_state.s = p[1]; 130 close(p[0]); 131 } 132 133 /* With "-dd", stop and wait here. For gdb "attach" etc. */ 134 if (debug > 1) { 135 log_print("monitor_init: stopped %s PID %d fd %d%s", 136 m_state.pid ? "priv" : "child", getpid(), m_state.s, 137 m_state.pid ? ", waiting for SIGCONT" : ""); 138 kill(getpid(), SIGSTOP); /* Wait here for SIGCONT. */ 139 if (m_state.pid) 140 kill(m_state.pid, SIGCONT); /* Continue child. */ 141 } 142 143 return m_state.pid; 144 } 145 146 void 147 monitor_exit(int code) 148 { 149 int status = 0, gotstatus = 0; 150 pid_t pid; 151 152 if (m_state.pid != 0) { 153 /* When called from the monitor, kill slave and wait for it */ 154 kill(m_state.pid, SIGTERM); 155 156 do { 157 pid = waitpid(m_state.pid, &status, 0); 158 } while (pid == -1 && errno == EINTR); 159 if (pid != -1) 160 gotstatus = 1; 161 162 /* Remove FIFO and pid files. */ 163 unlink(ui_fifo); 164 unlink(pid_file); 165 } 166 167 close(m_state.s); 168 if (code == 0 && gotstatus) 169 exit(WIFEXITED(status)? WEXITSTATUS(status) : 1); 170 else 171 exit(code); 172 } 173 174 int 175 monitor_pf_key_v2_open(void) 176 { 177 int err, cmd; 178 179 cmd = MONITOR_PFKEY_OPEN; 180 must_write(&cmd, sizeof cmd); 181 182 must_read(&err, sizeof err); 183 if (err < 0) { 184 log_error("monitor_pf_key_v2_open: parent could not create " 185 "PF_KEY socket"); 186 return -1; 187 } 188 pf_key_v2_socket = mm_receive_fd(m_state.s); 189 if (pf_key_v2_socket < 0) { 190 log_error("monitor_pf_key_v2_open: mm_receive_fd() failed"); 191 return -1; 192 } 193 194 return pf_key_v2_socket; 195 } 196 197 int 198 monitor_open(const char *path, int flags, mode_t mode) 199 { 200 size_t len; 201 int fd, err, cmd; 202 char pathreal[PATH_MAX]; 203 204 if (path[0] == '/') 205 strlcpy(pathreal, path, sizeof pathreal); 206 else 207 snprintf(pathreal, sizeof pathreal, "%s/%s", m_state.root, 208 path); 209 210 cmd = MONITOR_GET_FD; 211 must_write(&cmd, sizeof cmd); 212 213 len = strlen(pathreal); 214 must_write(&len, sizeof len); 215 must_write(&pathreal, len); 216 217 must_write(&flags, sizeof flags); 218 must_write(&mode, sizeof mode); 219 220 must_read(&err, sizeof err); 221 if (err != 0) { 222 errno = err; 223 return -1; 224 } 225 226 fd = mm_receive_fd(m_state.s); 227 if (fd < 0) { 228 log_error("monitor_open: mm_receive_fd () failed"); 229 return -1; 230 } 231 232 return fd; 233 } 234 235 FILE * 236 monitor_fopen(const char *path, const char *mode) 237 { 238 FILE *fp; 239 int fd, flags = 0, saved_errno; 240 mode_t mask, cur_umask; 241 242 /* Only the child process is supposed to run this. */ 243 if (m_state.pid) 244 log_fatal("[priv] bad call to monitor_fopen"); 245 246 switch (mode[0]) { 247 case 'r': 248 flags = (mode[1] == '+' ? O_RDWR : O_RDONLY); 249 break; 250 case 'w': 251 flags = (mode[1] == '+' ? O_RDWR : O_WRONLY) | O_CREAT | 252 O_TRUNC; 253 break; 254 case 'a': 255 flags = (mode[1] == '+' ? O_RDWR : O_WRONLY) | O_CREAT | 256 O_APPEND; 257 break; 258 default: 259 log_fatal("monitor_fopen: bad call"); 260 } 261 262 cur_umask = umask(0); 263 (void)umask(cur_umask); 264 mask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; 265 mask &= ~cur_umask; 266 267 fd = monitor_open(path, flags, mask); 268 if (fd < 0) 269 return NULL; 270 271 /* Got the fd, attach a FILE * to it. */ 272 fp = fdopen(fd, mode); 273 if (!fp) { 274 log_error("monitor_fopen: fdopen() failed"); 275 saved_errno = errno; 276 close(fd); 277 errno = saved_errno; 278 return NULL; 279 } 280 return fp; 281 } 282 283 int 284 monitor_stat(const char *path, struct stat *sb) 285 { 286 int fd, r, saved_errno; 287 288 /* O_NONBLOCK is needed for stat'ing fifos. */ 289 fd = monitor_open(path, O_RDONLY | O_NONBLOCK, 0); 290 if (fd < 0) 291 return -1; 292 293 r = fstat(fd, sb); 294 saved_errno = errno; 295 close(fd); 296 errno = saved_errno; 297 return r; 298 } 299 300 int 301 monitor_setsockopt(int s, int level, int optname, const void *optval, 302 socklen_t optlen) 303 { 304 int ret, err, cmd; 305 306 cmd = MONITOR_SETSOCKOPT; 307 must_write(&cmd, sizeof cmd); 308 if (mm_send_fd(m_state.s, s)) { 309 log_print("monitor_setsockopt: read/write error"); 310 return -1; 311 } 312 313 must_write(&level, sizeof level); 314 must_write(&optname, sizeof optname); 315 must_write(&optlen, sizeof optlen); 316 must_write(optval, optlen); 317 318 must_read(&err, sizeof err); 319 must_read(&ret, sizeof ret); 320 if (err != 0) 321 errno = err; 322 return ret; 323 } 324 325 int 326 monitor_bind(int s, const struct sockaddr *name, socklen_t namelen) 327 { 328 int ret, err, cmd; 329 330 cmd = MONITOR_BIND; 331 must_write(&cmd, sizeof cmd); 332 if (mm_send_fd(m_state.s, s)) { 333 log_print("monitor_bind: read/write error"); 334 return -1; 335 } 336 337 must_write(&namelen, sizeof namelen); 338 must_write(name, namelen); 339 340 must_read(&err, sizeof err); 341 must_read(&ret, sizeof ret); 342 if (err != 0) 343 errno = err; 344 return ret; 345 } 346 347 int 348 monitor_req_readdir(const char *filename) 349 { 350 int cmd, err; 351 size_t len; 352 353 cmd = MONITOR_REQ_READDIR; 354 must_write(&cmd, sizeof cmd); 355 356 len = strlen(filename); 357 must_write(&len, sizeof len); 358 must_write(filename, len); 359 360 must_read(&err, sizeof err); 361 if (err == -1) 362 must_read(&errno, sizeof errno); 363 364 return err; 365 } 366 367 int 368 monitor_readdir(char *file, size_t size) 369 { 370 int fd; 371 size_t len; 372 373 must_read(&len, sizeof len); 374 if (len == 0) 375 return -1; 376 if (len >= size) 377 log_fatal("monitor_readdir: received bad length from monitor"); 378 must_read(file, len); 379 file[len] = '\0'; 380 fd = mm_receive_fd(m_state.s); 381 return fd; 382 } 383 384 void 385 monitor_init_done(void) 386 { 387 int cmd; 388 389 cmd = MONITOR_INIT_DONE; 390 must_write(&cmd, sizeof cmd); 391 } 392 393 /* 394 * Start of code running with privileges (the monitor process). 395 */ 396 397 static void 398 set_monitor_signals(void) 399 { 400 int n; 401 402 for (n = 1; n < _NSIG; n++) 403 signal(n, SIG_DFL); 404 405 /* Forward some signals to the child. */ 406 signal(SIGTERM, sig_pass_to_chld); 407 signal(SIGHUP, sig_pass_to_chld); 408 signal(SIGUSR1, sig_pass_to_chld); 409 } 410 411 static void 412 sig_pass_to_chld(int sig) 413 { 414 int oerrno = errno; 415 416 if (m_state.pid > 0) 417 kill(m_state.pid, sig); 418 errno = oerrno; 419 } 420 421 /* This function is where the privileged process waits(loops) indefinitely. */ 422 void 423 monitor_loop(int debug) 424 { 425 int msgcode; 426 427 if (!debug) 428 log_to(0); 429 430 for (;;) { 431 must_read(&msgcode, sizeof msgcode); 432 433 switch (msgcode) { 434 case MONITOR_GET_FD: 435 m_priv_getfd(); 436 break; 437 438 case MONITOR_PFKEY_OPEN: 439 LOG_DBG((LOG_MISC, 80, 440 "monitor_loop: MONITOR_PFKEY_OPEN")); 441 m_priv_pfkey_open(); 442 break; 443 444 case MONITOR_SETSOCKOPT: 445 LOG_DBG((LOG_MISC, 80, 446 "monitor_loop: MONITOR_SETSOCKOPT")); 447 m_priv_setsockopt(); 448 break; 449 450 case MONITOR_BIND: 451 LOG_DBG((LOG_MISC, 80, 452 "monitor_loop: MONITOR_BIND")); 453 m_priv_bind(); 454 break; 455 456 case MONITOR_REQ_READDIR: 457 LOG_DBG((LOG_MISC, 80, 458 "monitor_loop: MONITOR_REQ_READDIR")); 459 m_priv_req_readdir(); 460 break; 461 462 case MONITOR_INIT_DONE: 463 LOG_DBG((LOG_MISC, 80, 464 "monitor_loop: MONITOR_INIT_DONE")); 465 break; 466 467 case MONITOR_SHUTDOWN: 468 LOG_DBG((LOG_MISC, 80, 469 "monitor_loop: MONITOR_SHUTDOWN")); 470 break; 471 472 default: 473 log_print("monitor_loop: got unknown code %d", 474 msgcode); 475 } 476 } 477 478 exit(0); 479 } 480 481 482 /* Privileged: called by monitor_loop. */ 483 static void 484 m_priv_pfkey_open(void) 485 { 486 int fd, err = 0; 487 488 fd = pf_key_v2_open(); 489 if (fd < 0) 490 err = -1; 491 492 must_write(&err, sizeof err); 493 494 if (fd > 0 && mm_send_fd(m_state.s, fd)) { 495 log_error("m_priv_pfkey_open: read/write operation failed"); 496 close(fd); 497 return; 498 } 499 close(fd); 500 } 501 502 /* Privileged: called by monitor_loop. */ 503 static void 504 m_priv_getfd(void) 505 { 506 char path[PATH_MAX]; 507 size_t len; 508 int v, flags, ret; 509 int err = 0; 510 mode_t mode; 511 512 must_read(&len, sizeof len); 513 if (len == 0 || len >= sizeof path) 514 log_fatal("m_priv_getfd: invalid pathname length"); 515 516 must_read(path, len); 517 path[len] = '\0'; 518 if (strlen(path) != len) 519 log_fatal("m_priv_getfd: invalid pathname"); 520 521 must_read(&flags, sizeof flags); 522 must_read(&mode, sizeof mode); 523 524 if ((ret = m_priv_local_sanitize_path(path, sizeof path, flags)) 525 != 0) { 526 if (errno != ENOENT) 527 log_print("m_priv_getfd: illegal path \"%s\"", path); 528 err = errno; 529 v = -1; 530 } else { 531 if ((v = open(path, flags, mode)) == -1) 532 err = errno; 533 } 534 535 must_write(&err, sizeof err); 536 537 if (v != -1) { 538 if (mm_send_fd(m_state.s, v) == -1) 539 log_error("m_priv_getfd: sending fd failed"); 540 close(v); 541 } 542 } 543 544 /* Privileged: called by monitor_loop. */ 545 static void 546 m_priv_setsockopt(void) 547 { 548 int sock, level, optname, v; 549 int err = 0; 550 char *optval = 0; 551 socklen_t optlen; 552 553 sock = mm_receive_fd(m_state.s); 554 if (sock < 0) { 555 log_print("m_priv_setsockopt: read/write error"); 556 return; 557 } 558 559 must_read(&level, sizeof level); 560 must_read(&optname, sizeof optname); 561 must_read(&optlen, sizeof optlen); 562 563 optval = malloc(optlen); 564 if (!optval) { 565 log_print("m_priv_setsockopt: malloc failed"); 566 close(sock); 567 return; 568 } 569 570 must_read(optval, optlen); 571 572 if (m_priv_check_sockopt(level, optname) != 0) { 573 err = EACCES; 574 v = -1; 575 } else { 576 v = setsockopt(sock, level, optname, optval, optlen); 577 if (v < 0) 578 err = errno; 579 } 580 581 close(sock); 582 sock = -1; 583 584 must_write(&err, sizeof err); 585 must_write(&v, sizeof v); 586 587 free(optval); 588 return; 589 } 590 591 /* Privileged: called by monitor_loop. */ 592 static void 593 m_priv_bind(void) 594 { 595 int sock, v, err = 0; 596 struct sockaddr *name = 0; 597 socklen_t namelen; 598 599 sock = mm_receive_fd(m_state.s); 600 if (sock < 0) { 601 log_print("m_priv_bind: read/write error"); 602 return; 603 } 604 605 must_read(&namelen, sizeof namelen); 606 name = malloc(namelen); 607 if (!name) { 608 log_print("m_priv_bind: malloc failed"); 609 close(sock); 610 return; 611 } 612 must_read((char *)name, namelen); 613 614 if (m_priv_check_bind(name, namelen) != 0) { 615 err = EACCES; 616 v = -1; 617 } else { 618 v = bind(sock, name, namelen); 619 if (v == -1) { 620 log_error("m_priv_bind: bind(%d,%p,%d) returned %d", 621 sock, name, namelen, v); 622 err = errno; 623 } 624 } 625 626 close(sock); 627 sock = -1; 628 629 must_write(&err, sizeof err); 630 must_write(&v, sizeof v); 631 632 free(name); 633 return; 634 } 635 636 /* 637 * Help functions, used by both privileged and unprivileged code 638 */ 639 640 /* 641 * Read data with the assertion that it all must come through, or else abort 642 * the process. Based on atomicio() from openssh. 643 */ 644 static void 645 must_read(void *buf, size_t n) 646 { 647 char *s = buf; 648 size_t pos = 0; 649 ssize_t res; 650 651 while (n > pos) { 652 res = read(m_state.s, s + pos, n - pos); 653 switch (res) { 654 case -1: 655 if (errno == EINTR || errno == EAGAIN) 656 continue; 657 case 0: 658 monitor_exit(0); 659 default: 660 pos += res; 661 } 662 } 663 } 664 665 /* 666 * Write data with the assertion that it all has to be written, or else abort 667 * the process. Based on atomicio() from openssh. 668 */ 669 static void 670 must_write(const void *buf, size_t n) 671 { 672 const char *s = buf; 673 size_t pos = 0; 674 ssize_t res; 675 676 while (n > pos) { 677 res = write(m_state.s, s + pos, n - pos); 678 switch (res) { 679 case -1: 680 if (errno == EINTR || errno == EAGAIN) 681 continue; 682 case 0: 683 monitor_exit(0); 684 default: 685 pos += res; 686 } 687 } 688 } 689 690 /* Check that path/mode is permitted. */ 691 static int 692 m_priv_local_sanitize_path(const char *path, size_t pmax, int flags) 693 { 694 char new_path[PATH_MAX], var_run[PATH_MAX], *enddir; 695 696 /* 697 * We only permit paths starting with 698 * /etc/isakmpd/ (read only) 699 * /var/run/ (rw) 700 */ 701 702 if (realpath(path, new_path) == NULL) { 703 if (errno != ENOENT) 704 return 1; 705 /* 706 * It is ok if the directory exists, 707 * but the file should be created. 708 */ 709 if (strlcpy(new_path, path, sizeof(new_path)) >= 710 sizeof(new_path)) 711 return 1; 712 enddir = strrchr(new_path, '/'); 713 if (enddir == NULL || enddir[1] == '\0') 714 return 1; 715 enddir[1] = '\0'; 716 if (realpath(new_path, new_path) == NULL) { 717 errno = ENOENT; 718 return 1; 719 } 720 enddir = strrchr(path, '/'); 721 strlcat(new_path, enddir, sizeof(new_path)); 722 } 723 724 if (realpath("/var/run/", var_run) == NULL) 725 return 1; 726 strlcat(var_run, "/", sizeof(var_run)); 727 728 if (strncmp(var_run, new_path, strlen(var_run)) == 0) 729 return 0; 730 731 if (strncmp(ISAKMPD_ROOT, new_path, strlen(ISAKMPD_ROOT)) == 0 && 732 (flags & O_ACCMODE) == O_RDONLY) 733 return 0; 734 735 errno = EACCES; 736 return 1; 737 } 738 739 /* Check setsockopt */ 740 static int 741 m_priv_check_sockopt(int level, int name) 742 { 743 switch (level) { 744 /* These are allowed */ 745 case SOL_SOCKET: 746 case IPPROTO_IP: 747 case IPPROTO_IPV6: 748 break; 749 750 default: 751 log_print("m_priv_check_sockopt: Illegal level %d", level); 752 return 1; 753 } 754 755 switch (name) { 756 /* These are allowed */ 757 case SO_REUSEPORT: 758 case SO_REUSEADDR: 759 case IP_AUTH_LEVEL: 760 case IP_ESP_TRANS_LEVEL: 761 case IP_ESP_NETWORK_LEVEL: 762 case IP_IPCOMP_LEVEL: 763 case IPV6_AUTH_LEVEL: 764 case IPV6_ESP_TRANS_LEVEL: 765 case IPV6_ESP_NETWORK_LEVEL: 766 case IPV6_IPCOMP_LEVEL: 767 break; 768 769 default: 770 log_print("m_priv_check_sockopt: Illegal option name %d", 771 name); 772 return 1; 773 } 774 775 return 0; 776 } 777 778 /* Check bind */ 779 static int 780 m_priv_check_bind(const struct sockaddr *sa, socklen_t salen) 781 { 782 in_port_t port; 783 784 if (sa == NULL) { 785 log_print("NULL address"); 786 return 1; 787 } 788 if (SA_LEN(sa) != salen) { 789 log_print("Length mismatch: %lu %lu", (unsigned long)sa->sa_len, 790 (unsigned long)salen); 791 return 1; 792 } 793 switch (sa->sa_family) { 794 case AF_INET: 795 if (salen != sizeof(struct sockaddr_in)) { 796 log_print("Invalid inet address length"); 797 return 1; 798 } 799 port = ((const struct sockaddr_in *)sa)->sin_port; 800 break; 801 case AF_INET6: 802 if (salen != sizeof(struct sockaddr_in6)) { 803 log_print("Invalid inet6 address length"); 804 return 1; 805 } 806 port = ((const struct sockaddr_in6 *)sa)->sin6_port; 807 break; 808 default: 809 log_print("Unknown address family"); 810 return 1; 811 } 812 813 port = ntohs(port); 814 815 if (port != ISAKMP_PORT_DEFAULT && port < 1024) { 816 log_print("Disallowed port %u", port); 817 return 1; 818 } 819 return 0; 820 } 821 822 static void 823 m_priv_req_readdir(void) 824 { 825 size_t len; 826 char path[PATH_MAX]; 827 DIR *dp; 828 struct dirent *file; 829 struct stat sb; 830 int off, size, fd, ret, serrno; 831 832 must_read(&len, sizeof len); 833 if (len == 0 || len >= sizeof path) 834 log_fatal("m_priv_req_readdir: invalid pathname length"); 835 must_read(path, len); 836 path[len] = '\0'; 837 if (strlen(path) != len) 838 log_fatal("m_priv_req_readdir: invalid pathname"); 839 840 off = strlen(path); 841 size = sizeof path - off; 842 843 if ((dp = opendir(path)) == NULL) { 844 serrno = errno; 845 ret = -1; 846 must_write(&ret, sizeof ret); 847 must_write(&serrno, sizeof serrno); 848 return; 849 } 850 851 /* report opendir() success */ 852 ret = 0; 853 must_write(&ret, sizeof ret); 854 855 while ((file = readdir(dp)) != NULL) { 856 strlcpy(path + off, file->d_name, size); 857 858 if (m_priv_local_sanitize_path(path, sizeof path, O_RDONLY) 859 != 0) 860 continue; 861 fd = open(path, O_RDONLY); 862 if (fd == -1) { 863 log_error("m_priv_req_readdir: open " 864 "(\"%s\", O_RDONLY, 0) failed", path); 865 continue; 866 } 867 if ((fstat(fd, &sb) == -1) || 868 !(S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode))) { 869 close(fd); 870 continue; 871 } 872 873 len = strlen(path); 874 must_write(&len, sizeof len); 875 must_write(path, len); 876 877 mm_send_fd(m_state.s, fd); 878 close(fd); 879 } 880 closedir(dp); 881 882 len = 0; 883 must_write(&len, sizeof len); 884 } 885