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