audit_pipe.c revision 184510
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 184510 2008-10-31 15:11:01Z 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> 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 60155408Srwatson * audit data. This is a "tee" of the data going to the file. It provides 61155408Srwatson * unreliable but timely access to audit events. Consumers of this interface 62159269Srwatson * should be very careful to avoid introducing event cycles. Consumers may 63159269Srwatson * express interest via a set of preselection ioctls. 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) 79156880Srwatson#define AUDIT_PIPE_QLIMIT_MIN (0) 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; 88184508Srwatson u_int ape_record_offset; 89155408Srwatson TAILQ_ENTRY(audit_pipe_entry) ape_queue; 90155408Srwatson}; 91155408Srwatson 92155408Srwatson/* 93159269Srwatson * Audit pipes allow processes to express "interest" in the set of records 94159269Srwatson * that are delivered via the pipe. They do this in a similar manner to the 95159269Srwatson * mechanism for audit trail configuration, by expressing two global masks, 96159269Srwatson * and optionally expressing per-auid masks. The following data structure is 97159269Srwatson * the per-auid mask description. The global state is stored in the audit 98159269Srwatson * pipe data structure. 99159269Srwatson * 100159269Srwatson * We may want to consider a more space/time-efficient data structure once 101159269Srwatson * usage patterns for per-auid specifications are clear. 102159269Srwatson */ 103159269Srwatsonstruct audit_pipe_preselect { 104159269Srwatson au_id_t app_auid; 105159269Srwatson au_mask_t app_mask; 106159269Srwatson TAILQ_ENTRY(audit_pipe_preselect) app_list; 107159269Srwatson}; 108159269Srwatson 109159269Srwatson/* 110155408Srwatson * Description of an individual audit_pipe. Consists largely of a bounded 111155408Srwatson * length queue. 112155408Srwatson */ 113155408Srwatson#define AUDIT_PIPE_ASYNC 0x00000001 114155408Srwatson#define AUDIT_PIPE_NBIO 0x00000002 115155408Srwatsonstruct audit_pipe { 116155408Srwatson int ap_open; /* Device open? */ 117155408Srwatson u_int ap_flags; 118155408Srwatson 119155408Srwatson struct selinfo ap_selinfo; 120155408Srwatson struct sigio *ap_sigio; 121155408Srwatson 122184488Srwatson /* 123184488Srwatson * Per-pipe mutex protecting most fields in this data structure. 124184488Srwatson */ 125184508Srwatson struct mtx ap_mtx; 126184488Srwatson 127184488Srwatson /* 128184508Srwatson * Per-pipe sleep lock serializing user-generated reads and flushes. 129184508Srwatson * uiomove() is called to copy out the current head record's data 130184508Srwatson * while the record remains in the queue, so we prevent other threads 131184508Srwatson * from removing it using this lock. 132184508Srwatson */ 133184508Srwatson struct sx ap_sx; 134184508Srwatson 135184508Srwatson /* 136184488Srwatson * Condition variable to signal when data has been delivered to a 137184488Srwatson * pipe. 138184488Srwatson */ 139184488Srwatson struct cv ap_cv; 140184488Srwatson 141155408Srwatson u_int ap_qlen; 142155408Srwatson u_int ap_qlimit; 143155408Srwatson 144155408Srwatson u_int64_t ap_inserts; /* Records added. */ 145155408Srwatson u_int64_t ap_reads; /* Records read. */ 146155408Srwatson u_int64_t ap_drops; /* Records dropped. */ 147155408Srwatson 148159269Srwatson /* 149159269Srwatson * Fields relating to pipe interest: global masks for unmatched 150159269Srwatson * processes (attributable, non-attributable), and a list of specific 151159269Srwatson * interest specifications by auid. 152159269Srwatson */ 153159269Srwatson int ap_preselect_mode; 154159269Srwatson au_mask_t ap_preselect_flags; 155159269Srwatson au_mask_t ap_preselect_naflags; 156159269Srwatson TAILQ_HEAD(, audit_pipe_preselect) ap_preselect_list; 157159269Srwatson 158159269Srwatson /* 159184508Srwatson * Current pending record list. Protected by a combination of ap_mtx 160184508Srwatson * and ap_sx. Note particularly that *both* locks are required to 161184508Srwatson * remove a record from the head of the queue, as an in-progress read * may sleep while copying and therefore cannot hold ap_mtx. 162159269Srwatson */ 163155408Srwatson TAILQ_HEAD(, audit_pipe_entry) ap_queue; 164155408Srwatson 165159269Srwatson /* 166159269Srwatson * Global pipe list. 167159269Srwatson */ 168155408Srwatson TAILQ_ENTRY(audit_pipe) ap_list; 169155408Srwatson}; 170155408Srwatson 171184508Srwatson#define AUDIT_PIPE_LOCK(ap) mtx_lock(&(ap)->ap_mtx) 172184508Srwatson#define AUDIT_PIPE_LOCK_ASSERT(ap) mtx_assert(&(ap)->ap_mtx, MA_OWNED) 173184508Srwatson#define AUDIT_PIPE_LOCK_DESTROY(ap) mtx_destroy(&(ap)->ap_mtx) 174184508Srwatson#define AUDIT_PIPE_LOCK_INIT(ap) mtx_init(&(ap)->ap_mtx, \ 175184508Srwatson "audit_pipe_mtx", NULL, MTX_DEF) 176184508Srwatson#define AUDIT_PIPE_UNLOCK(ap) mtx_unlock(&(ap)->ap_mtx) 177184508Srwatson#define AUDIT_PIPE_MTX(ap) (&(ap)->ap_mtx) 178184488Srwatson 179184508Srwatson#define AUDIT_PIPE_SX_LOCK_DESTROY(ap) sx_destroy(&(ap)->ap_sx) 180184508Srwatson#define AUDIT_PIPE_SX_LOCK_INIT(ap) sx_init(&(ap)->ap_sx, "audit_pipe_sx") 181184508Srwatson#define AUDIT_PIPE_SX_XLOCK_ASSERT(ap) sx_assert(&(ap)->ap_sx, SA_XLOCKED) 182184508Srwatson#define AUDIT_PIPE_SX_XLOCK_SIG(ap) sx_xlock_sig(&(ap)->ap_sx) 183184508Srwatson#define AUDIT_PIPE_SX_XUNLOCK(ap) sx_xunlock(&(ap)->ap_sx) 184184508Srwatson 185155408Srwatson/* 186184488Srwatson * Global list of audit pipes, rwlock to protect it. Individual record 187184488Srwatson * queues on pipes are protected by per-pipe locks; these locks synchronize 188184488Srwatson * between threads walking the list to deliver to individual pipes and add/ 189184488Srwatson * remove of pipes, and are mostly acquired for read. 190155408Srwatson */ 191155408Srwatsonstatic TAILQ_HEAD(, audit_pipe) audit_pipe_list; 192184488Srwatsonstatic struct rwlock audit_pipe_lock; 193155408Srwatson 194184488Srwatson#define AUDIT_PIPE_LIST_LOCK_INIT() rw_init(&audit_pipe_lock, \ 195184488Srwatson "audit_pipe_list_lock") 196184488Srwatson#define AUDIT_PIPE_LIST_RLOCK() rw_rlock(&audit_pipe_lock) 197184488Srwatson#define AUDIT_PIPE_LIST_RUNLOCK() rw_runlock(&audit_pipe_lock) 198184488Srwatson#define AUDIT_PIPE_LIST_WLOCK() rw_wlock(&audit_pipe_lock) 199184488Srwatson#define AUDIT_PIPE_LIST_WLOCK_ASSERT() rw_assert(&audit_pipe_lock, \ 200184488Srwatson RA_WLOCKED) 201184488Srwatson#define AUDIT_PIPE_LIST_WUNLOCK() rw_wunlock(&audit_pipe_lock) 202155408Srwatson 203155408Srwatson/* 204155408Srwatson * Cloning related variables and constants. 205155408Srwatson */ 206155408Srwatson#define AUDIT_PIPE_NAME "auditpipe" 207155408Srwatsonstatic eventhandler_tag audit_pipe_eh_tag; 208155408Srwatsonstatic struct clonedevs *audit_pipe_clones; 209155408Srwatson 210155408Srwatson/* 211155408Srwatson * Special device methods and definition. 212155408Srwatson */ 213155408Srwatsonstatic d_open_t audit_pipe_open; 214155408Srwatsonstatic d_close_t audit_pipe_close; 215155408Srwatsonstatic d_read_t audit_pipe_read; 216155408Srwatsonstatic d_ioctl_t audit_pipe_ioctl; 217155408Srwatsonstatic d_poll_t audit_pipe_poll; 218161582Srwatsonstatic d_kqfilter_t audit_pipe_kqfilter; 219155408Srwatson 220155408Srwatsonstatic struct cdevsw audit_pipe_cdevsw = { 221155408Srwatson .d_version = D_VERSION, 222179726Sed .d_flags = D_PSEUDO | D_NEEDGIANT | D_NEEDMINOR, 223155408Srwatson .d_open = audit_pipe_open, 224155408Srwatson .d_close = audit_pipe_close, 225155408Srwatson .d_read = audit_pipe_read, 226155408Srwatson .d_ioctl = audit_pipe_ioctl, 227155408Srwatson .d_poll = audit_pipe_poll, 228161582Srwatson .d_kqfilter = audit_pipe_kqfilter, 229155408Srwatson .d_name = AUDIT_PIPE_NAME, 230155408Srwatson}; 231155408Srwatson 232161582Srwatsonstatic int audit_pipe_kqread(struct knote *note, long hint); 233161582Srwatsonstatic void audit_pipe_kqdetach(struct knote *note); 234161582Srwatson 235161582Srwatsonstatic struct filterops audit_pipe_read_filterops = { 236161582Srwatson .f_isfd = 1, 237161582Srwatson .f_attach = NULL, 238161582Srwatson .f_detach = audit_pipe_kqdetach, 239161582Srwatson .f_event = audit_pipe_kqread, 240161582Srwatson}; 241161582Srwatson 242155408Srwatson/* 243155408Srwatson * Some global statistics on audit pipes. 244155408Srwatson */ 245155408Srwatsonstatic int audit_pipe_count; /* Current number of pipes. */ 246155408Srwatsonstatic u_int64_t audit_pipe_ever; /* Pipes ever allocated. */ 247155408Srwatsonstatic u_int64_t audit_pipe_records; /* Records seen. */ 248155408Srwatsonstatic u_int64_t audit_pipe_drops; /* Global record drop count. */ 249155408Srwatson 250155408Srwatson/* 251155408Srwatson * Free an audit pipe entry. 252155408Srwatson */ 253155408Srwatsonstatic void 254155408Srwatsonaudit_pipe_entry_free(struct audit_pipe_entry *ape) 255155408Srwatson{ 256155408Srwatson 257155408Srwatson free(ape->ape_record, M_AUDIT_PIPE_ENTRY); 258155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 259155408Srwatson} 260155408Srwatson 261155408Srwatson/* 262159269Srwatson * Find an audit pipe preselection specification for an auid, if any. 263159269Srwatson */ 264159269Srwatsonstatic struct audit_pipe_preselect * 265159269Srwatsonaudit_pipe_preselect_find(struct audit_pipe *ap, au_id_t auid) 266159269Srwatson{ 267159269Srwatson struct audit_pipe_preselect *app; 268159269Srwatson 269184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 270159269Srwatson 271159269Srwatson TAILQ_FOREACH(app, &ap->ap_preselect_list, app_list) { 272159269Srwatson if (app->app_auid == auid) 273159269Srwatson return (app); 274159269Srwatson } 275159269Srwatson return (NULL); 276159269Srwatson} 277159269Srwatson 278159269Srwatson/* 279159269Srwatson * Query the per-pipe mask for a specific auid. 280159269Srwatson */ 281159269Srwatsonstatic int 282159269Srwatsonaudit_pipe_preselect_get(struct audit_pipe *ap, au_id_t auid, 283159269Srwatson au_mask_t *maskp) 284159269Srwatson{ 285159269Srwatson struct audit_pipe_preselect *app; 286159269Srwatson int error; 287159269Srwatson 288184488Srwatson AUDIT_PIPE_LOCK(ap); 289159269Srwatson app = audit_pipe_preselect_find(ap, auid); 290159269Srwatson if (app != NULL) { 291159269Srwatson *maskp = app->app_mask; 292159269Srwatson error = 0; 293159269Srwatson } else 294159269Srwatson error = ENOENT; 295184488Srwatson AUDIT_PIPE_UNLOCK(ap); 296159269Srwatson return (error); 297159269Srwatson} 298159269Srwatson 299159269Srwatson/* 300159269Srwatson * Set the per-pipe mask for a specific auid. Add a new entry if needed; 301159269Srwatson * otherwise, update the current entry. 302159269Srwatson */ 303159269Srwatsonstatic void 304159269Srwatsonaudit_pipe_preselect_set(struct audit_pipe *ap, au_id_t auid, au_mask_t mask) 305159269Srwatson{ 306159269Srwatson struct audit_pipe_preselect *app, *app_new; 307159269Srwatson 308159269Srwatson /* 309159269Srwatson * Pessimistically assume that the auid doesn't already have a mask 310159269Srwatson * set, and allocate. We will free it if it is unneeded. 311159269Srwatson */ 312159269Srwatson app_new = malloc(sizeof(*app_new), M_AUDIT_PIPE_PRESELECT, M_WAITOK); 313184488Srwatson AUDIT_PIPE_LOCK(ap); 314159269Srwatson app = audit_pipe_preselect_find(ap, auid); 315159269Srwatson if (app == NULL) { 316159269Srwatson app = app_new; 317159269Srwatson app_new = NULL; 318159269Srwatson app->app_auid = auid; 319159269Srwatson TAILQ_INSERT_TAIL(&ap->ap_preselect_list, app, app_list); 320159269Srwatson } 321159269Srwatson app->app_mask = mask; 322184488Srwatson AUDIT_PIPE_UNLOCK(ap); 323159269Srwatson if (app_new != NULL) 324159269Srwatson free(app_new, M_AUDIT_PIPE_PRESELECT); 325159269Srwatson} 326159269Srwatson 327159269Srwatson/* 328159269Srwatson * Delete a per-auid mask on an audit pipe. 329159269Srwatson */ 330159269Srwatsonstatic int 331159269Srwatsonaudit_pipe_preselect_delete(struct audit_pipe *ap, au_id_t auid) 332159269Srwatson{ 333159269Srwatson struct audit_pipe_preselect *app; 334159269Srwatson int error; 335159269Srwatson 336184488Srwatson AUDIT_PIPE_LOCK(ap); 337159269Srwatson app = audit_pipe_preselect_find(ap, auid); 338159269Srwatson if (app != NULL) { 339159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 340159269Srwatson error = 0; 341159269Srwatson } else 342159269Srwatson error = ENOENT; 343184488Srwatson AUDIT_PIPE_UNLOCK(ap); 344159269Srwatson if (app != NULL) 345159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 346159269Srwatson return (error); 347159269Srwatson} 348159269Srwatson 349159269Srwatson/* 350159269Srwatson * Delete all per-auid masks on an audit pipe. 351159269Srwatson */ 352159269Srwatsonstatic void 353159269Srwatsonaudit_pipe_preselect_flush_locked(struct audit_pipe *ap) 354159269Srwatson{ 355159269Srwatson struct audit_pipe_preselect *app; 356159269Srwatson 357184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 358159269Srwatson 359159269Srwatson while ((app = TAILQ_FIRST(&ap->ap_preselect_list)) != NULL) { 360159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 361159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 362159269Srwatson } 363159269Srwatson} 364159269Srwatson 365159269Srwatsonstatic void 366159269Srwatsonaudit_pipe_preselect_flush(struct audit_pipe *ap) 367159269Srwatson{ 368159269Srwatson 369184488Srwatson AUDIT_PIPE_LOCK(ap); 370159269Srwatson audit_pipe_preselect_flush_locked(ap); 371184488Srwatson AUDIT_PIPE_UNLOCK(ap); 372159269Srwatson} 373159269Srwatson 374170196Srwatson/*- 375159269Srwatson * Determine whether a specific audit pipe matches a record with these 376159269Srwatson * properties. Algorithm is as follows: 377159269Srwatson * 378159269Srwatson * - If the pipe is configured to track the default trail configuration, then 379159269Srwatson * use the results of global preselection matching. 380159269Srwatson * - If not, search for a specifically configured auid entry matching the 381159269Srwatson * event. If an entry is found, use that. 382159269Srwatson * - Otherwise, use the default flags or naflags configured for the pipe. 383159269Srwatson */ 384159269Srwatsonstatic int 385159269Srwatsonaudit_pipe_preselect_check(struct audit_pipe *ap, au_id_t auid, 386159269Srwatson au_event_t event, au_class_t class, int sorf, int trail_preselect) 387159269Srwatson{ 388159269Srwatson struct audit_pipe_preselect *app; 389159269Srwatson 390184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 391159269Srwatson 392159269Srwatson switch (ap->ap_preselect_mode) { 393159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 394159269Srwatson return (trail_preselect); 395159269Srwatson 396159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 397159269Srwatson app = audit_pipe_preselect_find(ap, auid); 398159269Srwatson if (app == NULL) { 399159269Srwatson if (auid == AU_DEFAUDITID) 400159269Srwatson return (au_preselect(event, class, 401159269Srwatson &ap->ap_preselect_naflags, sorf)); 402159269Srwatson else 403159269Srwatson return (au_preselect(event, class, 404159269Srwatson &ap->ap_preselect_flags, sorf)); 405159269Srwatson } else 406159269Srwatson return (au_preselect(event, class, &app->app_mask, 407159269Srwatson sorf)); 408159269Srwatson 409159269Srwatson default: 410159269Srwatson panic("audit_pipe_preselect_check: mode %d", 411159269Srwatson ap->ap_preselect_mode); 412159269Srwatson } 413159269Srwatson 414159269Srwatson return (0); 415159269Srwatson} 416159269Srwatson 417159269Srwatson/* 418159269Srwatson * Determine whether there exists a pipe interested in a record with specific 419159269Srwatson * properties. 420159269Srwatson */ 421159269Srwatsonint 422159269Srwatsonaudit_pipe_preselect(au_id_t auid, au_event_t event, au_class_t class, 423159269Srwatson int sorf, int trail_preselect) 424159269Srwatson{ 425159269Srwatson struct audit_pipe *ap; 426159269Srwatson 427184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 428159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 429184488Srwatson AUDIT_PIPE_LOCK(ap); 430159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 431159269Srwatson trail_preselect)) { 432184488Srwatson AUDIT_PIPE_UNLOCK(ap); 433184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 434159269Srwatson return (1); 435159269Srwatson } 436184488Srwatson AUDIT_PIPE_UNLOCK(ap); 437159269Srwatson } 438184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 439159269Srwatson return (0); 440159269Srwatson} 441159269Srwatson 442159269Srwatson/* 443159269Srwatson * Append individual record to a queue -- allocate queue-local buffer, and 444184489Srwatson * add to the queue. If the queue is full or we can't allocate memory, drop 445184489Srwatson * the newest record. 446155408Srwatson */ 447155408Srwatsonstatic void 448155408Srwatsonaudit_pipe_append(struct audit_pipe *ap, void *record, u_int record_len) 449155408Srwatson{ 450184489Srwatson struct audit_pipe_entry *ape; 451155408Srwatson 452184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 453155408Srwatson 454184489Srwatson if (ap->ap_qlen >= ap->ap_qlimit) { 455184489Srwatson ap->ap_drops++; 456184489Srwatson audit_pipe_drops++; 457184489Srwatson return; 458184489Srwatson } 459184489Srwatson 460155408Srwatson ape = malloc(sizeof(*ape), M_AUDIT_PIPE_ENTRY, M_NOWAIT | M_ZERO); 461155408Srwatson if (ape == NULL) { 462155408Srwatson ap->ap_drops++; 463156292Srwatson audit_pipe_drops++; 464155408Srwatson return; 465155408Srwatson } 466155408Srwatson 467155408Srwatson ape->ape_record = malloc(record_len, M_AUDIT_PIPE_ENTRY, M_NOWAIT); 468155408Srwatson if (ape->ape_record == NULL) { 469155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 470155408Srwatson ap->ap_drops++; 471155408Srwatson audit_pipe_drops++; 472155408Srwatson return; 473155408Srwatson } 474155408Srwatson 475155408Srwatson bcopy(record, ape->ape_record, record_len); 476155408Srwatson ape->ape_record_len = record_len; 477184508Srwatson ape->ape_record_offset = 0; 478155408Srwatson 479155408Srwatson TAILQ_INSERT_TAIL(&ap->ap_queue, ape, ape_queue); 480155408Srwatson ap->ap_inserts++; 481155408Srwatson ap->ap_qlen++; 482155408Srwatson selwakeuppri(&ap->ap_selinfo, PSOCK); 483161582Srwatson KNOTE_LOCKED(&ap->ap_selinfo.si_note, 0); 484155408Srwatson if (ap->ap_flags & AUDIT_PIPE_ASYNC) 485155408Srwatson pgsigio(&ap->ap_sigio, SIGIO, 0); 486184488Srwatson cv_broadcast(&ap->ap_cv); 487155408Srwatson} 488155408Srwatson 489155408Srwatson/* 490155408Srwatson * audit_pipe_submit(): audit_worker submits audit records via this 491155408Srwatson * interface, which arranges for them to be delivered to pipe queues. 492155408Srwatson */ 493155408Srwatsonvoid 494159269Srwatsonaudit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class, int sorf, 495159269Srwatson int trail_select, void *record, u_int record_len) 496155408Srwatson{ 497155408Srwatson struct audit_pipe *ap; 498155408Srwatson 499155408Srwatson /* 500184488Srwatson * Lockless read to avoid lock overhead if pipes are not in use. 501155408Srwatson */ 502155408Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 503155408Srwatson return; 504155408Srwatson 505184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 506159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 507184488Srwatson AUDIT_PIPE_LOCK(ap); 508159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 509159269Srwatson trail_select)) 510159269Srwatson audit_pipe_append(ap, record, record_len); 511184488Srwatson AUDIT_PIPE_UNLOCK(ap); 512159269Srwatson } 513184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 514184488Srwatson 515184488Srwatson /* Unlocked increment. */ 516159269Srwatson audit_pipe_records++; 517159269Srwatson} 518159269Srwatson 519159269Srwatson/* 520159269Srwatson * audit_pipe_submit_user(): the same as audit_pipe_submit(), except that 521159269Srwatson * since we don't currently have selection information available, it is 522159269Srwatson * delivered to the pipe unconditionally. 523159269Srwatson * 524159269Srwatson * XXXRW: This is a bug. The BSM check routine for submitting a user record 525159269Srwatson * should parse that information and return it. 526159269Srwatson */ 527159269Srwatsonvoid 528159269Srwatsonaudit_pipe_submit_user(void *record, u_int record_len) 529159269Srwatson{ 530159269Srwatson struct audit_pipe *ap; 531159269Srwatson 532159269Srwatson /* 533184488Srwatson * Lockless read to avoid lock overhead if pipes are not in use. 534159269Srwatson */ 535159269Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 536159269Srwatson return; 537159269Srwatson 538184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 539184488Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 540184488Srwatson AUDIT_PIPE_LOCK(ap); 541155408Srwatson audit_pipe_append(ap, record, record_len); 542184488Srwatson AUDIT_PIPE_UNLOCK(ap); 543184488Srwatson } 544184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 545184488Srwatson 546184488Srwatson /* Unlocked increment. */ 547155408Srwatson audit_pipe_records++; 548155408Srwatson} 549155408Srwatson 550155408Srwatson/* 551155408Srwatson * Allocate a new audit pipe. Connects the pipe, on success, to the global 552155408Srwatson * list and updates statistics. 553155408Srwatson */ 554155408Srwatsonstatic struct audit_pipe * 555155408Srwatsonaudit_pipe_alloc(void) 556155408Srwatson{ 557155408Srwatson struct audit_pipe *ap; 558155408Srwatson 559184488Srwatson AUDIT_PIPE_LIST_WLOCK_ASSERT(); 560155408Srwatson 561155408Srwatson ap = malloc(sizeof(*ap), M_AUDIT_PIPE, M_NOWAIT | M_ZERO); 562155408Srwatson if (ap == NULL) 563155408Srwatson return (NULL); 564155408Srwatson ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT; 565155408Srwatson TAILQ_INIT(&ap->ap_queue); 566184488Srwatson knlist_init(&ap->ap_selinfo.si_note, AUDIT_PIPE_MTX(ap), NULL, NULL, 567161582Srwatson NULL); 568184488Srwatson AUDIT_PIPE_LOCK_INIT(ap); 569184508Srwatson AUDIT_PIPE_SX_LOCK_INIT(ap); 570184488Srwatson cv_init(&ap->ap_cv, "audit_pipe"); 571159269Srwatson 572159269Srwatson /* 573159269Srwatson * Default flags, naflags, and auid-specific preselection settings to 574159269Srwatson * 0. Initialize the mode to the global trail so that if praudit(1) 575159269Srwatson * is run on /dev/auditpipe, it sees events associated with the 576159269Srwatson * default trail. Pipe-aware application can clear the flag, set 577159269Srwatson * custom masks, and flush the pipe as needed. 578159269Srwatson */ 579159269Srwatson bzero(&ap->ap_preselect_flags, sizeof(ap->ap_preselect_flags)); 580159269Srwatson bzero(&ap->ap_preselect_naflags, sizeof(ap->ap_preselect_naflags)); 581159269Srwatson TAILQ_INIT(&ap->ap_preselect_list); 582159269Srwatson ap->ap_preselect_mode = AUDITPIPE_PRESELECT_MODE_TRAIL; 583159269Srwatson 584161582Srwatson /* 585161582Srwatson * Add to global list and update global statistics. 586161582Srwatson */ 587155408Srwatson TAILQ_INSERT_HEAD(&audit_pipe_list, ap, ap_list); 588155408Srwatson audit_pipe_count++; 589155408Srwatson audit_pipe_ever++; 590159269Srwatson 591155408Srwatson return (ap); 592155408Srwatson} 593155408Srwatson 594155408Srwatson/* 595159269Srwatson * Flush all records currently present in an audit pipe; assume mutex is held. 596155408Srwatson */ 597155408Srwatsonstatic void 598159269Srwatsonaudit_pipe_flush(struct audit_pipe *ap) 599155408Srwatson{ 600155408Srwatson struct audit_pipe_entry *ape; 601155408Srwatson 602184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 603155408Srwatson 604155408Srwatson while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL) { 605155408Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 606155408Srwatson audit_pipe_entry_free(ape); 607155408Srwatson ap->ap_qlen--; 608155408Srwatson } 609155408Srwatson KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qlen")); 610159269Srwatson} 611159269Srwatson 612159269Srwatson/* 613159269Srwatson * Free an audit pipe; this means freeing all preselection state and all 614184488Srwatson * records in the pipe. Assumes global write lock and pipe mutex are held to 615184488Srwatson * prevent any new records from being inserted during the free, and that the 616184488Srwatson * audit pipe is still on the global list. 617159269Srwatson */ 618159269Srwatsonstatic void 619159269Srwatsonaudit_pipe_free(struct audit_pipe *ap) 620159269Srwatson{ 621159269Srwatson 622184488Srwatson AUDIT_PIPE_LIST_WLOCK_ASSERT(); 623184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 624159269Srwatson 625159269Srwatson audit_pipe_preselect_flush_locked(ap); 626159269Srwatson audit_pipe_flush(ap); 627184488Srwatson cv_destroy(&ap->ap_cv); 628184508Srwatson AUDIT_PIPE_SX_LOCK_DESTROY(ap); 629184488Srwatson AUDIT_PIPE_LOCK_DESTROY(ap); 630161582Srwatson knlist_destroy(&ap->ap_selinfo.si_note); 631159269Srwatson TAILQ_REMOVE(&audit_pipe_list, ap, ap_list); 632155408Srwatson free(ap, M_AUDIT_PIPE); 633155408Srwatson audit_pipe_count--; 634155408Srwatson} 635155408Srwatson 636155408Srwatson/* 637155408Srwatson * Audit pipe clone routine -- provide specific requested audit pipe, or a 638155408Srwatson * fresh one if a specific one is not requested. 639155408Srwatson */ 640155408Srwatsonstatic void 641155408Srwatsonaudit_pipe_clone(void *arg, struct ucred *cred, char *name, int namelen, 642155408Srwatson struct cdev **dev) 643155408Srwatson{ 644155408Srwatson int i, u; 645155408Srwatson 646155408Srwatson if (*dev != NULL) 647155408Srwatson return; 648155408Srwatson 649155408Srwatson if (strcmp(name, AUDIT_PIPE_NAME) == 0) 650155408Srwatson u = -1; 651155408Srwatson else if (dev_stdclone(name, NULL, AUDIT_PIPE_NAME, &u) != 1) 652155408Srwatson return; 653155408Srwatson 654155408Srwatson i = clone_create(&audit_pipe_clones, &audit_pipe_cdevsw, &u, dev, 0); 655155408Srwatson if (i) { 656183381Sed *dev = make_dev(&audit_pipe_cdevsw, u, UID_ROOT, 657155408Srwatson GID_WHEEL, 0600, "%s%d", AUDIT_PIPE_NAME, u); 658155408Srwatson if (*dev != NULL) { 659155408Srwatson dev_ref(*dev); 660155408Srwatson (*dev)->si_flags |= SI_CHEAPCLONE; 661155408Srwatson } 662155408Srwatson } 663155408Srwatson} 664155408Srwatson 665155408Srwatson/* 666164033Srwatson * Audit pipe open method. Explicit privilege check isn't used as this 667164033Srwatson * allows file permissions on the special device to be used to grant audit 668164033Srwatson * review access. Those file permissions should be managed carefully. 669155408Srwatson */ 670155408Srwatsonstatic int 671155408Srwatsonaudit_pipe_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 672155408Srwatson{ 673155408Srwatson struct audit_pipe *ap; 674155408Srwatson 675184488Srwatson AUDIT_PIPE_LIST_WLOCK(); 676155408Srwatson ap = dev->si_drv1; 677155408Srwatson if (ap == NULL) { 678155408Srwatson ap = audit_pipe_alloc(); 679155408Srwatson if (ap == NULL) { 680184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 681155408Srwatson return (ENOMEM); 682155408Srwatson } 683155408Srwatson dev->si_drv1 = ap; 684155408Srwatson } else { 685155408Srwatson KASSERT(ap->ap_open, ("audit_pipe_open: ap && !ap_open")); 686184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 687155408Srwatson return (EBUSY); 688155408Srwatson } 689184488Srwatson ap->ap_open = 1; /* No lock required yet. */ 690184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 691155408Srwatson fsetown(td->td_proc->p_pid, &ap->ap_sigio); 692155408Srwatson return (0); 693155408Srwatson} 694155408Srwatson 695155408Srwatson/* 696155408Srwatson * Close audit pipe, tear down all records, etc. 697155408Srwatson */ 698155408Srwatsonstatic int 699155408Srwatsonaudit_pipe_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 700155408Srwatson{ 701155408Srwatson struct audit_pipe *ap; 702155408Srwatson 703155408Srwatson ap = dev->si_drv1; 704155408Srwatson KASSERT(ap != NULL, ("audit_pipe_close: ap == NULL")); 705155408Srwatson KASSERT(ap->ap_open, ("audit_pipe_close: !ap_open")); 706184488Srwatson 707155408Srwatson funsetown(&ap->ap_sigio); 708184488Srwatson AUDIT_PIPE_LIST_WLOCK(); 709184488Srwatson AUDIT_PIPE_LOCK(ap); 710155408Srwatson ap->ap_open = 0; 711155408Srwatson audit_pipe_free(ap); 712155408Srwatson dev->si_drv1 = NULL; 713184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 714155408Srwatson return (0); 715155408Srwatson} 716155408Srwatson 717155408Srwatson/* 718156880Srwatson * Audit pipe ioctl() routine. Handle file descriptor and audit pipe layer 719156880Srwatson * commands. 720155408Srwatson * 721155408Srwatson * Would be desirable to support filtering, although perhaps something simple 722155408Srwatson * like an event mask, as opposed to something complicated like BPF. 723155408Srwatson */ 724155408Srwatsonstatic int 725155408Srwatsonaudit_pipe_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, 726155408Srwatson struct thread *td) 727155408Srwatson{ 728159269Srwatson struct auditpipe_ioctl_preselect *aip; 729155408Srwatson struct audit_pipe *ap; 730159269Srwatson au_mask_t *maskp; 731159269Srwatson int error, mode; 732159269Srwatson au_id_t auid; 733155408Srwatson 734155408Srwatson ap = dev->si_drv1; 735155408Srwatson KASSERT(ap != NULL, ("audit_pipe_ioctl: ap == NULL")); 736159269Srwatson 737159269Srwatson /* 738159269Srwatson * Audit pipe ioctls: first come standard device node ioctls, then 739159269Srwatson * manipulation of pipe settings, and finally, statistics query 740159269Srwatson * ioctls. 741159269Srwatson */ 742155408Srwatson switch (cmd) { 743155408Srwatson case FIONBIO: 744184488Srwatson AUDIT_PIPE_LOCK(ap); 745155408Srwatson if (*(int *)data) 746155408Srwatson ap->ap_flags |= AUDIT_PIPE_NBIO; 747155408Srwatson else 748155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_NBIO; 749184488Srwatson AUDIT_PIPE_UNLOCK(ap); 750155408Srwatson error = 0; 751155408Srwatson break; 752155408Srwatson 753155408Srwatson case FIONREAD: 754184488Srwatson AUDIT_PIPE_LOCK(ap); 755155408Srwatson if (TAILQ_FIRST(&ap->ap_queue) != NULL) 756155408Srwatson *(int *)data = 757184508Srwatson TAILQ_FIRST(&ap->ap_queue)->ape_record_len - 758184508Srwatson TAILQ_FIRST(&ap->ap_queue)->ape_record_offset; 759155408Srwatson else 760155408Srwatson *(int *)data = 0; 761184488Srwatson AUDIT_PIPE_UNLOCK(ap); 762155408Srwatson error = 0; 763155408Srwatson break; 764155408Srwatson 765155408Srwatson case FIOASYNC: 766184488Srwatson AUDIT_PIPE_LOCK(ap); 767155408Srwatson if (*(int *)data) 768155408Srwatson ap->ap_flags |= AUDIT_PIPE_ASYNC; 769155408Srwatson else 770155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_ASYNC; 771184488Srwatson AUDIT_PIPE_UNLOCK(ap); 772155408Srwatson error = 0; 773155408Srwatson break; 774155408Srwatson 775155408Srwatson case FIOSETOWN: 776155408Srwatson error = fsetown(*(int *)data, &ap->ap_sigio); 777155408Srwatson break; 778155408Srwatson 779155408Srwatson case FIOGETOWN: 780155408Srwatson *(int *)data = fgetown(&ap->ap_sigio); 781155408Srwatson error = 0; 782156880Srwatson break; 783155408Srwatson 784156880Srwatson case AUDITPIPE_GET_QLEN: 785156880Srwatson *(u_int *)data = ap->ap_qlen; 786156880Srwatson error = 0; 787156880Srwatson break; 788156880Srwatson 789156880Srwatson case AUDITPIPE_GET_QLIMIT: 790156880Srwatson *(u_int *)data = ap->ap_qlimit; 791156880Srwatson error = 0; 792156880Srwatson break; 793156880Srwatson 794156880Srwatson case AUDITPIPE_SET_QLIMIT: 795156880Srwatson /* Lockless integer write. */ 796156880Srwatson if (*(u_int *)data >= AUDIT_PIPE_QLIMIT_MIN || 797156880Srwatson *(u_int *)data <= AUDIT_PIPE_QLIMIT_MAX) { 798156880Srwatson ap->ap_qlimit = *(u_int *)data; 799156880Srwatson error = 0; 800156880Srwatson } else 801156880Srwatson error = EINVAL; 802156880Srwatson break; 803156880Srwatson 804156884Srwatson case AUDITPIPE_GET_QLIMIT_MIN: 805156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MIN; 806156884Srwatson error = 0; 807156884Srwatson break; 808156884Srwatson 809156884Srwatson case AUDITPIPE_GET_QLIMIT_MAX: 810156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MAX; 811156884Srwatson error = 0; 812156884Srwatson break; 813156884Srwatson 814159269Srwatson case AUDITPIPE_GET_PRESELECT_FLAGS: 815184488Srwatson AUDIT_PIPE_LOCK(ap); 816159269Srwatson maskp = (au_mask_t *)data; 817159269Srwatson *maskp = ap->ap_preselect_flags; 818184488Srwatson AUDIT_PIPE_UNLOCK(ap); 819159269Srwatson error = 0; 820159269Srwatson break; 821159269Srwatson 822159269Srwatson case AUDITPIPE_SET_PRESELECT_FLAGS: 823184488Srwatson AUDIT_PIPE_LOCK(ap); 824159269Srwatson maskp = (au_mask_t *)data; 825159269Srwatson ap->ap_preselect_flags = *maskp; 826184488Srwatson AUDIT_PIPE_UNLOCK(ap); 827159269Srwatson error = 0; 828159269Srwatson break; 829159269Srwatson 830159269Srwatson case AUDITPIPE_GET_PRESELECT_NAFLAGS: 831184488Srwatson AUDIT_PIPE_LOCK(ap); 832159269Srwatson maskp = (au_mask_t *)data; 833159269Srwatson *maskp = ap->ap_preselect_naflags; 834184488Srwatson AUDIT_PIPE_UNLOCK(ap); 835159269Srwatson error = 0; 836159269Srwatson break; 837159269Srwatson 838159269Srwatson case AUDITPIPE_SET_PRESELECT_NAFLAGS: 839184488Srwatson AUDIT_PIPE_LOCK(ap); 840159269Srwatson maskp = (au_mask_t *)data; 841159269Srwatson ap->ap_preselect_naflags = *maskp; 842184488Srwatson AUDIT_PIPE_UNLOCK(ap); 843159269Srwatson error = 0; 844159269Srwatson break; 845159269Srwatson 846159269Srwatson case AUDITPIPE_GET_PRESELECT_AUID: 847159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 848159269Srwatson error = audit_pipe_preselect_get(ap, aip->aip_auid, 849159269Srwatson &aip->aip_mask); 850159269Srwatson break; 851159269Srwatson 852159269Srwatson case AUDITPIPE_SET_PRESELECT_AUID: 853159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 854159269Srwatson audit_pipe_preselect_set(ap, aip->aip_auid, aip->aip_mask); 855159269Srwatson error = 0; 856159269Srwatson break; 857159269Srwatson 858159269Srwatson case AUDITPIPE_DELETE_PRESELECT_AUID: 859159269Srwatson auid = *(au_id_t *)data; 860159269Srwatson error = audit_pipe_preselect_delete(ap, auid); 861159269Srwatson break; 862159269Srwatson 863159269Srwatson case AUDITPIPE_FLUSH_PRESELECT_AUID: 864159269Srwatson audit_pipe_preselect_flush(ap); 865159269Srwatson error = 0; 866159269Srwatson break; 867159269Srwatson 868159269Srwatson case AUDITPIPE_GET_PRESELECT_MODE: 869184488Srwatson AUDIT_PIPE_LOCK(ap); 870159269Srwatson *(int *)data = ap->ap_preselect_mode; 871184488Srwatson AUDIT_PIPE_UNLOCK(ap); 872159269Srwatson error = 0; 873159269Srwatson break; 874159269Srwatson 875159269Srwatson case AUDITPIPE_SET_PRESELECT_MODE: 876159269Srwatson mode = *(int *)data; 877159269Srwatson switch (mode) { 878159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 879159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 880184488Srwatson AUDIT_PIPE_LOCK(ap); 881159269Srwatson ap->ap_preselect_mode = mode; 882184488Srwatson AUDIT_PIPE_UNLOCK(ap); 883159269Srwatson error = 0; 884159269Srwatson break; 885159269Srwatson 886159269Srwatson default: 887159269Srwatson error = EINVAL; 888159269Srwatson } 889159269Srwatson break; 890159269Srwatson 891159269Srwatson case AUDITPIPE_FLUSH: 892184508Srwatson if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) 893184508Srwatson return (EINTR); 894184488Srwatson AUDIT_PIPE_LOCK(ap); 895159269Srwatson audit_pipe_flush(ap); 896184488Srwatson AUDIT_PIPE_UNLOCK(ap); 897184508Srwatson AUDIT_PIPE_SX_XUNLOCK(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: 922184510Srwatson *(u_int *)data = 0; 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; 952184508Srwatson u_int toread; 953155408Srwatson int error; 954155408Srwatson 955155408Srwatson ap = dev->si_drv1; 956155408Srwatson KASSERT(ap != NULL, ("audit_pipe_read: ap == NULL")); 957184488Srwatson 958184508Srwatson /* 959184508Srwatson * We hold an sx(9) lock over read and flush because we rely on the 960184508Srwatson * stability of a record in the queue during uiomove(9). 961184508Srwatson */ 962184508Srwatson if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) 963184508Srwatson return (EINTR); 964184488Srwatson AUDIT_PIPE_LOCK(ap); 965184508Srwatson while (TAILQ_EMPTY(&ap->ap_queue)) { 966184508Srwatson if (ap->ap_flags & AUDIT_PIPE_NBIO) { 967184508Srwatson AUDIT_PIPE_UNLOCK(ap); 968184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 969184508Srwatson return (EAGAIN); 970155408Srwatson } 971184508Srwatson error = cv_wait_sig(&ap->ap_cv, AUDIT_PIPE_MTX(ap)); 972184508Srwatson if (error) { 973184508Srwatson AUDIT_PIPE_UNLOCK(ap); 974184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 975184508Srwatson return (error); 976184508Srwatson } 977184508Srwatson } 978184508Srwatson 979184508Srwatson /* 980184508Srwatson * Copy as many remaining bytes from the current record to userspace 981184508Srwatson * as we can. 982184508Srwatson * 983184508Srwatson * Note: we rely on the SX lock to maintain ape's stability here. 984184508Srwatson */ 985173083Scsjp ap->ap_reads++; 986184508Srwatson ape = TAILQ_FIRST(&ap->ap_queue); 987184508Srwatson toread = MIN(ape->ape_record_len - ape->ape_record_offset, 988184508Srwatson uio->uio_resid); 989184488Srwatson AUDIT_PIPE_UNLOCK(ap); 990184508Srwatson error = uiomove((char *)ape->ape_record + ape->ape_record_offset, 991184508Srwatson toread, uio); 992184508Srwatson if (error) { 993184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 994184508Srwatson return (error); 995184508Srwatson } 996155408Srwatson 997155408Srwatson /* 998184508Srwatson * If the copy succeeded, update book-keeping, and if no bytes remain 999184508Srwatson * in the current record, free it. 1000155408Srwatson */ 1001184508Srwatson AUDIT_PIPE_LOCK(ap); 1002184508Srwatson KASSERT(TAILQ_FIRST(&ap->ap_queue) == ape, 1003184508Srwatson ("audit_pipe_read: queue out of sync after uiomove")); 1004184508Srwatson ape->ape_record_offset += toread; 1005184508Srwatson if (ape->ape_record_offset == ape->ape_record_len) { 1006184508Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 1007184508Srwatson ap->ap_qlen--; 1008184508Srwatson } else 1009184508Srwatson ape = NULL; 1010184508Srwatson AUDIT_PIPE_UNLOCK(ap); 1011184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 1012184508Srwatson if (ape != NULL) 1013184508Srwatson audit_pipe_entry_free(ape); 1014155408Srwatson return (error); 1015155408Srwatson} 1016155408Srwatson 1017155408Srwatson/* 1018155408Srwatson * Audit pipe poll. 1019155408Srwatson */ 1020155408Srwatsonstatic int 1021155408Srwatsonaudit_pipe_poll(struct cdev *dev, int events, struct thread *td) 1022155408Srwatson{ 1023155408Srwatson struct audit_pipe *ap; 1024155408Srwatson int revents; 1025155408Srwatson 1026155408Srwatson revents = 0; 1027155408Srwatson ap = dev->si_drv1; 1028155408Srwatson KASSERT(ap != NULL, ("audit_pipe_poll: ap == NULL")); 1029184488Srwatson 1030155408Srwatson if (events & (POLLIN | POLLRDNORM)) { 1031184488Srwatson AUDIT_PIPE_LOCK(ap); 1032155408Srwatson if (TAILQ_FIRST(&ap->ap_queue) != NULL) 1033155408Srwatson revents |= events & (POLLIN | POLLRDNORM); 1034155408Srwatson else 1035155408Srwatson selrecord(td, &ap->ap_selinfo); 1036184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1037155408Srwatson } 1038155408Srwatson return (revents); 1039155408Srwatson} 1040155408Srwatson 1041155408Srwatson/* 1042161582Srwatson * Audit pipe kqfilter. 1043161582Srwatson */ 1044161582Srwatsonstatic int 1045161582Srwatsonaudit_pipe_kqfilter(struct cdev *dev, struct knote *kn) 1046161582Srwatson{ 1047161582Srwatson struct audit_pipe *ap; 1048161582Srwatson 1049161582Srwatson ap = dev->si_drv1; 1050161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqfilter: ap == NULL")); 1051161582Srwatson 1052161582Srwatson if (kn->kn_filter != EVFILT_READ) 1053161582Srwatson return (EINVAL); 1054161582Srwatson 1055161582Srwatson kn->kn_fop = &audit_pipe_read_filterops; 1056161582Srwatson kn->kn_hook = ap; 1057161582Srwatson 1058184488Srwatson AUDIT_PIPE_LOCK(ap); 1059161582Srwatson knlist_add(&ap->ap_selinfo.si_note, kn, 1); 1060184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1061161582Srwatson return (0); 1062161582Srwatson} 1063161582Srwatson 1064161582Srwatson/* 1065161582Srwatson * Return true if there are records available for reading on the pipe. 1066161582Srwatson */ 1067161582Srwatsonstatic int 1068161582Srwatsonaudit_pipe_kqread(struct knote *kn, long hint) 1069161582Srwatson{ 1070161582Srwatson struct audit_pipe_entry *ape; 1071161582Srwatson struct audit_pipe *ap; 1072161582Srwatson 1073161582Srwatson ap = (struct audit_pipe *)kn->kn_hook; 1074161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqread: ap == NULL")); 1075161582Srwatson 1076184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 1077184488Srwatson 1078161582Srwatson if (ap->ap_qlen != 0) { 1079161582Srwatson ape = TAILQ_FIRST(&ap->ap_queue); 1080161582Srwatson KASSERT(ape != NULL, ("audit_pipe_kqread: ape == NULL")); 1081161582Srwatson 1082184508Srwatson kn->kn_data = ape->ape_record_len - ape->ape_record_offset; 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