1155192Srwatson/*- 2155192Srwatson * Copyright (c) 2005 Wayne J. Salamon 3155192Srwatson * All rights reserved. 4155192Srwatson * 5155192Srwatson * This software was developed by Wayne Salamon for the TrustedBSD Project. 6155192Srwatson * 7155192Srwatson * Redistribution and use in source and binary forms, with or without 8155192Srwatson * modification, are permitted provided that the following conditions 9155192Srwatson * are met: 10155192Srwatson * 1. Redistributions of source code must retain the above copyright 11155192Srwatson * notice, this list of conditions and the following disclaimer. 12155192Srwatson * 2. Redistributions in binary form must reproduce the above copyright 13155192Srwatson * notice, this list of conditions and the following disclaimer in the 14155192Srwatson * documentation and/or other materials provided with the distribution. 15155192Srwatson * 16155192Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17155192Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18155192Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19155192Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20155192Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21155192Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22155192Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23155192Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24155192Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25155192Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26155192Srwatson * SUCH DAMAGE. 27155192Srwatson */ 28155192Srwatson 29178186Srwatson#include <sys/cdefs.h> 30178186Srwatson__FBSDID("$FreeBSD$"); 31178186Srwatson 32155192Srwatson#include <sys/param.h> 33155192Srwatson#include <sys/conf.h> 34155192Srwatson#include <sys/kernel.h> 35155192Srwatson#include <sys/malloc.h> 36155192Srwatson#include <sys/proc.h> 37155192Srwatson#include <sys/queue.h> 38155192Srwatson#include <sys/systm.h> 39155192Srwatson#include <sys/uio.h> 40155192Srwatson 41155192Srwatson#include <security/audit/audit.h> 42155192Srwatson#include <security/audit/audit_private.h> 43155192Srwatson 44155192Srwatson/* 45155192Srwatson * Structures and operations to support the basic character special device 46165604Srwatson * used to communicate with userland. /dev/audit reliably delivers one-byte 47165604Srwatson * messages to a listening application (or discards them if there is no 48165604Srwatson * listening application). 49165604Srwatson * 50165604Srwatson * Currently, select/poll are not supported on the trigger device. 51155192Srwatson */ 52155192Srwatsonstruct trigger_info { 53155192Srwatson unsigned int trigger; 54155192Srwatson TAILQ_ENTRY(trigger_info) list; 55155192Srwatson}; 56165604Srwatson 57155192Srwatsonstatic MALLOC_DEFINE(M_AUDITTRIGGER, "audit_trigger", "Audit trigger events"); 58155192Srwatsonstatic struct cdev *audit_dev; 59155192Srwatsonstatic int audit_isopen = 0; 60155192Srwatsonstatic TAILQ_HEAD(, trigger_info) trigger_list; 61155192Srwatsonstatic struct mtx audit_trigger_mtx; 62155192Srwatson 63155192Srwatsonstatic int 64155192Srwatsonaudit_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 65155192Srwatson{ 66155192Srwatson int error; 67155192Srwatson 68159414Srwatson /* Only one process may open the device at a time. */ 69155192Srwatson mtx_lock(&audit_trigger_mtx); 70155192Srwatson if (!audit_isopen) { 71155192Srwatson error = 0; 72155192Srwatson audit_isopen = 1; 73155192Srwatson } else 74155192Srwatson error = EBUSY; 75155192Srwatson mtx_unlock(&audit_trigger_mtx); 76155192Srwatson 77155192Srwatson return (error); 78155192Srwatson} 79155192Srwatson 80155192Srwatsonstatic int 81155192Srwatsonaudit_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 82155192Srwatson{ 83155192Srwatson struct trigger_info *ti; 84155192Srwatson 85155192Srwatson /* Flush the queue of pending trigger events. */ 86155192Srwatson mtx_lock(&audit_trigger_mtx); 87155192Srwatson audit_isopen = 0; 88155192Srwatson while (!TAILQ_EMPTY(&trigger_list)) { 89155192Srwatson ti = TAILQ_FIRST(&trigger_list); 90155192Srwatson TAILQ_REMOVE(&trigger_list, ti, list); 91155192Srwatson free(ti, M_AUDITTRIGGER); 92155192Srwatson } 93155192Srwatson mtx_unlock(&audit_trigger_mtx); 94155192Srwatson 95155192Srwatson return (0); 96155192Srwatson} 97155192Srwatson 98155192Srwatsonstatic int 99155192Srwatsonaudit_read(struct cdev *dev, struct uio *uio, int ioflag) 100155192Srwatson{ 101155192Srwatson int error = 0; 102155192Srwatson struct trigger_info *ti = NULL; 103155192Srwatson 104155192Srwatson mtx_lock(&audit_trigger_mtx); 105155192Srwatson while (TAILQ_EMPTY(&trigger_list)) { 106155192Srwatson error = msleep(&trigger_list, &audit_trigger_mtx, 107155192Srwatson PSOCK | PCATCH, "auditd", 0); 108155192Srwatson if (error) 109155192Srwatson break; 110155192Srwatson } 111155192Srwatson if (!error) { 112155192Srwatson ti = TAILQ_FIRST(&trigger_list); 113155192Srwatson TAILQ_REMOVE(&trigger_list, ti, list); 114155192Srwatson } 115155192Srwatson mtx_unlock(&audit_trigger_mtx); 116155192Srwatson if (!error) { 117176749Srwatson error = uiomove(&ti->trigger, sizeof(ti->trigger), uio); 118155192Srwatson free(ti, M_AUDITTRIGGER); 119155192Srwatson } 120155192Srwatson return (error); 121155192Srwatson} 122155192Srwatson 123155192Srwatsonstatic int 124155192Srwatsonaudit_write(struct cdev *dev, struct uio *uio, int ioflag) 125155192Srwatson{ 126155192Srwatson 127155192Srwatson /* Communication is kernel->userspace only. */ 128155192Srwatson return (EOPNOTSUPP); 129155192Srwatson} 130155192Srwatson 131156845Srwatsonint 132176686Srwatsonaudit_send_trigger(unsigned int trigger) 133155192Srwatson{ 134155192Srwatson struct trigger_info *ti; 135155192Srwatson 136155192Srwatson ti = malloc(sizeof *ti, M_AUDITTRIGGER, M_WAITOK); 137155192Srwatson mtx_lock(&audit_trigger_mtx); 138170687Srwatson if (!audit_isopen) { 139170687Srwatson /* If nobody's listening, we ain't talking. */ 140170687Srwatson mtx_unlock(&audit_trigger_mtx); 141170687Srwatson free(ti, M_AUDITTRIGGER); 142170687Srwatson return (ENODEV); 143170687Srwatson } 144155192Srwatson ti->trigger = trigger; 145155192Srwatson TAILQ_INSERT_TAIL(&trigger_list, ti, list); 146155192Srwatson wakeup(&trigger_list); 147155192Srwatson mtx_unlock(&audit_trigger_mtx); 148156845Srwatson return (0); 149155192Srwatson} 150155192Srwatson 151155192Srwatsonstatic struct cdevsw audit_cdevsw = { 152155192Srwatson .d_version = D_VERSION, 153180709Srwatson .d_open = audit_open, 154180709Srwatson .d_close = audit_close, 155180709Srwatson .d_read = audit_read, 156180709Srwatson .d_write = audit_write, 157180709Srwatson .d_name = "audit" 158155192Srwatson}; 159155192Srwatson 160155192Srwatsonvoid 161155192Srwatsonaudit_trigger_init(void) 162155192Srwatson{ 163155192Srwatson 164155192Srwatson TAILQ_INIT(&trigger_list); 165155192Srwatson mtx_init(&audit_trigger_mtx, "audit_trigger_mtx", NULL, MTX_DEF); 166155192Srwatson} 167155192Srwatson 168155192Srwatsonstatic void 169155192Srwatsonaudit_trigger_cdev_init(void *unused) 170155192Srwatson{ 171155192Srwatson 172155192Srwatson /* Create the special device file. */ 173155192Srwatson audit_dev = make_dev(&audit_cdevsw, 0, UID_ROOT, GID_KMEM, 0600, 174155192Srwatson AUDITDEV_FILENAME); 175155192Srwatson} 176155192Srwatson 177155192SrwatsonSYSINIT(audit_trigger_cdev_init, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, 178155192Srwatson audit_trigger_cdev_init, NULL); 179