xref: /illumos-gate/usr/src/cmd/auditd/auditd.c (revision 50d967713af8725306d090dd29033d9efe924715)
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 (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 /* Audit daemon server */
26 /*
27  * These routines make up the audit daemon server.  This daemon, called
28  * auditd, handles the user level parts of auditing.  It receives buffered
29  * audit records (usually one or more per buffer, potentially less than
30  * one) and passes them to one or more plugins for processing.
31  *
32  * The major interrupts are SIGHUP (start over), SIGTERM (start shutting down),
33  * SIGALRM (quit), and SIGUSR1 (start a new audit log file). SIGTERM is also
34  * used for the child to tell the parent that audit is ready.
35  *
36  * Configuration data comes from audit service configuration
37  * (AUDITD_FMRI/smf(5)) and the auditon system call.
38  *
39  * The major errors are EBUSY (auditing is already in use) and EINTR
40  * (one of the above signals was received).  File space errors are
41  * handled by the audit_binfile plugin
42  */
43 
44 /* #define	DEBUG    - define for debug messages to be generated */
45 /* #define	MEM_TEST - define to generate core dump on exit */
46 #define	DEBUG		0
47 #define	MEM_TEST	0
48 
49 #include <assert.h>
50 #include <bsm/adt.h>
51 #include <bsm/audit.h>
52 #include <bsm/audit_record.h>
53 #include <bsm/libbsm.h>
54 #include <fcntl.h>
55 #include <libintl.h>
56 #include <locale.h>
57 #include <netdb.h>
58 #include <pwd.h>
59 #include <secdb.h>
60 #include <signal.h>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <syslog.h>
65 #include <errno.h>
66 #include <sys/file.h>
67 #include <sys/param.h>
68 #include <sys/stat.h>
69 #include <sys/statvfs.h>
70 #include <sys/time.h>
71 #include <sys/types.h>
72 #include <sys/wait.h>
73 #include <termios.h>
74 #include <unistd.h>
75 #include "plugin.h"
76 #include <audit_plugin.h>
77 #include <audit_scf.h>
78 
79 #if !defined(TEXT_DOMAIN)
80 #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
81 #endif
82 /*
83  * After we get a SIGTERM, we want to set a timer for 2 seconds
84  * and let c2audit write as many records as it can until the timer
85  * goes off (at which point it returns to auditd with SIGALRM).
86  * If any other signals are received during that time, we call
87  * __audit_dowarn() to indicate that the queue may not have been fully
88  * flushed.
89  */
90 #define	ALRM_TIME	2
91 #define	SLEEP_TIME	20	/* # of seconds to sleep in all hard loop */
92 
93 static plugin_t	*binfile = NULL;
94 
95 static int	turn_audit_on  = AUC_AUDITING;
96 static int	turn_audit_off = AUC_NOAUDIT;
97 
98 static int	running = 1;
99 
100 /*
101  * GLOBALS:
102  */
103 plugin_t		*plugin_head = NULL;
104 static thr_data_t	main_thr;	/* auditd thread (0) */
105 pthread_mutex_t		plugin_mutex;	/* for plugin_t list */
106 
107 static int	caught_alrm = 0;	/* number of SIGALRMs pending */
108 static int	caught_readc = 0;	/* number of SIGHUPs pending */
109 static int	caught_term = 0;	/* number of SIGTERMs pending */
110 static int	caught_nextd = 0;	/* number of SIGUSR1s pending */
111 
112 static int	reset_list = 1;	/* 1 to re-read audit configuration */
113 static int	reset_file = 1; /* 1 to close/open binary log */
114 
115 static int	auditing_set = 0;	/* 1 if auditon(A_SETCOND, on... */
116 
117 static void	my_sleep();
118 static void	*signal_thread(void *);
119 static void	loadauditlist();
120 static void	block_signals();
121 static int	do_sethost();
122 
123 static void	conf_to_kernel();
124 static void	scf_to_kernel_qctrl();
125 static void	scf_to_kernel_policy();
126 
127 /*
128  * err_exit() - exit function after the unsuccessful call to auditon();
129  * prints_out / saves_via_syslog the necessary error messages.
130  */
131 static void
132 err_exit(char *msg)
133 {
134 	if (msg != NULL) {
135 		DPRINT((dbfp, "%s\n", msg));
136 		__audit_syslog("auditd", LOG_PID | LOG_CONS | LOG_NOWAIT,
137 		    LOG_DAEMON, LOG_ALERT, msg);
138 		free(msg);
139 	} else {
140 		DPRINT((dbfp, "the memory allocation failed\n"));
141 		__audit_syslog("auditd", LOG_PID | LOG_CONS | LOG_NOWAIT,
142 		    LOG_DAEMON, LOG_ALERT, gettext("no memory"));
143 	}
144 	auditd_thread_close();
145 	auditd_exit(1);
146 }
147 
148 /* common exit function */
149 void
150 auditd_exit(int status)
151 {
152 #if MEM_TEST
153 	DPRINT((dbfp, "mem_test intentional abort (status=%d)\n",
154 	    status));
155 	abort();
156 #endif
157 	DPRINT((dbfp, "%ld exit status = %d auditing_set = %d\n",
158 	    getpid(), status, auditing_set));
159 
160 	if (auditing_set)
161 		(void) auditon(A_SETCOND, (caddr_t)&turn_audit_off,
162 		    sizeof (int));
163 
164 #if DEBUG
165 	(void) fclose(dbfp);
166 #endif
167 
168 	exit(status);
169 }
170 
171 /* ARGSUSED */
172 int
173 main(int argc, char *argv[])
174 {
175 	auditinfo_addr_t	as_null;	/* audit state to set */
176 	au_id_t			auid;
177 	pthread_t		tid;
178 	plugin_t		*p;
179 	pid_t			pid;
180 
181 #if DEBUG
182 #if MEM_TEST
183 	char	*envp;
184 #endif
185 	if (dbfp == NULL) {
186 		dbfp = __auditd_debug_file_open();
187 	}
188 #endif
189 	(void) setsid();
190 
191 	/* Internationalization */
192 	(void) setlocale(LC_ALL, "");
193 	(void) textdomain(TEXT_DOMAIN);
194 
195 	/*
196 	 * Set the audit host-id.
197 	 */
198 	if (do_sethost() != 0) {
199 		__audit_dowarn("nostart", "", 0);
200 		auditd_exit(1);
201 	}
202 
203 	/*
204 	 * Turn off all auditing for this process.
205 	 */
206 	if (getaudit_addr(&as_null, sizeof (as_null)) == -1) {
207 		__audit_dowarn("nostart", "", 0);
208 		auditd_exit(1);
209 	}
210 	as_null.ai_mask.as_success = 0;
211 	as_null.ai_mask.as_failure = 0;
212 	(void) setaudit_addr(&as_null, sizeof (as_null));
213 	auid = AU_NOAUDITID;
214 	(void) setauid(&auid);
215 	/*
216 	 * Set the audit state flag to AUDITING.
217 	 */
218 	if (auditon(A_SETCOND, (caddr_t)&turn_audit_on, sizeof (int)) !=
219 	    0) {
220 		DPRINT((dbfp, "auditon(A_SETCOND...) failed (exit)\n"));
221 		__audit_dowarn("nostart", "", 0);
222 		auditd_exit(1);
223 	}
224 
225 	block_signals();
226 
227 	/*
228 	 * wait for "ready" signal before exit -- for greenline
229 	 */
230 	if (fork()) {
231 		sigset_t	set;
232 		int		signal_caught = 0;
233 
234 		(void) sigemptyset(&set);
235 		(void) sigaddset(&set, SIGTERM);
236 
237 		while (signal_caught != SIGTERM)
238 			signal_caught = sigwait(&set);
239 
240 		DPRINT((dbfp, "init complete:  parent can now exit\n"));
241 
242 		auditd_exit(0);
243 	}
244 	pid = getppid();
245 
246 	auditing_set = 1;
247 
248 #if DEBUG && MEM_TEST
249 	envp = getenv("UMEM_DEBUG");
250 	if (envp != NULL)
251 		DPRINT((dbfp, "UMEM_DEBUG=%s\n", envp));
252 	envp = getenv("UMEM_LOGGING");
253 	if (envp != NULL)
254 		DPRINT((dbfp, "UMEM_LOGGING=%s\n", envp));
255 #endif
256 	DPRINT((dbfp, "auditd pid=%ld\n", getpid()));
257 
258 	/* thread 0 sync */
259 	(void) pthread_mutex_init(&(main_thr.thd_mutex), NULL);
260 	(void) pthread_cond_init(&(main_thr.thd_cv), NULL);
261 	(void) pthread_mutex_init(&plugin_mutex, NULL);
262 	/*
263 	 * Set up a separate thread for signal handling.
264 	 */
265 	if (pthread_create(&tid, NULL, signal_thread, NULL)) {
266 		(void) fprintf(stderr, gettext(
267 		    "auditd can't create a thread\n"));
268 		auditd_exit(1);
269 	}
270 	/*
271 	 * Set the umask so that only audit or other users in the audit group
272 	 * can get to the files created by auditd.
273 	 */
274 	(void) umask(007);
275 
276 	if (__logpost("")) {	/* Cannot unlink pointer to audit.log(4) file */
277 		DPRINT((dbfp, "logpost failed\n"));
278 		auditd_exit(1);
279 	}
280 	/*
281 	 * Here is the main body of the audit daemon. running == 0 means that
282 	 * after flushing out the audit queue, it is time to exit in response
283 	 * to SIGTERM.
284 	 */
285 	while (running) {
286 		/*
287 		 * Read auditd / auditd plugins related configuration from
288 		 * smf(5) repository and create plugin lists.
289 		 *
290 		 * loadauditlist() and auditd_thread_init() are called
291 		 * while under the plugin_mutex lock to avoid a race
292 		 * with unload_plugin().
293 		 */
294 		if (reset_list || reset_file) {
295 			if (reset_list) {
296 				conf_to_kernel();
297 				scf_to_kernel_qctrl();
298 				scf_to_kernel_policy();
299 				(void) pthread_mutex_lock(&plugin_mutex);
300 				loadauditlist();
301 			} else {
302 				(void) pthread_mutex_lock(&plugin_mutex);
303 			}
304 
305 			if (auditd_thread_init()) {
306 				auditd_thread_close();
307 				/* continue; wait for audit -s */
308 			}
309 			(void) pthread_mutex_unlock(&plugin_mutex);
310 
311 			if (reset_list && reset_file) {
312 				(void) printf(gettext("auditd started\n"));
313 			} else {
314 				(void) printf(gettext("auditd refreshed\n"));
315 			}
316 
317 			reset_list = 0;
318 			reset_file = 0;
319 		}
320 		/*
321 		 * tell parent I'm running whether or not the initialization
322 		 * actually worked.  The failure case is to wait for an
323 		 * audit -n or audit -s to fix the problem.
324 		 */
325 		if (pid != 0) {
326 			(void) kill(pid, SIGTERM);
327 			pid = 0;
328 		}
329 		/*
330 		 * thread_signal() signals main (this thread) when
331 		 * it has received a signal.
332 		 */
333 		DPRINT((dbfp, "main thread is waiting for signal\n"));
334 		(void) pthread_mutex_lock(&(main_thr.thd_mutex));
335 
336 		if (!(caught_readc || caught_term || caught_alrm ||
337 		    caught_nextd))
338 			(void) pthread_cond_wait(&(main_thr.thd_cv),
339 			    &(main_thr.thd_mutex));
340 		(void) pthread_mutex_unlock(&(main_thr.thd_mutex));
341 		/*
342 		 * Got here because a signal came in.
343 		 * Since we may have gotten more than one, we assume a
344 		 * priority scheme with SIGALRM being the most
345 		 * significant.
346 		 */
347 		if (caught_alrm) {
348 			/*
349 			 * We have returned from our timed wait for
350 			 * c2audit to calm down.  We need to really shut
351 			 * down here.
352 			 */
353 			caught_alrm = 0;
354 			running = 0;	/* shut down now */
355 		} else if (caught_term) {
356 			/*
357 			 * we are going to shut down, but need to
358 			 * allow time for the audit queues in
359 			 * c2audit and for the threads to empty.
360 			 */
361 
362 			p = plugin_head;
363 			while (p != NULL) {
364 				DPRINT((dbfp, "signalling thread %d\n",
365 				    p->plg_tid));
366 				(void) pthread_mutex_lock(&(p->plg_mutex));
367 				p->plg_removed = 1;
368 
369 				if (p->plg_initialized)
370 					(void) pthread_cond_signal(
371 					    &(p->plg_cv));
372 
373 				(void) pthread_mutex_unlock(&(p->plg_mutex));
374 				p = p->plg_next;
375 			}
376 
377 			caught_alrm = 0;
378 			caught_readc  = 0;
379 			caught_term = 0;
380 			caught_nextd = 0;
381 
382 			DPRINT((dbfp,
383 			    "main thread is pausing before exit.\n"));
384 			(void) pthread_mutex_lock(&(main_thr.thd_mutex));
385 			caught_alrm = 0;
386 			(void) alarm(ALRM_TIME);
387 			while (!caught_alrm)
388 				(void) pthread_cond_wait(&(main_thr.thd_cv),
389 				    &(main_thr.thd_mutex));
390 
391 			(void) pthread_mutex_unlock(&(main_thr.thd_mutex));
392 
393 			running = 0;	/* Close down auditing and exit */
394 		} else if (caught_readc) {
395 			/*
396 			 * if both hup and usr1 are caught, the logic in
397 			 * loadauditlist() results in hup winning.  The
398 			 * result will be that the audit file is not rolled
399 			 * over unless audit configuration actually changed.
400 			 *
401 			 * They want to reread the audit configuration from
402 			 * smf(5) repository (AUDITD_FMRI). Set reset_list
403 			 * which will return us to the main while loop in the
404 			 * main routine.
405 			 */
406 			caught_readc = 0;
407 			reset_list = 1;
408 		} else if (caught_nextd) {
409 			/*
410 			 * This is a special case for the binfile plugin.
411 			 * (audit -n)  NULL out kvlist so binfile won't
412 			 * re-read audit configuration.
413 			 */
414 			caught_nextd = 0;
415 			reset_file = 1;
416 			if (binfile != NULL) {
417 				_kva_free(binfile->plg_kvlist);
418 				binfile->plg_kvlist = NULL;
419 				binfile->plg_reopen = 1;
420 			}
421 		}
422 	}	/* end while (running) */
423 	auditd_thread_close();
424 
425 	auditd_exit(0);
426 	return (0);
427 }
428 
429 /*
430  * my_sleep - sleep for SLEEP_TIME seconds but only accept the signals
431  *	that we want to accept.  (Premature termination just means the
432  *	caller retries more often, not a big deal.)
433  */
434 
435 static void
436 my_sleep()
437 {
438 	DPRINT((dbfp, "auditd: sleeping for 20 seconds\n"));
439 	/*
440 	 * Set timer to "sleep"
441 	 */
442 	(void) alarm(SLEEP_TIME);
443 
444 	DPRINT((dbfp, "main thread is waiting for SIGALRM before exit.\n"));
445 	(void) pthread_mutex_lock(&(main_thr.thd_mutex));
446 	(void) pthread_cond_wait(&(main_thr.thd_cv), &(main_thr.thd_mutex));
447 	(void) pthread_mutex_unlock(&(main_thr.thd_mutex));
448 
449 	if (caught_term) {
450 		DPRINT((dbfp, "normal SIGTERM exit\n"));
451 		/*
452 		 * Exit, as requested.
453 		 */
454 		auditd_thread_close();
455 	}
456 	if (caught_readc)
457 		reset_list = 1;		/* Reread the audit configuration */
458 
459 	caught_readc = 0;
460 	caught_nextd = 0;
461 }
462 
463 /*
464  * search for $ISA/ in path and replace it with "" if auditd
465  * is 32 bit, else "sparcv9/"  The plugin $ISA must match however
466  * auditd was compiled.
467  */
468 
469 static void
470 isa_ified(char *path, char **newpath)
471 {
472 	char	*p, *q;
473 
474 	if (((p = strchr(path, '$')) != NULL) &&
475 	    (strncmp("$ISA/", p, 5) == 0)) {
476 		(void) memcpy(*newpath, path, p - path);
477 		q = *newpath + (p - path);
478 #ifdef __sparcv9
479 		q += strlcpy(q, "sparcv9/", avail_length);
480 #endif
481 		(void) strcpy(q, p + 5);
482 	} else
483 		*newpath = path;
484 }
485 
486 /*
487  * init_plugin first searches the existing plugin list to see if the plugin
488  * already has been defined; if not, it creates it and links it into the list.
489  * It returns a pointer to the found or created struct. Note, that
490  * (manual/unsupported) change of path property in audit service configuration
491  * for given plugin will cause a miss.
492  */
493 /*
494  * for 64 bits, the path name can grow 3 bytes (minus 5 for the
495  * removed "$ISA" and plus 8 for the added "sparcv9/"
496  */
497 
498 #define	ISA_GROW	8 - 5
499 
500 static plugin_t *
501 init_plugin(char *name, kva_t *list, int cnt_flag)
502 {
503 	plugin_t	*p, *q;
504 	char		filepath[MAXPATHLEN + 1 + ISA_GROW];
505 	char		*path = filepath;
506 
507 	if (*name != '/') {
508 #ifdef  __sparcv9
509 		(void) strcpy(filepath, "/usr/lib/security/sparcv9/");
510 #else
511 		(void) strcpy(filepath, "/usr/lib/security/");
512 #endif
513 		if (strlcat(filepath, name, MAXPATHLEN) >= MAXPATHLEN)
514 			return (NULL);
515 	} else {
516 		if (strlen(name) > MAXPATHLEN + ISA_GROW)
517 			return (NULL);
518 		isa_ified(name, &path);
519 	}
520 	p = plugin_head;
521 	q = plugin_head;
522 	while (p != NULL) {
523 		if (p->plg_path != NULL) {
524 			if (strcmp(p->plg_path, path) == 0) {
525 				p->plg_removed = 0;
526 				p->plg_to_be_removed = 0;
527 				p->plg_cnt = cnt_flag;
528 
529 				_kva_free(p->plg_kvlist);
530 				p->plg_kvlist = _kva_dup(list);
531 				if (list != NULL && p->plg_kvlist == NULL) {
532 					err_exit(NULL);
533 				}
534 				p->plg_reopen = 1;
535 				DPRINT((dbfp, "reusing %s\n", p->plg_path));
536 				return (p);
537 			}
538 		}
539 		q = p;
540 		p = p->plg_next;
541 	}
542 	DPRINT((dbfp, "creating new plugin structure for %s\n", path));
543 
544 	p = malloc(sizeof (plugin_t));
545 
546 	if (p == NULL) {
547 		perror("auditd");
548 		return (NULL);
549 	}
550 	if (q == NULL)
551 		plugin_head = p;
552 	else
553 		q->plg_next = p;
554 
555 	p->plg_next = NULL;
556 	p->plg_initialized = 0;
557 	p->plg_reopen = 1;
558 	p->plg_tid = 0;
559 	p->plg_removed = 0;
560 	p->plg_to_be_removed = 0;
561 	p->plg_tossed = 0;
562 	p->plg_queued = 0;
563 	p->plg_output = 0;
564 	p->plg_sequence = 1;
565 	p->plg_last_seq_out = 0;
566 	p->plg_path = strdup(path);
567 	p->plg_kvlist = _kva_dup(list);
568 	p->plg_cnt = cnt_flag;
569 	p->plg_retry_time = SLEEP_TIME;
570 	p->plg_qmax = 0;
571 	p->plg_save_q_copy = NULL;
572 
573 	if (list != NULL && p->plg_kvlist == NULL || p->plg_path == NULL) {
574 		err_exit(NULL);
575 	}
576 
577 	DPRINT((dbfp, "created plugin:  %s\n", path));
578 	return (p);
579 }
580 
581 /*
582  * loadauditlist() - read the auditd plugin configuration from smf(5) and
583  * prepare appropriate plugin related structures (plugin_t). Set cnt policy here
584  * based on currently active policy settings. (future could have a policy =
585  * {+|-}cnt entry per plugin with auditconfig providing the default)
586  */
587 static void
588 loadauditlist()
589 {
590 	char			*value;
591 	char			*endptr;
592 	plugin_t		*p;
593 	uint32_t		policy;
594 	int			cnt_flag;
595 	struct au_qctrl		kqmax;
596 	scf_plugin_kva_node_t	*plugin_kva_ll;
597 	scf_plugin_kva_node_t	*plugin_kva_ll_head;
598 
599 	if (auditon(A_GETPOLICY, (char *)&policy, 0) == -1) {
600 		DPRINT((dbfp, "auditon(A_GETPOLICY...) failed (exit)\n"));
601 		__audit_dowarn("auditoff", "", 0);
602 		auditd_thread_close();
603 		auditd_exit(1);
604 	}
605 	cnt_flag = ((policy & AUDIT_CNT) != 0) ? 1 : 0;
606 	DPRINT((dbfp, "loadauditlist: policy is to %s\n", (cnt_flag == 1) ?
607 	    "continue" : "block"));
608 
609 #if DEBUG
610 	{
611 		int	acresult;
612 		if (auditon(A_GETCOND, (caddr_t)&acresult, sizeof (int)) != 0) {
613 			DPRINT((dbfp, "auditon(A_GETCOND...) failed (exit)\n"));
614 		}
615 		DPRINT((dbfp, "audit cond = %d (1 is on)\n", acresult));
616 	}
617 #endif
618 
619 
620 	if (auditon(A_GETQCTRL, (char *)&kqmax, sizeof (struct au_qctrl)) !=
621 	    0) {
622 		DPRINT((dbfp, "auditon(A_GETQCTRL...) failed (exit)\n"));
623 		__audit_dowarn("auditoff", "", 0);
624 		auditd_thread_close();
625 		auditd_exit(1);
626 	}
627 	kqmax.aq_hiwater *= 5;		/* RAM is cheaper in userspace */
628 	DPRINT((dbfp, "auditd: reading audit configuration\n"));
629 
630 	p = plugin_head;
631 	/*
632 	 * two-step on setting p->plg_removed because the input thread
633 	 * in doorway.c uses p->plg_removed to decide if the plugin is
634 	 * active.
635 	 */
636 	while (p != NULL) {
637 		DPRINT((dbfp, "loadauditlist: %p, %s previously created\n",
638 		    (void *)p, p->plg_path));
639 		p->plg_to_be_removed = 1;	/* tentative removal */
640 		p = p->plg_next;
641 	}
642 
643 	if (!do_getpluginconfig_scf(NULL, &plugin_kva_ll)) {
644 		DPRINT((dbfp, "Could not get plugin configuration.\n"));
645 		auditd_thread_close();
646 		auditd_exit(1);
647 	}
648 	plugin_kva_ll_head = plugin_kva_ll;
649 
650 	while (plugin_kva_ll != NULL) {
651 		DPRINT((dbfp, "loadauditlist: starting with %s",
652 		    plugin_kva_ll->plugin_name));
653 
654 		/* skip inactive plugins */
655 		value = kva_match(plugin_kva_ll->plugin_kva, PLUGIN_ACTIVE);
656 		if (strcmp(value, "1") != 0) {
657 			DPRINT((dbfp, " (inactive:%s) skipping..\n", value));
658 			plugin_kva_ll = plugin_kva_ll->next;
659 			continue;
660 		}
661 		DPRINT((dbfp, " (active)\n"));
662 
663 		value = kva_match(plugin_kva_ll->plugin_kva, PLUGIN_PATH);
664 		DPRINT((dbfp, "loadauditlist: have an entry for %s (%s)\n",
665 		    plugin_kva_ll->plugin_name, value));
666 
667 		p = init_plugin(value, plugin_kva_ll->plugin_kva, cnt_flag);
668 		if (p == NULL) {
669 			DPRINT((dbfp, "Unsuccessful plugin_t "
670 			    "initialization.\n"));
671 			my_sleep();
672 			continue;
673 		}
674 
675 		if (strcmp(plugin_kva_ll->plugin_name, "audit_binfile") == 0) {
676 			binfile = p;
677 		}
678 
679 		p->plg_qmax = kqmax.aq_hiwater; /* default */
680 		value = kva_match(plugin_kva_ll->plugin_kva, PLUGIN_QSIZE);
681 		if (value != NULL) {
682 			long	tmp;
683 			tmp = strtol(value, &endptr, 10);
684 			if (*endptr == '\0' && tmp != 0) {
685 				p->plg_qmax = tmp;
686 			}
687 		}
688 		DPRINT((dbfp, "%s queue max = %d\n", p->plg_path, p->plg_qmax));
689 
690 		plugin_kva_ll = plugin_kva_ll->next;
691 	}
692 
693 	p = plugin_head;
694 	while (p != NULL) {
695 		DPRINT((dbfp, "loadauditlist: %s remove flag=%d; cnt=%d\n",
696 		    p->plg_path, p->plg_to_be_removed, p->plg_cnt));
697 		p->plg_removed = p->plg_to_be_removed;
698 		p = p->plg_next;
699 	}
700 
701 	plugin_kva_ll_free(plugin_kva_ll_head);
702 }
703 
704 /*
705  * block signals -- thread-specific blocking of the signals expected
706  * by the main thread.
707  */
708 
709 static void
710 block_signals()
711 {
712 	sigset_t	set;
713 
714 	(void) sigfillset(&set);
715 	(void) pthread_sigmask(SIG_BLOCK, &set, NULL);
716 }
717 
718 /*
719  * signal_thread is the designated signal catcher.  It wakes up the
720  * main thread whenever it receives a signal and then goes back to
721  * sleep; it does not exit.  The global variables caught_* let
722  * the main thread which signal was received.
723  *
724  * The thread is created with all signals blocked.
725  */
726 
727 static void *
728 signal_thread(void *arg __unused)
729 {
730 	sigset_t	set;
731 	int		signal_caught;
732 
733 	DPRINT((dbfp, "the signal thread is thread %d\n",
734 	    pthread_self()));
735 
736 	(void) sigemptyset(&set);
737 	(void) sigaddset(&set, SIGALRM);
738 	(void) sigaddset(&set, SIGTERM);
739 	(void) sigaddset(&set, SIGHUP);
740 	(void) sigaddset(&set, SIGUSR1);
741 
742 	for (;;) {
743 		signal_caught = sigwait(&set);
744 		switch (signal_caught) {
745 		case SIGALRM:
746 			caught_alrm++;
747 			DPRINT((dbfp, "caught SIGALRM\n"));
748 			break;
749 		case SIGTERM:
750 			caught_term++;
751 			DPRINT((dbfp, "caught SIGTERM\n"));
752 			break;
753 		case SIGHUP:
754 			caught_readc++;
755 			DPRINT((dbfp, "caught SIGHUP\n"));
756 			break;
757 		case SIGUSR1:
758 			caught_nextd++;
759 			DPRINT((dbfp, "caught SIGUSR1\n"));
760 			break;
761 		default:
762 			DPRINT((dbfp, "caught unexpected signal:  %d\n",
763 			    signal_caught));
764 			break;
765 		}
766 		(void) pthread_cond_signal(&(main_thr.thd_cv));
767 	}
768 	return (NULL);
769 }
770 
771 /*
772  * do_sethost - do auditon(2) to set the audit host-id.
773  *		Returns 0 if success or -1 otherwise.
774  */
775 static int
776 do_sethost(void)
777 {
778 	au_tid_addr_t	*termid;
779 	auditinfo_addr_t	audit_info;
780 	char	msg[512];
781 
782 	if (adt_load_hostname(NULL, (adt_termid_t **)&termid) < 0) {
783 		(void) snprintf(msg, sizeof (msg), "unable to get local "
784 		    "IP address: %s", strerror(errno));
785 		goto fail;
786 	}
787 	/* Get current kernel audit info, and fill in the IP address */
788 	if (auditon(A_GETKAUDIT, (caddr_t)&audit_info,
789 	    sizeof (audit_info)) < 0) {
790 		(void) snprintf(msg, sizeof (msg), "unable to get kernel "
791 		    "audit info: %s", strerror(errno));
792 		goto fail;
793 	}
794 
795 	audit_info.ai_termid = *termid;
796 
797 	/* Update the kernel audit info with new IP address */
798 	if (auditon(A_SETKAUDIT, (caddr_t)&audit_info,
799 	    sizeof (audit_info)) < 0) {
800 		(void) snprintf(msg, sizeof (msg), "unable to set kernel "
801 		    "audit info: %s", strerror(errno));
802 		goto fail;
803 	}
804 
805 	free(termid);
806 	return (0);
807 
808 fail:
809 	free(termid);
810 	__audit_syslog("auditd", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_DAEMON,
811 	    LOG_ALERT, msg);
812 	return (-1);
813 }
814 
815 /*
816  * conf_to_kernel() - configure the event to class mapping; see also
817  * auditconfig(1M) -conf option.
818  */
819 static void
820 conf_to_kernel(void)
821 {
822 	au_event_ent_t		*evp;
823 	int			i;
824 	char			*msg;
825 	au_evclass_map_t	ec;
826 	au_stat_t		as;
827 
828 	if (auditon(A_GETSTAT, (caddr_t)&as, 0) != 0) {
829 		(void) asprintf(&msg, gettext("Audit module does not appear "
830 		    "to be loaded."));
831 		err_exit(msg);
832 	}
833 
834 	i = 0;
835 	setauevent();
836 	while ((evp = getauevent()) != NULL) {
837 		if (evp->ae_number <= as.as_numevent) {
838 			++i;
839 			ec.ec_number = evp->ae_number;
840 			ec.ec_class = evp->ae_class;
841 
842 			if (auditon(A_SETCLASS, (caddr_t)&ec,
843 			    sizeof (ec)) != 0) {
844 				(void) asprintf(&msg,
845 				    gettext("Could not configure kernel audit "
846 				    "event to class mappings."));
847 				err_exit(msg);
848 			}
849 		}
850 	}
851 	endauevent();
852 
853 	DPRINT((dbfp, "configured %d kernel events.\n", i));
854 }
855 
856 /*
857  * scf_to_kernel_qctrl() - update the kernel queue control parameters
858  */
859 static void
860 scf_to_kernel_qctrl(void)
861 {
862 	struct au_qctrl	act_qctrl;
863 	struct au_qctrl	cfg_qctrl;
864 	char		*msg;
865 
866 	if (!do_getqctrl_scf(&cfg_qctrl)) {
867 		(void) asprintf(&msg, gettext("Unable to gather audit queue "
868 		    "control parameters from the SMF repository."));
869 		err_exit(msg);
870 	}
871 
872 	DPRINT((dbfp, "will check and set qctrl parameters:\n"));
873 	DPRINT((dbfp, "\thiwater: %d\n", cfg_qctrl.aq_hiwater));
874 	DPRINT((dbfp, "\tlowater: %d\n", cfg_qctrl.aq_lowater));
875 	DPRINT((dbfp, "\tbufsz: %d\n", cfg_qctrl.aq_bufsz));
876 	DPRINT((dbfp, "\tdelay: %ld\n", cfg_qctrl.aq_delay));
877 
878 	if (auditon(A_GETQCTRL, (caddr_t)&act_qctrl, 0) != 0) {
879 		(void) asprintf(&msg, gettext("Could not retrieve "
880 		    "audit queue controls from kernel."));
881 		err_exit(msg);
882 	}
883 
884 	/* overwrite the default (zeros) from the qctrl configuration */
885 	if (cfg_qctrl.aq_hiwater == 0) {
886 		cfg_qctrl.aq_hiwater = act_qctrl.aq_hiwater;
887 		DPRINT((dbfp, "hiwater changed to active value: %u\n",
888 		    cfg_qctrl.aq_hiwater));
889 	}
890 	if (cfg_qctrl.aq_lowater == 0) {
891 		cfg_qctrl.aq_lowater = act_qctrl.aq_lowater;
892 		DPRINT((dbfp, "lowater changed to active value: %u\n",
893 		    cfg_qctrl.aq_lowater));
894 	}
895 	if (cfg_qctrl.aq_bufsz == 0) {
896 		cfg_qctrl.aq_bufsz = act_qctrl.aq_bufsz;
897 		DPRINT((dbfp, "bufsz changed to active value: %u\n",
898 		    cfg_qctrl.aq_bufsz));
899 	}
900 	if (cfg_qctrl.aq_delay == 0) {
901 		cfg_qctrl.aq_delay = act_qctrl.aq_delay;
902 		DPRINT((dbfp, "delay changed to active value: %ld\n",
903 		    cfg_qctrl.aq_delay));
904 	}
905 
906 	if (auditon(A_SETQCTRL, (caddr_t)&cfg_qctrl, 0) != 0) {
907 		(void) asprintf(&msg,
908 		    gettext("Could not configure audit queue controls."));
909 		err_exit(msg);
910 	}
911 
912 	DPRINT((dbfp, "qctrl parameters set\n"));
913 }
914 
915 /*
916  * scf_to_kernel_policy() - update the audit service policies
917  */
918 static void
919 scf_to_kernel_policy(void)
920 {
921 	uint32_t	policy;
922 	char		*msg;
923 
924 	if (!do_getpolicy_scf(&policy)) {
925 		(void) asprintf(&msg, gettext("Unable to get audit policy "
926 		    "configuration from the SMF repository."));
927 		err_exit(msg);
928 	}
929 
930 	if (auditon(A_SETPOLICY, (caddr_t)&policy, 0) != 0) {
931 		(void) asprintf(&msg,
932 		    gettext("Could not update active policy settings."));
933 		err_exit(msg);
934 	}
935 
936 	DPRINT((dbfp, "kernel policy settings updated\n"));
937 }
938