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