audit_pipe.c revision 184545
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 184545 2008-11-02 00:25:48Z 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 60184545Srwatson * audit data. Consumers receive a "tee" of the system audit trail by 61184545Srwatson * default, but may also define alternative event selections using ioctls. 62184545Srwatson * This interface provides unreliable but timely access to audit events. 63184545Srwatson * Consumers should be very careful to avoid introducing event cycles. 64155408Srwatson */ 65155408Srwatson 66155408Srwatson/* 67155408Srwatson * Memory types. 68155408Srwatson */ 69155408Srwatsonstatic MALLOC_DEFINE(M_AUDIT_PIPE, "audit_pipe", "Audit pipes"); 70155408Srwatsonstatic MALLOC_DEFINE(M_AUDIT_PIPE_ENTRY, "audit_pipeent", 71155408Srwatson "Audit pipe entries and buffers"); 72174894Swkoszekstatic MALLOC_DEFINE(M_AUDIT_PIPE_PRESELECT, "audit_pipe_presel", 73159269Srwatson "Audit pipe preselection structure"); 74155408Srwatson 75155408Srwatson/* 76155408Srwatson * Audit pipe buffer parameters. 77155408Srwatson */ 78156883Srwatson#define AUDIT_PIPE_QLIMIT_DEFAULT (128) 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 */ 736155408Srwatsonstatic int 737155408Srwatsonaudit_pipe_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, 738155408Srwatson struct thread *td) 739155408Srwatson{ 740159269Srwatson struct auditpipe_ioctl_preselect *aip; 741155408Srwatson struct audit_pipe *ap; 742159269Srwatson au_mask_t *maskp; 743159269Srwatson int error, mode; 744159269Srwatson au_id_t auid; 745155408Srwatson 746155408Srwatson ap = dev->si_drv1; 747155408Srwatson KASSERT(ap != NULL, ("audit_pipe_ioctl: ap == NULL")); 748159269Srwatson 749159269Srwatson /* 750159269Srwatson * Audit pipe ioctls: first come standard device node ioctls, then 751159269Srwatson * manipulation of pipe settings, and finally, statistics query 752159269Srwatson * ioctls. 753159269Srwatson */ 754155408Srwatson switch (cmd) { 755155408Srwatson case FIONBIO: 756184488Srwatson AUDIT_PIPE_LOCK(ap); 757155408Srwatson if (*(int *)data) 758155408Srwatson ap->ap_flags |= AUDIT_PIPE_NBIO; 759155408Srwatson else 760155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_NBIO; 761184488Srwatson AUDIT_PIPE_UNLOCK(ap); 762155408Srwatson error = 0; 763155408Srwatson break; 764155408Srwatson 765155408Srwatson case FIONREAD: 766184488Srwatson AUDIT_PIPE_LOCK(ap); 767184536Srwatson *(int *)data = ap->ap_qbyteslen - ap->ap_qoffset; 768184488Srwatson AUDIT_PIPE_UNLOCK(ap); 769155408Srwatson error = 0; 770155408Srwatson break; 771155408Srwatson 772155408Srwatson case FIOASYNC: 773184488Srwatson AUDIT_PIPE_LOCK(ap); 774155408Srwatson if (*(int *)data) 775155408Srwatson ap->ap_flags |= AUDIT_PIPE_ASYNC; 776155408Srwatson else 777155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_ASYNC; 778184488Srwatson AUDIT_PIPE_UNLOCK(ap); 779155408Srwatson error = 0; 780155408Srwatson break; 781155408Srwatson 782155408Srwatson case FIOSETOWN: 783155408Srwatson error = fsetown(*(int *)data, &ap->ap_sigio); 784155408Srwatson break; 785155408Srwatson 786155408Srwatson case FIOGETOWN: 787155408Srwatson *(int *)data = fgetown(&ap->ap_sigio); 788155408Srwatson error = 0; 789156880Srwatson break; 790155408Srwatson 791156880Srwatson case AUDITPIPE_GET_QLEN: 792156880Srwatson *(u_int *)data = ap->ap_qlen; 793156880Srwatson error = 0; 794156880Srwatson break; 795156880Srwatson 796156880Srwatson case AUDITPIPE_GET_QLIMIT: 797156880Srwatson *(u_int *)data = ap->ap_qlimit; 798156880Srwatson error = 0; 799156880Srwatson break; 800156880Srwatson 801156880Srwatson case AUDITPIPE_SET_QLIMIT: 802156880Srwatson /* Lockless integer write. */ 803156880Srwatson if (*(u_int *)data >= AUDIT_PIPE_QLIMIT_MIN || 804156880Srwatson *(u_int *)data <= AUDIT_PIPE_QLIMIT_MAX) { 805156880Srwatson ap->ap_qlimit = *(u_int *)data; 806156880Srwatson error = 0; 807156880Srwatson } else 808156880Srwatson error = EINVAL; 809156880Srwatson break; 810156880Srwatson 811156884Srwatson case AUDITPIPE_GET_QLIMIT_MIN: 812156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MIN; 813156884Srwatson error = 0; 814156884Srwatson break; 815156884Srwatson 816156884Srwatson case AUDITPIPE_GET_QLIMIT_MAX: 817156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MAX; 818156884Srwatson error = 0; 819156884Srwatson break; 820156884Srwatson 821159269Srwatson case AUDITPIPE_GET_PRESELECT_FLAGS: 822184488Srwatson AUDIT_PIPE_LOCK(ap); 823159269Srwatson maskp = (au_mask_t *)data; 824159269Srwatson *maskp = ap->ap_preselect_flags; 825184488Srwatson AUDIT_PIPE_UNLOCK(ap); 826159269Srwatson error = 0; 827159269Srwatson break; 828159269Srwatson 829159269Srwatson case AUDITPIPE_SET_PRESELECT_FLAGS: 830184488Srwatson AUDIT_PIPE_LOCK(ap); 831159269Srwatson maskp = (au_mask_t *)data; 832159269Srwatson ap->ap_preselect_flags = *maskp; 833184488Srwatson AUDIT_PIPE_UNLOCK(ap); 834159269Srwatson error = 0; 835159269Srwatson break; 836159269Srwatson 837159269Srwatson case AUDITPIPE_GET_PRESELECT_NAFLAGS: 838184488Srwatson AUDIT_PIPE_LOCK(ap); 839159269Srwatson maskp = (au_mask_t *)data; 840159269Srwatson *maskp = ap->ap_preselect_naflags; 841184488Srwatson AUDIT_PIPE_UNLOCK(ap); 842159269Srwatson error = 0; 843159269Srwatson break; 844159269Srwatson 845159269Srwatson case AUDITPIPE_SET_PRESELECT_NAFLAGS: 846184488Srwatson AUDIT_PIPE_LOCK(ap); 847159269Srwatson maskp = (au_mask_t *)data; 848159269Srwatson ap->ap_preselect_naflags = *maskp; 849184488Srwatson AUDIT_PIPE_UNLOCK(ap); 850159269Srwatson error = 0; 851159269Srwatson break; 852159269Srwatson 853159269Srwatson case AUDITPIPE_GET_PRESELECT_AUID: 854159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 855159269Srwatson error = audit_pipe_preselect_get(ap, aip->aip_auid, 856159269Srwatson &aip->aip_mask); 857159269Srwatson break; 858159269Srwatson 859159269Srwatson case AUDITPIPE_SET_PRESELECT_AUID: 860159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 861159269Srwatson audit_pipe_preselect_set(ap, aip->aip_auid, aip->aip_mask); 862159269Srwatson error = 0; 863159269Srwatson break; 864159269Srwatson 865159269Srwatson case AUDITPIPE_DELETE_PRESELECT_AUID: 866159269Srwatson auid = *(au_id_t *)data; 867159269Srwatson error = audit_pipe_preselect_delete(ap, auid); 868159269Srwatson break; 869159269Srwatson 870159269Srwatson case AUDITPIPE_FLUSH_PRESELECT_AUID: 871159269Srwatson audit_pipe_preselect_flush(ap); 872159269Srwatson error = 0; 873159269Srwatson break; 874159269Srwatson 875159269Srwatson case AUDITPIPE_GET_PRESELECT_MODE: 876184488Srwatson AUDIT_PIPE_LOCK(ap); 877159269Srwatson *(int *)data = ap->ap_preselect_mode; 878184488Srwatson AUDIT_PIPE_UNLOCK(ap); 879159269Srwatson error = 0; 880159269Srwatson break; 881159269Srwatson 882159269Srwatson case AUDITPIPE_SET_PRESELECT_MODE: 883159269Srwatson mode = *(int *)data; 884159269Srwatson switch (mode) { 885159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 886159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 887184488Srwatson AUDIT_PIPE_LOCK(ap); 888159269Srwatson ap->ap_preselect_mode = mode; 889184488Srwatson AUDIT_PIPE_UNLOCK(ap); 890159269Srwatson error = 0; 891159269Srwatson break; 892159269Srwatson 893159269Srwatson default: 894159269Srwatson error = EINVAL; 895159269Srwatson } 896159269Srwatson break; 897159269Srwatson 898159269Srwatson case AUDITPIPE_FLUSH: 899184508Srwatson if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) 900184508Srwatson return (EINTR); 901184488Srwatson AUDIT_PIPE_LOCK(ap); 902159269Srwatson audit_pipe_flush(ap); 903184488Srwatson AUDIT_PIPE_UNLOCK(ap); 904184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 905159269Srwatson error = 0; 906159269Srwatson break; 907159269Srwatson 908161646Srwatson case AUDITPIPE_GET_MAXAUDITDATA: 909161646Srwatson *(u_int *)data = MAXAUDITDATA; 910161646Srwatson error = 0; 911161646Srwatson break; 912161646Srwatson 913156880Srwatson case AUDITPIPE_GET_INSERTS: 914156880Srwatson *(u_int *)data = ap->ap_inserts; 915156880Srwatson error = 0; 916156880Srwatson break; 917156880Srwatson 918156880Srwatson case AUDITPIPE_GET_READS: 919156880Srwatson *(u_int *)data = ap->ap_reads; 920156880Srwatson error = 0; 921156880Srwatson break; 922156880Srwatson 923156880Srwatson case AUDITPIPE_GET_DROPS: 924156880Srwatson *(u_int *)data = ap->ap_drops; 925156880Srwatson error = 0; 926156880Srwatson break; 927156880Srwatson 928156880Srwatson case AUDITPIPE_GET_TRUNCATES: 929184510Srwatson *(u_int *)data = 0; 930156880Srwatson error = 0; 931156880Srwatson break; 932156880Srwatson 933155408Srwatson default: 934155408Srwatson error = ENOTTY; 935155408Srwatson } 936155408Srwatson return (error); 937155408Srwatson} 938155408Srwatson 939155408Srwatson/* 940184534Srwatson * Audit pipe read. Read one or more partial or complete records to user 941184534Srwatson * memory. 942155408Srwatson */ 943155408Srwatsonstatic int 944155408Srwatsonaudit_pipe_read(struct cdev *dev, struct uio *uio, int flag) 945155408Srwatson{ 946155408Srwatson struct audit_pipe_entry *ape; 947155408Srwatson struct audit_pipe *ap; 948184508Srwatson u_int toread; 949155408Srwatson int error; 950155408Srwatson 951155408Srwatson ap = dev->si_drv1; 952155408Srwatson KASSERT(ap != NULL, ("audit_pipe_read: ap == NULL")); 953184488Srwatson 954184508Srwatson /* 955184508Srwatson * We hold an sx(9) lock over read and flush because we rely on the 956184508Srwatson * stability of a record in the queue during uiomove(9). 957184508Srwatson */ 958184508Srwatson if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) 959184508Srwatson return (EINTR); 960184488Srwatson AUDIT_PIPE_LOCK(ap); 961184508Srwatson while (TAILQ_EMPTY(&ap->ap_queue)) { 962184508Srwatson if (ap->ap_flags & AUDIT_PIPE_NBIO) { 963184508Srwatson AUDIT_PIPE_UNLOCK(ap); 964184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 965184508Srwatson return (EAGAIN); 966155408Srwatson } 967184508Srwatson error = cv_wait_sig(&ap->ap_cv, AUDIT_PIPE_MTX(ap)); 968184508Srwatson if (error) { 969184508Srwatson AUDIT_PIPE_UNLOCK(ap); 970184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 971184508Srwatson return (error); 972184508Srwatson } 973184508Srwatson } 974184508Srwatson 975184508Srwatson /* 976184508Srwatson * Copy as many remaining bytes from the current record to userspace 977184534Srwatson * as we can. Keep processing records until we run out of records in 978184534Srwatson * the queue, or until the user buffer runs out of space. 979184508Srwatson * 980184508Srwatson * Note: we rely on the SX lock to maintain ape's stability here. 981184508Srwatson */ 982173083Scsjp ap->ap_reads++; 983184534Srwatson while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL && 984184534Srwatson uio->uio_resid > 0) { 985184534Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 986184534Srwatson 987184536Srwatson KASSERT(ape->ape_record_len > ap->ap_qoffset, 988184536Srwatson ("audit_pipe_read: record_len > qoffset (1)")); 989184536Srwatson toread = MIN(ape->ape_record_len - ap->ap_qoffset, 990184534Srwatson uio->uio_resid); 991184534Srwatson AUDIT_PIPE_UNLOCK(ap); 992184536Srwatson error = uiomove((char *)ape->ape_record + ap->ap_qoffset, 993184536Srwatson toread, uio); 994184534Srwatson if (error) { 995184534Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 996184534Srwatson return (error); 997184534Srwatson } 998184534Srwatson 999184534Srwatson /* 1000184534Srwatson * If the copy succeeded, update book-keeping, and if no 1001184534Srwatson * bytes remain in the current record, free it. 1002184534Srwatson */ 1003184534Srwatson AUDIT_PIPE_LOCK(ap); 1004184534Srwatson KASSERT(TAILQ_FIRST(&ap->ap_queue) == ape, 1005184534Srwatson ("audit_pipe_read: queue out of sync after uiomove")); 1006184536Srwatson ap->ap_qoffset += toread; 1007184536Srwatson KASSERT(ape->ape_record_len >= ap->ap_qoffset, 1008184536Srwatson ("audit_pipe_read: record_len >= qoffset (2)")); 1009184536Srwatson if (ap->ap_qoffset == ape->ape_record_len) { 1010184534Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 1011184536Srwatson ap->ap_qbyteslen -= ape->ape_record_len; 1012184534Srwatson audit_pipe_entry_free(ape); 1013184534Srwatson ap->ap_qlen--; 1014184536Srwatson ap->ap_qoffset = 0; 1015184534Srwatson } 1016184508Srwatson } 1017184508Srwatson AUDIT_PIPE_UNLOCK(ap); 1018184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 1019184534Srwatson return (0); 1020155408Srwatson} 1021155408Srwatson 1022155408Srwatson/* 1023155408Srwatson * Audit pipe poll. 1024155408Srwatson */ 1025155408Srwatsonstatic int 1026155408Srwatsonaudit_pipe_poll(struct cdev *dev, int events, struct thread *td) 1027155408Srwatson{ 1028155408Srwatson struct audit_pipe *ap; 1029155408Srwatson int revents; 1030155408Srwatson 1031155408Srwatson revents = 0; 1032155408Srwatson ap = dev->si_drv1; 1033155408Srwatson KASSERT(ap != NULL, ("audit_pipe_poll: ap == NULL")); 1034184488Srwatson 1035155408Srwatson if (events & (POLLIN | POLLRDNORM)) { 1036184488Srwatson AUDIT_PIPE_LOCK(ap); 1037155408Srwatson if (TAILQ_FIRST(&ap->ap_queue) != NULL) 1038155408Srwatson revents |= events & (POLLIN | POLLRDNORM); 1039155408Srwatson else 1040155408Srwatson selrecord(td, &ap->ap_selinfo); 1041184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1042155408Srwatson } 1043155408Srwatson return (revents); 1044155408Srwatson} 1045155408Srwatson 1046155408Srwatson/* 1047161582Srwatson * Audit pipe kqfilter. 1048161582Srwatson */ 1049161582Srwatsonstatic int 1050161582Srwatsonaudit_pipe_kqfilter(struct cdev *dev, struct knote *kn) 1051161582Srwatson{ 1052161582Srwatson struct audit_pipe *ap; 1053161582Srwatson 1054161582Srwatson ap = dev->si_drv1; 1055161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqfilter: ap == NULL")); 1056161582Srwatson 1057161582Srwatson if (kn->kn_filter != EVFILT_READ) 1058161582Srwatson return (EINVAL); 1059161582Srwatson 1060161582Srwatson kn->kn_fop = &audit_pipe_read_filterops; 1061161582Srwatson kn->kn_hook = ap; 1062161582Srwatson 1063184488Srwatson AUDIT_PIPE_LOCK(ap); 1064161582Srwatson knlist_add(&ap->ap_selinfo.si_note, kn, 1); 1065184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1066161582Srwatson return (0); 1067161582Srwatson} 1068161582Srwatson 1069161582Srwatson/* 1070161582Srwatson * Return true if there are records available for reading on the pipe. 1071161582Srwatson */ 1072161582Srwatsonstatic int 1073161582Srwatsonaudit_pipe_kqread(struct knote *kn, long hint) 1074161582Srwatson{ 1075161582Srwatson struct audit_pipe_entry *ape; 1076161582Srwatson struct audit_pipe *ap; 1077161582Srwatson 1078161582Srwatson ap = (struct audit_pipe *)kn->kn_hook; 1079161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqread: ap == NULL")); 1080161582Srwatson 1081184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 1082184488Srwatson 1083161582Srwatson if (ap->ap_qlen != 0) { 1084161582Srwatson ape = TAILQ_FIRST(&ap->ap_queue); 1085161582Srwatson KASSERT(ape != NULL, ("audit_pipe_kqread: ape == NULL")); 1086161582Srwatson 1087184536Srwatson kn->kn_data = ap->ap_qbyteslen - ap->ap_qoffset; 1088161582Srwatson return (1); 1089161582Srwatson } else { 1090161582Srwatson kn->kn_data = 0; 1091161582Srwatson return (0); 1092161582Srwatson } 1093161582Srwatson} 1094161582Srwatson 1095161582Srwatson/* 1096161582Srwatson * Detach kqueue state from audit pipe. 1097161582Srwatson */ 1098161582Srwatsonstatic void 1099161582Srwatsonaudit_pipe_kqdetach(struct knote *kn) 1100161582Srwatson{ 1101161582Srwatson struct audit_pipe *ap; 1102161582Srwatson 1103161582Srwatson ap = (struct audit_pipe *)kn->kn_hook; 1104161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqdetach: ap == NULL")); 1105161582Srwatson 1106184488Srwatson AUDIT_PIPE_LOCK(ap); 1107161582Srwatson knlist_remove(&ap->ap_selinfo.si_note, kn, 1); 1108184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1109161582Srwatson} 1110161582Srwatson 1111161582Srwatson/* 1112155408Srwatson * Initialize the audit pipe system. 1113155408Srwatson */ 1114155408Srwatsonstatic void 1115155408Srwatsonaudit_pipe_init(void *unused) 1116155408Srwatson{ 1117155408Srwatson 1118155408Srwatson TAILQ_INIT(&audit_pipe_list); 1119184488Srwatson AUDIT_PIPE_LIST_LOCK_INIT(); 1120155408Srwatson 1121155408Srwatson clone_setup(&audit_pipe_clones); 1122155408Srwatson audit_pipe_eh_tag = EVENTHANDLER_REGISTER(dev_clone, 1123155408Srwatson audit_pipe_clone, 0, 1000); 1124155408Srwatson if (audit_pipe_eh_tag == NULL) 1125155408Srwatson panic("audit_pipe_init: EVENTHANDLER_REGISTER"); 1126155408Srwatson} 1127155408Srwatson 1128155408SrwatsonSYSINIT(audit_pipe_init, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, audit_pipe_init, 1129155408Srwatson NULL); 1130