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