xref: /illumos-gate/usr/src/cmd/auditd/auditd.c (revision bb9b6b3f59b8820022416cea99b49c50fef6e391)
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