/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Copyright 2019 by Western Digital Corporation */ /* * au_preselect.c */ #include #include #include #include #include #include #include #define ALLOC_INIT (600) /* initially allocate ALLOC_INIT map entries */ #define ALLOC_INCR (100) /* if more map entries are needed, realloc */ /* in ALLOC_INCR increments */ static int alloc_map(); static int load_map(); static int realloc_map(); typedef struct event_map { au_event_t event; /* audit event number */ au_class_t class; /* audit event class mask */ } event_map_t; static event_map_t *event_map; /* the map */ static uint_t alloc_count; /* number of entries currently allocated */ static uint_t event_count; /* number of entries in map */ static mutex_t mutex_au_preselect = DEFAULTMUTEX; /* * au_preselect: * * Keep a dynamic array of event<-->class mappings. * Refresh the map when the value of flag is AU_PRS_REREAD. * Return: * 1: The event is preselected. * 0: The event is not preselected. * -1: There was an error: * Couldn't allocate memory. * Couldn't find event. */ int au_preselect(au_event_t au_event, au_mask_t *au_mask_p, int sorf, int flag) { static char been_here_before; /* we cache the map */ register int i; register au_class_t comp_class; (void) mutex_lock(&mutex_au_preselect); if (!been_here_before) { if (alloc_map() == -1) { (void) mutex_unlock(&mutex_au_preselect); return (-1); } if (load_map() == -1) { (void) mutex_unlock(&mutex_au_preselect); return (-1); } been_here_before = 1; } /* * Don't use the cache. Re-read the audit_event(5) db every time */ if (flag == AU_PRS_REREAD) { if (load_map() == -1) { (void) mutex_unlock(&mutex_au_preselect); return (-1); } } /* Determine what portion of the preselection mask to check. */ if (sorf == AU_PRS_SUCCESS) comp_class = au_mask_p->am_success; else if (sorf == AU_PRS_FAILURE) comp_class = au_mask_p->am_failure; else comp_class = au_mask_p->am_success | au_mask_p->am_failure; for (i = 0; i < event_count; i++) { if (event_map[i].event == au_event) { if (event_map[i].class & comp_class) { (void) mutex_unlock(&mutex_au_preselect); return (1); } else { (void) mutex_unlock(&mutex_au_preselect); return (0); } } } (void) mutex_unlock(&mutex_au_preselect); return (-1); /* could not find event in the table */ } /* * Initially allocate about as many map entries as are there * are audit events shipped with the system. For sites * that don't add audit events, this should be enough. */ static int alloc_map() { if ((event_map = (event_map_t *) calloc(ALLOC_INIT, (size_t)sizeof (event_map_t))) == (event_map_t *)NULL) return (-1); else alloc_count = ALLOC_INIT; return (0); } /* * load the event<->class map into memory */ static int load_map() { register au_event_ent_t *evp; event_count = 0; setauevent(); while ((evp = getauevent()) != (au_event_ent_t *)NULL) { if (event_count == alloc_count && realloc_map() == -1) { endauevent(); return (-1); } event_map[event_count].event = evp->ae_number; event_map[event_count].class = evp->ae_class; ++event_count; } endauevent(); return (0); } /* * realloc the event map in ALLOC_INCR increments */ static int realloc_map() { uint_t new_alloc_count; event_map_t *new_event_map; new_alloc_count = alloc_count + ALLOC_INCR; if (new_alloc_count <= alloc_count) { errno = ENOMEM; return (-1); } if ((new_event_map = recallocarray(event_map, alloc_count, new_alloc_count, sizeof (event_map_t))) == NULL) return (-1); alloc_count = new_alloc_count; event_map = new_event_map; return (0); }