1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* Audit daemon server */ 29 /* 30 * These routines make up the audit daemon server. This daemon, called 31 * auditd, handles the user level parts of auditing. It receives buffered 32 * audit records (usually one or more per buffer, potentially less than 33 * one) and passes them to one or more plugins for processing. 34 * 35 * The major interrupts are AU_SIG_READ_CONTROL (start over), 36 * AU_SIG_DISABLE (start shutting down), SIGALRM (quit), and 37 * AU_SIG_NEXT_DIR (start a new audit log file). SIGTERM (the implementation 38 * value of AU_SIG_DISABLE) is also used for the child to tell the parent 39 * that audit is ready. 40 * 41 * Configuration data comes from /etc/security/audit_control and the auditon 42 * system call. 43 * 44 * The major errors are EBUSY (auditing is already in use) and EINTR 45 * (one of the above signals was received). File space errors are 46 * handled by the audit_binfile plugin 47 */ 48 49 #define DEBUG 0 50 #define MEM_TEST 0 /* set to one to generate core dump on exit */ 51 52 #include <assert.h> 53 #include <bsm/adt.h> 54 #include <bsm/audit.h> 55 #include <bsm/audit_record.h> 56 #include <bsm/libbsm.h> 57 #include <fcntl.h> 58 #include <libintl.h> 59 #include <locale.h> 60 #include <netdb.h> 61 #include <pwd.h> 62 #include <secdb.h> 63 #include <signal.h> 64 #include <stdio.h> 65 #include <stdlib.h> 66 #include <string.h> 67 #include <syslog.h> 68 #include <errno.h> 69 #include <sys/file.h> 70 #include <sys/param.h> 71 #include <sys/stat.h> 72 #include <sys/statvfs.h> 73 #include <sys/time.h> 74 #include <sys/types.h> 75 #include <sys/wait.h> 76 #include <termios.h> 77 #include <unistd.h> 78 #include "plugin.h" 79 #include "audit_sig_infc.h" 80 #include <audit_plugin.h> 81 82 #if !defined(TEXT_DOMAIN) 83 #define TEXT_DOMAIN "SUNW_OST_OSCMD" 84 #endif 85 /* 86 * After we get a AU_SIG_DISABLE, we want to set a timer for 2 seconds 87 * and let c2audit write as many records as it can until the timer 88 * goes off(at which point it returns to auditd with SIGALRM). If any 89 * other signals are received during that time, we call 90 * __audit_dowarn() to indicate that the queue may not have been fully 91 * flushed. 92 */ 93 #define ALRM_TIME 2 94 #define SLEEP_TIME 20 /* # of seconds to sleep in all hard loop */ 95 96 #if DEBUG 97 #define DPRINT(x) {(void) fprintf x; } 98 static FILE *dbfp; /* debug file */ 99 #else 100 #define DPRINT(x) 101 #endif /* DEBUG */ 102 103 static plugin_t *binfile = NULL; 104 105 static int turn_audit_on = AUC_AUDITING; 106 static int turn_audit_off = AUC_NOAUDIT; 107 108 static int running = 1; 109 110 /* 111 * GLOBALS: 112 */ 113 plugin_t *plugin_head = NULL; 114 static thr_data_t main_thr; /* auditd thread (0) */ 115 pthread_mutex_t plugin_mutex; /* for plugin_t list */ 116 117 static int caught_alrm = 0; /* number of SIGALRMs pending */ 118 static int caught_readc = 0; /* number of AU_SIG_READ_CONTROLs */ 119 static int caught_term = 0; /* number of AU_SIG_DISABLEs pending */ 120 static int caught_nextd = 0; /* number of AU_SIG_NEXT_DIRs pending */ 121 122 static int reset_list = 1; /* 1 to re-read audit_control */ 123 static int reset_file = 1; /* 1 to close/open binary log */ 124 125 static int auditing_set = 0; /* 1 if auditon(A_SETCOND, on... */ 126 127 static void my_sleep(); 128 static void signal_thread(); 129 static void loadauditlist(); 130 static void block_signals(); 131 static int do_sethost(); 132 133 /* common exit function */ 134 void 135 auditd_exit(int status) 136 { 137 #if MEM_TEST 138 sigset_t set; 139 140 DPRINT((dbfp, "mem_test intentional abort (status=%d)\n", 141 status)); 142 abort(); 143 #endif 144 DPRINT((dbfp, "%ld exit status = %d auditing_set = %d\n", 145 getpid(), status, auditing_set)); 146 147 if (auditing_set) 148 (void) auditon(A_SETCOND, (caddr_t)&turn_audit_off, 149 (int)sizeof (int)); 150 151 exit(status); 152 } 153 154 /* ARGSUSED */ 155 int 156 main(int argc, char *argv[]) 157 { 158 auditinfo_addr_t as_null; /* audit state to set */ 159 au_id_t auid; 160 pthread_t tid; 161 plugin_t *p; 162 pid_t pid; 163 164 #if DEBUG 165 /* LINTED */ 166 char *envp; 167 dbfp = __auditd_debug_file_open(); 168 #endif 169 (void) setsid(); 170 171 /* Internationalization */ 172 (void) setlocale(LC_ALL, ""); 173 (void) textdomain(TEXT_DOMAIN); 174 175 /* 176 * Set the audit host-id. 177 */ 178 if (do_sethost() != 0) { 179 __audit_dowarn("nostart", "", 0); 180 auditd_exit(1); 181 } 182 183 /* 184 * Turn off all auditing for this process. 185 */ 186 if (getaudit_addr(&as_null, sizeof (as_null)) == -1) { 187 __audit_dowarn("nostart", "", 0); 188 auditd_exit(2); 189 } 190 as_null.ai_mask.as_success = 0; 191 as_null.ai_mask.as_failure = 0; 192 (void) setaudit_addr(&as_null, sizeof (as_null)); 193 auid = AU_NOAUDITID; 194 (void) setauid(&auid); 195 /* 196 * Set the audit state flag to AUDITING. 197 */ 198 if (auditon(A_SETCOND, (caddr_t)&turn_audit_on, (int)sizeof (int)) != 199 0) { 200 DPRINT((dbfp, "auditon(A_SETCOND...) failed (exit)\n")); 201 __audit_dowarn("nostart", "", 0); 202 auditd_exit(7); 203 } 204 205 block_signals(); 206 207 #if DEBUG 208 /* output to dbfp shouldn't be duplicated by parent and child */ 209 (void) fflush(dbfp); 210 #endif 211 /* 212 * wait for "ready" signal before exit -- for greenline 213 */ 214 if (fork()) { 215 sigset_t set; 216 int signal_caught = 0; 217 218 (void) sigemptyset(&set); 219 (void) sigaddset(&set, AU_SIG_DISABLE); 220 221 while (signal_caught != AU_SIG_DISABLE) 222 signal_caught = sigwait(&set); 223 224 DPRINT((dbfp, "init complete: parent can now exit\n")); 225 226 auditd_exit(0); 227 } 228 pid = getppid(); 229 230 auditing_set = 1; 231 232 #if DEBUG && MEM_TEST 233 envp = getenv("UMEM_DEBUG"); 234 if (envp != NULL) 235 DPRINT((dbfp, "UMEM_DEBUG=%s\n", envp)); 236 envp = getenv("UMEM_LOGGING"); 237 if (envp != NULL) 238 DPRINT((dbfp, "UMEM_LOGGING=%s\n", envp)); 239 #endif 240 DPRINT((dbfp, "auditd pid=%ld\n", getpid())); 241 242 /* thread 0 sync */ 243 (void) pthread_mutex_init(&(main_thr.thd_mutex), NULL); 244 (void) pthread_cond_init(&(main_thr.thd_cv), NULL); 245 (void) pthread_mutex_init(&plugin_mutex, NULL); 246 /* 247 * Set up a separate thread for signal handling. 248 */ 249 if (pthread_create(&tid, NULL, (void *(*)(void *))signal_thread, 250 NULL)) { 251 (void) fprintf(stderr, gettext( 252 "auditd can't create a thread\n")); 253 auditd_exit(3); 254 } 255 /* 256 * Set the umask so that only audit or other users in the audit group 257 * can get to the files created by auditd. 258 */ 259 (void) umask(007); 260 261 if (__logpost("")) { /* Open the audit_data file. */ 262 DPRINT((dbfp, "logpost failed\n")); 263 auditd_exit(4); 264 } 265 /* 266 * Here is the main body of the audit daemon. running == 0 means that 267 * after flushing out the audit queue, it is time to exit in response to 268 * AU_SIG_DISABLE 269 */ 270 while (running) { 271 /* 272 * Read audit_control and create plugin lists. 273 * 274 * loadauditlist() and auditd_thread_init() are called 275 * while under the plugin_mutex lock to avoid a race 276 * with unload_plugin(). 277 */ 278 if (reset_list || reset_file) { 279 (void) pthread_mutex_lock(&plugin_mutex); 280 if (reset_list) 281 loadauditlist(); 282 283 if (auditd_thread_init()) { 284 auditd_thread_close(); 285 /* continue; wait for audit -s */ 286 } 287 (void) pthread_mutex_unlock(&plugin_mutex); 288 reset_list = 0; 289 } 290 /* 291 * tell parent I'm running whether or not the initialization 292 * actually worked. The failure case is to wait for an 293 * audit -n or audit -s to fix the problem. 294 */ 295 if (pid != 0) { 296 (void) kill(pid, AU_SIG_DISABLE); 297 pid = 0; 298 } 299 /* 300 * thread_signal() signals main (this thread) when 301 * it has received a signal. 302 */ 303 DPRINT((dbfp, "main thread is waiting\n")); 304 (void) pthread_mutex_lock(&(main_thr.thd_mutex)); 305 306 if (!(caught_readc || caught_term || caught_alrm || 307 caught_nextd)) 308 (void) pthread_cond_wait(&(main_thr.thd_cv), 309 &(main_thr.thd_mutex)); 310 (void) pthread_mutex_unlock(&(main_thr.thd_mutex)); 311 /* 312 * Got here because a signal came in. 313 * Since we may have gotten more than one, we assume a 314 * priority scheme with SIGALRM being the most 315 * significant. 316 */ 317 if (caught_alrm) { 318 /* 319 * We have returned from our timed wait for 320 * c2audit to calm down. We need to really shut 321 * down here. 322 */ 323 caught_alrm = 0; 324 running = 0; /* shut down now */ 325 } else if (caught_term) { 326 /* 327 * we are going to shut down, but need to 328 * allow time for the audit queues in 329 * c2audit and for the threads to empty. 330 */ 331 332 p = plugin_head; 333 while (p != NULL) { 334 DPRINT((dbfp, "signalling thread %d\n", 335 p->plg_tid)); 336 (void) pthread_mutex_lock(&(p->plg_mutex)); 337 p->plg_removed = 1; 338 339 if (p->plg_initialized) 340 (void) pthread_cond_signal( 341 &(p->plg_cv)); 342 343 (void) pthread_mutex_unlock(&(p->plg_mutex)); 344 p = p->plg_next; 345 } 346 347 caught_alrm = 0; 348 caught_readc = 0; 349 caught_term = 0; 350 caught_nextd = 0; 351 352 DPRINT((dbfp, 353 "main thread is pausing before exit.\n")); 354 (void) pthread_mutex_lock(&(main_thr.thd_mutex)); 355 caught_alrm = 0; 356 (void) alarm(ALRM_TIME); 357 while (!caught_alrm) 358 (void) pthread_cond_wait(&(main_thr.thd_cv), 359 &(main_thr.thd_mutex)); 360 361 (void) pthread_mutex_unlock(&(main_thr.thd_mutex)); 362 363 running = 0; /* Close down auditing and exit */ 364 } else if (caught_readc) { 365 /* 366 * if both hup and usr1 are caught, the logic in 367 * loadauditlist() results in hup winning. The 368 * result will be that the audit file is not rolled 369 * over unless audit_control actually changed. 370 * 371 * They want to reread the audit_control file. 372 * Set reset_list which will return us to the 373 * main while loop in the main routine. 374 */ 375 caught_readc = 0; 376 reset_list = 1; 377 } else if (caught_nextd) { 378 /* 379 * This is a special case for the binfile 380 * plugin. (audit -n) NULL out kvlist 381 * so binfile won't re-read audit_control 382 */ 383 caught_nextd = 0; 384 reset_file = 1; 385 if (binfile != NULL) { 386 _kva_free(binfile->plg_kvlist); 387 binfile->plg_kvlist = NULL; 388 binfile->plg_reopen = 1; 389 } 390 } 391 } /* end while (running) */ 392 auditd_thread_close(); 393 394 auditd_exit(0); 395 return (0); 396 } 397 398 /* 399 * my_sleep - sleep for SLEEP_TIME seconds but only accept the signals 400 * that we want to accept. (Premature termination just means the 401 * caller retries more often, not a big deal.) 402 */ 403 404 static void 405 my_sleep() 406 { 407 DPRINT((dbfp, "auditd: sleeping for 20 seconds\n")); 408 /* 409 * Set timer to "sleep" 410 */ 411 (void) alarm(SLEEP_TIME); 412 413 DPRINT((dbfp, "main thread is waiting for SIGALRM before exit.\n")); 414 (void) pthread_mutex_lock(&(main_thr.thd_mutex)); 415 (void) pthread_cond_wait(&(main_thr.thd_cv), &(main_thr.thd_mutex)); 416 (void) pthread_mutex_unlock(&(main_thr.thd_mutex)); 417 418 if (caught_term) { 419 DPRINT((dbfp, "normal AU_SIG_DISABLE exit\n")); 420 /* 421 * Exit, as requested. 422 */ 423 auditd_thread_close(); 424 } 425 if (caught_readc) 426 reset_list = 1; /* Reread the audit_control file */ 427 428 caught_readc = 0; 429 caught_nextd = 0; 430 } 431 432 /* 433 * search for $ISA/ in path and replace it with "" if auditd 434 * is 32 bit, else "sparcv9/" The plugin $ISA must match however 435 * auditd was compiled. 436 */ 437 438 static void 439 isa_ified(char *path, char **newpath) 440 { 441 char *p, *q; 442 443 if (((p = strchr(path, '$')) != NULL) && 444 (strncmp("$ISA/", p, 5) == 0)) { 445 (void) memcpy(*newpath, path, p - path); 446 q = *newpath + (p - path); 447 #ifdef __sparcv9 448 q += strlcpy(q, "sparcv9/", avail_length); 449 #endif 450 (void) strcpy(q, p + 5); 451 } else 452 *newpath = path; 453 } 454 455 /* 456 * init_plugin first searches the existing plugin list to see 457 * if the plugin already has been defined; if not, it creates it 458 * and links it into the list. It returns a pointer to the found 459 * or created struct. A change of path in audit_control for a 460 * given plugin will cause a miss. 461 */ 462 /* 463 * for 64 bits, the path name can grow 3 bytes (minus 5 for the 464 * removed "$ISA" and plus 8 for the added "sparcv9/" 465 */ 466 467 #define ISA_GROW 8 - 5 468 469 static plugin_t * 470 init_plugin(char *name, kva_t *list, int cnt_flag) 471 { 472 plugin_t *p, *q; 473 char filepath[MAXPATHLEN + 1 + ISA_GROW]; 474 char *path = filepath; 475 476 if (*name != '/') { 477 #ifdef __sparcv9 478 (void) strcpy(filepath, "/usr/lib/security/sparcv9/"); 479 #else 480 (void) strcpy(filepath, "/usr/lib/security/"); 481 #endif 482 if (strlcat(filepath, name, MAXPATHLEN) >= MAXPATHLEN) 483 return (NULL); 484 } else { 485 if (strlen(name) > MAXPATHLEN + ISA_GROW) 486 return (NULL); 487 isa_ified(name, &path); 488 } 489 p = plugin_head; 490 q = plugin_head; 491 while (p != NULL) { 492 if (p->plg_path != NULL) { 493 if (strcmp(p->plg_path, path) == 0) { 494 p->plg_removed = 0; 495 p->plg_to_be_removed = 0; 496 p->plg_cnt = cnt_flag; 497 498 _kva_free(p->plg_kvlist); 499 p->plg_kvlist = list; 500 p->plg_reopen = 1; 501 DPRINT((dbfp, "reusing %s\n", p->plg_path)); 502 return (p); 503 } 504 } 505 q = p; 506 p = p->plg_next; 507 } 508 DPRINT((dbfp, "creating new plugin structure for %s\n", path)); 509 510 p = malloc(sizeof (plugin_t)); 511 512 if (p == NULL) { 513 perror("auditd"); 514 return (NULL); 515 } 516 if (q == NULL) 517 plugin_head = p; 518 else 519 q->plg_next = p; 520 521 p->plg_next = NULL; 522 p->plg_initialized = 0; 523 p->plg_reopen = 1; 524 p->plg_tid = 0; 525 p->plg_removed = 0; 526 p->plg_to_be_removed = 0; 527 p->plg_tossed = 0; 528 p->plg_queued = 0; 529 p->plg_output = 0; 530 p->plg_sequence = 1; 531 p->plg_last_seq_out = 0; 532 p->plg_path = strdup(path); 533 p->plg_kvlist = list; 534 p->plg_cnt = cnt_flag; 535 p->plg_retry_time = SLEEP_TIME; 536 p->plg_qmax = 0; 537 p->plg_save_q_copy = NULL; 538 539 DPRINT((dbfp, "created plugin: %s\n", path)); 540 return (p); 541 } 542 543 /* 544 * loadauditlist - read the directory list from the audit_control file. 545 * to determine if a binary file is to be written. 546 * - read the plugin entries from the audit_control file 547 * 548 * globals - 549 * 550 * plugin queues 551 * 552 * success is when at least one plug in is defined. 553 * 554 * set cnt policy here based on auditconfig setting. future could 555 * have a policy = {+|-}cnt entry per plugin with auditconfig providing the 556 * default. 557 */ 558 559 static void 560 loadauditlist() 561 { 562 char buf[MAXPATHLEN]; 563 char *value; 564 plugin_t *p; 565 int acresult; 566 int wait_count = 0; 567 kva_t *kvlist; 568 long policy; 569 int cnt_flag; 570 struct au_qctrl kqmax; 571 au_acinfo_t *ach = NULL; 572 int got_dir = 0; 573 int have_plugin = 0; 574 char *endptr; 575 576 if (auditon(A_GETPOLICY, (char *)&policy, 0) == -1) { 577 DPRINT((dbfp, "auditon(A_GETPOLICY...) failed (exit)\n")); 578 __audit_dowarn("auditoff", "", 0); 579 auditd_thread_close(); 580 auditd_exit(5); 581 } 582 cnt_flag = ((policy & AUDIT_CNT) != 0) ? 1 : 0; 583 DPRINT((dbfp, "loadauditlist: policy is to %s\n", (cnt_flag == 1) ? 584 "continue" : "block")); 585 586 #if DEBUG 587 if (auditon(A_GETCOND, (caddr_t)&acresult, (int)sizeof (int)) != 588 0) 589 DPRINT((dbfp, "auditon(A_GETCOND...) failed (exit)\n")); 590 #endif 591 DPRINT((dbfp, "audit cond = %d (1 is on)\n", acresult)); 592 593 594 if (auditon(A_GETQCTRL, (char *)&kqmax, sizeof (struct au_qctrl)) != 595 0) { 596 DPRINT((dbfp, "auditon(A_GETQCTRL...) failed (exit)\n")); 597 __audit_dowarn("auditoff", "", 0); 598 auditd_thread_close(); 599 auditd_exit(6); 600 } 601 kqmax.aq_hiwater *= 5; /* RAM is cheaper in userspace */ 602 DPRINT((dbfp, "auditd: reading audit_control\n")); 603 604 p = plugin_head; 605 /* 606 * two-step on setting p->plg_removed because the input thread 607 * in doorway.c uses p->plg_removed to decide if the plugin is 608 * active. 609 */ 610 while (p != NULL) { 611 DPRINT((dbfp, "loadauditlist: %X, %s previously created\n", 612 p, p->plg_path)); 613 p->plg_to_be_removed = 1; /* tentative removal */ 614 p = p->plg_next; 615 } 616 /* 617 * have_plugin may over count by one if both a "dir" entry 618 * and a "plugin" entry for binfile are found. All that 619 * matters is that it be zero if no plugin or dir entries 620 * are found. 621 */ 622 have_plugin = 0; 623 for (;;) { 624 /* NULL == use standard path for audit_control */ 625 ach = _openac(NULL); 626 /* 627 * loop until a directory entry is found (0) or eof (-1) 628 */ 629 while (((acresult = _getacdir(ach, buf, sizeof (buf))) != 0) && 630 acresult != -1) { 631 } 632 if (acresult == 0) { 633 DPRINT((dbfp, 634 "loadauditlist: " 635 "got binfile via old config syntax\n")); 636 /* 637 * A directory entry was found. 638 */ 639 got_dir = 1; 640 kvlist = _str2kva("name=audit_binfile.so.1", 641 "=", ";"); 642 643 p = init_plugin("audit_binfile.so.1", kvlist, cnt_flag); 644 645 if (p != NULL) { 646 binfile = p; 647 p->plg_qmax = kqmax.aq_hiwater; 648 have_plugin++; 649 } 650 } 651 /* 652 * collect plugin entries. If there is an entry for 653 * binfile.so.1, the parameters from the plugin line 654 * override those set above. For binfile, p_dir is 655 * required only if dir wasn't specified elsewhere in 656 * audit_control 657 */ 658 _rewindac(ach); 659 while ((acresult = _getacplug(ach, &kvlist)) == 0) { 660 value = kva_match(kvlist, "name"); 661 if (value == NULL) 662 break; 663 DPRINT((dbfp, "loadauditlist: have an entry for %s\n", 664 value)); 665 p = init_plugin(value, kvlist, cnt_flag); 666 if (p == NULL) 667 continue; 668 669 if (strstr(value, "/audit_binfile.so") != NULL) { 670 binfile = p; 671 if (!got_dir && 672 (kva_match(kvlist, "p_dir") == 673 NULL)) { 674 __audit_dowarn("getacdir", "", 675 wait_count); 676 } 677 } 678 p->plg_qmax = kqmax.aq_hiwater; /* default */ 679 value = kva_match(kvlist, "qsize"); 680 if (value != NULL) { 681 long tmp; 682 683 tmp = strtol(value, &endptr, 10); 684 if (*endptr == '\0') 685 p->plg_qmax = tmp; 686 } 687 DPRINT((dbfp, "%s queue max = %d\n", p->plg_path, 688 p->plg_qmax)); 689 690 have_plugin++; 691 } 692 _endac(ach); 693 if (have_plugin != 0) 694 break; 695 /* 696 * there was a problem getting the directory 697 * list or remote host info from the audit_control file 698 */ 699 wait_count++; 700 #if DEBUG 701 if (wait_count < 2) 702 DPRINT((dbfp, 703 "auditd: problem getting directory " 704 "/ or plugin list from audit_control.\n")); 705 #endif /* DEBUG */ 706 __audit_dowarn("getacdir", "", wait_count); 707 /* 708 * sleep for SLEEP_TIME seconds. 709 */ 710 my_sleep(); 711 } /* end for(;;) */ 712 713 p = plugin_head; 714 while (p != NULL) { 715 DPRINT((dbfp, "loadauditlist: %s remove flag=%d; cnt=%d\n", 716 p->plg_path, p->plg_to_be_removed, p->plg_cnt)); 717 p->plg_removed = p->plg_to_be_removed; 718 p = p->plg_next; 719 } 720 } 721 722 /* 723 * block signals -- thread-specific blocking of the signals expected 724 * by the main thread. 725 */ 726 727 static void 728 block_signals() 729 { 730 sigset_t set; 731 732 (void) sigfillset(&set); 733 (void) pthread_sigmask(SIG_BLOCK, &set, NULL); 734 } 735 736 /* 737 * signal_thread is the designated signal catcher. It wakes up the 738 * main thread whenever it receives a signal and then goes back to 739 * sleep; it does not exit. The global variables caught_* let 740 * the main thread which signal was received. 741 * 742 * The thread is created with all signals blocked. 743 */ 744 745 static void 746 signal_thread() 747 { 748 sigset_t set; 749 int signal_caught; 750 751 DPRINT((dbfp, "the signal thread is thread %d\n", 752 pthread_self())); 753 754 (void) sigemptyset(&set); 755 (void) sigaddset(&set, SIGALRM); 756 (void) sigaddset(&set, AU_SIG_DISABLE); 757 (void) sigaddset(&set, AU_SIG_READ_CONTROL); 758 (void) sigaddset(&set, AU_SIG_NEXT_DIR); 759 760 for (;;) { 761 signal_caught = sigwait(&set); 762 switch (signal_caught) { 763 case SIGALRM: 764 caught_alrm++; 765 DPRINT((dbfp, "caught SIGALRM\n")); 766 break; 767 case AU_SIG_DISABLE: 768 caught_term++; 769 DPRINT((dbfp, "caught AU_SIG_DISABLE\n")); 770 break; 771 case AU_SIG_READ_CONTROL: 772 caught_readc++; 773 DPRINT((dbfp, "caught AU_SIG_READ_CONTROL\n")); 774 break; 775 case AU_SIG_NEXT_DIR: 776 caught_nextd++; 777 DPRINT((dbfp, "caught AU_SIG_NEXT_DIR\n")); 778 break; 779 default: 780 DPRINT((dbfp, "caught unexpected signal: %d\n", 781 signal_caught)); 782 break; 783 } 784 (void) pthread_cond_signal(&(main_thr.thd_cv)); 785 } 786 } 787 788 /* 789 * do_sethost - do auditon(2) to set the audit host-id. 790 * Returns 0 if success or -1 otherwise. 791 */ 792 static int 793 do_sethost(void) 794 { 795 au_tid_addr_t *termid; 796 auditinfo_addr_t audit_info; 797 char msg[512]; 798 799 if (adt_load_hostname(NULL, (adt_termid_t **)&termid) < 0) { 800 (void) snprintf(msg, sizeof (msg), "unable to get local " 801 "IP address: %s", strerror(errno)); 802 goto fail; 803 } 804 /* Get current kernel audit info, and fill in the IP address */ 805 if (auditon(A_GETKAUDIT, (caddr_t)&audit_info, 806 sizeof (audit_info)) < 0) { 807 (void) snprintf(msg, sizeof (msg), "unable to get kernel " 808 "audit info: %s", strerror(errno)); 809 goto fail; 810 } 811 812 audit_info.ai_termid = *termid; 813 814 /* Update the kernel audit info with new IP address */ 815 if (auditon(A_SETKAUDIT, (caddr_t)&audit_info, 816 sizeof (audit_info)) < 0) { 817 (void) snprintf(msg, sizeof (msg), "unable to set kernel " 818 "audit info: %s", strerror(errno)); 819 goto fail; 820 } 821 822 free(termid); 823 return (0); 824 825 fail: 826 free(termid); 827 __audit_syslog("auditd", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_DAEMON, 828 LOG_ALERT, msg); 829 return (-1); 830 } 831