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 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 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 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 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