audit_pipe.c revision 184540
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 184540 2008-11-01 23:05:49Z 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; 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 172184508Srwatson * remove a record from the head of the queue, as an in-progress read * may sleep while copying and therefore cannot hold ap_mtx. 173159269Srwatson */ 174155408Srwatson TAILQ_HEAD(, audit_pipe_entry) ap_queue; 175155408Srwatson 176159269Srwatson /* 177159269Srwatson * Global pipe list. 178159269Srwatson */ 179155408Srwatson TAILQ_ENTRY(audit_pipe) ap_list; 180155408Srwatson}; 181155408Srwatson 182184508Srwatson#define AUDIT_PIPE_LOCK(ap) mtx_lock(&(ap)->ap_mtx) 183184508Srwatson#define AUDIT_PIPE_LOCK_ASSERT(ap) mtx_assert(&(ap)->ap_mtx, MA_OWNED) 184184508Srwatson#define AUDIT_PIPE_LOCK_DESTROY(ap) mtx_destroy(&(ap)->ap_mtx) 185184508Srwatson#define AUDIT_PIPE_LOCK_INIT(ap) mtx_init(&(ap)->ap_mtx, \ 186184508Srwatson "audit_pipe_mtx", NULL, MTX_DEF) 187184508Srwatson#define AUDIT_PIPE_UNLOCK(ap) mtx_unlock(&(ap)->ap_mtx) 188184508Srwatson#define AUDIT_PIPE_MTX(ap) (&(ap)->ap_mtx) 189184488Srwatson 190184508Srwatson#define AUDIT_PIPE_SX_LOCK_DESTROY(ap) sx_destroy(&(ap)->ap_sx) 191184508Srwatson#define AUDIT_PIPE_SX_LOCK_INIT(ap) sx_init(&(ap)->ap_sx, "audit_pipe_sx") 192184508Srwatson#define AUDIT_PIPE_SX_XLOCK_ASSERT(ap) sx_assert(&(ap)->ap_sx, SA_XLOCKED) 193184508Srwatson#define AUDIT_PIPE_SX_XLOCK_SIG(ap) sx_xlock_sig(&(ap)->ap_sx) 194184508Srwatson#define AUDIT_PIPE_SX_XUNLOCK(ap) sx_xunlock(&(ap)->ap_sx) 195184508Srwatson 196155408Srwatson/* 197184488Srwatson * Global list of audit pipes, rwlock to protect it. Individual record 198184488Srwatson * queues on pipes are protected by per-pipe locks; these locks synchronize 199184488Srwatson * between threads walking the list to deliver to individual pipes and add/ 200184488Srwatson * remove of pipes, and are mostly acquired for read. 201155408Srwatson */ 202155408Srwatsonstatic TAILQ_HEAD(, audit_pipe) audit_pipe_list; 203184488Srwatsonstatic struct rwlock audit_pipe_lock; 204155408Srwatson 205184488Srwatson#define AUDIT_PIPE_LIST_LOCK_INIT() rw_init(&audit_pipe_lock, \ 206184488Srwatson "audit_pipe_list_lock") 207184488Srwatson#define AUDIT_PIPE_LIST_RLOCK() rw_rlock(&audit_pipe_lock) 208184488Srwatson#define AUDIT_PIPE_LIST_RUNLOCK() rw_runlock(&audit_pipe_lock) 209184488Srwatson#define AUDIT_PIPE_LIST_WLOCK() rw_wlock(&audit_pipe_lock) 210184488Srwatson#define AUDIT_PIPE_LIST_WLOCK_ASSERT() rw_assert(&audit_pipe_lock, \ 211184488Srwatson RA_WLOCKED) 212184488Srwatson#define AUDIT_PIPE_LIST_WUNLOCK() rw_wunlock(&audit_pipe_lock) 213155408Srwatson 214155408Srwatson/* 215155408Srwatson * Cloning related variables and constants. 216155408Srwatson */ 217155408Srwatson#define AUDIT_PIPE_NAME "auditpipe" 218155408Srwatsonstatic eventhandler_tag audit_pipe_eh_tag; 219155408Srwatsonstatic struct clonedevs *audit_pipe_clones; 220155408Srwatson 221155408Srwatson/* 222155408Srwatson * Special device methods and definition. 223155408Srwatson */ 224155408Srwatsonstatic d_open_t audit_pipe_open; 225155408Srwatsonstatic d_close_t audit_pipe_close; 226155408Srwatsonstatic d_read_t audit_pipe_read; 227155408Srwatsonstatic d_ioctl_t audit_pipe_ioctl; 228155408Srwatsonstatic d_poll_t audit_pipe_poll; 229161582Srwatsonstatic d_kqfilter_t audit_pipe_kqfilter; 230155408Srwatson 231155408Srwatsonstatic struct cdevsw audit_pipe_cdevsw = { 232155408Srwatson .d_version = D_VERSION, 233179726Sed .d_flags = D_PSEUDO | D_NEEDGIANT | D_NEEDMINOR, 234155408Srwatson .d_open = audit_pipe_open, 235155408Srwatson .d_close = audit_pipe_close, 236155408Srwatson .d_read = audit_pipe_read, 237155408Srwatson .d_ioctl = audit_pipe_ioctl, 238155408Srwatson .d_poll = audit_pipe_poll, 239161582Srwatson .d_kqfilter = audit_pipe_kqfilter, 240155408Srwatson .d_name = AUDIT_PIPE_NAME, 241155408Srwatson}; 242155408Srwatson 243161582Srwatsonstatic int audit_pipe_kqread(struct knote *note, long hint); 244161582Srwatsonstatic void audit_pipe_kqdetach(struct knote *note); 245161582Srwatson 246161582Srwatsonstatic struct filterops audit_pipe_read_filterops = { 247161582Srwatson .f_isfd = 1, 248161582Srwatson .f_attach = NULL, 249161582Srwatson .f_detach = audit_pipe_kqdetach, 250161582Srwatson .f_event = audit_pipe_kqread, 251161582Srwatson}; 252161582Srwatson 253155408Srwatson/* 254155408Srwatson * Some global statistics on audit pipes. 255155408Srwatson */ 256155408Srwatsonstatic int audit_pipe_count; /* Current number of pipes. */ 257155408Srwatsonstatic u_int64_t audit_pipe_ever; /* Pipes ever allocated. */ 258155408Srwatsonstatic u_int64_t audit_pipe_records; /* Records seen. */ 259155408Srwatsonstatic u_int64_t audit_pipe_drops; /* Global record drop count. */ 260155408Srwatson 261155408Srwatson/* 262155408Srwatson * Free an audit pipe entry. 263155408Srwatson */ 264155408Srwatsonstatic void 265155408Srwatsonaudit_pipe_entry_free(struct audit_pipe_entry *ape) 266155408Srwatson{ 267155408Srwatson 268155408Srwatson free(ape->ape_record, M_AUDIT_PIPE_ENTRY); 269155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 270155408Srwatson} 271155408Srwatson 272155408Srwatson/* 273159269Srwatson * Find an audit pipe preselection specification for an auid, if any. 274159269Srwatson */ 275159269Srwatsonstatic struct audit_pipe_preselect * 276159269Srwatsonaudit_pipe_preselect_find(struct audit_pipe *ap, au_id_t auid) 277159269Srwatson{ 278159269Srwatson struct audit_pipe_preselect *app; 279159269Srwatson 280184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 281159269Srwatson 282159269Srwatson TAILQ_FOREACH(app, &ap->ap_preselect_list, app_list) { 283159269Srwatson if (app->app_auid == auid) 284159269Srwatson return (app); 285159269Srwatson } 286159269Srwatson return (NULL); 287159269Srwatson} 288159269Srwatson 289159269Srwatson/* 290159269Srwatson * Query the per-pipe mask for a specific auid. 291159269Srwatson */ 292159269Srwatsonstatic int 293159269Srwatsonaudit_pipe_preselect_get(struct audit_pipe *ap, au_id_t auid, 294159269Srwatson au_mask_t *maskp) 295159269Srwatson{ 296159269Srwatson struct audit_pipe_preselect *app; 297159269Srwatson int error; 298159269Srwatson 299184488Srwatson AUDIT_PIPE_LOCK(ap); 300159269Srwatson app = audit_pipe_preselect_find(ap, auid); 301159269Srwatson if (app != NULL) { 302159269Srwatson *maskp = app->app_mask; 303159269Srwatson error = 0; 304159269Srwatson } else 305159269Srwatson error = ENOENT; 306184488Srwatson AUDIT_PIPE_UNLOCK(ap); 307159269Srwatson return (error); 308159269Srwatson} 309159269Srwatson 310159269Srwatson/* 311159269Srwatson * Set the per-pipe mask for a specific auid. Add a new entry if needed; 312159269Srwatson * otherwise, update the current entry. 313159269Srwatson */ 314159269Srwatsonstatic void 315159269Srwatsonaudit_pipe_preselect_set(struct audit_pipe *ap, au_id_t auid, au_mask_t mask) 316159269Srwatson{ 317159269Srwatson struct audit_pipe_preselect *app, *app_new; 318159269Srwatson 319159269Srwatson /* 320159269Srwatson * Pessimistically assume that the auid doesn't already have a mask 321159269Srwatson * set, and allocate. We will free it if it is unneeded. 322159269Srwatson */ 323159269Srwatson app_new = malloc(sizeof(*app_new), M_AUDIT_PIPE_PRESELECT, M_WAITOK); 324184488Srwatson AUDIT_PIPE_LOCK(ap); 325159269Srwatson app = audit_pipe_preselect_find(ap, auid); 326159269Srwatson if (app == NULL) { 327159269Srwatson app = app_new; 328159269Srwatson app_new = NULL; 329159269Srwatson app->app_auid = auid; 330159269Srwatson TAILQ_INSERT_TAIL(&ap->ap_preselect_list, app, app_list); 331159269Srwatson } 332159269Srwatson app->app_mask = mask; 333184488Srwatson AUDIT_PIPE_UNLOCK(ap); 334159269Srwatson if (app_new != NULL) 335159269Srwatson free(app_new, M_AUDIT_PIPE_PRESELECT); 336159269Srwatson} 337159269Srwatson 338159269Srwatson/* 339159269Srwatson * Delete a per-auid mask on an audit pipe. 340159269Srwatson */ 341159269Srwatsonstatic int 342159269Srwatsonaudit_pipe_preselect_delete(struct audit_pipe *ap, au_id_t auid) 343159269Srwatson{ 344159269Srwatson struct audit_pipe_preselect *app; 345159269Srwatson int error; 346159269Srwatson 347184488Srwatson AUDIT_PIPE_LOCK(ap); 348159269Srwatson app = audit_pipe_preselect_find(ap, auid); 349159269Srwatson if (app != NULL) { 350159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 351159269Srwatson error = 0; 352159269Srwatson } else 353159269Srwatson error = ENOENT; 354184488Srwatson AUDIT_PIPE_UNLOCK(ap); 355159269Srwatson if (app != NULL) 356159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 357159269Srwatson return (error); 358159269Srwatson} 359159269Srwatson 360159269Srwatson/* 361159269Srwatson * Delete all per-auid masks on an audit pipe. 362159269Srwatson */ 363159269Srwatsonstatic void 364159269Srwatsonaudit_pipe_preselect_flush_locked(struct audit_pipe *ap) 365159269Srwatson{ 366159269Srwatson struct audit_pipe_preselect *app; 367159269Srwatson 368184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 369159269Srwatson 370159269Srwatson while ((app = TAILQ_FIRST(&ap->ap_preselect_list)) != NULL) { 371159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 372159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 373159269Srwatson } 374159269Srwatson} 375159269Srwatson 376159269Srwatsonstatic void 377159269Srwatsonaudit_pipe_preselect_flush(struct audit_pipe *ap) 378159269Srwatson{ 379159269Srwatson 380184488Srwatson AUDIT_PIPE_LOCK(ap); 381159269Srwatson audit_pipe_preselect_flush_locked(ap); 382184488Srwatson AUDIT_PIPE_UNLOCK(ap); 383159269Srwatson} 384159269Srwatson 385170196Srwatson/*- 386159269Srwatson * Determine whether a specific audit pipe matches a record with these 387159269Srwatson * properties. Algorithm is as follows: 388159269Srwatson * 389159269Srwatson * - If the pipe is configured to track the default trail configuration, then 390159269Srwatson * use the results of global preselection matching. 391159269Srwatson * - If not, search for a specifically configured auid entry matching the 392159269Srwatson * event. If an entry is found, use that. 393159269Srwatson * - Otherwise, use the default flags or naflags configured for the pipe. 394159269Srwatson */ 395159269Srwatsonstatic int 396159269Srwatsonaudit_pipe_preselect_check(struct audit_pipe *ap, au_id_t auid, 397159269Srwatson au_event_t event, au_class_t class, int sorf, int trail_preselect) 398159269Srwatson{ 399159269Srwatson struct audit_pipe_preselect *app; 400159269Srwatson 401184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 402159269Srwatson 403159269Srwatson switch (ap->ap_preselect_mode) { 404159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 405159269Srwatson return (trail_preselect); 406159269Srwatson 407159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 408159269Srwatson app = audit_pipe_preselect_find(ap, auid); 409159269Srwatson if (app == NULL) { 410159269Srwatson if (auid == AU_DEFAUDITID) 411159269Srwatson return (au_preselect(event, class, 412159269Srwatson &ap->ap_preselect_naflags, sorf)); 413159269Srwatson else 414159269Srwatson return (au_preselect(event, class, 415159269Srwatson &ap->ap_preselect_flags, sorf)); 416159269Srwatson } else 417159269Srwatson return (au_preselect(event, class, &app->app_mask, 418159269Srwatson sorf)); 419159269Srwatson 420159269Srwatson default: 421159269Srwatson panic("audit_pipe_preselect_check: mode %d", 422159269Srwatson ap->ap_preselect_mode); 423159269Srwatson } 424159269Srwatson 425159269Srwatson return (0); 426159269Srwatson} 427159269Srwatson 428159269Srwatson/* 429159269Srwatson * Determine whether there exists a pipe interested in a record with specific 430159269Srwatson * properties. 431159269Srwatson */ 432159269Srwatsonint 433159269Srwatsonaudit_pipe_preselect(au_id_t auid, au_event_t event, au_class_t class, 434159269Srwatson int sorf, int trail_preselect) 435159269Srwatson{ 436159269Srwatson struct audit_pipe *ap; 437159269Srwatson 438184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 439159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 440184488Srwatson AUDIT_PIPE_LOCK(ap); 441159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 442159269Srwatson trail_preselect)) { 443184488Srwatson AUDIT_PIPE_UNLOCK(ap); 444184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 445159269Srwatson return (1); 446159269Srwatson } 447184488Srwatson AUDIT_PIPE_UNLOCK(ap); 448159269Srwatson } 449184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 450159269Srwatson return (0); 451159269Srwatson} 452159269Srwatson 453159269Srwatson/* 454159269Srwatson * Append individual record to a queue -- allocate queue-local buffer, and 455184489Srwatson * add to the queue. If the queue is full or we can't allocate memory, drop 456184489Srwatson * the newest record. 457155408Srwatson */ 458155408Srwatsonstatic void 459155408Srwatsonaudit_pipe_append(struct audit_pipe *ap, void *record, u_int record_len) 460155408Srwatson{ 461184489Srwatson struct audit_pipe_entry *ape; 462155408Srwatson 463184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 464155408Srwatson 465184489Srwatson if (ap->ap_qlen >= ap->ap_qlimit) { 466184489Srwatson ap->ap_drops++; 467184489Srwatson audit_pipe_drops++; 468184489Srwatson return; 469184489Srwatson } 470184489Srwatson 471155408Srwatson ape = malloc(sizeof(*ape), M_AUDIT_PIPE_ENTRY, M_NOWAIT | M_ZERO); 472155408Srwatson if (ape == NULL) { 473155408Srwatson ap->ap_drops++; 474156292Srwatson audit_pipe_drops++; 475155408Srwatson return; 476155408Srwatson } 477155408Srwatson 478155408Srwatson ape->ape_record = malloc(record_len, M_AUDIT_PIPE_ENTRY, M_NOWAIT); 479155408Srwatson if (ape->ape_record == NULL) { 480155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 481155408Srwatson ap->ap_drops++; 482155408Srwatson audit_pipe_drops++; 483155408Srwatson return; 484155408Srwatson } 485155408Srwatson 486155408Srwatson bcopy(record, ape->ape_record, record_len); 487155408Srwatson ape->ape_record_len = record_len; 488155408Srwatson 489155408Srwatson TAILQ_INSERT_TAIL(&ap->ap_queue, ape, ape_queue); 490155408Srwatson ap->ap_inserts++; 491155408Srwatson ap->ap_qlen++; 492184536Srwatson ap->ap_qbyteslen += ape->ape_record_len; 493155408Srwatson selwakeuppri(&ap->ap_selinfo, PSOCK); 494161582Srwatson KNOTE_LOCKED(&ap->ap_selinfo.si_note, 0); 495155408Srwatson if (ap->ap_flags & AUDIT_PIPE_ASYNC) 496155408Srwatson pgsigio(&ap->ap_sigio, SIGIO, 0); 497184488Srwatson cv_broadcast(&ap->ap_cv); 498155408Srwatson} 499155408Srwatson 500155408Srwatson/* 501155408Srwatson * audit_pipe_submit(): audit_worker submits audit records via this 502155408Srwatson * interface, which arranges for them to be delivered to pipe queues. 503155408Srwatson */ 504155408Srwatsonvoid 505159269Srwatsonaudit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class, int sorf, 506159269Srwatson int trail_select, void *record, u_int record_len) 507155408Srwatson{ 508155408Srwatson struct audit_pipe *ap; 509155408Srwatson 510155408Srwatson /* 511184488Srwatson * Lockless read to avoid lock overhead if pipes are not in use. 512155408Srwatson */ 513155408Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 514155408Srwatson return; 515155408Srwatson 516184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 517159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 518184488Srwatson AUDIT_PIPE_LOCK(ap); 519159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 520159269Srwatson trail_select)) 521159269Srwatson audit_pipe_append(ap, record, record_len); 522184488Srwatson AUDIT_PIPE_UNLOCK(ap); 523159269Srwatson } 524184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 525184488Srwatson 526184488Srwatson /* Unlocked increment. */ 527159269Srwatson audit_pipe_records++; 528159269Srwatson} 529159269Srwatson 530159269Srwatson/* 531159269Srwatson * audit_pipe_submit_user(): the same as audit_pipe_submit(), except that 532159269Srwatson * since we don't currently have selection information available, it is 533159269Srwatson * delivered to the pipe unconditionally. 534159269Srwatson * 535159269Srwatson * XXXRW: This is a bug. The BSM check routine for submitting a user record 536159269Srwatson * should parse that information and return it. 537159269Srwatson */ 538159269Srwatsonvoid 539159269Srwatsonaudit_pipe_submit_user(void *record, u_int record_len) 540159269Srwatson{ 541159269Srwatson struct audit_pipe *ap; 542159269Srwatson 543159269Srwatson /* 544184488Srwatson * Lockless read to avoid lock overhead if pipes are not in use. 545159269Srwatson */ 546159269Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 547159269Srwatson return; 548159269Srwatson 549184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 550184488Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 551184488Srwatson AUDIT_PIPE_LOCK(ap); 552155408Srwatson audit_pipe_append(ap, record, record_len); 553184488Srwatson AUDIT_PIPE_UNLOCK(ap); 554184488Srwatson } 555184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 556184488Srwatson 557184488Srwatson /* Unlocked increment. */ 558155408Srwatson audit_pipe_records++; 559155408Srwatson} 560155408Srwatson 561155408Srwatson/* 562155408Srwatson * Allocate a new audit pipe. Connects the pipe, on success, to the global 563155408Srwatson * list and updates statistics. 564155408Srwatson */ 565155408Srwatsonstatic struct audit_pipe * 566155408Srwatsonaudit_pipe_alloc(void) 567155408Srwatson{ 568155408Srwatson struct audit_pipe *ap; 569155408Srwatson 570184488Srwatson AUDIT_PIPE_LIST_WLOCK_ASSERT(); 571155408Srwatson 572155408Srwatson ap = malloc(sizeof(*ap), M_AUDIT_PIPE, M_NOWAIT | M_ZERO); 573155408Srwatson if (ap == NULL) 574155408Srwatson return (NULL); 575155408Srwatson ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT; 576155408Srwatson TAILQ_INIT(&ap->ap_queue); 577184488Srwatson knlist_init(&ap->ap_selinfo.si_note, AUDIT_PIPE_MTX(ap), NULL, NULL, 578161582Srwatson NULL); 579184488Srwatson AUDIT_PIPE_LOCK_INIT(ap); 580184508Srwatson AUDIT_PIPE_SX_LOCK_INIT(ap); 581184488Srwatson cv_init(&ap->ap_cv, "audit_pipe"); 582159269Srwatson 583159269Srwatson /* 584159269Srwatson * Default flags, naflags, and auid-specific preselection settings to 585159269Srwatson * 0. Initialize the mode to the global trail so that if praudit(1) 586159269Srwatson * is run on /dev/auditpipe, it sees events associated with the 587159269Srwatson * default trail. Pipe-aware application can clear the flag, set 588159269Srwatson * custom masks, and flush the pipe as needed. 589159269Srwatson */ 590159269Srwatson bzero(&ap->ap_preselect_flags, sizeof(ap->ap_preselect_flags)); 591159269Srwatson bzero(&ap->ap_preselect_naflags, sizeof(ap->ap_preselect_naflags)); 592159269Srwatson TAILQ_INIT(&ap->ap_preselect_list); 593159269Srwatson ap->ap_preselect_mode = AUDITPIPE_PRESELECT_MODE_TRAIL; 594159269Srwatson 595161582Srwatson /* 596161582Srwatson * Add to global list and update global statistics. 597161582Srwatson */ 598155408Srwatson TAILQ_INSERT_HEAD(&audit_pipe_list, ap, ap_list); 599155408Srwatson audit_pipe_count++; 600155408Srwatson audit_pipe_ever++; 601159269Srwatson 602155408Srwatson return (ap); 603155408Srwatson} 604155408Srwatson 605155408Srwatson/* 606159269Srwatson * Flush all records currently present in an audit pipe; assume mutex is held. 607155408Srwatson */ 608155408Srwatsonstatic void 609159269Srwatsonaudit_pipe_flush(struct audit_pipe *ap) 610155408Srwatson{ 611155408Srwatson struct audit_pipe_entry *ape; 612155408Srwatson 613184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 614155408Srwatson 615155408Srwatson while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL) { 616155408Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 617184536Srwatson ap->ap_qbyteslen -= ape->ape_record_len; 618155408Srwatson audit_pipe_entry_free(ape); 619155408Srwatson ap->ap_qlen--; 620155408Srwatson } 621184536Srwatson ap->ap_qoffset = 0; 622184536Srwatson 623184536Srwatson KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qbyteslen")); 624184536Srwatson KASSERT(ap->ap_qbyteslen == 0, ("audit_pipe_flush: ap_qbyteslen")); 625159269Srwatson} 626159269Srwatson 627159269Srwatson/* 628159269Srwatson * Free an audit pipe; this means freeing all preselection state and all 629184488Srwatson * records in the pipe. Assumes global write lock and pipe mutex are held to 630184488Srwatson * prevent any new records from being inserted during the free, and that the 631184488Srwatson * audit pipe is still on the global list. 632159269Srwatson */ 633159269Srwatsonstatic void 634159269Srwatsonaudit_pipe_free(struct audit_pipe *ap) 635159269Srwatson{ 636159269Srwatson 637184488Srwatson AUDIT_PIPE_LIST_WLOCK_ASSERT(); 638184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 639159269Srwatson 640159269Srwatson audit_pipe_preselect_flush_locked(ap); 641159269Srwatson audit_pipe_flush(ap); 642184488Srwatson cv_destroy(&ap->ap_cv); 643184508Srwatson AUDIT_PIPE_SX_LOCK_DESTROY(ap); 644184488Srwatson AUDIT_PIPE_LOCK_DESTROY(ap); 645161582Srwatson knlist_destroy(&ap->ap_selinfo.si_note); 646159269Srwatson TAILQ_REMOVE(&audit_pipe_list, ap, ap_list); 647155408Srwatson free(ap, M_AUDIT_PIPE); 648155408Srwatson audit_pipe_count--; 649155408Srwatson} 650155408Srwatson 651155408Srwatson/* 652155408Srwatson * Audit pipe clone routine -- provide specific requested audit pipe, or a 653155408Srwatson * fresh one if a specific one is not requested. 654155408Srwatson */ 655155408Srwatsonstatic void 656155408Srwatsonaudit_pipe_clone(void *arg, struct ucred *cred, char *name, int namelen, 657155408Srwatson struct cdev **dev) 658155408Srwatson{ 659155408Srwatson int i, u; 660155408Srwatson 661155408Srwatson if (*dev != NULL) 662155408Srwatson return; 663155408Srwatson 664155408Srwatson if (strcmp(name, AUDIT_PIPE_NAME) == 0) 665155408Srwatson u = -1; 666155408Srwatson else if (dev_stdclone(name, NULL, AUDIT_PIPE_NAME, &u) != 1) 667155408Srwatson return; 668155408Srwatson 669155408Srwatson i = clone_create(&audit_pipe_clones, &audit_pipe_cdevsw, &u, dev, 0); 670155408Srwatson if (i) { 671183381Sed *dev = make_dev(&audit_pipe_cdevsw, u, UID_ROOT, 672155408Srwatson GID_WHEEL, 0600, "%s%d", AUDIT_PIPE_NAME, u); 673155408Srwatson if (*dev != NULL) { 674155408Srwatson dev_ref(*dev); 675155408Srwatson (*dev)->si_flags |= SI_CHEAPCLONE; 676155408Srwatson } 677155408Srwatson } 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 * 736155408Srwatson * Would be desirable to support filtering, although perhaps something simple 737155408Srwatson * like an event mask, as opposed to something complicated like BPF. 738155408Srwatson */ 739155408Srwatsonstatic int 740155408Srwatsonaudit_pipe_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, 741155408Srwatson struct thread *td) 742155408Srwatson{ 743159269Srwatson struct auditpipe_ioctl_preselect *aip; 744155408Srwatson struct audit_pipe *ap; 745159269Srwatson au_mask_t *maskp; 746159269Srwatson int error, mode; 747159269Srwatson au_id_t auid; 748155408Srwatson 749155408Srwatson ap = dev->si_drv1; 750155408Srwatson KASSERT(ap != NULL, ("audit_pipe_ioctl: ap == NULL")); 751159269Srwatson 752159269Srwatson /* 753159269Srwatson * Audit pipe ioctls: first come standard device node ioctls, then 754159269Srwatson * manipulation of pipe settings, and finally, statistics query 755159269Srwatson * ioctls. 756159269Srwatson */ 757155408Srwatson switch (cmd) { 758155408Srwatson case FIONBIO: 759184488Srwatson AUDIT_PIPE_LOCK(ap); 760155408Srwatson if (*(int *)data) 761155408Srwatson ap->ap_flags |= AUDIT_PIPE_NBIO; 762155408Srwatson else 763155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_NBIO; 764184488Srwatson AUDIT_PIPE_UNLOCK(ap); 765155408Srwatson error = 0; 766155408Srwatson break; 767155408Srwatson 768155408Srwatson case FIONREAD: 769184488Srwatson AUDIT_PIPE_LOCK(ap); 770184536Srwatson *(int *)data = ap->ap_qbyteslen - ap->ap_qoffset; 771184488Srwatson AUDIT_PIPE_UNLOCK(ap); 772155408Srwatson error = 0; 773155408Srwatson break; 774155408Srwatson 775155408Srwatson case FIOASYNC: 776184488Srwatson AUDIT_PIPE_LOCK(ap); 777155408Srwatson if (*(int *)data) 778155408Srwatson ap->ap_flags |= AUDIT_PIPE_ASYNC; 779155408Srwatson else 780155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_ASYNC; 781184488Srwatson AUDIT_PIPE_UNLOCK(ap); 782155408Srwatson error = 0; 783155408Srwatson break; 784155408Srwatson 785155408Srwatson case FIOSETOWN: 786155408Srwatson error = fsetown(*(int *)data, &ap->ap_sigio); 787155408Srwatson break; 788155408Srwatson 789155408Srwatson case FIOGETOWN: 790155408Srwatson *(int *)data = fgetown(&ap->ap_sigio); 791155408Srwatson error = 0; 792156880Srwatson break; 793155408Srwatson 794156880Srwatson case AUDITPIPE_GET_QLEN: 795156880Srwatson *(u_int *)data = ap->ap_qlen; 796156880Srwatson error = 0; 797156880Srwatson break; 798156880Srwatson 799156880Srwatson case AUDITPIPE_GET_QLIMIT: 800156880Srwatson *(u_int *)data = ap->ap_qlimit; 801156880Srwatson error = 0; 802156880Srwatson break; 803156880Srwatson 804156880Srwatson case AUDITPIPE_SET_QLIMIT: 805156880Srwatson /* Lockless integer write. */ 806156880Srwatson if (*(u_int *)data >= AUDIT_PIPE_QLIMIT_MIN || 807156880Srwatson *(u_int *)data <= AUDIT_PIPE_QLIMIT_MAX) { 808156880Srwatson ap->ap_qlimit = *(u_int *)data; 809156880Srwatson error = 0; 810156880Srwatson } else 811156880Srwatson error = EINVAL; 812156880Srwatson break; 813156880Srwatson 814156884Srwatson case AUDITPIPE_GET_QLIMIT_MIN: 815156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MIN; 816156884Srwatson error = 0; 817156884Srwatson break; 818156884Srwatson 819156884Srwatson case AUDITPIPE_GET_QLIMIT_MAX: 820156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MAX; 821156884Srwatson error = 0; 822156884Srwatson break; 823156884Srwatson 824159269Srwatson case AUDITPIPE_GET_PRESELECT_FLAGS: 825184488Srwatson AUDIT_PIPE_LOCK(ap); 826159269Srwatson maskp = (au_mask_t *)data; 827159269Srwatson *maskp = ap->ap_preselect_flags; 828184488Srwatson AUDIT_PIPE_UNLOCK(ap); 829159269Srwatson error = 0; 830159269Srwatson break; 831159269Srwatson 832159269Srwatson case AUDITPIPE_SET_PRESELECT_FLAGS: 833184488Srwatson AUDIT_PIPE_LOCK(ap); 834159269Srwatson maskp = (au_mask_t *)data; 835159269Srwatson ap->ap_preselect_flags = *maskp; 836184488Srwatson AUDIT_PIPE_UNLOCK(ap); 837159269Srwatson error = 0; 838159269Srwatson break; 839159269Srwatson 840159269Srwatson case AUDITPIPE_GET_PRESELECT_NAFLAGS: 841184488Srwatson AUDIT_PIPE_LOCK(ap); 842159269Srwatson maskp = (au_mask_t *)data; 843159269Srwatson *maskp = ap->ap_preselect_naflags; 844184488Srwatson AUDIT_PIPE_UNLOCK(ap); 845159269Srwatson error = 0; 846159269Srwatson break; 847159269Srwatson 848159269Srwatson case AUDITPIPE_SET_PRESELECT_NAFLAGS: 849184488Srwatson AUDIT_PIPE_LOCK(ap); 850159269Srwatson maskp = (au_mask_t *)data; 851159269Srwatson ap->ap_preselect_naflags = *maskp; 852184488Srwatson AUDIT_PIPE_UNLOCK(ap); 853159269Srwatson error = 0; 854159269Srwatson break; 855159269Srwatson 856159269Srwatson case AUDITPIPE_GET_PRESELECT_AUID: 857159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 858159269Srwatson error = audit_pipe_preselect_get(ap, aip->aip_auid, 859159269Srwatson &aip->aip_mask); 860159269Srwatson break; 861159269Srwatson 862159269Srwatson case AUDITPIPE_SET_PRESELECT_AUID: 863159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 864159269Srwatson audit_pipe_preselect_set(ap, aip->aip_auid, aip->aip_mask); 865159269Srwatson error = 0; 866159269Srwatson break; 867159269Srwatson 868159269Srwatson case AUDITPIPE_DELETE_PRESELECT_AUID: 869159269Srwatson auid = *(au_id_t *)data; 870159269Srwatson error = audit_pipe_preselect_delete(ap, auid); 871159269Srwatson break; 872159269Srwatson 873159269Srwatson case AUDITPIPE_FLUSH_PRESELECT_AUID: 874159269Srwatson audit_pipe_preselect_flush(ap); 875159269Srwatson error = 0; 876159269Srwatson break; 877159269Srwatson 878159269Srwatson case AUDITPIPE_GET_PRESELECT_MODE: 879184488Srwatson AUDIT_PIPE_LOCK(ap); 880159269Srwatson *(int *)data = ap->ap_preselect_mode; 881184488Srwatson AUDIT_PIPE_UNLOCK(ap); 882159269Srwatson error = 0; 883159269Srwatson break; 884159269Srwatson 885159269Srwatson case AUDITPIPE_SET_PRESELECT_MODE: 886159269Srwatson mode = *(int *)data; 887159269Srwatson switch (mode) { 888159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 889159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 890184488Srwatson AUDIT_PIPE_LOCK(ap); 891159269Srwatson ap->ap_preselect_mode = mode; 892184488Srwatson AUDIT_PIPE_UNLOCK(ap); 893159269Srwatson error = 0; 894159269Srwatson break; 895159269Srwatson 896159269Srwatson default: 897159269Srwatson error = EINVAL; 898159269Srwatson } 899159269Srwatson break; 900159269Srwatson 901159269Srwatson case AUDITPIPE_FLUSH: 902184508Srwatson if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) 903184508Srwatson return (EINTR); 904184488Srwatson AUDIT_PIPE_LOCK(ap); 905159269Srwatson audit_pipe_flush(ap); 906184488Srwatson AUDIT_PIPE_UNLOCK(ap); 907184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 908159269Srwatson error = 0; 909159269Srwatson break; 910159269Srwatson 911161646Srwatson case AUDITPIPE_GET_MAXAUDITDATA: 912161646Srwatson *(u_int *)data = MAXAUDITDATA; 913161646Srwatson error = 0; 914161646Srwatson break; 915161646Srwatson 916156880Srwatson case AUDITPIPE_GET_INSERTS: 917156880Srwatson *(u_int *)data = ap->ap_inserts; 918156880Srwatson error = 0; 919156880Srwatson break; 920156880Srwatson 921156880Srwatson case AUDITPIPE_GET_READS: 922156880Srwatson *(u_int *)data = ap->ap_reads; 923156880Srwatson error = 0; 924156880Srwatson break; 925156880Srwatson 926156880Srwatson case AUDITPIPE_GET_DROPS: 927156880Srwatson *(u_int *)data = ap->ap_drops; 928156880Srwatson error = 0; 929156880Srwatson break; 930156880Srwatson 931156880Srwatson case AUDITPIPE_GET_TRUNCATES: 932184510Srwatson *(u_int *)data = 0; 933156880Srwatson error = 0; 934156880Srwatson break; 935156880Srwatson 936155408Srwatson default: 937155408Srwatson error = ENOTTY; 938155408Srwatson } 939155408Srwatson return (error); 940155408Srwatson} 941155408Srwatson 942155408Srwatson/* 943184534Srwatson * Audit pipe read. Read one or more partial or complete records to user 944184534Srwatson * memory. 945155408Srwatson */ 946155408Srwatsonstatic int 947155408Srwatsonaudit_pipe_read(struct cdev *dev, struct uio *uio, int flag) 948155408Srwatson{ 949155408Srwatson struct audit_pipe_entry *ape; 950155408Srwatson struct audit_pipe *ap; 951184508Srwatson u_int toread; 952155408Srwatson int error; 953155408Srwatson 954155408Srwatson ap = dev->si_drv1; 955155408Srwatson KASSERT(ap != NULL, ("audit_pipe_read: ap == NULL")); 956184488Srwatson 957184508Srwatson /* 958184508Srwatson * We hold an sx(9) lock over read and flush because we rely on the 959184508Srwatson * stability of a record in the queue during uiomove(9). 960184508Srwatson */ 961184508Srwatson if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) 962184508Srwatson return (EINTR); 963184488Srwatson AUDIT_PIPE_LOCK(ap); 964184508Srwatson while (TAILQ_EMPTY(&ap->ap_queue)) { 965184508Srwatson if (ap->ap_flags & AUDIT_PIPE_NBIO) { 966184508Srwatson AUDIT_PIPE_UNLOCK(ap); 967184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 968184508Srwatson return (EAGAIN); 969155408Srwatson } 970184508Srwatson error = cv_wait_sig(&ap->ap_cv, AUDIT_PIPE_MTX(ap)); 971184508Srwatson if (error) { 972184508Srwatson AUDIT_PIPE_UNLOCK(ap); 973184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 974184508Srwatson return (error); 975184508Srwatson } 976184508Srwatson } 977184508Srwatson 978184508Srwatson /* 979184508Srwatson * Copy as many remaining bytes from the current record to userspace 980184534Srwatson * as we can. Keep processing records until we run out of records in 981184534Srwatson * the queue, or until the user buffer runs out of space. 982184508Srwatson * 983184508Srwatson * Note: we rely on the SX lock to maintain ape's stability here. 984184508Srwatson */ 985173083Scsjp ap->ap_reads++; 986184534Srwatson while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL && 987184534Srwatson uio->uio_resid > 0) { 988184534Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 989184534Srwatson 990184536Srwatson KASSERT(ape->ape_record_len > ap->ap_qoffset, 991184536Srwatson ("audit_pipe_read: record_len > qoffset (1)")); 992184536Srwatson toread = MIN(ape->ape_record_len - ap->ap_qoffset, 993184534Srwatson uio->uio_resid); 994184534Srwatson AUDIT_PIPE_UNLOCK(ap); 995184536Srwatson error = uiomove((char *)ape->ape_record + ap->ap_qoffset, 996184536Srwatson toread, uio); 997184534Srwatson if (error) { 998184534Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 999184534Srwatson return (error); 1000184534Srwatson } 1001184534Srwatson 1002184534Srwatson /* 1003184534Srwatson * If the copy succeeded, update book-keeping, and if no 1004184534Srwatson * bytes remain in the current record, free it. 1005184534Srwatson */ 1006184534Srwatson AUDIT_PIPE_LOCK(ap); 1007184534Srwatson KASSERT(TAILQ_FIRST(&ap->ap_queue) == ape, 1008184534Srwatson ("audit_pipe_read: queue out of sync after uiomove")); 1009184536Srwatson ap->ap_qoffset += toread; 1010184536Srwatson KASSERT(ape->ape_record_len >= ap->ap_qoffset, 1011184536Srwatson ("audit_pipe_read: record_len >= qoffset (2)")); 1012184536Srwatson if (ap->ap_qoffset == ape->ape_record_len) { 1013184534Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 1014184536Srwatson ap->ap_qbyteslen -= ape->ape_record_len; 1015184534Srwatson audit_pipe_entry_free(ape); 1016184534Srwatson ap->ap_qlen--; 1017184536Srwatson ap->ap_qoffset = 0; 1018184534Srwatson } 1019184508Srwatson } 1020184508Srwatson AUDIT_PIPE_UNLOCK(ap); 1021184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 1022184534Srwatson return (0); 1023155408Srwatson} 1024155408Srwatson 1025155408Srwatson/* 1026155408Srwatson * Audit pipe poll. 1027155408Srwatson */ 1028155408Srwatsonstatic int 1029155408Srwatsonaudit_pipe_poll(struct cdev *dev, int events, struct thread *td) 1030155408Srwatson{ 1031155408Srwatson struct audit_pipe *ap; 1032155408Srwatson int revents; 1033155408Srwatson 1034155408Srwatson revents = 0; 1035155408Srwatson ap = dev->si_drv1; 1036155408Srwatson KASSERT(ap != NULL, ("audit_pipe_poll: ap == NULL")); 1037184488Srwatson 1038155408Srwatson if (events & (POLLIN | POLLRDNORM)) { 1039184488Srwatson AUDIT_PIPE_LOCK(ap); 1040155408Srwatson if (TAILQ_FIRST(&ap->ap_queue) != NULL) 1041155408Srwatson revents |= events & (POLLIN | POLLRDNORM); 1042155408Srwatson else 1043155408Srwatson selrecord(td, &ap->ap_selinfo); 1044184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1045155408Srwatson } 1046155408Srwatson return (revents); 1047155408Srwatson} 1048155408Srwatson 1049155408Srwatson/* 1050161582Srwatson * Audit pipe kqfilter. 1051161582Srwatson */ 1052161582Srwatsonstatic int 1053161582Srwatsonaudit_pipe_kqfilter(struct cdev *dev, struct knote *kn) 1054161582Srwatson{ 1055161582Srwatson struct audit_pipe *ap; 1056161582Srwatson 1057161582Srwatson ap = dev->si_drv1; 1058161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqfilter: ap == NULL")); 1059161582Srwatson 1060161582Srwatson if (kn->kn_filter != EVFILT_READ) 1061161582Srwatson return (EINVAL); 1062161582Srwatson 1063161582Srwatson kn->kn_fop = &audit_pipe_read_filterops; 1064161582Srwatson kn->kn_hook = ap; 1065161582Srwatson 1066184488Srwatson AUDIT_PIPE_LOCK(ap); 1067161582Srwatson knlist_add(&ap->ap_selinfo.si_note, kn, 1); 1068184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1069161582Srwatson return (0); 1070161582Srwatson} 1071161582Srwatson 1072161582Srwatson/* 1073161582Srwatson * Return true if there are records available for reading on the pipe. 1074161582Srwatson */ 1075161582Srwatsonstatic int 1076161582Srwatsonaudit_pipe_kqread(struct knote *kn, long hint) 1077161582Srwatson{ 1078161582Srwatson struct audit_pipe_entry *ape; 1079161582Srwatson struct audit_pipe *ap; 1080161582Srwatson 1081161582Srwatson ap = (struct audit_pipe *)kn->kn_hook; 1082161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqread: ap == NULL")); 1083161582Srwatson 1084184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 1085184488Srwatson 1086161582Srwatson if (ap->ap_qlen != 0) { 1087161582Srwatson ape = TAILQ_FIRST(&ap->ap_queue); 1088161582Srwatson KASSERT(ape != NULL, ("audit_pipe_kqread: ape == NULL")); 1089161582Srwatson 1090184536Srwatson kn->kn_data = ap->ap_qbyteslen - ap->ap_qoffset; 1091161582Srwatson return (1); 1092161582Srwatson } else { 1093161582Srwatson kn->kn_data = 0; 1094161582Srwatson return (0); 1095161582Srwatson } 1096161582Srwatson} 1097161582Srwatson 1098161582Srwatson/* 1099161582Srwatson * Detach kqueue state from audit pipe. 1100161582Srwatson */ 1101161582Srwatsonstatic void 1102161582Srwatsonaudit_pipe_kqdetach(struct knote *kn) 1103161582Srwatson{ 1104161582Srwatson struct audit_pipe *ap; 1105161582Srwatson 1106161582Srwatson ap = (struct audit_pipe *)kn->kn_hook; 1107161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqdetach: ap == NULL")); 1108161582Srwatson 1109184488Srwatson AUDIT_PIPE_LOCK(ap); 1110161582Srwatson knlist_remove(&ap->ap_selinfo.si_note, kn, 1); 1111184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1112161582Srwatson} 1113161582Srwatson 1114161582Srwatson/* 1115155408Srwatson * Initialize the audit pipe system. 1116155408Srwatson */ 1117155408Srwatsonstatic void 1118155408Srwatsonaudit_pipe_init(void *unused) 1119155408Srwatson{ 1120155408Srwatson 1121155408Srwatson TAILQ_INIT(&audit_pipe_list); 1122184488Srwatson AUDIT_PIPE_LIST_LOCK_INIT(); 1123155408Srwatson 1124155408Srwatson clone_setup(&audit_pipe_clones); 1125155408Srwatson audit_pipe_eh_tag = EVENTHANDLER_REGISTER(dev_clone, 1126155408Srwatson audit_pipe_clone, 0, 1000); 1127155408Srwatson if (audit_pipe_eh_tag == NULL) 1128155408Srwatson panic("audit_pipe_init: EVENTHANDLER_REGISTER"); 1129155408Srwatson} 1130155408Srwatson 1131155408SrwatsonSYSINIT(audit_pipe_init, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, audit_pipe_init, 1132155408Srwatson NULL); 1133