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