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 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 *
26 * Copyright 2019 by Western Digital Corporation
27 */
28
29 /*
30 * au_preselect.c
31 */
32
33 #include <sys/types.h>
34 #include <errno.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <bsm/audit.h>
38 #include <bsm/libbsm.h>
39 #include <synch.h>
40
41 #define ALLOC_INIT (600) /* initially allocate ALLOC_INIT map entries */
42 #define ALLOC_INCR (100) /* if more map entries are needed, realloc */
43 /* in ALLOC_INCR increments */
44
45 static int alloc_map();
46 static int load_map();
47 static int realloc_map();
48
49 typedef struct event_map {
50 au_event_t event; /* audit event number */
51 au_class_t class; /* audit event class mask */
52 } event_map_t;
53
54 static event_map_t *event_map; /* the map */
55 static uint_t alloc_count; /* number of entries currently allocated */
56 static uint_t event_count; /* number of entries in map */
57 static mutex_t mutex_au_preselect = DEFAULTMUTEX;
58
59 /*
60 * au_preselect:
61 *
62 * Keep a dynamic array of event<-->class mappings.
63 * Refresh the map when the value of flag is AU_PRS_REREAD.
64 * Return:
65 * 1: The event is preselected.
66 * 0: The event is not preselected.
67 * -1: There was an error:
68 * Couldn't allocate memory.
69 * Couldn't find event.
70 */
71 int
au_preselect(au_event_t au_event,au_mask_t * au_mask_p,int sorf,int flag)72 au_preselect(au_event_t au_event, au_mask_t *au_mask_p, int sorf, int flag)
73 {
74 static char been_here_before; /* we cache the map */
75 register int i;
76 register au_class_t comp_class;
77
78 (void) mutex_lock(&mutex_au_preselect);
79 if (!been_here_before) {
80 if (alloc_map() == -1) {
81 (void) mutex_unlock(&mutex_au_preselect);
82 return (-1);
83 }
84
85 if (load_map() == -1) {
86 (void) mutex_unlock(&mutex_au_preselect);
87 return (-1);
88 }
89
90 been_here_before = 1;
91 }
92
93 /*
94 * Don't use the cache. Re-read the audit_event(5) db every time
95 */
96 if (flag == AU_PRS_REREAD) {
97 if (load_map() == -1) {
98 (void) mutex_unlock(&mutex_au_preselect);
99 return (-1);
100 }
101 }
102
103 /* Determine what portion of the preselection mask to check. */
104 if (sorf == AU_PRS_SUCCESS)
105 comp_class = au_mask_p->am_success;
106 else if (sorf == AU_PRS_FAILURE)
107 comp_class = au_mask_p->am_failure;
108 else
109 comp_class = au_mask_p->am_success | au_mask_p->am_failure;
110
111 for (i = 0; i < event_count; i++) {
112 if (event_map[i].event == au_event) {
113 if (event_map[i].class & comp_class) {
114 (void) mutex_unlock(&mutex_au_preselect);
115 return (1);
116 } else {
117 (void) mutex_unlock(&mutex_au_preselect);
118 return (0);
119 }
120 }
121 }
122
123 (void) mutex_unlock(&mutex_au_preselect);
124 return (-1); /* could not find event in the table */
125 }
126
127 /*
128 * Initially allocate about as many map entries as are there
129 * are audit events shipped with the system. For sites
130 * that don't add audit events, this should be enough.
131 */
132 static int
alloc_map()133 alloc_map()
134 {
135 if ((event_map = (event_map_t *)
136 calloc(ALLOC_INIT, (size_t)sizeof (event_map_t))) ==
137 (event_map_t *)NULL)
138 return (-1);
139 else
140 alloc_count = ALLOC_INIT;
141
142 return (0);
143 }
144
145 /*
146 * load the event<->class map into memory
147 */
148 static int
load_map()149 load_map()
150 {
151 register au_event_ent_t *evp;
152
153 event_count = 0;
154 setauevent();
155 while ((evp = getauevent()) != (au_event_ent_t *)NULL) {
156 if (event_count == alloc_count && realloc_map() == -1) {
157 endauevent();
158 return (-1);
159 }
160 event_map[event_count].event = evp->ae_number;
161 event_map[event_count].class = evp->ae_class;
162 ++event_count;
163 }
164 endauevent();
165
166 return (0);
167 }
168
169 /*
170 * realloc the event map in ALLOC_INCR increments
171 */
172 static int
realloc_map()173 realloc_map()
174 {
175 uint_t new_alloc_count;
176 event_map_t *new_event_map;
177
178 new_alloc_count = alloc_count + ALLOC_INCR;
179 if (new_alloc_count <= alloc_count) {
180 errno = ENOMEM;
181 return (-1);
182 }
183
184 if ((new_event_map = recallocarray(event_map, alloc_count,
185 new_alloc_count, sizeof (event_map_t))) == NULL)
186 return (-1);
187
188 alloc_count = new_alloc_count;
189 event_map = new_event_map;
190
191 return (0);
192 }
193