1 /* $OpenBSD: privsep.c,v 1.57 2021/10/24 21:24:19 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2003 Can Erkin Acar 5 * Copyright (c) 2003 Anil Madhavapeddy <anil@recoil.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/socket.h> 22 #include <sys/wait.h> 23 #include <sys/ioctl.h> 24 25 #include <netinet/in.h> 26 #include <net/if.h> 27 #include <netinet/if_ether.h> 28 #include <net/bpf.h> 29 #include <net/pfvar.h> 30 31 #include <rpc/rpc.h> 32 33 #include <err.h> 34 #include <errno.h> 35 #include <fcntl.h> 36 #include <netdb.h> 37 #include <paths.h> 38 #include <pwd.h> 39 #include <signal.h> 40 #include <stdarg.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <syslog.h> 45 #include <unistd.h> 46 47 #include "interface.h" 48 #include "privsep.h" 49 #include "pfctl_parser.h" 50 51 /* 52 * tcpdump goes through four states: STATE_INIT is where the 53 * bpf device and the input file is opened. In STATE_BPF, the 54 * pcap filter gets set. STATE_FILTER is used for parsing 55 * /etc/services and /etc/protocols and opening the output 56 * file. STATE_RUN is the packet processing part. 57 */ 58 59 enum priv_state { 60 STATE_INIT, /* initial state */ 61 STATE_BPF, /* input file/device opened */ 62 STATE_FILTER, /* filter applied */ 63 STATE_RUN, /* running and accepting network traffic */ 64 STATE_EXIT /* in the process of dying */ 65 }; 66 67 #define ALLOW(action) (1 << (action)) 68 69 /* 70 * Set of maximum allowed actions. 71 */ 72 static const int allowed_max[] = { 73 /* INIT */ ALLOW(PRIV_OPEN_BPF) | ALLOW(PRIV_OPEN_DUMP) | 74 ALLOW(PRIV_SETFILTER), 75 /* BPF */ ALLOW(PRIV_SETFILTER), 76 /* FILTER */ ALLOW(PRIV_OPEN_PFOSFP) | ALLOW(PRIV_OPEN_OUTPUT) | 77 ALLOW(PRIV_GETSERVENTRIES) | 78 ALLOW(PRIV_GETPROTOENTRIES) | 79 ALLOW(PRIV_ETHER_NTOHOST) | ALLOW(PRIV_INIT_DONE), 80 /* RUN */ ALLOW(PRIV_GETHOSTBYADDR) | ALLOW(PRIV_ETHER_NTOHOST) | 81 ALLOW(PRIV_GETRPCBYNUMBER) | ALLOW(PRIV_LOCALTIME) | 82 ALLOW(PRIV_PCAP_STATS), 83 /* EXIT */ 0 84 }; 85 86 /* 87 * Default set of allowed actions. More actions get added 88 * later depending on the supplied parameters. 89 */ 90 static int allowed_ext[] = { 91 /* INIT */ ALLOW(PRIV_SETFILTER), 92 /* BPF */ ALLOW(PRIV_SETFILTER), 93 /* FILTER */ ALLOW(PRIV_GETSERVENTRIES), 94 /* RUN */ ALLOW(PRIV_LOCALTIME) | ALLOW(PRIV_PCAP_STATS), 95 /* EXIT */ 0 96 }; 97 98 int debug_level = LOG_INFO; 99 int priv_fd = -1; 100 volatile pid_t child_pid = -1; 101 static volatile sig_atomic_t cur_state = STATE_INIT; 102 103 extern void set_slave_signals(void); 104 105 static void drop_privs(int); 106 107 static void impl_open_bpf(int, int *); 108 static void impl_open_dump(int, const char *); 109 static void impl_open_pfosfp(int); 110 static void impl_open_output(int, const char *); 111 static void impl_setfilter(int, char *, int *); 112 static void impl_init_done(int, int *); 113 static void impl_gethostbyaddr(int); 114 static void impl_ether_ntohost(int); 115 static void impl_getrpcbynumber(int); 116 static void impl_getserventries(int); 117 static void impl_getprotoentries(int); 118 static void impl_localtime(int fd); 119 static void impl_pcap_stats(int, int *); 120 121 static void test_state(int, int); 122 static void logmsg(int, const char *, ...); 123 124 static void 125 drop_privs(int nochroot) 126 { 127 struct passwd *pw; 128 129 /* 130 * If run as regular user, then tcpdump will rely on 131 * pledge(2). If we are root, we want to chroot also.. 132 */ 133 if (getuid() != 0) 134 return; 135 136 pw = getpwnam("_tcpdump"); 137 if (pw == NULL) 138 errx(1, "unknown user _tcpdump"); 139 140 if (!nochroot) { 141 if (chroot(pw->pw_dir) == -1) 142 err(1, "unable to chroot"); 143 if (chdir("/") == -1) 144 err(1, "unable to chdir"); 145 } 146 147 /* drop to _tcpdump */ 148 if (setgroups(1, &pw->pw_gid) == -1) 149 err(1, "setgroups() failed"); 150 if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) 151 err(1, "setresgid() failed"); 152 if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) 153 err(1, "setresuid() failed"); 154 } 155 156 int 157 priv_init(int argc, char **argv) 158 { 159 int i, nargc, socks[2]; 160 sigset_t allsigs, oset; 161 char **privargv; 162 163 closefrom(STDERR_FILENO + 1); 164 for (i = 1; i < _NSIG; i++) 165 signal(i, SIG_DFL); 166 167 /* Create sockets */ 168 if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, socks) == -1) 169 err(1, "socketpair() failed"); 170 171 sigfillset(&allsigs); 172 sigprocmask(SIG_BLOCK, &allsigs, &oset); 173 174 child_pid = fork(); 175 if (child_pid == -1) 176 err(1, "fork() failed"); 177 178 if (child_pid) { 179 close(socks[0]); 180 priv_fd = socks[1]; 181 182 set_slave_signals(); 183 sigprocmask(SIG_SETMASK, &oset, NULL); 184 185 drop_privs(0); 186 187 return (0); 188 } 189 close(socks[1]); 190 191 if (dup2(socks[0], 3) == -1) 192 err(1, "dup2 priv sock failed"); 193 closefrom(4); 194 195 if ((privargv = reallocarray(NULL, argc + 2, sizeof(char *))) == NULL) 196 err(1, "alloc priv argv failed"); 197 nargc = 0; 198 privargv[nargc++] = argv[0]; 199 privargv[nargc++] = "-P"; 200 for (i = 1; i < argc; i++) 201 privargv[nargc++] = argv[i]; 202 privargv[nargc] = NULL; 203 execvp(privargv[0], privargv); 204 err(1, "exec priv '%s' failed", privargv[0]); 205 } 206 207 __dead void 208 priv_exec(int argc, char *argv[]) 209 { 210 int bpfd = -1; 211 int i, sock, cmd, nflag = 0, oflag = 0, Pflag = 0; 212 char *cmdbuf, *infile = NULL; 213 char *RFileName = NULL; 214 char *WFileName = NULL; 215 216 sock = 3; 217 218 closefrom(4); 219 for (i = 1; i < _NSIG; i++) 220 signal(i, SIG_DFL); 221 222 signal(SIGINT, SIG_IGN); 223 224 /* parse the arguments for required options */ 225 opterr = 0; 226 while ((i = getopt(argc, argv, 227 "aB:c:D:deE:fF:i:lLnNOopPqr:s:StT:vw:xXy:")) != -1) { 228 switch (i) { 229 case 'n': 230 nflag++; 231 break; 232 233 case 'o': 234 oflag = 1; 235 break; 236 237 case 'r': 238 RFileName = optarg; 239 break; 240 241 case 'w': 242 WFileName = optarg; 243 break; 244 245 case 'F': 246 infile = optarg; 247 break; 248 249 case 'P': 250 Pflag = 1; 251 break; 252 253 default: 254 /* nothing */ 255 break; 256 } 257 } 258 259 if (!Pflag) 260 errx(1, "exec without priv"); 261 262 if (RFileName != NULL) { 263 if (strcmp(RFileName, "-") != 0) 264 allowed_ext[STATE_INIT] |= ALLOW(PRIV_OPEN_DUMP); 265 } else 266 allowed_ext[STATE_INIT] |= ALLOW(PRIV_OPEN_BPF); 267 if (WFileName != NULL) { 268 if (strcmp(WFileName, "-") != 0) 269 allowed_ext[STATE_FILTER] |= ALLOW(PRIV_OPEN_OUTPUT); 270 } 271 allowed_ext[STATE_FILTER] |= ALLOW(PRIV_INIT_DONE); 272 if (!nflag) { 273 allowed_ext[STATE_RUN] |= ALLOW(PRIV_GETHOSTBYADDR); 274 allowed_ext[STATE_FILTER] |= ALLOW(PRIV_ETHER_NTOHOST); 275 allowed_ext[STATE_RUN] |= ALLOW(PRIV_ETHER_NTOHOST); 276 allowed_ext[STATE_RUN] |= ALLOW(PRIV_GETRPCBYNUMBER); 277 allowed_ext[STATE_FILTER] |= ALLOW(PRIV_GETPROTOENTRIES); 278 } 279 if (oflag) 280 allowed_ext[STATE_FILTER] |= ALLOW(PRIV_OPEN_PFOSFP); 281 282 if (infile) 283 cmdbuf = read_infile(infile); 284 else 285 cmdbuf = copy_argv(&argv[optind]); 286 287 setproctitle("[priv]"); 288 289 for (;;) { 290 if (may_read(sock, &cmd, sizeof(int))) 291 break; 292 switch (cmd) { 293 case PRIV_OPEN_BPF: 294 test_state(cmd, STATE_BPF); 295 impl_open_bpf(sock, &bpfd); 296 break; 297 case PRIV_OPEN_DUMP: 298 test_state(cmd, STATE_BPF); 299 impl_open_dump(sock, RFileName); 300 break; 301 case PRIV_OPEN_PFOSFP: 302 test_state(cmd, STATE_FILTER); 303 impl_open_pfosfp(sock); 304 break; 305 case PRIV_OPEN_OUTPUT: 306 test_state(cmd, STATE_FILTER); 307 impl_open_output(sock, WFileName); 308 break; 309 case PRIV_SETFILTER: 310 test_state(cmd, STATE_FILTER); 311 impl_setfilter(sock, cmdbuf, &bpfd); 312 break; 313 case PRIV_INIT_DONE: 314 test_state(cmd, STATE_RUN); 315 impl_init_done(sock, &bpfd); 316 317 drop_privs(1); 318 if (unveil("/etc/ethers", "r") == -1) 319 err(1, "unveil /etc/ethers"); 320 if (unveil("/etc/rpc", "r") == -1) 321 err(1, "unveil /etc/rpc"); 322 if (pledge("stdio rpath dns bpf", NULL) == -1) 323 err(1, "pledge"); 324 325 break; 326 case PRIV_GETHOSTBYADDR: 327 test_state(cmd, STATE_RUN); 328 impl_gethostbyaddr(sock); 329 break; 330 case PRIV_ETHER_NTOHOST: 331 test_state(cmd, cur_state); 332 impl_ether_ntohost(sock); 333 break; 334 case PRIV_GETRPCBYNUMBER: 335 test_state(cmd, STATE_RUN); 336 impl_getrpcbynumber(sock); 337 break; 338 case PRIV_GETSERVENTRIES: 339 test_state(cmd, STATE_FILTER); 340 impl_getserventries(sock); 341 break; 342 case PRIV_GETPROTOENTRIES: 343 test_state(cmd, STATE_FILTER); 344 impl_getprotoentries(sock); 345 break; 346 case PRIV_LOCALTIME: 347 test_state(cmd, STATE_RUN); 348 impl_localtime(sock); 349 break; 350 case PRIV_PCAP_STATS: 351 test_state(cmd, STATE_RUN); 352 impl_pcap_stats(sock, &bpfd); 353 break; 354 default: 355 logmsg(LOG_ERR, "[priv]: unknown command %d", cmd); 356 exit(1); 357 /* NOTREACHED */ 358 } 359 } 360 361 /* NOTREACHED */ 362 exit(0); 363 } 364 365 static void 366 impl_open_bpf(int fd, int *bpfd) 367 { 368 int snaplen, promisc, err; 369 u_int dlt, dirfilt, fildrop; 370 char device[IFNAMSIZ]; 371 size_t iflen; 372 373 logmsg(LOG_DEBUG, "[priv]: msg PRIV_OPEN_BPF received"); 374 375 must_read(fd, &snaplen, sizeof(int)); 376 must_read(fd, &promisc, sizeof(int)); 377 must_read(fd, &dlt, sizeof(u_int)); 378 must_read(fd, &dirfilt, sizeof(u_int)); 379 must_read(fd, &fildrop, sizeof(fildrop)); 380 iflen = read_string(fd, device, sizeof(device), __func__); 381 if (iflen == 0) 382 errx(1, "Invalid interface size specified"); 383 *bpfd = pcap_live(device, snaplen, promisc, dlt, dirfilt, fildrop); 384 err = errno; 385 if (*bpfd < 0) 386 logmsg(LOG_DEBUG, 387 "[priv]: failed to open bpf device for %s: %s", 388 device, strerror(errno)); 389 send_fd(fd, *bpfd); 390 must_write(fd, &err, sizeof(int)); 391 /* do not close bpfd until filter is set */ 392 } 393 394 static void 395 impl_open_dump(int fd, const char *RFileName) 396 { 397 int file, err = 0; 398 399 logmsg(LOG_DEBUG, "[priv]: msg PRIV_OPEN_DUMP received"); 400 401 if (RFileName == NULL) { 402 file = -1; 403 logmsg(LOG_ERR, "[priv]: No offline file specified"); 404 } else { 405 file = open(RFileName, O_RDONLY); 406 err = errno; 407 if (file == -1) 408 logmsg(LOG_DEBUG, "[priv]: failed to open %s: %s", 409 RFileName, strerror(errno)); 410 } 411 send_fd(fd, file); 412 must_write(fd, &err, sizeof(int)); 413 if (file >= 0) 414 close(file); 415 } 416 417 static void 418 impl_open_pfosfp(int fd) 419 { 420 int file, err = 0; 421 422 logmsg(LOG_DEBUG, "[priv]: msg PRIV_OPEN_PFOSFP received"); 423 424 file = open(PF_OSFP_FILE, O_RDONLY); 425 err = errno; 426 if (file == -1) 427 logmsg(LOG_DEBUG, "[priv]: failed to open %s: %s", 428 PF_OSFP_FILE, strerror(errno)); 429 send_fd(fd, file); 430 must_write(fd, &err, sizeof(int)); 431 if (file >= 0) 432 close(file); 433 } 434 435 static void 436 impl_open_output(int fd, const char *WFileName) 437 { 438 int file, err; 439 440 logmsg(LOG_DEBUG, "[priv]: msg PRIV_OPEN_OUTPUT received"); 441 442 file = open(WFileName, O_WRONLY|O_CREAT|O_TRUNC, 0666); 443 err = errno; 444 send_fd(fd, file); 445 must_write(fd, &err, sizeof(int)); 446 if (file == -1) 447 logmsg(LOG_DEBUG, "[priv]: failed to open %s: %s", 448 WFileName, strerror(err)); 449 else 450 close(file); 451 } 452 453 static void 454 impl_setfilter(int fd, char *cmdbuf, int *bpfd) 455 { 456 logmsg(LOG_DEBUG, "[priv]: msg PRIV_SETFILTER received"); 457 458 if (setfilter(*bpfd, fd, cmdbuf)) 459 logmsg(LOG_DEBUG, "[priv]: setfilter() failed"); 460 } 461 462 static void 463 impl_init_done(int fd, int *bpfd) 464 { 465 int ret; 466 467 logmsg(LOG_DEBUG, "[priv]: msg PRIV_INIT_DONE received"); 468 469 ret = 0; 470 must_write(fd, &ret, sizeof(ret)); 471 } 472 473 static void 474 impl_gethostbyaddr(int fd) 475 { 476 char hostname[HOST_NAME_MAX+1]; 477 size_t hostname_len; 478 int addr_af; 479 struct hostent *hp; 480 481 logmsg(LOG_DEBUG, "[priv]: msg PRIV_GETHOSTBYADDR received"); 482 483 /* Expecting: address block, address family */ 484 hostname_len = read_block(fd, hostname, sizeof(hostname), __func__); 485 if (hostname_len == 0) 486 _exit(1); 487 must_read(fd, &addr_af, sizeof(int)); 488 hp = gethostbyaddr(hostname, hostname_len, addr_af); 489 if (hp == NULL) 490 write_zero(fd); 491 else 492 write_string(fd, hp->h_name); 493 } 494 495 static void 496 impl_ether_ntohost(int fd) 497 { 498 struct ether_addr ether; 499 char hostname[HOST_NAME_MAX+1]; 500 501 logmsg(LOG_DEBUG, "[priv]: msg PRIV_ETHER_NTOHOST received"); 502 503 /* Expecting: ethernet address */ 504 must_read(fd, ðer, sizeof(ether)); 505 if (ether_ntohost(hostname, ðer) == -1) 506 write_zero(fd); 507 else 508 write_string(fd, hostname); 509 } 510 511 static void 512 impl_getrpcbynumber(int fd) 513 { 514 int rpc; 515 struct rpcent *rpce; 516 517 logmsg(LOG_DEBUG, "[priv]: msg PRIV_GETRPCBYNUMBER received"); 518 519 must_read(fd, &rpc, sizeof(int)); 520 rpce = getrpcbynumber(rpc); 521 if (rpce == NULL) 522 write_zero(fd); 523 else 524 write_string(fd, rpce->r_name); 525 } 526 527 static void 528 impl_getserventries(int fd) 529 { 530 struct servent *sp; 531 532 logmsg(LOG_DEBUG, "[priv]: msg PRIV_GETSERVENTRIES received"); 533 534 for (;;) { 535 sp = getservent(); 536 if (sp == NULL) { 537 write_zero(fd); 538 break; 539 } else { 540 write_string(fd, sp->s_name); 541 must_write(fd, &sp->s_port, sizeof(int)); 542 write_string(fd, sp->s_proto); 543 } 544 } 545 endservent(); 546 } 547 548 static void 549 impl_getprotoentries(int fd) 550 { 551 struct protoent *pe; 552 553 logmsg(LOG_DEBUG, "[priv]: msg PRIV_GETPROTOENTRIES received"); 554 555 for (;;) { 556 pe = getprotoent(); 557 if (pe == NULL) { 558 write_zero(fd); 559 break; 560 } else { 561 write_string(fd, pe->p_name); 562 must_write(fd, &pe->p_proto, sizeof(int)); 563 } 564 } 565 endprotoent(); 566 } 567 568 /* read the time and send the corresponding localtime and gmtime 569 * results back to the unprivileged process */ 570 static void 571 impl_localtime(int fd) 572 { 573 struct tm *lt, *gt; 574 time_t t; 575 576 logmsg(LOG_DEBUG, "[priv]: msg PRIV_LOCALTIME received"); 577 578 must_read(fd, &t, sizeof(time_t)); 579 580 /* this must be done separately, since they apparently use the 581 * same local buffer */ 582 if ((lt = localtime(&t)) == NULL) 583 errx(1, "localtime()"); 584 must_write(fd, lt, sizeof(*lt)); 585 586 if ((gt = gmtime(&t)) == NULL) 587 errx(1, "gmtime()"); 588 must_write(fd, gt, sizeof(*gt)); 589 590 if (lt->tm_zone == NULL) 591 write_zero(fd); 592 else 593 write_string(fd, lt->tm_zone); 594 } 595 596 static void 597 impl_pcap_stats(int fd, int *bpfd) 598 { 599 struct pcap_stat stats; 600 601 logmsg(LOG_DEBUG, "[priv]: msg PRIV_PCAP_STATS received"); 602 603 if (ioctl(*bpfd, BIOCGSTATS, &stats) == -1) 604 write_zero(fd); 605 else 606 must_write(fd, &stats, sizeof(stats)); 607 } 608 609 void 610 priv_init_done(void) 611 { 612 int ret; 613 614 if (priv_fd < 0) 615 errx(1, "%s: called from privileged portion", __func__); 616 617 write_command(priv_fd, PRIV_INIT_DONE); 618 must_read(priv_fd, &ret, sizeof(int)); 619 } 620 621 /* Reverse address resolution; response is placed into res, and length of 622 * response is returned (zero on error) */ 623 size_t 624 priv_gethostbyaddr(char *addr, size_t addr_len, int af, char *res, size_t res_len) 625 { 626 if (priv_fd < 0) 627 errx(1, "%s called from privileged portion", __func__); 628 629 write_command(priv_fd, PRIV_GETHOSTBYADDR); 630 write_block(priv_fd, addr_len, addr); 631 must_write(priv_fd, &af, sizeof(int)); 632 633 return (read_string(priv_fd, res, res_len, __func__)); 634 } 635 636 size_t 637 priv_ether_ntohost(char *name, size_t name_len, struct ether_addr *e) 638 { 639 if (priv_fd < 0) 640 errx(1, "%s called from privileged portion", __func__); 641 642 write_command(priv_fd, PRIV_ETHER_NTOHOST); 643 must_write(priv_fd, e, sizeof(*e)); 644 645 /* Read the host name */ 646 return (read_string(priv_fd, name, name_len, __func__)); 647 } 648 649 size_t 650 priv_getrpcbynumber(int rpc, char *progname, size_t progname_len) 651 { 652 if (priv_fd < 0) 653 errx(1, "%s called from privileged portion", __func__); 654 655 write_command(priv_fd, PRIV_GETRPCBYNUMBER); 656 must_write(priv_fd, &rpc, sizeof(int)); 657 658 return read_string(priv_fd, progname, progname_len, __func__); 659 } 660 661 /* start getting service entries */ 662 void 663 priv_getserventries(void) 664 { 665 if (priv_fd < 0) 666 errx(1, "%s called from privileged portion", __func__); 667 668 write_command(priv_fd, PRIV_GETSERVENTRIES); 669 } 670 671 /* retrieve a service entry, should be called repeatedly after calling 672 priv_getserventries(), until it returns zero. */ 673 size_t 674 priv_getserventry(char *name, size_t name_len, int *port, char *prot, 675 size_t prot_len) 676 { 677 if (priv_fd < 0) 678 errx(1, "%s called from privileged portion", __func__); 679 680 /* read the service name */ 681 if (read_string(priv_fd, name, name_len, __func__) == 0) 682 return 0; 683 684 /* read the port */ 685 must_read(priv_fd, port, sizeof(int)); 686 687 /* read the protocol */ 688 return (read_string(priv_fd, prot, prot_len, __func__)); 689 } 690 691 /* start getting ip protocol entries */ 692 void 693 priv_getprotoentries(void) 694 { 695 if (priv_fd < 0) 696 errx(1, "%s called from privileged portion", __func__); 697 698 write_command(priv_fd, PRIV_GETPROTOENTRIES); 699 } 700 701 /* retrieve a ip protocol entry, should be called repeatedly after calling 702 priv_getprotoentries(), until it returns zero. */ 703 size_t 704 priv_getprotoentry(char *name, size_t name_len, int *num) 705 { 706 if (priv_fd < 0) 707 errx(1, "%s called from privileged portion", __func__); 708 709 /* read the proto name */ 710 if (read_string(priv_fd, name, name_len, __func__) == 0) 711 return 0; 712 713 /* read the num */ 714 must_read(priv_fd, num, sizeof(int)); 715 716 return (1); 717 } 718 719 /* localtime() replacement: ask the privileged process for localtime and 720 * gmtime, cache the localtime for about one minute i.e. until one of the 721 * fields other than seconds changes. The check is done using gmtime 722 * values since they are the same in parent and child. */ 723 struct tm * 724 priv_localtime(const time_t *t) 725 { 726 static struct tm lt, gt0; 727 static struct tm *gt = NULL; 728 static char zone[PATH_MAX]; 729 730 if (gt != NULL) { 731 gt = gmtime(t); 732 gt0.tm_sec = gt->tm_sec; 733 gt0.tm_zone = gt->tm_zone; 734 735 if (memcmp(gt, >0, sizeof(struct tm)) == 0) { 736 lt.tm_sec = gt0.tm_sec; 737 return < 738 } 739 } 740 741 write_command(priv_fd, PRIV_LOCALTIME); 742 must_write(priv_fd, t, sizeof(time_t)); 743 must_read(priv_fd, <, sizeof(lt)); 744 must_read(priv_fd, >0, sizeof(gt0)); 745 746 if (read_string(priv_fd, zone, sizeof(zone), __func__)) 747 lt.tm_zone = zone; 748 else 749 lt.tm_zone = NULL; 750 751 gt0.tm_zone = NULL; 752 gt = >0; 753 754 return < 755 } 756 757 int 758 priv_pcap_stats(struct pcap_stat *ps) 759 { 760 if (priv_fd < 0) 761 errx(1, "%s: called from privileged portion", __func__); 762 763 write_command(priv_fd, PRIV_PCAP_STATS); 764 must_read(priv_fd, ps, sizeof(*ps)); 765 return (0); 766 } 767 768 int 769 priv_open_pfosfp(void) 770 { 771 int fd, err = 0; 772 write_command(priv_fd, PRIV_OPEN_PFOSFP); 773 774 fd = receive_fd(priv_fd); 775 must_read(priv_fd, &err, sizeof(int)); 776 if (fd < 0) { 777 warnc(err, "%s", PF_OSFP_FILE); 778 return (-1); 779 } 780 781 return (fd); 782 } 783 784 /* Read all data or return 1 for error. */ 785 int 786 may_read(int fd, void *buf, size_t n) 787 { 788 char *s = buf; 789 ssize_t res, pos = 0; 790 791 while (n > pos) { 792 res = read(fd, s + pos, n - pos); 793 switch (res) { 794 case -1: 795 if (errno == EINTR || errno == EAGAIN) 796 continue; 797 /* FALLTHROUGH */ 798 case 0: 799 return (1); 800 default: 801 pos += res; 802 } 803 } 804 return (0); 805 } 806 807 /* Read data with the assertion that it all must come through, or 808 * else abort the process. Based on atomicio() from openssh. */ 809 void 810 must_read(int fd, void *buf, size_t n) 811 { 812 char *s = buf; 813 ssize_t res, pos = 0; 814 815 while (n > pos) { 816 res = read(fd, s + pos, n - pos); 817 switch (res) { 818 case -1: 819 if (errno == EINTR || errno == EAGAIN) 820 continue; 821 /* FALLTHROUGH */ 822 case 0: 823 _exit(0); 824 default: 825 pos += res; 826 } 827 } 828 } 829 830 /* Write data with the assertion that it all has to be written, or 831 * else abort the process. Based on atomicio() from openssh. */ 832 void 833 must_write(int fd, const void *buf, size_t n) 834 { 835 const char *s = buf; 836 ssize_t res, pos = 0; 837 838 while (n > pos) { 839 res = write(fd, s + pos, n - pos); 840 switch (res) { 841 case -1: 842 if (errno == EINTR || errno == EAGAIN) 843 continue; 844 /* FALLTHROUGH */ 845 case 0: 846 _exit(0); 847 default: 848 pos += res; 849 } 850 } 851 } 852 853 /* test for a given state, and possibly increase state */ 854 static void 855 test_state(int action, int next) 856 { 857 if (cur_state < 0 || cur_state > STATE_RUN) { 858 logmsg(LOG_ERR, "[priv] Invalid state: %d", cur_state); 859 _exit(1); 860 } 861 if ((allowed_max[cur_state] & allowed_ext[cur_state] 862 & ALLOW(action)) == 0) { 863 logmsg(LOG_ERR, "[priv] Invalid action %d in state %d", 864 action, cur_state); 865 _exit(1); 866 } 867 if (next < cur_state) { 868 logmsg(LOG_ERR, "[priv] Invalid next state: %d < %d", 869 next, cur_state); 870 _exit(1); 871 } 872 873 cur_state = next; 874 } 875 876 static void 877 logmsg(int pri, const char *message, ...) 878 { 879 va_list ap; 880 if (pri > debug_level) 881 return; 882 va_start(ap, message); 883 884 vfprintf(stderr, message, ap); 885 fprintf(stderr, "\n"); 886 va_end(ap); 887 } 888 889 /* write a command to the peer */ 890 void 891 write_command(int fd, int cmd) 892 { 893 must_write(fd, &cmd, sizeof(cmd)); 894 } 895 896 /* write a zero 'length' to signal an error to read_{string|block} */ 897 void 898 write_zero(int fd) 899 { 900 size_t len = 0; 901 must_write(fd, &len, sizeof(size_t)); 902 } 903 904 /* send a string */ 905 void 906 write_string(int fd, const char *str) 907 { 908 size_t len; 909 910 len = strlen(str) + 1; 911 must_write(fd, &len, sizeof(size_t)); 912 must_write(fd, str, len); 913 } 914 915 /* send a block of data of given size */ 916 void 917 write_block(int fd, size_t size, const char *str) 918 { 919 must_write(fd, &size, sizeof(size_t)); 920 must_write(fd, str, size); 921 } 922 923 /* read a string from the channel, return 0 if error, or total size of 924 * the buffer, including the terminating '\0' */ 925 size_t 926 read_string(int fd, char *buf, size_t size, const char *func) 927 { 928 size_t len; 929 930 len = read_block(fd, buf, size, func); 931 if (len == 0) 932 return (0); 933 934 if (buf[len - 1] != '\0') 935 errx(1, "%s: received invalid string", func); 936 937 return (len); 938 } 939 940 /* read a block of data from the channel, return length of data, or 0 941 * if error */ 942 size_t 943 read_block(int fd, char *buf, size_t size, const char *func) 944 { 945 size_t len; 946 /* Expect back an integer size, and then a string of that length */ 947 must_read(fd, &len, sizeof(size_t)); 948 949 /* Check there was no error (indicated by a return of 0) */ 950 if (len == 0) 951 return (0); 952 953 /* Make sure we aren't overflowing the passed in buffer */ 954 if (size < len) 955 errx(1, "%s: overflow attempt in return", func); 956 957 /* Read the string and make sure we got all of it */ 958 must_read(fd, buf, len); 959 return (len); 960 } 961