1 /* $OpenBSD: proc.c,v 1.34 2021/01/28 01:20:37 mortimer Exp $ */ 2 3 /* 4 * Copyright (c) 2010 - 2014 Reyk Floeter <reyk@openbsd.org> 5 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/types.h> 21 #include <sys/queue.h> 22 #include <sys/socket.h> 23 #include <sys/wait.h> 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <unistd.h> 28 #include <string.h> 29 #include <errno.h> 30 #include <signal.h> 31 #include <pwd.h> 32 #include <event.h> 33 #include <imsg.h> 34 35 #include "iked.h" 36 37 enum privsep_procid privsep_process; 38 39 void proc_open(struct privsep *, struct privsep_proc *, 40 struct privsep_proc *, size_t); 41 void proc_close(struct privsep *); 42 int proc_ispeer(struct privsep_proc *, unsigned int, enum privsep_procid); 43 void proc_shutdown(struct privsep_proc *); 44 void proc_sig_handler(int, short, void *); 45 void proc_range(struct privsep *, enum privsep_procid, int *, int *); 46 int proc_dispatch_null(int, struct privsep_proc *, struct imsg *); 47 48 int 49 proc_ispeer(struct privsep_proc *procs, unsigned int nproc, 50 enum privsep_procid type) 51 { 52 unsigned int i; 53 54 for (i = 0; i < nproc; i++) 55 if (procs[i].p_id == type) 56 return (1); 57 return (0); 58 } 59 60 void 61 proc_init(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc) 62 { 63 unsigned int i, j, src, dst; 64 struct privsep_pipes *pp; 65 66 /* 67 * Allocate pipes for all process instances (incl. parent) 68 * 69 * - ps->ps_pipes: N:M mapping 70 * N source processes connected to M destination processes: 71 * [src][instances][dst][instances], for example 72 * [PROC_RELAY][3][PROC_CA][3] 73 * 74 * - ps->ps_pp: per-process 1:M part of ps->ps_pipes 75 * Each process instance has a destination array of socketpair fds: 76 * [dst][instances], for example 77 * [PROC_PARENT][0] 78 */ 79 for (src = 0; src < PROC_MAX; src++) { 80 /* Allocate destination array for each process */ 81 if ((ps->ps_pipes[src] = calloc(ps->ps_ninstances, 82 sizeof(struct privsep_pipes))) == NULL) 83 fatal("proc_init: calloc"); 84 85 for (i = 0; i < ps->ps_ninstances; i++) { 86 pp = &ps->ps_pipes[src][i]; 87 88 for (dst = 0; dst < PROC_MAX; dst++) { 89 /* Allocate maximum fd integers */ 90 if ((pp->pp_pipes[dst] = 91 calloc(ps->ps_ninstances, 92 sizeof(int))) == NULL) 93 fatal("proc_init: calloc"); 94 95 /* Mark fd as unused */ 96 for (j = 0; j < ps->ps_ninstances; j++) 97 pp->pp_pipes[dst][j] = -1; 98 } 99 } 100 } 101 102 /* 103 * Setup and run the parent and its children 104 */ 105 privsep_process = PROC_PARENT; 106 ps->ps_instances[PROC_PARENT] = 1; 107 ps->ps_title[PROC_PARENT] = "parent"; 108 ps->ps_pid[PROC_PARENT] = getpid(); 109 ps->ps_pp = &ps->ps_pipes[privsep_process][0]; 110 111 for (i = 0; i < nproc; i++) { 112 /* Default to 1 process instance */ 113 if (ps->ps_instances[procs[i].p_id] < 1) 114 ps->ps_instances[procs[i].p_id] = 1; 115 ps->ps_title[procs[i].p_id] = procs[i].p_title; 116 } 117 118 proc_open(ps, NULL, procs, nproc); 119 120 /* Engage! */ 121 for (i = 0; i < nproc; i++) 122 ps->ps_pid[procs[i].p_id] = (*procs[i].p_init)(ps, &procs[i]); 123 } 124 125 void 126 proc_kill(struct privsep *ps) 127 { 128 pid_t pid; 129 unsigned int i; 130 131 if (privsep_process != PROC_PARENT) 132 return; 133 134 for (i = 0; i < PROC_MAX; i++) { 135 if (ps->ps_pid[i] == 0) 136 continue; 137 killpg(ps->ps_pid[i], SIGTERM); 138 } 139 140 do { 141 pid = waitpid(WAIT_ANY, NULL, 0); 142 } while (pid != -1 || (pid == -1 && errno == EINTR)); 143 144 proc_close(ps); 145 } 146 147 void 148 proc_open(struct privsep *ps, struct privsep_proc *p, 149 struct privsep_proc *procs, size_t nproc) 150 { 151 struct privsep_pipes *pa, *pb; 152 int fds[2]; 153 unsigned int i, j, src, proc; 154 155 if (p == NULL) 156 src = privsep_process; /* parent */ 157 else 158 src = p->p_id; 159 160 /* 161 * Open socket pairs for our peers 162 */ 163 for (proc = 0; proc < nproc; proc++) { 164 procs[proc].p_ps = ps; 165 procs[proc].p_env = ps->ps_env; 166 if (procs[proc].p_cb == NULL) 167 procs[proc].p_cb = proc_dispatch_null; 168 169 for (i = 0; i < ps->ps_instances[src]; i++) { 170 for (j = 0; j < ps->ps_instances[procs[proc].p_id]; 171 j++) { 172 pa = &ps->ps_pipes[src][i]; 173 pb = &ps->ps_pipes[procs[proc].p_id][j]; 174 175 /* Check if fds are already set by peer */ 176 if (pa->pp_pipes[procs[proc].p_id][j] != -1) 177 continue; 178 179 if (socketpair(AF_UNIX, 180 SOCK_STREAM | SOCK_NONBLOCK, 181 PF_UNSPEC, fds) == -1) 182 fatal("socketpair"); 183 184 pa->pp_pipes[procs[proc].p_id][j] = fds[0]; 185 pb->pp_pipes[src][i] = fds[1]; 186 } 187 } 188 } 189 } 190 191 void 192 proc_listen(struct privsep *ps, struct privsep_proc *procs, size_t nproc) 193 { 194 unsigned int i, dst, src, n, m; 195 struct privsep_pipes *pp; 196 197 /* 198 * Close unused pipes 199 */ 200 for (src = 0; src < PROC_MAX; src++) { 201 for (n = 0; n < ps->ps_instances[src]; n++) { 202 /* Ingore current process */ 203 if (src == (unsigned int)privsep_process && 204 n == ps->ps_instance) 205 continue; 206 207 pp = &ps->ps_pipes[src][n]; 208 209 for (dst = 0; dst < PROC_MAX; dst++) { 210 if (src == dst) 211 continue; 212 for (m = 0; m < ps->ps_instances[dst]; m++) { 213 if (pp->pp_pipes[dst][m] == -1) 214 continue; 215 216 /* Close and invalidate fd */ 217 close(pp->pp_pipes[dst][m]); 218 pp->pp_pipes[dst][m] = -1; 219 } 220 } 221 } 222 } 223 224 src = privsep_process; 225 ps->ps_pp = pp = &ps->ps_pipes[src][ps->ps_instance]; 226 227 /* 228 * Listen on appropriate pipes 229 */ 230 for (i = 0; i < nproc; i++) { 231 dst = procs[i].p_id; 232 233 if (src == dst) 234 fatal("proc_listen: cannot peer with oneself"); 235 236 if ((ps->ps_ievs[dst] = calloc(ps->ps_instances[dst], 237 sizeof(struct imsgev))) == NULL) 238 fatal("proc_open"); 239 240 for (n = 0; n < ps->ps_instances[dst]; n++) { 241 if (pp->pp_pipes[dst][n] == -1) 242 continue; 243 244 imsg_init(&(ps->ps_ievs[dst][n].ibuf), 245 pp->pp_pipes[dst][n]); 246 ps->ps_ievs[dst][n].handler = proc_dispatch; 247 ps->ps_ievs[dst][n].events = EV_READ; 248 ps->ps_ievs[dst][n].proc = &procs[i]; 249 ps->ps_ievs[dst][n].data = &ps->ps_ievs[dst][n]; 250 procs[i].p_instance = n; 251 252 event_set(&(ps->ps_ievs[dst][n].ev), 253 ps->ps_ievs[dst][n].ibuf.fd, 254 ps->ps_ievs[dst][n].events, 255 ps->ps_ievs[dst][n].handler, 256 ps->ps_ievs[dst][n].data); 257 event_add(&(ps->ps_ievs[dst][n].ev), NULL); 258 } 259 } 260 } 261 262 void 263 proc_close(struct privsep *ps) 264 { 265 unsigned int src, dst, n, i, j; 266 struct privsep_pipes *pp; 267 268 if (ps == NULL) 269 return; 270 271 pp = ps->ps_pp; 272 273 for (dst = 0; dst < PROC_MAX; dst++) { 274 if (ps->ps_ievs[dst] == NULL) 275 continue; 276 277 for (n = 0; n < ps->ps_instances[dst]; n++) { 278 if (pp->pp_pipes[dst][n] == -1) 279 continue; 280 281 /* Cancel the fd, close and invalidate the fd */ 282 event_del(&(ps->ps_ievs[dst][n].ev)); 283 imsg_clear(&(ps->ps_ievs[dst][n].ibuf)); 284 close(pp->pp_pipes[dst][n]); 285 pp->pp_pipes[dst][n] = -1; 286 } 287 free(ps->ps_ievs[dst]); 288 } 289 290 /* undo proc_init() */ 291 for (src = 0; src < PROC_MAX; src++) { 292 for (i = 0; i < ps->ps_ninstances; i++) { 293 pp = &ps->ps_pipes[src][i]; 294 for (dst = 0; dst < PROC_MAX; dst++) { 295 for (j = 0; j < ps->ps_ninstances; j++) 296 if (pp->pp_pipes[dst][j] != -1) 297 close(pp->pp_pipes[dst][j]); 298 free(pp->pp_pipes[dst]); 299 } 300 } 301 free(ps->ps_pipes[src]); 302 } 303 } 304 305 void 306 proc_shutdown(struct privsep_proc *p) 307 { 308 struct privsep *ps = p->p_ps; 309 310 if (p->p_shutdown != NULL) 311 (*p->p_shutdown)(p); 312 313 proc_close(ps); 314 315 log_info("%s exiting, pid %d", p->p_title, getpid()); 316 317 _exit(0); 318 } 319 320 void 321 proc_sig_handler(int sig, short event, void *arg) 322 { 323 struct privsep_proc *p = arg; 324 325 switch (sig) { 326 case SIGINT: 327 case SIGTERM: 328 proc_shutdown(p); 329 break; 330 case SIGCHLD: 331 case SIGHUP: 332 case SIGPIPE: 333 case SIGUSR1: 334 /* ignore */ 335 break; 336 default: 337 fatalx("proc_sig_handler: unexpected signal"); 338 /* NOTREACHED */ 339 } 340 } 341 342 pid_t 343 proc_run(struct privsep *ps, struct privsep_proc *p, 344 struct privsep_proc *procs, unsigned int nproc, 345 void (*run)(struct privsep *, struct privsep_proc *, void *), void *arg) 346 { 347 pid_t pid; 348 struct passwd *pw; 349 const char *root; 350 struct control_sock *rcs; 351 unsigned int n; 352 353 if (ps->ps_noaction) 354 return (0); 355 356 proc_open(ps, p, procs, nproc); 357 358 /* Fork child handlers */ 359 switch (pid = fork()) { 360 case -1: 361 fatal("proc_run: cannot fork"); 362 case 0: 363 log_procinit(p->p_title); 364 365 /* Set the process group of the current process */ 366 setpgid(0, 0); 367 break; 368 default: 369 return (pid); 370 } 371 372 pw = ps->ps_pw; 373 374 if (p->p_id == PROC_CONTROL && ps->ps_instance == 0) { 375 if (control_init(ps, &ps->ps_csock) == -1) 376 fatalx(__func__); 377 TAILQ_FOREACH(rcs, &ps->ps_rcsocks, cs_entry) 378 if (control_init(ps, rcs) == -1) 379 fatalx(__func__); 380 } 381 382 /* Change root directory */ 383 if (p->p_chroot != NULL) 384 root = p->p_chroot; 385 else 386 root = pw->pw_dir; 387 388 if (chroot(root) == -1) 389 fatal("proc_run: chroot"); 390 if (chdir("/") == -1) 391 fatal("proc_run: chdir(\"/\")"); 392 393 privsep_process = p->p_id; 394 395 setproctitle("%s", p->p_title); 396 397 if (setgroups(1, &pw->pw_gid) || 398 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 399 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 400 fatal("proc_run: cannot drop privileges"); 401 402 /* Fork child handlers */ 403 for (n = 1; n < ps->ps_instances[p->p_id]; n++) { 404 if (fork() == 0) { 405 ps->ps_instance = p->p_instance = n; 406 break; 407 } 408 } 409 410 #ifdef DEBUG 411 log_debug("%s: %s %d/%d, pid %d", __func__, p->p_title, 412 ps->ps_instance + 1, ps->ps_instances[p->p_id], getpid()); 413 #endif 414 415 event_init(); 416 417 signal_set(&ps->ps_evsigint, SIGINT, proc_sig_handler, p); 418 signal_set(&ps->ps_evsigterm, SIGTERM, proc_sig_handler, p); 419 signal_set(&ps->ps_evsigchld, SIGCHLD, proc_sig_handler, p); 420 signal_set(&ps->ps_evsighup, SIGHUP, proc_sig_handler, p); 421 signal_set(&ps->ps_evsigpipe, SIGPIPE, proc_sig_handler, p); 422 signal_set(&ps->ps_evsigusr1, SIGUSR1, proc_sig_handler, p); 423 424 signal_add(&ps->ps_evsigint, NULL); 425 signal_add(&ps->ps_evsigterm, NULL); 426 signal_add(&ps->ps_evsigchld, NULL); 427 signal_add(&ps->ps_evsighup, NULL); 428 signal_add(&ps->ps_evsigpipe, NULL); 429 signal_add(&ps->ps_evsigusr1, NULL); 430 431 proc_listen(ps, procs, nproc); 432 433 if (p->p_id == PROC_CONTROL && ps->ps_instance == 0) { 434 TAILQ_INIT(&ctl_conns); 435 if (control_listen(&ps->ps_csock) == -1) 436 fatalx(__func__); 437 TAILQ_FOREACH(rcs, &ps->ps_rcsocks, cs_entry) 438 if (control_listen(rcs) == -1) 439 fatalx(__func__); 440 } 441 442 if (run != NULL) 443 run(ps, p, arg); 444 445 event_dispatch(); 446 447 proc_shutdown(p); 448 449 return (0); 450 } 451 452 void 453 proc_dispatch(int fd, short event, void *arg) 454 { 455 struct imsgev *iev = arg; 456 struct privsep_proc *p = iev->proc; 457 struct privsep *ps = p->p_ps; 458 struct imsgbuf *ibuf; 459 struct imsg imsg; 460 ssize_t n; 461 int verbose; 462 const char *title; 463 464 title = ps->ps_title[privsep_process]; 465 ibuf = &iev->ibuf; 466 467 if (event & EV_READ) { 468 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 469 fatal(__func__); 470 if (n == 0) { 471 /* this pipe is dead, so remove the event handler */ 472 event_del(&iev->ev); 473 event_loopexit(NULL); 474 return; 475 } 476 } 477 478 if (event & EV_WRITE) { 479 if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) 480 fatal(__func__); 481 } 482 483 for (;;) { 484 if ((n = imsg_get(ibuf, &imsg)) == -1) 485 fatal(__func__); 486 if (n == 0) 487 break; 488 489 #if DEBUG > 1 490 log_debug("%s: %s %d got imsg %d peerid %d from %s %d", 491 __func__, title, ps->ps_instance + 1, 492 imsg.hdr.type, imsg.hdr.peerid, p->p_title, p->p_instance); 493 #endif 494 495 /* 496 * Check the message with the program callback 497 */ 498 if ((p->p_cb)(fd, p, &imsg) == 0) { 499 /* Message was handled by the callback, continue */ 500 imsg_free(&imsg); 501 continue; 502 } 503 504 /* 505 * Generic message handling 506 */ 507 switch (imsg.hdr.type) { 508 case IMSG_CTL_VERBOSE: 509 IMSG_SIZE_CHECK(&imsg, &verbose); 510 memcpy(&verbose, imsg.data, sizeof(verbose)); 511 log_setverbose(verbose); 512 break; 513 default: 514 log_warnx("%s: %s %d got invalid imsg %d peerid %d " 515 "from %s %d", 516 __func__, title, ps->ps_instance + 1, 517 imsg.hdr.type, imsg.hdr.peerid, 518 p->p_title, p->p_instance); 519 fatalx(__func__); 520 } 521 imsg_free(&imsg); 522 } 523 imsg_event_add(iev); 524 } 525 526 int 527 proc_dispatch_null(int fd, struct privsep_proc *p, struct imsg *imsg) 528 { 529 return (-1); 530 } 531 532 /* 533 * imsg helper functions 534 */ 535 536 void 537 imsg_event_add(struct imsgev *iev) 538 { 539 if (iev->handler == NULL) { 540 imsg_flush(&iev->ibuf); 541 return; 542 } 543 544 iev->events = EV_READ; 545 if (iev->ibuf.w.queued) 546 iev->events |= EV_WRITE; 547 548 event_del(&iev->ev); 549 event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev->data); 550 event_add(&iev->ev, NULL); 551 } 552 553 int 554 imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid, 555 pid_t pid, int fd, void *data, uint16_t datalen) 556 { 557 int ret; 558 559 if ((ret = imsg_compose(&iev->ibuf, type, peerid, 560 pid, fd, data, datalen)) == -1) 561 return (ret); 562 imsg_event_add(iev); 563 return (ret); 564 } 565 566 int 567 imsg_composev_event(struct imsgev *iev, uint16_t type, uint32_t peerid, 568 pid_t pid, int fd, const struct iovec *iov, int iovcnt) 569 { 570 int ret; 571 572 if ((ret = imsg_composev(&iev->ibuf, type, peerid, 573 pid, fd, iov, iovcnt)) == -1) 574 return (ret); 575 imsg_event_add(iev); 576 return (ret); 577 } 578 579 void 580 proc_range(struct privsep *ps, enum privsep_procid id, int *n, int *m) 581 { 582 if (*n == -1) { 583 /* Use a range of all target instances */ 584 *n = 0; 585 *m = ps->ps_instances[id]; 586 } else { 587 /* Use only a single slot of the specified peer process */ 588 *m = *n + 1; 589 } 590 } 591 592 int 593 proc_compose_imsg(struct privsep *ps, enum privsep_procid id, int n, 594 uint16_t type, uint32_t peerid, int fd, void *data, uint16_t datalen) 595 { 596 int m; 597 598 proc_range(ps, id, &n, &m); 599 for (; n < m; n++) { 600 if (imsg_compose_event(&ps->ps_ievs[id][n], 601 type, peerid, 0, fd, data, datalen) == -1) 602 return (-1); 603 } 604 605 return (0); 606 } 607 608 int 609 proc_compose(struct privsep *ps, enum privsep_procid id, 610 uint16_t type, void *data, uint16_t datalen) 611 { 612 return (proc_compose_imsg(ps, id, -1, type, -1, -1, data, datalen)); 613 } 614 615 int 616 proc_composev_imsg(struct privsep *ps, enum privsep_procid id, int n, 617 uint16_t type, uint32_t peerid, int fd, const struct iovec *iov, int iovcnt) 618 { 619 int m; 620 621 proc_range(ps, id, &n, &m); 622 for (; n < m; n++) 623 if (imsg_composev_event(&ps->ps_ievs[id][n], 624 type, peerid, 0, fd, iov, iovcnt) == -1) 625 return (-1); 626 627 return (0); 628 } 629 630 int 631 proc_composev(struct privsep *ps, enum privsep_procid id, 632 uint16_t type, const struct iovec *iov, int iovcnt) 633 { 634 return (proc_composev_imsg(ps, id, -1, type, -1, -1, iov, iovcnt)); 635 } 636 637 int 638 proc_forward_imsg(struct privsep *ps, struct imsg *imsg, 639 enum privsep_procid id, int n) 640 { 641 return (proc_compose_imsg(ps, id, n, imsg->hdr.type, 642 imsg->hdr.peerid, imsg->fd, imsg->data, IMSG_DATA_SIZE(imsg))); 643 } 644 645 struct imsgbuf * 646 proc_ibuf(struct privsep *ps, enum privsep_procid id, int n) 647 { 648 int m; 649 650 proc_range(ps, id, &n, &m); 651 return (&ps->ps_ievs[id][n].ibuf); 652 } 653 654 struct imsgev * 655 proc_iev(struct privsep *ps, enum privsep_procid id, int n) 656 { 657 int m; 658 659 proc_range(ps, id, &n, &m); 660 return (&ps->ps_ievs[id][n]); 661 } 662