audit_pipe.c revision 184488
1155408Srwatson/*- 2155408Srwatson * Copyright (c) 2006 Robert N. M. Watson 3184488Srwatson * Copyright (c) 2008 Apple, Inc. 4155408Srwatson * All rights reserved. 5155408Srwatson * 6155408Srwatson * This software was developed by Robert Watson for the TrustedBSD Project. 7155408Srwatson * 8155408Srwatson * Redistribution and use in source and binary forms, with or without 9155408Srwatson * modification, are permitted provided that the following conditions 10155408Srwatson * are met: 11155408Srwatson * 1. Redistributions of source code must retain the above copyright 12155408Srwatson * notice, this list of conditions and the following disclaimer. 13155408Srwatson * 2. Redistributions in binary form must reproduce the above copyright 14155408Srwatson * notice, this list of conditions and the following disclaimer in the 15155408Srwatson * documentation and/or other materials provided with the distribution. 16155408Srwatson * 17155408Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18155408Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19155408Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20155408Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21155408Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22155408Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23155408Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24155408Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25155408Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26155408Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27155408Srwatson * SUCH DAMAGE. 28155408Srwatson */ 29155408Srwatson 30178186Srwatson#include <sys/cdefs.h> 31178186Srwatson__FBSDID("$FreeBSD: head/sys/security/audit/audit_pipe.c 184488 2008-10-30 21:58:39Z rwatson $"); 32178186Srwatson 33155408Srwatson#include <sys/param.h> 34155408Srwatson#include <sys/condvar.h> 35155408Srwatson#include <sys/conf.h> 36155408Srwatson#include <sys/eventhandler.h> 37155408Srwatson#include <sys/filio.h> 38155408Srwatson#include <sys/kernel.h> 39155408Srwatson#include <sys/lock.h> 40155408Srwatson#include <sys/malloc.h> 41155408Srwatson#include <sys/mutex.h> 42155408Srwatson#include <sys/poll.h> 43155408Srwatson#include <sys/proc.h> 44155408Srwatson#include <sys/queue.h> 45184488Srwatson#include <sys/rwlock.h> 46155408Srwatson#include <sys/selinfo.h> 47155408Srwatson#include <sys/sigio.h> 48155408Srwatson#include <sys/signal.h> 49155408Srwatson#include <sys/signalvar.h> 50155408Srwatson#include <sys/systm.h> 51155408Srwatson#include <sys/uio.h> 52155408Srwatson 53155408Srwatson#include <security/audit/audit.h> 54156880Srwatson#include <security/audit/audit_ioctl.h> 55155408Srwatson#include <security/audit/audit_private.h> 56155408Srwatson 57155408Srwatson/* 58155408Srwatson * Implementation of a clonable special device providing a live stream of BSM 59155408Srwatson * audit data. This is a "tee" of the data going to the file. It provides 60155408Srwatson * unreliable but timely access to audit events. Consumers of this interface 61159269Srwatson * should be very careful to avoid introducing event cycles. Consumers may 62159269Srwatson * express interest via a set of preselection ioctls. 63155408Srwatson */ 64155408Srwatson 65155408Srwatson/* 66155408Srwatson * Memory types. 67155408Srwatson */ 68155408Srwatsonstatic MALLOC_DEFINE(M_AUDIT_PIPE, "audit_pipe", "Audit pipes"); 69155408Srwatsonstatic MALLOC_DEFINE(M_AUDIT_PIPE_ENTRY, "audit_pipeent", 70155408Srwatson "Audit pipe entries and buffers"); 71174894Swkoszekstatic MALLOC_DEFINE(M_AUDIT_PIPE_PRESELECT, "audit_pipe_presel", 72159269Srwatson "Audit pipe preselection structure"); 73155408Srwatson 74155408Srwatson/* 75155408Srwatson * Audit pipe buffer parameters. 76155408Srwatson */ 77156883Srwatson#define AUDIT_PIPE_QLIMIT_DEFAULT (128) 78156880Srwatson#define AUDIT_PIPE_QLIMIT_MIN (0) 79155408Srwatson#define AUDIT_PIPE_QLIMIT_MAX (1024) 80155408Srwatson 81155408Srwatson/* 82155408Srwatson * Description of an entry in an audit_pipe. 83155408Srwatson */ 84155408Srwatsonstruct audit_pipe_entry { 85155408Srwatson void *ape_record; 86155408Srwatson u_int ape_record_len; 87155408Srwatson TAILQ_ENTRY(audit_pipe_entry) ape_queue; 88155408Srwatson}; 89155408Srwatson 90155408Srwatson/* 91159269Srwatson * Audit pipes allow processes to express "interest" in the set of records 92159269Srwatson * that are delivered via the pipe. They do this in a similar manner to the 93159269Srwatson * mechanism for audit trail configuration, by expressing two global masks, 94159269Srwatson * and optionally expressing per-auid masks. The following data structure is 95159269Srwatson * the per-auid mask description. The global state is stored in the audit 96159269Srwatson * pipe data structure. 97159269Srwatson * 98159269Srwatson * We may want to consider a more space/time-efficient data structure once 99159269Srwatson * usage patterns for per-auid specifications are clear. 100159269Srwatson */ 101159269Srwatsonstruct audit_pipe_preselect { 102159269Srwatson au_id_t app_auid; 103159269Srwatson au_mask_t app_mask; 104159269Srwatson TAILQ_ENTRY(audit_pipe_preselect) app_list; 105159269Srwatson}; 106159269Srwatson 107159269Srwatson/* 108155408Srwatson * Description of an individual audit_pipe. Consists largely of a bounded 109155408Srwatson * length queue. 110155408Srwatson */ 111155408Srwatson#define AUDIT_PIPE_ASYNC 0x00000001 112155408Srwatson#define AUDIT_PIPE_NBIO 0x00000002 113155408Srwatsonstruct audit_pipe { 114155408Srwatson int ap_open; /* Device open? */ 115155408Srwatson u_int ap_flags; 116155408Srwatson 117155408Srwatson struct selinfo ap_selinfo; 118155408Srwatson struct sigio *ap_sigio; 119155408Srwatson 120184488Srwatson /* 121184488Srwatson * Per-pipe mutex protecting most fields in this data structure. 122184488Srwatson */ 123184488Srwatson struct mtx ap_lock; 124184488Srwatson 125184488Srwatson /* 126184488Srwatson * Condition variable to signal when data has been delivered to a 127184488Srwatson * pipe. 128184488Srwatson */ 129184488Srwatson struct cv ap_cv; 130184488Srwatson 131155408Srwatson u_int ap_qlen; 132155408Srwatson u_int ap_qlimit; 133155408Srwatson 134155408Srwatson u_int64_t ap_inserts; /* Records added. */ 135155408Srwatson u_int64_t ap_reads; /* Records read. */ 136155408Srwatson u_int64_t ap_drops; /* Records dropped. */ 137155408Srwatson u_int64_t ap_truncates; /* Records too long. */ 138155408Srwatson 139159269Srwatson /* 140159269Srwatson * Fields relating to pipe interest: global masks for unmatched 141159269Srwatson * processes (attributable, non-attributable), and a list of specific 142159269Srwatson * interest specifications by auid. 143159269Srwatson */ 144159269Srwatson int ap_preselect_mode; 145159269Srwatson au_mask_t ap_preselect_flags; 146159269Srwatson au_mask_t ap_preselect_naflags; 147159269Srwatson TAILQ_HEAD(, audit_pipe_preselect) ap_preselect_list; 148159269Srwatson 149159269Srwatson /* 150159269Srwatson * Current pending record list. 151159269Srwatson */ 152155408Srwatson TAILQ_HEAD(, audit_pipe_entry) ap_queue; 153155408Srwatson 154159269Srwatson /* 155159269Srwatson * Global pipe list. 156159269Srwatson */ 157155408Srwatson TAILQ_ENTRY(audit_pipe) ap_list; 158155408Srwatson}; 159155408Srwatson 160184488Srwatson#define AUDIT_PIPE_LOCK(ap) mtx_lock(&(ap)->ap_lock) 161184488Srwatson#define AUDIT_PIPE_LOCK_ASSERT(ap) mtx_assert(&(ap)->ap_lock, MA_OWNED) 162184488Srwatson#define AUDIT_PIPE_LOCK_DESTROY(ap) mtx_destroy(&(ap)->ap_lock) 163184488Srwatson#define AUDIT_PIPE_LOCK_INIT(ap) mtx_init(&(ap)->ap_lock, \ 164184488Srwatson "audit_pipe_lock", NULL, MTX_DEF) 165184488Srwatson#define AUDIT_PIPE_UNLOCK(ap) mtx_unlock(&(ap)->ap_lock) 166184488Srwatson#define AUDIT_PIPE_MTX(ap) (&(ap)->ap_lock) 167184488Srwatson 168155408Srwatson/* 169184488Srwatson * Global list of audit pipes, rwlock to protect it. Individual record 170184488Srwatson * queues on pipes are protected by per-pipe locks; these locks synchronize 171184488Srwatson * between threads walking the list to deliver to individual pipes and add/ 172184488Srwatson * remove of pipes, and are mostly acquired for read. 173155408Srwatson */ 174155408Srwatsonstatic TAILQ_HEAD(, audit_pipe) audit_pipe_list; 175184488Srwatsonstatic struct rwlock audit_pipe_lock; 176155408Srwatson 177184488Srwatson#define AUDIT_PIPE_LIST_LOCK_INIT() rw_init(&audit_pipe_lock, \ 178184488Srwatson "audit_pipe_list_lock") 179184488Srwatson#define AUDIT_PIPE_LIST_RLOCK() rw_rlock(&audit_pipe_lock) 180184488Srwatson#define AUDIT_PIPE_LIST_RUNLOCK() rw_runlock(&audit_pipe_lock) 181184488Srwatson#define AUDIT_PIPE_LIST_WLOCK() rw_wlock(&audit_pipe_lock) 182184488Srwatson#define AUDIT_PIPE_LIST_WLOCK_ASSERT() rw_assert(&audit_pipe_lock, \ 183184488Srwatson RA_WLOCKED) 184184488Srwatson#define AUDIT_PIPE_LIST_WUNLOCK() rw_wunlock(&audit_pipe_lock) 185155408Srwatson 186155408Srwatson/* 187155408Srwatson * Cloning related variables and constants. 188155408Srwatson */ 189155408Srwatson#define AUDIT_PIPE_NAME "auditpipe" 190155408Srwatsonstatic eventhandler_tag audit_pipe_eh_tag; 191155408Srwatsonstatic struct clonedevs *audit_pipe_clones; 192155408Srwatson 193155408Srwatson/* 194155408Srwatson * Special device methods and definition. 195155408Srwatson */ 196155408Srwatsonstatic d_open_t audit_pipe_open; 197155408Srwatsonstatic d_close_t audit_pipe_close; 198155408Srwatsonstatic d_read_t audit_pipe_read; 199155408Srwatsonstatic d_ioctl_t audit_pipe_ioctl; 200155408Srwatsonstatic d_poll_t audit_pipe_poll; 201161582Srwatsonstatic d_kqfilter_t audit_pipe_kqfilter; 202155408Srwatson 203155408Srwatsonstatic struct cdevsw audit_pipe_cdevsw = { 204155408Srwatson .d_version = D_VERSION, 205179726Sed .d_flags = D_PSEUDO | D_NEEDGIANT | D_NEEDMINOR, 206155408Srwatson .d_open = audit_pipe_open, 207155408Srwatson .d_close = audit_pipe_close, 208155408Srwatson .d_read = audit_pipe_read, 209155408Srwatson .d_ioctl = audit_pipe_ioctl, 210155408Srwatson .d_poll = audit_pipe_poll, 211161582Srwatson .d_kqfilter = audit_pipe_kqfilter, 212155408Srwatson .d_name = AUDIT_PIPE_NAME, 213155408Srwatson}; 214155408Srwatson 215161582Srwatsonstatic int audit_pipe_kqread(struct knote *note, long hint); 216161582Srwatsonstatic void audit_pipe_kqdetach(struct knote *note); 217161582Srwatson 218161582Srwatsonstatic struct filterops audit_pipe_read_filterops = { 219161582Srwatson .f_isfd = 1, 220161582Srwatson .f_attach = NULL, 221161582Srwatson .f_detach = audit_pipe_kqdetach, 222161582Srwatson .f_event = audit_pipe_kqread, 223161582Srwatson}; 224161582Srwatson 225155408Srwatson/* 226155408Srwatson * Some global statistics on audit pipes. 227155408Srwatson */ 228155408Srwatsonstatic int audit_pipe_count; /* Current number of pipes. */ 229155408Srwatsonstatic u_int64_t audit_pipe_ever; /* Pipes ever allocated. */ 230155408Srwatsonstatic u_int64_t audit_pipe_records; /* Records seen. */ 231155408Srwatsonstatic u_int64_t audit_pipe_drops; /* Global record drop count. */ 232155408Srwatson 233155408Srwatson/* 234155408Srwatson * Free an audit pipe entry. 235155408Srwatson */ 236155408Srwatsonstatic void 237155408Srwatsonaudit_pipe_entry_free(struct audit_pipe_entry *ape) 238155408Srwatson{ 239155408Srwatson 240155408Srwatson free(ape->ape_record, M_AUDIT_PIPE_ENTRY); 241155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 242155408Srwatson} 243155408Srwatson 244155408Srwatson/* 245159269Srwatson * Find an audit pipe preselection specification for an auid, if any. 246159269Srwatson */ 247159269Srwatsonstatic struct audit_pipe_preselect * 248159269Srwatsonaudit_pipe_preselect_find(struct audit_pipe *ap, au_id_t auid) 249159269Srwatson{ 250159269Srwatson struct audit_pipe_preselect *app; 251159269Srwatson 252184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 253159269Srwatson 254159269Srwatson TAILQ_FOREACH(app, &ap->ap_preselect_list, app_list) { 255159269Srwatson if (app->app_auid == auid) 256159269Srwatson return (app); 257159269Srwatson } 258159269Srwatson return (NULL); 259159269Srwatson} 260159269Srwatson 261159269Srwatson/* 262159269Srwatson * Query the per-pipe mask for a specific auid. 263159269Srwatson */ 264159269Srwatsonstatic int 265159269Srwatsonaudit_pipe_preselect_get(struct audit_pipe *ap, au_id_t auid, 266159269Srwatson au_mask_t *maskp) 267159269Srwatson{ 268159269Srwatson struct audit_pipe_preselect *app; 269159269Srwatson int error; 270159269Srwatson 271184488Srwatson AUDIT_PIPE_LOCK(ap); 272159269Srwatson app = audit_pipe_preselect_find(ap, auid); 273159269Srwatson if (app != NULL) { 274159269Srwatson *maskp = app->app_mask; 275159269Srwatson error = 0; 276159269Srwatson } else 277159269Srwatson error = ENOENT; 278184488Srwatson AUDIT_PIPE_UNLOCK(ap); 279159269Srwatson return (error); 280159269Srwatson} 281159269Srwatson 282159269Srwatson/* 283159269Srwatson * Set the per-pipe mask for a specific auid. Add a new entry if needed; 284159269Srwatson * otherwise, update the current entry. 285159269Srwatson */ 286159269Srwatsonstatic void 287159269Srwatsonaudit_pipe_preselect_set(struct audit_pipe *ap, au_id_t auid, au_mask_t mask) 288159269Srwatson{ 289159269Srwatson struct audit_pipe_preselect *app, *app_new; 290159269Srwatson 291159269Srwatson /* 292159269Srwatson * Pessimistically assume that the auid doesn't already have a mask 293159269Srwatson * set, and allocate. We will free it if it is unneeded. 294159269Srwatson */ 295159269Srwatson app_new = malloc(sizeof(*app_new), M_AUDIT_PIPE_PRESELECT, M_WAITOK); 296184488Srwatson AUDIT_PIPE_LOCK(ap); 297159269Srwatson app = audit_pipe_preselect_find(ap, auid); 298159269Srwatson if (app == NULL) { 299159269Srwatson app = app_new; 300159269Srwatson app_new = NULL; 301159269Srwatson app->app_auid = auid; 302159269Srwatson TAILQ_INSERT_TAIL(&ap->ap_preselect_list, app, app_list); 303159269Srwatson } 304159269Srwatson app->app_mask = mask; 305184488Srwatson AUDIT_PIPE_UNLOCK(ap); 306159269Srwatson if (app_new != NULL) 307159269Srwatson free(app_new, M_AUDIT_PIPE_PRESELECT); 308159269Srwatson} 309159269Srwatson 310159269Srwatson/* 311159269Srwatson * Delete a per-auid mask on an audit pipe. 312159269Srwatson */ 313159269Srwatsonstatic int 314159269Srwatsonaudit_pipe_preselect_delete(struct audit_pipe *ap, au_id_t auid) 315159269Srwatson{ 316159269Srwatson struct audit_pipe_preselect *app; 317159269Srwatson int error; 318159269Srwatson 319184488Srwatson AUDIT_PIPE_LOCK(ap); 320159269Srwatson app = audit_pipe_preselect_find(ap, auid); 321159269Srwatson if (app != NULL) { 322159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 323159269Srwatson error = 0; 324159269Srwatson } else 325159269Srwatson error = ENOENT; 326184488Srwatson AUDIT_PIPE_UNLOCK(ap); 327159269Srwatson if (app != NULL) 328159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 329159269Srwatson return (error); 330159269Srwatson} 331159269Srwatson 332159269Srwatson/* 333159269Srwatson * Delete all per-auid masks on an audit pipe. 334159269Srwatson */ 335159269Srwatsonstatic void 336159269Srwatsonaudit_pipe_preselect_flush_locked(struct audit_pipe *ap) 337159269Srwatson{ 338159269Srwatson struct audit_pipe_preselect *app; 339159269Srwatson 340184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 341159269Srwatson 342159269Srwatson while ((app = TAILQ_FIRST(&ap->ap_preselect_list)) != NULL) { 343159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 344159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 345159269Srwatson } 346159269Srwatson} 347159269Srwatson 348159269Srwatsonstatic void 349159269Srwatsonaudit_pipe_preselect_flush(struct audit_pipe *ap) 350159269Srwatson{ 351159269Srwatson 352184488Srwatson AUDIT_PIPE_LOCK(ap); 353159269Srwatson audit_pipe_preselect_flush_locked(ap); 354184488Srwatson AUDIT_PIPE_UNLOCK(ap); 355159269Srwatson} 356159269Srwatson 357170196Srwatson/*- 358159269Srwatson * Determine whether a specific audit pipe matches a record with these 359159269Srwatson * properties. Algorithm is as follows: 360159269Srwatson * 361159269Srwatson * - If the pipe is configured to track the default trail configuration, then 362159269Srwatson * use the results of global preselection matching. 363159269Srwatson * - If not, search for a specifically configured auid entry matching the 364159269Srwatson * event. If an entry is found, use that. 365159269Srwatson * - Otherwise, use the default flags or naflags configured for the pipe. 366159269Srwatson */ 367159269Srwatsonstatic int 368159269Srwatsonaudit_pipe_preselect_check(struct audit_pipe *ap, au_id_t auid, 369159269Srwatson au_event_t event, au_class_t class, int sorf, int trail_preselect) 370159269Srwatson{ 371159269Srwatson struct audit_pipe_preselect *app; 372159269Srwatson 373184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 374159269Srwatson 375159269Srwatson switch (ap->ap_preselect_mode) { 376159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 377159269Srwatson return (trail_preselect); 378159269Srwatson 379159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 380159269Srwatson app = audit_pipe_preselect_find(ap, auid); 381159269Srwatson if (app == NULL) { 382159269Srwatson if (auid == AU_DEFAUDITID) 383159269Srwatson return (au_preselect(event, class, 384159269Srwatson &ap->ap_preselect_naflags, sorf)); 385159269Srwatson else 386159269Srwatson return (au_preselect(event, class, 387159269Srwatson &ap->ap_preselect_flags, sorf)); 388159269Srwatson } else 389159269Srwatson return (au_preselect(event, class, &app->app_mask, 390159269Srwatson sorf)); 391159269Srwatson 392159269Srwatson default: 393159269Srwatson panic("audit_pipe_preselect_check: mode %d", 394159269Srwatson ap->ap_preselect_mode); 395159269Srwatson } 396159269Srwatson 397159269Srwatson return (0); 398159269Srwatson} 399159269Srwatson 400159269Srwatson/* 401159269Srwatson * Determine whether there exists a pipe interested in a record with specific 402159269Srwatson * properties. 403159269Srwatson */ 404159269Srwatsonint 405159269Srwatsonaudit_pipe_preselect(au_id_t auid, au_event_t event, au_class_t class, 406159269Srwatson int sorf, int trail_preselect) 407159269Srwatson{ 408159269Srwatson struct audit_pipe *ap; 409159269Srwatson 410184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 411159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 412184488Srwatson AUDIT_PIPE_LOCK(ap); 413159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 414159269Srwatson trail_preselect)) { 415184488Srwatson AUDIT_PIPE_UNLOCK(ap); 416184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 417159269Srwatson return (1); 418159269Srwatson } 419184488Srwatson AUDIT_PIPE_UNLOCK(ap); 420159269Srwatson } 421184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 422159269Srwatson return (0); 423159269Srwatson} 424159269Srwatson 425159269Srwatson/* 426159269Srwatson * Append individual record to a queue -- allocate queue-local buffer, and 427155408Srwatson * add to the queue. We try to drop from the head of the queue so that more 428155408Srwatson * recent events take precedence over older ones, but if allocation fails we 429155408Srwatson * do drop the new event. 430155408Srwatson */ 431155408Srwatsonstatic void 432155408Srwatsonaudit_pipe_append(struct audit_pipe *ap, void *record, u_int record_len) 433155408Srwatson{ 434155408Srwatson struct audit_pipe_entry *ape, *ape_remove; 435155408Srwatson 436184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 437155408Srwatson 438155408Srwatson ape = malloc(sizeof(*ape), M_AUDIT_PIPE_ENTRY, M_NOWAIT | M_ZERO); 439155408Srwatson if (ape == NULL) { 440155408Srwatson ap->ap_drops++; 441156292Srwatson audit_pipe_drops++; 442155408Srwatson return; 443155408Srwatson } 444155408Srwatson 445155408Srwatson ape->ape_record = malloc(record_len, M_AUDIT_PIPE_ENTRY, M_NOWAIT); 446155408Srwatson if (ape->ape_record == NULL) { 447155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 448155408Srwatson ap->ap_drops++; 449155408Srwatson audit_pipe_drops++; 450155408Srwatson return; 451155408Srwatson } 452155408Srwatson 453155408Srwatson bcopy(record, ape->ape_record, record_len); 454155408Srwatson ape->ape_record_len = record_len; 455155408Srwatson 456155408Srwatson if (ap->ap_qlen >= ap->ap_qlimit) { 457155408Srwatson ape_remove = TAILQ_FIRST(&ap->ap_queue); 458155408Srwatson TAILQ_REMOVE(&ap->ap_queue, ape_remove, ape_queue); 459155408Srwatson audit_pipe_entry_free(ape_remove); 460155428Srwatson ap->ap_qlen--; 461155408Srwatson ap->ap_drops++; 462155408Srwatson audit_pipe_drops++; 463155408Srwatson } 464155408Srwatson 465155408Srwatson TAILQ_INSERT_TAIL(&ap->ap_queue, ape, ape_queue); 466155408Srwatson ap->ap_inserts++; 467155408Srwatson ap->ap_qlen++; 468155408Srwatson selwakeuppri(&ap->ap_selinfo, PSOCK); 469161582Srwatson KNOTE_LOCKED(&ap->ap_selinfo.si_note, 0); 470155408Srwatson if (ap->ap_flags & AUDIT_PIPE_ASYNC) 471155408Srwatson pgsigio(&ap->ap_sigio, SIGIO, 0); 472184488Srwatson cv_broadcast(&ap->ap_cv); 473155408Srwatson} 474155408Srwatson 475155408Srwatson/* 476155408Srwatson * audit_pipe_submit(): audit_worker submits audit records via this 477155408Srwatson * interface, which arranges for them to be delivered to pipe queues. 478155408Srwatson */ 479155408Srwatsonvoid 480159269Srwatsonaudit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class, int sorf, 481159269Srwatson int trail_select, void *record, u_int record_len) 482155408Srwatson{ 483155408Srwatson struct audit_pipe *ap; 484155408Srwatson 485155408Srwatson /* 486184488Srwatson * Lockless read to avoid lock overhead if pipes are not in use. 487155408Srwatson */ 488155408Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 489155408Srwatson return; 490155408Srwatson 491184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 492159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 493184488Srwatson AUDIT_PIPE_LOCK(ap); 494159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 495159269Srwatson trail_select)) 496159269Srwatson audit_pipe_append(ap, record, record_len); 497184488Srwatson AUDIT_PIPE_UNLOCK(ap); 498159269Srwatson } 499184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 500184488Srwatson 501184488Srwatson /* Unlocked increment. */ 502159269Srwatson audit_pipe_records++; 503159269Srwatson} 504159269Srwatson 505159269Srwatson/* 506159269Srwatson * audit_pipe_submit_user(): the same as audit_pipe_submit(), except that 507159269Srwatson * since we don't currently have selection information available, it is 508159269Srwatson * delivered to the pipe unconditionally. 509159269Srwatson * 510159269Srwatson * XXXRW: This is a bug. The BSM check routine for submitting a user record 511159269Srwatson * should parse that information and return it. 512159269Srwatson */ 513159269Srwatsonvoid 514159269Srwatsonaudit_pipe_submit_user(void *record, u_int record_len) 515159269Srwatson{ 516159269Srwatson struct audit_pipe *ap; 517159269Srwatson 518159269Srwatson /* 519184488Srwatson * Lockless read to avoid lock overhead if pipes are not in use. 520159269Srwatson */ 521159269Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 522159269Srwatson return; 523159269Srwatson 524184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 525184488Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 526184488Srwatson AUDIT_PIPE_LOCK(ap); 527155408Srwatson audit_pipe_append(ap, record, record_len); 528184488Srwatson AUDIT_PIPE_UNLOCK(ap); 529184488Srwatson } 530184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 531184488Srwatson 532184488Srwatson /* Unlocked increment. */ 533155408Srwatson audit_pipe_records++; 534155408Srwatson} 535155408Srwatson 536155408Srwatson/* 537159269Srwatson * Pop the next record off of an audit pipe. 538155408Srwatson */ 539155408Srwatsonstatic struct audit_pipe_entry * 540155408Srwatsonaudit_pipe_pop(struct audit_pipe *ap) 541155408Srwatson{ 542155408Srwatson struct audit_pipe_entry *ape; 543155408Srwatson 544184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 545155408Srwatson 546155408Srwatson ape = TAILQ_FIRST(&ap->ap_queue); 547155408Srwatson KASSERT((ape == NULL && ap->ap_qlen == 0) || 548155408Srwatson (ape != NULL && ap->ap_qlen != 0), ("audit_pipe_pop: qlen")); 549155408Srwatson if (ape == NULL) 550155408Srwatson return (NULL); 551155408Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 552155408Srwatson ap->ap_qlen--; 553155408Srwatson return (ape); 554155408Srwatson} 555155408Srwatson 556155408Srwatson/* 557155408Srwatson * Allocate a new audit pipe. Connects the pipe, on success, to the global 558155408Srwatson * list and updates statistics. 559155408Srwatson */ 560155408Srwatsonstatic struct audit_pipe * 561155408Srwatsonaudit_pipe_alloc(void) 562155408Srwatson{ 563155408Srwatson struct audit_pipe *ap; 564155408Srwatson 565184488Srwatson AUDIT_PIPE_LIST_WLOCK_ASSERT(); 566155408Srwatson 567155408Srwatson ap = malloc(sizeof(*ap), M_AUDIT_PIPE, M_NOWAIT | M_ZERO); 568155408Srwatson if (ap == NULL) 569155408Srwatson return (NULL); 570155408Srwatson ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT; 571155408Srwatson TAILQ_INIT(&ap->ap_queue); 572184488Srwatson knlist_init(&ap->ap_selinfo.si_note, AUDIT_PIPE_MTX(ap), NULL, NULL, 573161582Srwatson NULL); 574184488Srwatson AUDIT_PIPE_LOCK_INIT(ap); 575184488Srwatson cv_init(&ap->ap_cv, "audit_pipe"); 576159269Srwatson 577159269Srwatson /* 578159269Srwatson * Default flags, naflags, and auid-specific preselection settings to 579159269Srwatson * 0. Initialize the mode to the global trail so that if praudit(1) 580159269Srwatson * is run on /dev/auditpipe, it sees events associated with the 581159269Srwatson * default trail. Pipe-aware application can clear the flag, set 582159269Srwatson * custom masks, and flush the pipe as needed. 583159269Srwatson */ 584159269Srwatson bzero(&ap->ap_preselect_flags, sizeof(ap->ap_preselect_flags)); 585159269Srwatson bzero(&ap->ap_preselect_naflags, sizeof(ap->ap_preselect_naflags)); 586159269Srwatson TAILQ_INIT(&ap->ap_preselect_list); 587159269Srwatson ap->ap_preselect_mode = AUDITPIPE_PRESELECT_MODE_TRAIL; 588159269Srwatson 589161582Srwatson /* 590161582Srwatson * Add to global list and update global statistics. 591161582Srwatson */ 592155408Srwatson TAILQ_INSERT_HEAD(&audit_pipe_list, ap, ap_list); 593155408Srwatson audit_pipe_count++; 594155408Srwatson audit_pipe_ever++; 595159269Srwatson 596155408Srwatson return (ap); 597155408Srwatson} 598155408Srwatson 599155408Srwatson/* 600159269Srwatson * Flush all records currently present in an audit pipe; assume mutex is held. 601155408Srwatson */ 602155408Srwatsonstatic void 603159269Srwatsonaudit_pipe_flush(struct audit_pipe *ap) 604155408Srwatson{ 605155408Srwatson struct audit_pipe_entry *ape; 606155408Srwatson 607184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 608155408Srwatson 609155408Srwatson while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL) { 610155408Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 611155408Srwatson audit_pipe_entry_free(ape); 612155408Srwatson ap->ap_qlen--; 613155408Srwatson } 614155408Srwatson KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qlen")); 615159269Srwatson} 616159269Srwatson 617159269Srwatson/* 618159269Srwatson * Free an audit pipe; this means freeing all preselection state and all 619184488Srwatson * records in the pipe. Assumes global write lock and pipe mutex are held to 620184488Srwatson * prevent any new records from being inserted during the free, and that the 621184488Srwatson * audit pipe is still on the global list. 622159269Srwatson */ 623159269Srwatsonstatic void 624159269Srwatsonaudit_pipe_free(struct audit_pipe *ap) 625159269Srwatson{ 626159269Srwatson 627184488Srwatson AUDIT_PIPE_LIST_WLOCK_ASSERT(); 628184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 629159269Srwatson 630159269Srwatson audit_pipe_preselect_flush_locked(ap); 631159269Srwatson audit_pipe_flush(ap); 632184488Srwatson cv_destroy(&ap->ap_cv); 633184488Srwatson AUDIT_PIPE_LOCK_DESTROY(ap); 634161582Srwatson knlist_destroy(&ap->ap_selinfo.si_note); 635159269Srwatson TAILQ_REMOVE(&audit_pipe_list, ap, ap_list); 636155408Srwatson free(ap, M_AUDIT_PIPE); 637155408Srwatson audit_pipe_count--; 638155408Srwatson} 639155408Srwatson 640155408Srwatson/* 641155408Srwatson * Audit pipe clone routine -- provide specific requested audit pipe, or a 642155408Srwatson * fresh one if a specific one is not requested. 643155408Srwatson */ 644155408Srwatsonstatic void 645155408Srwatsonaudit_pipe_clone(void *arg, struct ucred *cred, char *name, int namelen, 646155408Srwatson struct cdev **dev) 647155408Srwatson{ 648155408Srwatson int i, u; 649155408Srwatson 650155408Srwatson if (*dev != NULL) 651155408Srwatson return; 652155408Srwatson 653155408Srwatson if (strcmp(name, AUDIT_PIPE_NAME) == 0) 654155408Srwatson u = -1; 655155408Srwatson else if (dev_stdclone(name, NULL, AUDIT_PIPE_NAME, &u) != 1) 656155408Srwatson return; 657155408Srwatson 658155408Srwatson i = clone_create(&audit_pipe_clones, &audit_pipe_cdevsw, &u, dev, 0); 659155408Srwatson if (i) { 660183381Sed *dev = make_dev(&audit_pipe_cdevsw, u, UID_ROOT, 661155408Srwatson GID_WHEEL, 0600, "%s%d", AUDIT_PIPE_NAME, u); 662155408Srwatson if (*dev != NULL) { 663155408Srwatson dev_ref(*dev); 664155408Srwatson (*dev)->si_flags |= SI_CHEAPCLONE; 665155408Srwatson } 666155408Srwatson } 667155408Srwatson} 668155408Srwatson 669155408Srwatson/* 670164033Srwatson * Audit pipe open method. Explicit privilege check isn't used as this 671164033Srwatson * allows file permissions on the special device to be used to grant audit 672164033Srwatson * review access. Those file permissions should be managed carefully. 673155408Srwatson */ 674155408Srwatsonstatic int 675155408Srwatsonaudit_pipe_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 676155408Srwatson{ 677155408Srwatson struct audit_pipe *ap; 678155408Srwatson 679184488Srwatson AUDIT_PIPE_LIST_WLOCK(); 680155408Srwatson ap = dev->si_drv1; 681155408Srwatson if (ap == NULL) { 682155408Srwatson ap = audit_pipe_alloc(); 683155408Srwatson if (ap == NULL) { 684184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 685155408Srwatson return (ENOMEM); 686155408Srwatson } 687155408Srwatson dev->si_drv1 = ap; 688155408Srwatson } else { 689155408Srwatson KASSERT(ap->ap_open, ("audit_pipe_open: ap && !ap_open")); 690184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 691155408Srwatson return (EBUSY); 692155408Srwatson } 693184488Srwatson ap->ap_open = 1; /* No lock required yet. */ 694184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 695155408Srwatson fsetown(td->td_proc->p_pid, &ap->ap_sigio); 696155408Srwatson return (0); 697155408Srwatson} 698155408Srwatson 699155408Srwatson/* 700155408Srwatson * Close audit pipe, tear down all records, etc. 701155408Srwatson */ 702155408Srwatsonstatic int 703155408Srwatsonaudit_pipe_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 704155408Srwatson{ 705155408Srwatson struct audit_pipe *ap; 706155408Srwatson 707155408Srwatson ap = dev->si_drv1; 708155408Srwatson KASSERT(ap != NULL, ("audit_pipe_close: ap == NULL")); 709155408Srwatson KASSERT(ap->ap_open, ("audit_pipe_close: !ap_open")); 710184488Srwatson 711155408Srwatson funsetown(&ap->ap_sigio); 712184488Srwatson AUDIT_PIPE_LIST_WLOCK(); 713184488Srwatson AUDIT_PIPE_LOCK(ap); 714155408Srwatson ap->ap_open = 0; 715155408Srwatson audit_pipe_free(ap); 716155408Srwatson dev->si_drv1 = NULL; 717184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 718155408Srwatson return (0); 719155408Srwatson} 720155408Srwatson 721155408Srwatson/* 722156880Srwatson * Audit pipe ioctl() routine. Handle file descriptor and audit pipe layer 723156880Srwatson * commands. 724155408Srwatson * 725155408Srwatson * Would be desirable to support filtering, although perhaps something simple 726155408Srwatson * like an event mask, as opposed to something complicated like BPF. 727155408Srwatson */ 728155408Srwatsonstatic int 729155408Srwatsonaudit_pipe_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, 730155408Srwatson struct thread *td) 731155408Srwatson{ 732159269Srwatson struct auditpipe_ioctl_preselect *aip; 733155408Srwatson struct audit_pipe *ap; 734159269Srwatson au_mask_t *maskp; 735159269Srwatson int error, mode; 736159269Srwatson au_id_t auid; 737155408Srwatson 738155408Srwatson ap = dev->si_drv1; 739155408Srwatson KASSERT(ap != NULL, ("audit_pipe_ioctl: ap == NULL")); 740159269Srwatson 741159269Srwatson /* 742159269Srwatson * Audit pipe ioctls: first come standard device node ioctls, then 743159269Srwatson * manipulation of pipe settings, and finally, statistics query 744159269Srwatson * ioctls. 745159269Srwatson */ 746155408Srwatson switch (cmd) { 747155408Srwatson case FIONBIO: 748184488Srwatson AUDIT_PIPE_LOCK(ap); 749155408Srwatson if (*(int *)data) 750155408Srwatson ap->ap_flags |= AUDIT_PIPE_NBIO; 751155408Srwatson else 752155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_NBIO; 753184488Srwatson AUDIT_PIPE_UNLOCK(ap); 754155408Srwatson error = 0; 755155408Srwatson break; 756155408Srwatson 757155408Srwatson case FIONREAD: 758184488Srwatson AUDIT_PIPE_LOCK(ap); 759155408Srwatson if (TAILQ_FIRST(&ap->ap_queue) != NULL) 760155408Srwatson *(int *)data = 761155408Srwatson TAILQ_FIRST(&ap->ap_queue)->ape_record_len; 762155408Srwatson else 763155408Srwatson *(int *)data = 0; 764184488Srwatson AUDIT_PIPE_UNLOCK(ap); 765155408Srwatson error = 0; 766155408Srwatson break; 767155408Srwatson 768155408Srwatson case FIOASYNC: 769184488Srwatson AUDIT_PIPE_LOCK(ap); 770155408Srwatson if (*(int *)data) 771155408Srwatson ap->ap_flags |= AUDIT_PIPE_ASYNC; 772155408Srwatson else 773155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_ASYNC; 774184488Srwatson AUDIT_PIPE_UNLOCK(ap); 775155408Srwatson error = 0; 776155408Srwatson break; 777155408Srwatson 778155408Srwatson case FIOSETOWN: 779155408Srwatson error = fsetown(*(int *)data, &ap->ap_sigio); 780155408Srwatson break; 781155408Srwatson 782155408Srwatson case FIOGETOWN: 783155408Srwatson *(int *)data = fgetown(&ap->ap_sigio); 784155408Srwatson error = 0; 785156880Srwatson break; 786155408Srwatson 787156880Srwatson case AUDITPIPE_GET_QLEN: 788156880Srwatson *(u_int *)data = ap->ap_qlen; 789156880Srwatson error = 0; 790156880Srwatson break; 791156880Srwatson 792156880Srwatson case AUDITPIPE_GET_QLIMIT: 793156880Srwatson *(u_int *)data = ap->ap_qlimit; 794156880Srwatson error = 0; 795156880Srwatson break; 796156880Srwatson 797156880Srwatson case AUDITPIPE_SET_QLIMIT: 798156880Srwatson /* Lockless integer write. */ 799156880Srwatson if (*(u_int *)data >= AUDIT_PIPE_QLIMIT_MIN || 800156880Srwatson *(u_int *)data <= AUDIT_PIPE_QLIMIT_MAX) { 801156880Srwatson ap->ap_qlimit = *(u_int *)data; 802156880Srwatson error = 0; 803156880Srwatson } else 804156880Srwatson error = EINVAL; 805156880Srwatson break; 806156880Srwatson 807156884Srwatson case AUDITPIPE_GET_QLIMIT_MIN: 808156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MIN; 809156884Srwatson error = 0; 810156884Srwatson break; 811156884Srwatson 812156884Srwatson case AUDITPIPE_GET_QLIMIT_MAX: 813156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MAX; 814156884Srwatson error = 0; 815156884Srwatson break; 816156884Srwatson 817159269Srwatson case AUDITPIPE_GET_PRESELECT_FLAGS: 818184488Srwatson AUDIT_PIPE_LOCK(ap); 819159269Srwatson maskp = (au_mask_t *)data; 820159269Srwatson *maskp = ap->ap_preselect_flags; 821184488Srwatson AUDIT_PIPE_UNLOCK(ap); 822159269Srwatson error = 0; 823159269Srwatson break; 824159269Srwatson 825159269Srwatson case AUDITPIPE_SET_PRESELECT_FLAGS: 826184488Srwatson AUDIT_PIPE_LOCK(ap); 827159269Srwatson maskp = (au_mask_t *)data; 828159269Srwatson ap->ap_preselect_flags = *maskp; 829184488Srwatson AUDIT_PIPE_UNLOCK(ap); 830159269Srwatson error = 0; 831159269Srwatson break; 832159269Srwatson 833159269Srwatson case AUDITPIPE_GET_PRESELECT_NAFLAGS: 834184488Srwatson AUDIT_PIPE_LOCK(ap); 835159269Srwatson maskp = (au_mask_t *)data; 836159269Srwatson *maskp = ap->ap_preselect_naflags; 837184488Srwatson AUDIT_PIPE_UNLOCK(ap); 838159269Srwatson error = 0; 839159269Srwatson break; 840159269Srwatson 841159269Srwatson case AUDITPIPE_SET_PRESELECT_NAFLAGS: 842184488Srwatson AUDIT_PIPE_LOCK(ap); 843159269Srwatson maskp = (au_mask_t *)data; 844159269Srwatson ap->ap_preselect_naflags = *maskp; 845184488Srwatson AUDIT_PIPE_UNLOCK(ap); 846159269Srwatson error = 0; 847159269Srwatson break; 848159269Srwatson 849159269Srwatson case AUDITPIPE_GET_PRESELECT_AUID: 850159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 851159269Srwatson error = audit_pipe_preselect_get(ap, aip->aip_auid, 852159269Srwatson &aip->aip_mask); 853159269Srwatson break; 854159269Srwatson 855159269Srwatson case AUDITPIPE_SET_PRESELECT_AUID: 856159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 857159269Srwatson audit_pipe_preselect_set(ap, aip->aip_auid, aip->aip_mask); 858159269Srwatson error = 0; 859159269Srwatson break; 860159269Srwatson 861159269Srwatson case AUDITPIPE_DELETE_PRESELECT_AUID: 862159269Srwatson auid = *(au_id_t *)data; 863159269Srwatson error = audit_pipe_preselect_delete(ap, auid); 864159269Srwatson break; 865159269Srwatson 866159269Srwatson case AUDITPIPE_FLUSH_PRESELECT_AUID: 867159269Srwatson audit_pipe_preselect_flush(ap); 868159269Srwatson error = 0; 869159269Srwatson break; 870159269Srwatson 871159269Srwatson case AUDITPIPE_GET_PRESELECT_MODE: 872184488Srwatson AUDIT_PIPE_LOCK(ap); 873159269Srwatson *(int *)data = ap->ap_preselect_mode; 874184488Srwatson AUDIT_PIPE_UNLOCK(ap); 875159269Srwatson error = 0; 876159269Srwatson break; 877159269Srwatson 878159269Srwatson case AUDITPIPE_SET_PRESELECT_MODE: 879159269Srwatson mode = *(int *)data; 880159269Srwatson switch (mode) { 881159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 882159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 883184488Srwatson AUDIT_PIPE_LOCK(ap); 884159269Srwatson ap->ap_preselect_mode = mode; 885184488Srwatson AUDIT_PIPE_UNLOCK(ap); 886159269Srwatson error = 0; 887159269Srwatson break; 888159269Srwatson 889159269Srwatson default: 890159269Srwatson error = EINVAL; 891159269Srwatson } 892159269Srwatson break; 893159269Srwatson 894159269Srwatson case AUDITPIPE_FLUSH: 895184488Srwatson AUDIT_PIPE_LOCK(ap); 896159269Srwatson audit_pipe_flush(ap); 897184488Srwatson AUDIT_PIPE_UNLOCK(ap); 898159269Srwatson error = 0; 899159269Srwatson break; 900159269Srwatson 901161646Srwatson case AUDITPIPE_GET_MAXAUDITDATA: 902161646Srwatson *(u_int *)data = MAXAUDITDATA; 903161646Srwatson error = 0; 904161646Srwatson break; 905161646Srwatson 906156880Srwatson case AUDITPIPE_GET_INSERTS: 907156880Srwatson *(u_int *)data = ap->ap_inserts; 908156880Srwatson error = 0; 909156880Srwatson break; 910156880Srwatson 911156880Srwatson case AUDITPIPE_GET_READS: 912156880Srwatson *(u_int *)data = ap->ap_reads; 913156880Srwatson error = 0; 914156880Srwatson break; 915156880Srwatson 916156880Srwatson case AUDITPIPE_GET_DROPS: 917156880Srwatson *(u_int *)data = ap->ap_drops; 918156880Srwatson error = 0; 919156880Srwatson break; 920156880Srwatson 921156880Srwatson case AUDITPIPE_GET_TRUNCATES: 922156880Srwatson *(u_int *)data = ap->ap_truncates; 923156880Srwatson error = 0; 924156880Srwatson break; 925156880Srwatson 926155408Srwatson default: 927155408Srwatson error = ENOTTY; 928155408Srwatson } 929155408Srwatson return (error); 930155408Srwatson} 931155408Srwatson 932155408Srwatson/* 933155408Srwatson * Audit pipe read. Pull one record off the queue and copy to user space. 934155408Srwatson * On error, the record is dropped. 935159269Srwatson * 936159269Srwatson * Providing more sophisticated behavior, such as partial reads, is tricky 937159269Srwatson * due to the potential for parallel I/O. If partial read support is 938159269Srwatson * required, it will require a per-pipe "current record being read" along 939159269Srwatson * with an offset into that trecord which has already been read. Threads 940159269Srwatson * performing partial reads will need to allocate per-thread copies of the 941159269Srwatson * data so that if another thread completes the read of the record, it can be 942159269Srwatson * freed without adding reference count logic. If this is added, a flag to 943159269Srwatson * indicate that only atomic record reads are desired would be useful, as if 944159269Srwatson * different threads are all waiting for records on the pipe, they will want 945159269Srwatson * independent record reads, which is currently the behavior. 946155408Srwatson */ 947155408Srwatsonstatic int 948155408Srwatsonaudit_pipe_read(struct cdev *dev, struct uio *uio, int flag) 949155408Srwatson{ 950155408Srwatson struct audit_pipe_entry *ape; 951155408Srwatson struct audit_pipe *ap; 952155408Srwatson int error; 953155408Srwatson 954155408Srwatson ap = dev->si_drv1; 955155408Srwatson KASSERT(ap != NULL, ("audit_pipe_read: ap == NULL")); 956184488Srwatson 957184488Srwatson AUDIT_PIPE_LOCK(ap); 958155408Srwatson do { 959155408Srwatson /* 960155408Srwatson * Wait for a record that fits into the read buffer, dropping 961155408Srwatson * records that would be truncated if actually passed to the 962155408Srwatson * process. This helps maintain the discreet record read 963155408Srwatson * interface. 964155408Srwatson */ 965155408Srwatson while ((ape = audit_pipe_pop(ap)) == NULL) { 966155408Srwatson if (ap->ap_flags & AUDIT_PIPE_NBIO) { 967184488Srwatson AUDIT_PIPE_UNLOCK(ap); 968155408Srwatson return (EAGAIN); 969155408Srwatson } 970184488Srwatson error = cv_wait_sig(&ap->ap_cv, AUDIT_PIPE_MTX(ap)); 971155408Srwatson if (error) { 972184488Srwatson AUDIT_PIPE_UNLOCK(ap); 973155408Srwatson return (error); 974155408Srwatson } 975155408Srwatson } 976155408Srwatson if (ape->ape_record_len <= uio->uio_resid) 977155408Srwatson break; 978155408Srwatson audit_pipe_entry_free(ape); 979155408Srwatson ap->ap_truncates++; 980155408Srwatson } while (1); 981173083Scsjp ap->ap_reads++; 982184488Srwatson AUDIT_PIPE_UNLOCK(ap); 983155408Srwatson 984155408Srwatson /* 985155408Srwatson * Now read record to user space memory. Even if the read is short, 986155408Srwatson * we abandon the remainder of the record, supporting only discreet 987155408Srwatson * record reads. 988155408Srwatson */ 989155408Srwatson error = uiomove(ape->ape_record, ape->ape_record_len, uio); 990155408Srwatson audit_pipe_entry_free(ape); 991155408Srwatson return (error); 992155408Srwatson} 993155408Srwatson 994155408Srwatson/* 995155408Srwatson * Audit pipe poll. 996155408Srwatson */ 997155408Srwatsonstatic int 998155408Srwatsonaudit_pipe_poll(struct cdev *dev, int events, struct thread *td) 999155408Srwatson{ 1000155408Srwatson struct audit_pipe *ap; 1001155408Srwatson int revents; 1002155408Srwatson 1003155408Srwatson revents = 0; 1004155408Srwatson ap = dev->si_drv1; 1005155408Srwatson KASSERT(ap != NULL, ("audit_pipe_poll: ap == NULL")); 1006184488Srwatson 1007155408Srwatson if (events & (POLLIN | POLLRDNORM)) { 1008184488Srwatson AUDIT_PIPE_LOCK(ap); 1009155408Srwatson if (TAILQ_FIRST(&ap->ap_queue) != NULL) 1010155408Srwatson revents |= events & (POLLIN | POLLRDNORM); 1011155408Srwatson else 1012155408Srwatson selrecord(td, &ap->ap_selinfo); 1013184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1014155408Srwatson } 1015155408Srwatson return (revents); 1016155408Srwatson} 1017155408Srwatson 1018155408Srwatson/* 1019161582Srwatson * Audit pipe kqfilter. 1020161582Srwatson */ 1021161582Srwatsonstatic int 1022161582Srwatsonaudit_pipe_kqfilter(struct cdev *dev, struct knote *kn) 1023161582Srwatson{ 1024161582Srwatson struct audit_pipe *ap; 1025161582Srwatson 1026161582Srwatson ap = dev->si_drv1; 1027161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqfilter: ap == NULL")); 1028161582Srwatson 1029161582Srwatson if (kn->kn_filter != EVFILT_READ) 1030161582Srwatson return (EINVAL); 1031161582Srwatson 1032161582Srwatson kn->kn_fop = &audit_pipe_read_filterops; 1033161582Srwatson kn->kn_hook = ap; 1034161582Srwatson 1035184488Srwatson AUDIT_PIPE_LOCK(ap); 1036161582Srwatson knlist_add(&ap->ap_selinfo.si_note, kn, 1); 1037184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1038161582Srwatson return (0); 1039161582Srwatson} 1040161582Srwatson 1041161582Srwatson/* 1042161582Srwatson * Return true if there are records available for reading on the pipe. 1043161582Srwatson */ 1044161582Srwatsonstatic int 1045161582Srwatsonaudit_pipe_kqread(struct knote *kn, long hint) 1046161582Srwatson{ 1047161582Srwatson struct audit_pipe_entry *ape; 1048161582Srwatson struct audit_pipe *ap; 1049161582Srwatson 1050161582Srwatson ap = (struct audit_pipe *)kn->kn_hook; 1051161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqread: ap == NULL")); 1052161582Srwatson 1053184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 1054184488Srwatson 1055161582Srwatson if (ap->ap_qlen != 0) { 1056161582Srwatson ape = TAILQ_FIRST(&ap->ap_queue); 1057161582Srwatson KASSERT(ape != NULL, ("audit_pipe_kqread: ape == NULL")); 1058161582Srwatson 1059161582Srwatson kn->kn_data = ape->ape_record_len; 1060161582Srwatson return (1); 1061161582Srwatson } else { 1062161582Srwatson kn->kn_data = 0; 1063161582Srwatson return (0); 1064161582Srwatson } 1065161582Srwatson} 1066161582Srwatson 1067161582Srwatson/* 1068161582Srwatson * Detach kqueue state from audit pipe. 1069161582Srwatson */ 1070161582Srwatsonstatic void 1071161582Srwatsonaudit_pipe_kqdetach(struct knote *kn) 1072161582Srwatson{ 1073161582Srwatson struct audit_pipe *ap; 1074161582Srwatson 1075161582Srwatson ap = (struct audit_pipe *)kn->kn_hook; 1076161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqdetach: ap == NULL")); 1077161582Srwatson 1078184488Srwatson AUDIT_PIPE_LOCK(ap); 1079161582Srwatson knlist_remove(&ap->ap_selinfo.si_note, kn, 1); 1080184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1081161582Srwatson} 1082161582Srwatson 1083161582Srwatson/* 1084155408Srwatson * Initialize the audit pipe system. 1085155408Srwatson */ 1086155408Srwatsonstatic void 1087155408Srwatsonaudit_pipe_init(void *unused) 1088155408Srwatson{ 1089155408Srwatson 1090155408Srwatson TAILQ_INIT(&audit_pipe_list); 1091184488Srwatson AUDIT_PIPE_LIST_LOCK_INIT(); 1092155408Srwatson 1093155408Srwatson clone_setup(&audit_pipe_clones); 1094155408Srwatson audit_pipe_eh_tag = EVENTHANDLER_REGISTER(dev_clone, 1095155408Srwatson audit_pipe_clone, 0, 1000); 1096155408Srwatson if (audit_pipe_eh_tag == NULL) 1097155408Srwatson panic("audit_pipe_init: EVENTHANDLER_REGISTER"); 1098155408Srwatson} 1099155408Srwatson 1100155408SrwatsonSYSINIT(audit_pipe_init, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, audit_pipe_init, 1101155408Srwatson NULL); 1102