1155408Srwatson/*- 2155408Srwatson * Copyright (c) 2006 Robert N. M. Watson 3188315Srwatson * Copyright (c) 2008-2009 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$"); 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> 50184508Srwatson#include <sys/sx.h> 51155408Srwatson#include <sys/systm.h> 52155408Srwatson#include <sys/uio.h> 53155408Srwatson 54155408Srwatson#include <security/audit/audit.h> 55156880Srwatson#include <security/audit/audit_ioctl.h> 56155408Srwatson#include <security/audit/audit_private.h> 57155408Srwatson 58155408Srwatson/* 59155408Srwatson * Implementation of a clonable special device providing a live stream of BSM 60184545Srwatson * audit data. Consumers receive a "tee" of the system audit trail by 61184545Srwatson * default, but may also define alternative event selections using ioctls. 62184545Srwatson * This interface provides unreliable but timely access to audit events. 63184545Srwatson * Consumers should be very careful to avoid introducing event cycles. 64155408Srwatson */ 65155408Srwatson 66155408Srwatson/* 67155408Srwatson * Memory types. 68155408Srwatson */ 69155408Srwatsonstatic MALLOC_DEFINE(M_AUDIT_PIPE, "audit_pipe", "Audit pipes"); 70155408Srwatsonstatic MALLOC_DEFINE(M_AUDIT_PIPE_ENTRY, "audit_pipeent", 71155408Srwatson "Audit pipe entries and buffers"); 72174894Swkoszekstatic MALLOC_DEFINE(M_AUDIT_PIPE_PRESELECT, "audit_pipe_presel", 73159269Srwatson "Audit pipe preselection structure"); 74155408Srwatson 75155408Srwatson/* 76155408Srwatson * Audit pipe buffer parameters. 77155408Srwatson */ 78156883Srwatson#define AUDIT_PIPE_QLIMIT_DEFAULT (128) 79188315Srwatson#define AUDIT_PIPE_QLIMIT_MIN (1) 80155408Srwatson#define AUDIT_PIPE_QLIMIT_MAX (1024) 81155408Srwatson 82155408Srwatson/* 83155408Srwatson * Description of an entry in an audit_pipe. 84155408Srwatson */ 85155408Srwatsonstruct audit_pipe_entry { 86155408Srwatson void *ape_record; 87155408Srwatson u_int ape_record_len; 88155408Srwatson TAILQ_ENTRY(audit_pipe_entry) ape_queue; 89155408Srwatson}; 90155408Srwatson 91155408Srwatson/* 92159269Srwatson * Audit pipes allow processes to express "interest" in the set of records 93159269Srwatson * that are delivered via the pipe. They do this in a similar manner to the 94159269Srwatson * mechanism for audit trail configuration, by expressing two global masks, 95159269Srwatson * and optionally expressing per-auid masks. The following data structure is 96159269Srwatson * the per-auid mask description. The global state is stored in the audit 97159269Srwatson * pipe data structure. 98159269Srwatson * 99159269Srwatson * We may want to consider a more space/time-efficient data structure once 100159269Srwatson * usage patterns for per-auid specifications are clear. 101159269Srwatson */ 102159269Srwatsonstruct audit_pipe_preselect { 103159269Srwatson au_id_t app_auid; 104159269Srwatson au_mask_t app_mask; 105159269Srwatson TAILQ_ENTRY(audit_pipe_preselect) app_list; 106159269Srwatson}; 107159269Srwatson 108159269Srwatson/* 109155408Srwatson * Description of an individual audit_pipe. Consists largely of a bounded 110155408Srwatson * length queue. 111155408Srwatson */ 112155408Srwatson#define AUDIT_PIPE_ASYNC 0x00000001 113155408Srwatson#define AUDIT_PIPE_NBIO 0x00000002 114155408Srwatsonstruct audit_pipe { 115155408Srwatson int ap_open; /* Device open? */ 116155408Srwatson u_int ap_flags; 117155408Srwatson 118155408Srwatson struct selinfo ap_selinfo; 119155408Srwatson struct sigio *ap_sigio; 120155408Srwatson 121184488Srwatson /* 122184488Srwatson * Per-pipe mutex protecting most fields in this data structure. 123184488Srwatson */ 124184508Srwatson struct mtx ap_mtx; 125184488Srwatson 126184488Srwatson /* 127184508Srwatson * Per-pipe sleep lock serializing user-generated reads and flushes. 128184508Srwatson * uiomove() is called to copy out the current head record's data 129184508Srwatson * while the record remains in the queue, so we prevent other threads 130184508Srwatson * from removing it using this lock. 131184508Srwatson */ 132184508Srwatson struct sx ap_sx; 133184508Srwatson 134184508Srwatson /* 135184488Srwatson * Condition variable to signal when data has been delivered to a 136184488Srwatson * pipe. 137184488Srwatson */ 138184488Srwatson struct cv ap_cv; 139184488Srwatson 140184536Srwatson /* 141184536Srwatson * Various queue-reated variables: qlen and qlimit are a count of 142184536Srwatson * records in the queue; qbyteslen is the number of bytes of data 143184536Srwatson * across all records, and qoffset is the amount read so far of the 144184536Srwatson * first record in the queue. The number of bytes available for 145184536Srwatson * reading in the queue is qbyteslen - qoffset. 146184536Srwatson */ 147155408Srwatson u_int ap_qlen; 148155408Srwatson u_int ap_qlimit; 149184536Srwatson u_int ap_qbyteslen; 150184536Srwatson u_int ap_qoffset; 151155408Srwatson 152184540Srwatson /* 153184540Srwatson * Per-pipe operation statistics. 154184540Srwatson */ 155155408Srwatson u_int64_t ap_inserts; /* Records added. */ 156155408Srwatson u_int64_t ap_reads; /* Records read. */ 157155408Srwatson u_int64_t ap_drops; /* Records dropped. */ 158155408Srwatson 159159269Srwatson /* 160159269Srwatson * Fields relating to pipe interest: global masks for unmatched 161159269Srwatson * processes (attributable, non-attributable), and a list of specific 162159269Srwatson * interest specifications by auid. 163159269Srwatson */ 164159269Srwatson int ap_preselect_mode; 165159269Srwatson au_mask_t ap_preselect_flags; 166159269Srwatson au_mask_t ap_preselect_naflags; 167159269Srwatson TAILQ_HEAD(, audit_pipe_preselect) ap_preselect_list; 168159269Srwatson 169159269Srwatson /* 170184508Srwatson * Current pending record list. Protected by a combination of ap_mtx 171184508Srwatson * and ap_sx. Note particularly that *both* locks are required to 172186662Srwatson * remove a record from the head of the queue, as an in-progress read 173186662Srwatson * may sleep while copying and therefore cannot hold ap_mtx. 174159269Srwatson */ 175155408Srwatson TAILQ_HEAD(, audit_pipe_entry) ap_queue; 176155408Srwatson 177159269Srwatson /* 178159269Srwatson * Global pipe list. 179159269Srwatson */ 180155408Srwatson TAILQ_ENTRY(audit_pipe) ap_list; 181155408Srwatson}; 182155408Srwatson 183184508Srwatson#define AUDIT_PIPE_LOCK(ap) mtx_lock(&(ap)->ap_mtx) 184184508Srwatson#define AUDIT_PIPE_LOCK_ASSERT(ap) mtx_assert(&(ap)->ap_mtx, MA_OWNED) 185184508Srwatson#define AUDIT_PIPE_LOCK_DESTROY(ap) mtx_destroy(&(ap)->ap_mtx) 186184508Srwatson#define AUDIT_PIPE_LOCK_INIT(ap) mtx_init(&(ap)->ap_mtx, \ 187184508Srwatson "audit_pipe_mtx", NULL, MTX_DEF) 188184508Srwatson#define AUDIT_PIPE_UNLOCK(ap) mtx_unlock(&(ap)->ap_mtx) 189184508Srwatson#define AUDIT_PIPE_MTX(ap) (&(ap)->ap_mtx) 190184488Srwatson 191184508Srwatson#define AUDIT_PIPE_SX_LOCK_DESTROY(ap) sx_destroy(&(ap)->ap_sx) 192184508Srwatson#define AUDIT_PIPE_SX_LOCK_INIT(ap) sx_init(&(ap)->ap_sx, "audit_pipe_sx") 193184508Srwatson#define AUDIT_PIPE_SX_XLOCK_ASSERT(ap) sx_assert(&(ap)->ap_sx, SA_XLOCKED) 194184508Srwatson#define AUDIT_PIPE_SX_XLOCK_SIG(ap) sx_xlock_sig(&(ap)->ap_sx) 195184508Srwatson#define AUDIT_PIPE_SX_XUNLOCK(ap) sx_xunlock(&(ap)->ap_sx) 196184508Srwatson 197155408Srwatson/* 198184488Srwatson * Global list of audit pipes, rwlock to protect it. Individual record 199184488Srwatson * queues on pipes are protected by per-pipe locks; these locks synchronize 200184488Srwatson * between threads walking the list to deliver to individual pipes and add/ 201184488Srwatson * remove of pipes, and are mostly acquired for read. 202155408Srwatson */ 203155408Srwatsonstatic TAILQ_HEAD(, audit_pipe) audit_pipe_list; 204184488Srwatsonstatic struct rwlock audit_pipe_lock; 205155408Srwatson 206184488Srwatson#define AUDIT_PIPE_LIST_LOCK_INIT() rw_init(&audit_pipe_lock, \ 207184488Srwatson "audit_pipe_list_lock") 208184488Srwatson#define AUDIT_PIPE_LIST_RLOCK() rw_rlock(&audit_pipe_lock) 209184488Srwatson#define AUDIT_PIPE_LIST_RUNLOCK() rw_runlock(&audit_pipe_lock) 210184488Srwatson#define AUDIT_PIPE_LIST_WLOCK() rw_wlock(&audit_pipe_lock) 211184488Srwatson#define AUDIT_PIPE_LIST_WLOCK_ASSERT() rw_assert(&audit_pipe_lock, \ 212184488Srwatson RA_WLOCKED) 213184488Srwatson#define AUDIT_PIPE_LIST_WUNLOCK() rw_wunlock(&audit_pipe_lock) 214155408Srwatson 215155408Srwatson/* 216155408Srwatson * Cloning related variables and constants. 217155408Srwatson */ 218155408Srwatson#define AUDIT_PIPE_NAME "auditpipe" 219155408Srwatsonstatic eventhandler_tag audit_pipe_eh_tag; 220155408Srwatsonstatic struct clonedevs *audit_pipe_clones; 221155408Srwatson 222155408Srwatson/* 223155408Srwatson * Special device methods and definition. 224155408Srwatson */ 225155408Srwatsonstatic d_open_t audit_pipe_open; 226155408Srwatsonstatic d_close_t audit_pipe_close; 227155408Srwatsonstatic d_read_t audit_pipe_read; 228155408Srwatsonstatic d_ioctl_t audit_pipe_ioctl; 229155408Srwatsonstatic d_poll_t audit_pipe_poll; 230161582Srwatsonstatic d_kqfilter_t audit_pipe_kqfilter; 231155408Srwatson 232155408Srwatsonstatic struct cdevsw audit_pipe_cdevsw = { 233155408Srwatson .d_version = D_VERSION, 234226500Sed .d_flags = D_NEEDMINOR, 235155408Srwatson .d_open = audit_pipe_open, 236155408Srwatson .d_close = audit_pipe_close, 237155408Srwatson .d_read = audit_pipe_read, 238155408Srwatson .d_ioctl = audit_pipe_ioctl, 239155408Srwatson .d_poll = audit_pipe_poll, 240161582Srwatson .d_kqfilter = audit_pipe_kqfilter, 241155408Srwatson .d_name = AUDIT_PIPE_NAME, 242155408Srwatson}; 243155408Srwatson 244161582Srwatsonstatic int audit_pipe_kqread(struct knote *note, long hint); 245161582Srwatsonstatic void audit_pipe_kqdetach(struct knote *note); 246161582Srwatson 247161582Srwatsonstatic struct filterops audit_pipe_read_filterops = { 248161582Srwatson .f_isfd = 1, 249161582Srwatson .f_attach = NULL, 250161582Srwatson .f_detach = audit_pipe_kqdetach, 251161582Srwatson .f_event = audit_pipe_kqread, 252161582Srwatson}; 253161582Srwatson 254155408Srwatson/* 255155408Srwatson * Some global statistics on audit pipes. 256155408Srwatson */ 257155408Srwatsonstatic int audit_pipe_count; /* Current number of pipes. */ 258155408Srwatsonstatic u_int64_t audit_pipe_ever; /* Pipes ever allocated. */ 259155408Srwatsonstatic u_int64_t audit_pipe_records; /* Records seen. */ 260155408Srwatsonstatic u_int64_t audit_pipe_drops; /* Global record drop count. */ 261155408Srwatson 262155408Srwatson/* 263155408Srwatson * Free an audit pipe entry. 264155408Srwatson */ 265155408Srwatsonstatic void 266155408Srwatsonaudit_pipe_entry_free(struct audit_pipe_entry *ape) 267155408Srwatson{ 268155408Srwatson 269155408Srwatson free(ape->ape_record, M_AUDIT_PIPE_ENTRY); 270155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 271155408Srwatson} 272155408Srwatson 273155408Srwatson/* 274159269Srwatson * Find an audit pipe preselection specification for an auid, if any. 275159269Srwatson */ 276159269Srwatsonstatic struct audit_pipe_preselect * 277159269Srwatsonaudit_pipe_preselect_find(struct audit_pipe *ap, au_id_t auid) 278159269Srwatson{ 279159269Srwatson struct audit_pipe_preselect *app; 280159269Srwatson 281184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 282159269Srwatson 283159269Srwatson TAILQ_FOREACH(app, &ap->ap_preselect_list, app_list) { 284159269Srwatson if (app->app_auid == auid) 285159269Srwatson return (app); 286159269Srwatson } 287159269Srwatson return (NULL); 288159269Srwatson} 289159269Srwatson 290159269Srwatson/* 291159269Srwatson * Query the per-pipe mask for a specific auid. 292159269Srwatson */ 293159269Srwatsonstatic int 294159269Srwatsonaudit_pipe_preselect_get(struct audit_pipe *ap, au_id_t auid, 295159269Srwatson au_mask_t *maskp) 296159269Srwatson{ 297159269Srwatson struct audit_pipe_preselect *app; 298159269Srwatson int error; 299159269Srwatson 300184488Srwatson AUDIT_PIPE_LOCK(ap); 301159269Srwatson app = audit_pipe_preselect_find(ap, auid); 302159269Srwatson if (app != NULL) { 303159269Srwatson *maskp = app->app_mask; 304159269Srwatson error = 0; 305159269Srwatson } else 306159269Srwatson error = ENOENT; 307184488Srwatson AUDIT_PIPE_UNLOCK(ap); 308159269Srwatson return (error); 309159269Srwatson} 310159269Srwatson 311159269Srwatson/* 312159269Srwatson * Set the per-pipe mask for a specific auid. Add a new entry if needed; 313159269Srwatson * otherwise, update the current entry. 314159269Srwatson */ 315159269Srwatsonstatic void 316159269Srwatsonaudit_pipe_preselect_set(struct audit_pipe *ap, au_id_t auid, au_mask_t mask) 317159269Srwatson{ 318159269Srwatson struct audit_pipe_preselect *app, *app_new; 319159269Srwatson 320159269Srwatson /* 321159269Srwatson * Pessimistically assume that the auid doesn't already have a mask 322159269Srwatson * set, and allocate. We will free it if it is unneeded. 323159269Srwatson */ 324159269Srwatson app_new = malloc(sizeof(*app_new), M_AUDIT_PIPE_PRESELECT, M_WAITOK); 325184488Srwatson AUDIT_PIPE_LOCK(ap); 326159269Srwatson app = audit_pipe_preselect_find(ap, auid); 327159269Srwatson if (app == NULL) { 328159269Srwatson app = app_new; 329159269Srwatson app_new = NULL; 330159269Srwatson app->app_auid = auid; 331159269Srwatson TAILQ_INSERT_TAIL(&ap->ap_preselect_list, app, app_list); 332159269Srwatson } 333159269Srwatson app->app_mask = mask; 334184488Srwatson AUDIT_PIPE_UNLOCK(ap); 335159269Srwatson if (app_new != NULL) 336159269Srwatson free(app_new, M_AUDIT_PIPE_PRESELECT); 337159269Srwatson} 338159269Srwatson 339159269Srwatson/* 340159269Srwatson * Delete a per-auid mask on an audit pipe. 341159269Srwatson */ 342159269Srwatsonstatic int 343159269Srwatsonaudit_pipe_preselect_delete(struct audit_pipe *ap, au_id_t auid) 344159269Srwatson{ 345159269Srwatson struct audit_pipe_preselect *app; 346159269Srwatson int error; 347159269Srwatson 348184488Srwatson AUDIT_PIPE_LOCK(ap); 349159269Srwatson app = audit_pipe_preselect_find(ap, auid); 350159269Srwatson if (app != NULL) { 351159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 352159269Srwatson error = 0; 353159269Srwatson } else 354159269Srwatson error = ENOENT; 355184488Srwatson AUDIT_PIPE_UNLOCK(ap); 356159269Srwatson if (app != NULL) 357159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 358159269Srwatson return (error); 359159269Srwatson} 360159269Srwatson 361159269Srwatson/* 362159269Srwatson * Delete all per-auid masks on an audit pipe. 363159269Srwatson */ 364159269Srwatsonstatic void 365159269Srwatsonaudit_pipe_preselect_flush_locked(struct audit_pipe *ap) 366159269Srwatson{ 367159269Srwatson struct audit_pipe_preselect *app; 368159269Srwatson 369184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 370159269Srwatson 371159269Srwatson while ((app = TAILQ_FIRST(&ap->ap_preselect_list)) != NULL) { 372159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 373159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 374159269Srwatson } 375159269Srwatson} 376159269Srwatson 377159269Srwatsonstatic void 378159269Srwatsonaudit_pipe_preselect_flush(struct audit_pipe *ap) 379159269Srwatson{ 380159269Srwatson 381184488Srwatson AUDIT_PIPE_LOCK(ap); 382159269Srwatson audit_pipe_preselect_flush_locked(ap); 383184488Srwatson AUDIT_PIPE_UNLOCK(ap); 384159269Srwatson} 385159269Srwatson 386170196Srwatson/*- 387159269Srwatson * Determine whether a specific audit pipe matches a record with these 388159269Srwatson * properties. Algorithm is as follows: 389159269Srwatson * 390159269Srwatson * - If the pipe is configured to track the default trail configuration, then 391159269Srwatson * use the results of global preselection matching. 392159269Srwatson * - If not, search for a specifically configured auid entry matching the 393159269Srwatson * event. If an entry is found, use that. 394159269Srwatson * - Otherwise, use the default flags or naflags configured for the pipe. 395159269Srwatson */ 396159269Srwatsonstatic int 397159269Srwatsonaudit_pipe_preselect_check(struct audit_pipe *ap, au_id_t auid, 398159269Srwatson au_event_t event, au_class_t class, int sorf, int trail_preselect) 399159269Srwatson{ 400159269Srwatson struct audit_pipe_preselect *app; 401159269Srwatson 402184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 403159269Srwatson 404159269Srwatson switch (ap->ap_preselect_mode) { 405159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 406159269Srwatson return (trail_preselect); 407159269Srwatson 408159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 409159269Srwatson app = audit_pipe_preselect_find(ap, auid); 410159269Srwatson if (app == NULL) { 411159269Srwatson if (auid == AU_DEFAUDITID) 412159269Srwatson return (au_preselect(event, class, 413159269Srwatson &ap->ap_preselect_naflags, sorf)); 414159269Srwatson else 415159269Srwatson return (au_preselect(event, class, 416159269Srwatson &ap->ap_preselect_flags, sorf)); 417159269Srwatson } else 418159269Srwatson return (au_preselect(event, class, &app->app_mask, 419159269Srwatson sorf)); 420159269Srwatson 421159269Srwatson default: 422159269Srwatson panic("audit_pipe_preselect_check: mode %d", 423159269Srwatson ap->ap_preselect_mode); 424159269Srwatson } 425159269Srwatson 426159269Srwatson return (0); 427159269Srwatson} 428159269Srwatson 429159269Srwatson/* 430159269Srwatson * Determine whether there exists a pipe interested in a record with specific 431159269Srwatson * properties. 432159269Srwatson */ 433159269Srwatsonint 434159269Srwatsonaudit_pipe_preselect(au_id_t auid, au_event_t event, au_class_t class, 435159269Srwatson int sorf, int trail_preselect) 436159269Srwatson{ 437159269Srwatson struct audit_pipe *ap; 438159269Srwatson 439186825Srwatson /* Lockless read to avoid acquiring the global lock if not needed. */ 440186825Srwatson if (TAILQ_EMPTY(&audit_pipe_list)) 441186825Srwatson return (0); 442186825Srwatson 443184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 444159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 445184488Srwatson AUDIT_PIPE_LOCK(ap); 446159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 447159269Srwatson trail_preselect)) { 448184488Srwatson AUDIT_PIPE_UNLOCK(ap); 449184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 450159269Srwatson return (1); 451159269Srwatson } 452184488Srwatson AUDIT_PIPE_UNLOCK(ap); 453159269Srwatson } 454184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 455159269Srwatson return (0); 456159269Srwatson} 457159269Srwatson 458159269Srwatson/* 459159269Srwatson * Append individual record to a queue -- allocate queue-local buffer, and 460184489Srwatson * add to the queue. If the queue is full or we can't allocate memory, drop 461184489Srwatson * the newest record. 462155408Srwatson */ 463155408Srwatsonstatic void 464155408Srwatsonaudit_pipe_append(struct audit_pipe *ap, void *record, u_int record_len) 465155408Srwatson{ 466184489Srwatson struct audit_pipe_entry *ape; 467155408Srwatson 468184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 469155408Srwatson 470184489Srwatson if (ap->ap_qlen >= ap->ap_qlimit) { 471184489Srwatson ap->ap_drops++; 472184489Srwatson audit_pipe_drops++; 473184489Srwatson return; 474184489Srwatson } 475184489Srwatson 476155408Srwatson ape = malloc(sizeof(*ape), M_AUDIT_PIPE_ENTRY, M_NOWAIT | M_ZERO); 477155408Srwatson if (ape == NULL) { 478155408Srwatson ap->ap_drops++; 479156292Srwatson audit_pipe_drops++; 480155408Srwatson return; 481155408Srwatson } 482155408Srwatson 483155408Srwatson ape->ape_record = malloc(record_len, M_AUDIT_PIPE_ENTRY, M_NOWAIT); 484155408Srwatson if (ape->ape_record == NULL) { 485155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 486155408Srwatson ap->ap_drops++; 487155408Srwatson audit_pipe_drops++; 488155408Srwatson return; 489155408Srwatson } 490155408Srwatson 491155408Srwatson bcopy(record, ape->ape_record, record_len); 492155408Srwatson ape->ape_record_len = record_len; 493155408Srwatson 494155408Srwatson TAILQ_INSERT_TAIL(&ap->ap_queue, ape, ape_queue); 495155408Srwatson ap->ap_inserts++; 496155408Srwatson ap->ap_qlen++; 497184536Srwatson ap->ap_qbyteslen += ape->ape_record_len; 498155408Srwatson selwakeuppri(&ap->ap_selinfo, PSOCK); 499161582Srwatson KNOTE_LOCKED(&ap->ap_selinfo.si_note, 0); 500155408Srwatson if (ap->ap_flags & AUDIT_PIPE_ASYNC) 501155408Srwatson pgsigio(&ap->ap_sigio, SIGIO, 0); 502184488Srwatson cv_broadcast(&ap->ap_cv); 503155408Srwatson} 504155408Srwatson 505155408Srwatson/* 506155408Srwatson * audit_pipe_submit(): audit_worker submits audit records via this 507155408Srwatson * interface, which arranges for them to be delivered to pipe queues. 508155408Srwatson */ 509155408Srwatsonvoid 510159269Srwatsonaudit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class, int sorf, 511159269Srwatson int trail_select, void *record, u_int record_len) 512155408Srwatson{ 513155408Srwatson struct audit_pipe *ap; 514155408Srwatson 515155408Srwatson /* 516184488Srwatson * Lockless read to avoid lock overhead if pipes are not in use. 517155408Srwatson */ 518155408Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 519155408Srwatson return; 520155408Srwatson 521184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 522159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 523184488Srwatson AUDIT_PIPE_LOCK(ap); 524159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 525159269Srwatson trail_select)) 526159269Srwatson audit_pipe_append(ap, record, record_len); 527184488Srwatson AUDIT_PIPE_UNLOCK(ap); 528159269Srwatson } 529184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 530184488Srwatson 531184488Srwatson /* Unlocked increment. */ 532159269Srwatson audit_pipe_records++; 533159269Srwatson} 534159269Srwatson 535159269Srwatson/* 536159269Srwatson * audit_pipe_submit_user(): the same as audit_pipe_submit(), except that 537159269Srwatson * since we don't currently have selection information available, it is 538159269Srwatson * delivered to the pipe unconditionally. 539159269Srwatson * 540159269Srwatson * XXXRW: This is a bug. The BSM check routine for submitting a user record 541159269Srwatson * should parse that information and return it. 542159269Srwatson */ 543159269Srwatsonvoid 544159269Srwatsonaudit_pipe_submit_user(void *record, u_int record_len) 545159269Srwatson{ 546159269Srwatson struct audit_pipe *ap; 547159269Srwatson 548159269Srwatson /* 549184488Srwatson * Lockless read to avoid lock overhead if pipes are not in use. 550159269Srwatson */ 551159269Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 552159269Srwatson return; 553159269Srwatson 554184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 555184488Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 556184488Srwatson AUDIT_PIPE_LOCK(ap); 557155408Srwatson audit_pipe_append(ap, record, record_len); 558184488Srwatson AUDIT_PIPE_UNLOCK(ap); 559184488Srwatson } 560184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 561184488Srwatson 562184488Srwatson /* Unlocked increment. */ 563155408Srwatson audit_pipe_records++; 564155408Srwatson} 565155408Srwatson 566155408Srwatson/* 567155408Srwatson * Allocate a new audit pipe. Connects the pipe, on success, to the global 568155408Srwatson * list and updates statistics. 569155408Srwatson */ 570155408Srwatsonstatic struct audit_pipe * 571155408Srwatsonaudit_pipe_alloc(void) 572155408Srwatson{ 573155408Srwatson struct audit_pipe *ap; 574155408Srwatson 575184488Srwatson AUDIT_PIPE_LIST_WLOCK_ASSERT(); 576155408Srwatson 577155408Srwatson ap = malloc(sizeof(*ap), M_AUDIT_PIPE, M_NOWAIT | M_ZERO); 578155408Srwatson if (ap == NULL) 579155408Srwatson return (NULL); 580155408Srwatson ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT; 581155408Srwatson TAILQ_INIT(&ap->ap_queue); 582193951Skib knlist_init_mtx(&ap->ap_selinfo.si_note, AUDIT_PIPE_MTX(ap)); 583184488Srwatson AUDIT_PIPE_LOCK_INIT(ap); 584184508Srwatson AUDIT_PIPE_SX_LOCK_INIT(ap); 585184488Srwatson cv_init(&ap->ap_cv, "audit_pipe"); 586159269Srwatson 587159269Srwatson /* 588159269Srwatson * Default flags, naflags, and auid-specific preselection settings to 589159269Srwatson * 0. Initialize the mode to the global trail so that if praudit(1) 590159269Srwatson * is run on /dev/auditpipe, it sees events associated with the 591159269Srwatson * default trail. Pipe-aware application can clear the flag, set 592159269Srwatson * custom masks, and flush the pipe as needed. 593159269Srwatson */ 594159269Srwatson bzero(&ap->ap_preselect_flags, sizeof(ap->ap_preselect_flags)); 595159269Srwatson bzero(&ap->ap_preselect_naflags, sizeof(ap->ap_preselect_naflags)); 596159269Srwatson TAILQ_INIT(&ap->ap_preselect_list); 597159269Srwatson ap->ap_preselect_mode = AUDITPIPE_PRESELECT_MODE_TRAIL; 598159269Srwatson 599161582Srwatson /* 600161582Srwatson * Add to global list and update global statistics. 601161582Srwatson */ 602155408Srwatson TAILQ_INSERT_HEAD(&audit_pipe_list, ap, ap_list); 603155408Srwatson audit_pipe_count++; 604155408Srwatson audit_pipe_ever++; 605159269Srwatson 606155408Srwatson return (ap); 607155408Srwatson} 608155408Srwatson 609155408Srwatson/* 610159269Srwatson * Flush all records currently present in an audit pipe; assume mutex is held. 611155408Srwatson */ 612155408Srwatsonstatic void 613159269Srwatsonaudit_pipe_flush(struct audit_pipe *ap) 614155408Srwatson{ 615155408Srwatson struct audit_pipe_entry *ape; 616155408Srwatson 617184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 618155408Srwatson 619155408Srwatson while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL) { 620155408Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 621184536Srwatson ap->ap_qbyteslen -= ape->ape_record_len; 622155408Srwatson audit_pipe_entry_free(ape); 623155408Srwatson ap->ap_qlen--; 624155408Srwatson } 625184536Srwatson ap->ap_qoffset = 0; 626184536Srwatson 627184536Srwatson KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qbyteslen")); 628184536Srwatson KASSERT(ap->ap_qbyteslen == 0, ("audit_pipe_flush: ap_qbyteslen")); 629159269Srwatson} 630159269Srwatson 631159269Srwatson/* 632159269Srwatson * Free an audit pipe; this means freeing all preselection state and all 633184488Srwatson * records in the pipe. Assumes global write lock and pipe mutex are held to 634184488Srwatson * prevent any new records from being inserted during the free, and that the 635184488Srwatson * audit pipe is still on the global list. 636159269Srwatson */ 637159269Srwatsonstatic void 638159269Srwatsonaudit_pipe_free(struct audit_pipe *ap) 639159269Srwatson{ 640159269Srwatson 641184488Srwatson AUDIT_PIPE_LIST_WLOCK_ASSERT(); 642184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 643159269Srwatson 644159269Srwatson audit_pipe_preselect_flush_locked(ap); 645159269Srwatson audit_pipe_flush(ap); 646184488Srwatson cv_destroy(&ap->ap_cv); 647184508Srwatson AUDIT_PIPE_SX_LOCK_DESTROY(ap); 648184488Srwatson AUDIT_PIPE_LOCK_DESTROY(ap); 649225177Sattilio seldrain(&ap->ap_selinfo); 650161582Srwatson knlist_destroy(&ap->ap_selinfo.si_note); 651159269Srwatson TAILQ_REMOVE(&audit_pipe_list, ap, ap_list); 652155408Srwatson free(ap, M_AUDIT_PIPE); 653155408Srwatson audit_pipe_count--; 654155408Srwatson} 655155408Srwatson 656155408Srwatson/* 657155408Srwatson * Audit pipe clone routine -- provide specific requested audit pipe, or a 658155408Srwatson * fresh one if a specific one is not requested. 659155408Srwatson */ 660155408Srwatsonstatic void 661155408Srwatsonaudit_pipe_clone(void *arg, struct ucred *cred, char *name, int namelen, 662155408Srwatson struct cdev **dev) 663155408Srwatson{ 664155408Srwatson int i, u; 665155408Srwatson 666155408Srwatson if (*dev != NULL) 667155408Srwatson return; 668155408Srwatson 669155408Srwatson if (strcmp(name, AUDIT_PIPE_NAME) == 0) 670155408Srwatson u = -1; 671155408Srwatson else if (dev_stdclone(name, NULL, AUDIT_PIPE_NAME, &u) != 1) 672155408Srwatson return; 673155408Srwatson 674155408Srwatson i = clone_create(&audit_pipe_clones, &audit_pipe_cdevsw, &u, dev, 0); 675255359Sdavide if (i) 676255359Sdavide *dev = make_dev_credf(MAKEDEV_REF, &audit_pipe_cdevsw, u, cred, 677255359Sdavide UID_ROOT, GID_WHEEL, 0600, "%s%d", AUDIT_PIPE_NAME, u); 678155408Srwatson} 679155408Srwatson 680155408Srwatson/* 681164033Srwatson * Audit pipe open method. Explicit privilege check isn't used as this 682164033Srwatson * allows file permissions on the special device to be used to grant audit 683164033Srwatson * review access. Those file permissions should be managed carefully. 684155408Srwatson */ 685155408Srwatsonstatic int 686155408Srwatsonaudit_pipe_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 687155408Srwatson{ 688155408Srwatson struct audit_pipe *ap; 689155408Srwatson 690184488Srwatson AUDIT_PIPE_LIST_WLOCK(); 691155408Srwatson ap = dev->si_drv1; 692155408Srwatson if (ap == NULL) { 693155408Srwatson ap = audit_pipe_alloc(); 694155408Srwatson if (ap == NULL) { 695184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 696155408Srwatson return (ENOMEM); 697155408Srwatson } 698155408Srwatson dev->si_drv1 = ap; 699155408Srwatson } else { 700155408Srwatson KASSERT(ap->ap_open, ("audit_pipe_open: ap && !ap_open")); 701184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 702155408Srwatson return (EBUSY); 703155408Srwatson } 704184488Srwatson ap->ap_open = 1; /* No lock required yet. */ 705184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 706155408Srwatson fsetown(td->td_proc->p_pid, &ap->ap_sigio); 707155408Srwatson return (0); 708155408Srwatson} 709155408Srwatson 710155408Srwatson/* 711155408Srwatson * Close audit pipe, tear down all records, etc. 712155408Srwatson */ 713155408Srwatsonstatic int 714155408Srwatsonaudit_pipe_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 715155408Srwatson{ 716155408Srwatson struct audit_pipe *ap; 717155408Srwatson 718155408Srwatson ap = dev->si_drv1; 719155408Srwatson KASSERT(ap != NULL, ("audit_pipe_close: ap == NULL")); 720155408Srwatson KASSERT(ap->ap_open, ("audit_pipe_close: !ap_open")); 721184488Srwatson 722155408Srwatson funsetown(&ap->ap_sigio); 723184488Srwatson AUDIT_PIPE_LIST_WLOCK(); 724184488Srwatson AUDIT_PIPE_LOCK(ap); 725155408Srwatson ap->ap_open = 0; 726155408Srwatson audit_pipe_free(ap); 727155408Srwatson dev->si_drv1 = NULL; 728184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 729155408Srwatson return (0); 730155408Srwatson} 731155408Srwatson 732155408Srwatson/* 733156880Srwatson * Audit pipe ioctl() routine. Handle file descriptor and audit pipe layer 734156880Srwatson * commands. 735155408Srwatson */ 736155408Srwatsonstatic int 737155408Srwatsonaudit_pipe_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, 738155408Srwatson struct thread *td) 739155408Srwatson{ 740159269Srwatson struct auditpipe_ioctl_preselect *aip; 741155408Srwatson struct audit_pipe *ap; 742159269Srwatson au_mask_t *maskp; 743159269Srwatson int error, mode; 744159269Srwatson au_id_t auid; 745155408Srwatson 746155408Srwatson ap = dev->si_drv1; 747155408Srwatson KASSERT(ap != NULL, ("audit_pipe_ioctl: ap == NULL")); 748159269Srwatson 749159269Srwatson /* 750159269Srwatson * Audit pipe ioctls: first come standard device node ioctls, then 751159269Srwatson * manipulation of pipe settings, and finally, statistics query 752159269Srwatson * ioctls. 753159269Srwatson */ 754155408Srwatson switch (cmd) { 755155408Srwatson case FIONBIO: 756184488Srwatson AUDIT_PIPE_LOCK(ap); 757155408Srwatson if (*(int *)data) 758155408Srwatson ap->ap_flags |= AUDIT_PIPE_NBIO; 759155408Srwatson else 760155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_NBIO; 761184488Srwatson AUDIT_PIPE_UNLOCK(ap); 762155408Srwatson error = 0; 763155408Srwatson break; 764155408Srwatson 765155408Srwatson case FIONREAD: 766184488Srwatson AUDIT_PIPE_LOCK(ap); 767184536Srwatson *(int *)data = ap->ap_qbyteslen - ap->ap_qoffset; 768184488Srwatson AUDIT_PIPE_UNLOCK(ap); 769155408Srwatson error = 0; 770155408Srwatson break; 771155408Srwatson 772155408Srwatson case FIOASYNC: 773184488Srwatson AUDIT_PIPE_LOCK(ap); 774155408Srwatson if (*(int *)data) 775155408Srwatson ap->ap_flags |= AUDIT_PIPE_ASYNC; 776155408Srwatson else 777155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_ASYNC; 778184488Srwatson AUDIT_PIPE_UNLOCK(ap); 779155408Srwatson error = 0; 780155408Srwatson break; 781155408Srwatson 782155408Srwatson case FIOSETOWN: 783155408Srwatson error = fsetown(*(int *)data, &ap->ap_sigio); 784155408Srwatson break; 785155408Srwatson 786155408Srwatson case FIOGETOWN: 787155408Srwatson *(int *)data = fgetown(&ap->ap_sigio); 788155408Srwatson error = 0; 789156880Srwatson break; 790155408Srwatson 791156880Srwatson case AUDITPIPE_GET_QLEN: 792156880Srwatson *(u_int *)data = ap->ap_qlen; 793156880Srwatson error = 0; 794156880Srwatson break; 795156880Srwatson 796156880Srwatson case AUDITPIPE_GET_QLIMIT: 797156880Srwatson *(u_int *)data = ap->ap_qlimit; 798156880Srwatson error = 0; 799156880Srwatson break; 800156880Srwatson 801156880Srwatson case AUDITPIPE_SET_QLIMIT: 802156880Srwatson /* Lockless integer write. */ 803156880Srwatson if (*(u_int *)data >= AUDIT_PIPE_QLIMIT_MIN || 804156880Srwatson *(u_int *)data <= AUDIT_PIPE_QLIMIT_MAX) { 805156880Srwatson ap->ap_qlimit = *(u_int *)data; 806156880Srwatson error = 0; 807156880Srwatson } else 808156880Srwatson error = EINVAL; 809156880Srwatson break; 810156880Srwatson 811156884Srwatson case AUDITPIPE_GET_QLIMIT_MIN: 812156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MIN; 813156884Srwatson error = 0; 814156884Srwatson break; 815156884Srwatson 816156884Srwatson case AUDITPIPE_GET_QLIMIT_MAX: 817156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MAX; 818156884Srwatson error = 0; 819156884Srwatson break; 820156884Srwatson 821159269Srwatson case AUDITPIPE_GET_PRESELECT_FLAGS: 822184488Srwatson AUDIT_PIPE_LOCK(ap); 823159269Srwatson maskp = (au_mask_t *)data; 824159269Srwatson *maskp = ap->ap_preselect_flags; 825184488Srwatson AUDIT_PIPE_UNLOCK(ap); 826159269Srwatson error = 0; 827159269Srwatson break; 828159269Srwatson 829159269Srwatson case AUDITPIPE_SET_PRESELECT_FLAGS: 830184488Srwatson AUDIT_PIPE_LOCK(ap); 831159269Srwatson maskp = (au_mask_t *)data; 832159269Srwatson ap->ap_preselect_flags = *maskp; 833184488Srwatson AUDIT_PIPE_UNLOCK(ap); 834159269Srwatson error = 0; 835159269Srwatson break; 836159269Srwatson 837159269Srwatson case AUDITPIPE_GET_PRESELECT_NAFLAGS: 838184488Srwatson AUDIT_PIPE_LOCK(ap); 839159269Srwatson maskp = (au_mask_t *)data; 840159269Srwatson *maskp = ap->ap_preselect_naflags; 841184488Srwatson AUDIT_PIPE_UNLOCK(ap); 842159269Srwatson error = 0; 843159269Srwatson break; 844159269Srwatson 845159269Srwatson case AUDITPIPE_SET_PRESELECT_NAFLAGS: 846184488Srwatson AUDIT_PIPE_LOCK(ap); 847159269Srwatson maskp = (au_mask_t *)data; 848159269Srwatson ap->ap_preselect_naflags = *maskp; 849184488Srwatson AUDIT_PIPE_UNLOCK(ap); 850159269Srwatson error = 0; 851159269Srwatson break; 852159269Srwatson 853159269Srwatson case AUDITPIPE_GET_PRESELECT_AUID: 854159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 855159269Srwatson error = audit_pipe_preselect_get(ap, aip->aip_auid, 856159269Srwatson &aip->aip_mask); 857159269Srwatson break; 858159269Srwatson 859159269Srwatson case AUDITPIPE_SET_PRESELECT_AUID: 860159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 861159269Srwatson audit_pipe_preselect_set(ap, aip->aip_auid, aip->aip_mask); 862159269Srwatson error = 0; 863159269Srwatson break; 864159269Srwatson 865159269Srwatson case AUDITPIPE_DELETE_PRESELECT_AUID: 866159269Srwatson auid = *(au_id_t *)data; 867159269Srwatson error = audit_pipe_preselect_delete(ap, auid); 868159269Srwatson break; 869159269Srwatson 870159269Srwatson case AUDITPIPE_FLUSH_PRESELECT_AUID: 871159269Srwatson audit_pipe_preselect_flush(ap); 872159269Srwatson error = 0; 873159269Srwatson break; 874159269Srwatson 875159269Srwatson case AUDITPIPE_GET_PRESELECT_MODE: 876184488Srwatson AUDIT_PIPE_LOCK(ap); 877159269Srwatson *(int *)data = ap->ap_preselect_mode; 878184488Srwatson AUDIT_PIPE_UNLOCK(ap); 879159269Srwatson error = 0; 880159269Srwatson break; 881159269Srwatson 882159269Srwatson case AUDITPIPE_SET_PRESELECT_MODE: 883159269Srwatson mode = *(int *)data; 884159269Srwatson switch (mode) { 885159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 886159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 887184488Srwatson AUDIT_PIPE_LOCK(ap); 888159269Srwatson ap->ap_preselect_mode = mode; 889184488Srwatson AUDIT_PIPE_UNLOCK(ap); 890159269Srwatson error = 0; 891159269Srwatson break; 892159269Srwatson 893159269Srwatson default: 894159269Srwatson error = EINVAL; 895159269Srwatson } 896159269Srwatson break; 897159269Srwatson 898159269Srwatson case AUDITPIPE_FLUSH: 899184508Srwatson if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) 900184508Srwatson return (EINTR); 901184488Srwatson AUDIT_PIPE_LOCK(ap); 902159269Srwatson audit_pipe_flush(ap); 903184488Srwatson AUDIT_PIPE_UNLOCK(ap); 904184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 905159269Srwatson error = 0; 906159269Srwatson break; 907159269Srwatson 908161646Srwatson case AUDITPIPE_GET_MAXAUDITDATA: 909161646Srwatson *(u_int *)data = MAXAUDITDATA; 910161646Srwatson error = 0; 911161646Srwatson break; 912161646Srwatson 913156880Srwatson case AUDITPIPE_GET_INSERTS: 914156880Srwatson *(u_int *)data = ap->ap_inserts; 915156880Srwatson error = 0; 916156880Srwatson break; 917156880Srwatson 918156880Srwatson case AUDITPIPE_GET_READS: 919156880Srwatson *(u_int *)data = ap->ap_reads; 920156880Srwatson error = 0; 921156880Srwatson break; 922156880Srwatson 923156880Srwatson case AUDITPIPE_GET_DROPS: 924156880Srwatson *(u_int *)data = ap->ap_drops; 925156880Srwatson error = 0; 926156880Srwatson break; 927156880Srwatson 928156880Srwatson case AUDITPIPE_GET_TRUNCATES: 929184510Srwatson *(u_int *)data = 0; 930156880Srwatson error = 0; 931156880Srwatson break; 932156880Srwatson 933155408Srwatson default: 934155408Srwatson error = ENOTTY; 935155408Srwatson } 936155408Srwatson return (error); 937155408Srwatson} 938155408Srwatson 939155408Srwatson/* 940184534Srwatson * Audit pipe read. Read one or more partial or complete records to user 941184534Srwatson * memory. 942155408Srwatson */ 943155408Srwatsonstatic int 944155408Srwatsonaudit_pipe_read(struct cdev *dev, struct uio *uio, int flag) 945155408Srwatson{ 946155408Srwatson struct audit_pipe_entry *ape; 947155408Srwatson struct audit_pipe *ap; 948184508Srwatson u_int toread; 949155408Srwatson int error; 950155408Srwatson 951155408Srwatson ap = dev->si_drv1; 952155408Srwatson KASSERT(ap != NULL, ("audit_pipe_read: ap == NULL")); 953184488Srwatson 954184508Srwatson /* 955184508Srwatson * We hold an sx(9) lock over read and flush because we rely on the 956184508Srwatson * stability of a record in the queue during uiomove(9). 957184508Srwatson */ 958184508Srwatson if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) 959184508Srwatson return (EINTR); 960184488Srwatson AUDIT_PIPE_LOCK(ap); 961184508Srwatson while (TAILQ_EMPTY(&ap->ap_queue)) { 962184508Srwatson if (ap->ap_flags & AUDIT_PIPE_NBIO) { 963184508Srwatson AUDIT_PIPE_UNLOCK(ap); 964184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 965184508Srwatson return (EAGAIN); 966155408Srwatson } 967184508Srwatson error = cv_wait_sig(&ap->ap_cv, AUDIT_PIPE_MTX(ap)); 968184508Srwatson if (error) { 969184508Srwatson AUDIT_PIPE_UNLOCK(ap); 970184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 971184508Srwatson return (error); 972184508Srwatson } 973184508Srwatson } 974184508Srwatson 975184508Srwatson /* 976184508Srwatson * Copy as many remaining bytes from the current record to userspace 977184534Srwatson * as we can. Keep processing records until we run out of records in 978184534Srwatson * the queue, or until the user buffer runs out of space. 979184508Srwatson * 980184508Srwatson * Note: we rely on the SX lock to maintain ape's stability here. 981184508Srwatson */ 982173083Scsjp ap->ap_reads++; 983184534Srwatson while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL && 984184534Srwatson uio->uio_resid > 0) { 985184534Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 986184534Srwatson 987184536Srwatson KASSERT(ape->ape_record_len > ap->ap_qoffset, 988184536Srwatson ("audit_pipe_read: record_len > qoffset (1)")); 989184536Srwatson toread = MIN(ape->ape_record_len - ap->ap_qoffset, 990184534Srwatson uio->uio_resid); 991184534Srwatson AUDIT_PIPE_UNLOCK(ap); 992184536Srwatson error = uiomove((char *)ape->ape_record + ap->ap_qoffset, 993184536Srwatson toread, uio); 994184534Srwatson if (error) { 995184534Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 996184534Srwatson return (error); 997184534Srwatson } 998184534Srwatson 999184534Srwatson /* 1000184534Srwatson * If the copy succeeded, update book-keeping, and if no 1001184534Srwatson * bytes remain in the current record, free it. 1002184534Srwatson */ 1003184534Srwatson AUDIT_PIPE_LOCK(ap); 1004184534Srwatson KASSERT(TAILQ_FIRST(&ap->ap_queue) == ape, 1005184534Srwatson ("audit_pipe_read: queue out of sync after uiomove")); 1006184536Srwatson ap->ap_qoffset += toread; 1007184536Srwatson KASSERT(ape->ape_record_len >= ap->ap_qoffset, 1008184536Srwatson ("audit_pipe_read: record_len >= qoffset (2)")); 1009184536Srwatson if (ap->ap_qoffset == ape->ape_record_len) { 1010184534Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 1011184536Srwatson ap->ap_qbyteslen -= ape->ape_record_len; 1012184534Srwatson audit_pipe_entry_free(ape); 1013184534Srwatson ap->ap_qlen--; 1014184536Srwatson ap->ap_qoffset = 0; 1015184534Srwatson } 1016184508Srwatson } 1017184508Srwatson AUDIT_PIPE_UNLOCK(ap); 1018184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 1019184534Srwatson return (0); 1020155408Srwatson} 1021155408Srwatson 1022155408Srwatson/* 1023155408Srwatson * Audit pipe poll. 1024155408Srwatson */ 1025155408Srwatsonstatic int 1026155408Srwatsonaudit_pipe_poll(struct cdev *dev, int events, struct thread *td) 1027155408Srwatson{ 1028155408Srwatson struct audit_pipe *ap; 1029155408Srwatson int revents; 1030155408Srwatson 1031155408Srwatson revents = 0; 1032155408Srwatson ap = dev->si_drv1; 1033155408Srwatson KASSERT(ap != NULL, ("audit_pipe_poll: ap == NULL")); 1034184488Srwatson 1035155408Srwatson if (events & (POLLIN | POLLRDNORM)) { 1036184488Srwatson AUDIT_PIPE_LOCK(ap); 1037155408Srwatson if (TAILQ_FIRST(&ap->ap_queue) != NULL) 1038155408Srwatson revents |= events & (POLLIN | POLLRDNORM); 1039155408Srwatson else 1040155408Srwatson selrecord(td, &ap->ap_selinfo); 1041184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1042155408Srwatson } 1043155408Srwatson return (revents); 1044155408Srwatson} 1045155408Srwatson 1046155408Srwatson/* 1047161582Srwatson * Audit pipe kqfilter. 1048161582Srwatson */ 1049161582Srwatsonstatic int 1050161582Srwatsonaudit_pipe_kqfilter(struct cdev *dev, struct knote *kn) 1051161582Srwatson{ 1052161582Srwatson struct audit_pipe *ap; 1053161582Srwatson 1054161582Srwatson ap = dev->si_drv1; 1055161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqfilter: ap == NULL")); 1056161582Srwatson 1057161582Srwatson if (kn->kn_filter != EVFILT_READ) 1058161582Srwatson return (EINVAL); 1059161582Srwatson 1060161582Srwatson kn->kn_fop = &audit_pipe_read_filterops; 1061161582Srwatson kn->kn_hook = ap; 1062161582Srwatson 1063184488Srwatson AUDIT_PIPE_LOCK(ap); 1064161582Srwatson knlist_add(&ap->ap_selinfo.si_note, kn, 1); 1065184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1066161582Srwatson return (0); 1067161582Srwatson} 1068161582Srwatson 1069161582Srwatson/* 1070161582Srwatson * Return true if there are records available for reading on the pipe. 1071161582Srwatson */ 1072161582Srwatsonstatic int 1073161582Srwatsonaudit_pipe_kqread(struct knote *kn, long hint) 1074161582Srwatson{ 1075161582Srwatson struct audit_pipe *ap; 1076161582Srwatson 1077161582Srwatson ap = (struct audit_pipe *)kn->kn_hook; 1078161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqread: ap == NULL")); 1079184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 1080184488Srwatson 1081161582Srwatson if (ap->ap_qlen != 0) { 1082184536Srwatson kn->kn_data = ap->ap_qbyteslen - ap->ap_qoffset; 1083161582Srwatson return (1); 1084161582Srwatson } else { 1085161582Srwatson kn->kn_data = 0; 1086161582Srwatson return (0); 1087161582Srwatson } 1088161582Srwatson} 1089161582Srwatson 1090161582Srwatson/* 1091161582Srwatson * Detach kqueue state from audit pipe. 1092161582Srwatson */ 1093161582Srwatsonstatic void 1094161582Srwatsonaudit_pipe_kqdetach(struct knote *kn) 1095161582Srwatson{ 1096161582Srwatson struct audit_pipe *ap; 1097161582Srwatson 1098161582Srwatson ap = (struct audit_pipe *)kn->kn_hook; 1099161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqdetach: ap == NULL")); 1100161582Srwatson 1101184488Srwatson AUDIT_PIPE_LOCK(ap); 1102161582Srwatson knlist_remove(&ap->ap_selinfo.si_note, kn, 1); 1103184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1104161582Srwatson} 1105161582Srwatson 1106161582Srwatson/* 1107155408Srwatson * Initialize the audit pipe system. 1108155408Srwatson */ 1109155408Srwatsonstatic void 1110155408Srwatsonaudit_pipe_init(void *unused) 1111155408Srwatson{ 1112155408Srwatson 1113155408Srwatson TAILQ_INIT(&audit_pipe_list); 1114184488Srwatson AUDIT_PIPE_LIST_LOCK_INIT(); 1115155408Srwatson 1116155408Srwatson clone_setup(&audit_pipe_clones); 1117155408Srwatson audit_pipe_eh_tag = EVENTHANDLER_REGISTER(dev_clone, 1118155408Srwatson audit_pipe_clone, 0, 1000); 1119155408Srwatson if (audit_pipe_eh_tag == NULL) 1120155408Srwatson panic("audit_pipe_init: EVENTHANDLER_REGISTER"); 1121155408Srwatson} 1122155408Srwatson 1123155408SrwatsonSYSINIT(audit_pipe_init, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, audit_pipe_init, 1124155408Srwatson NULL); 1125