audit_pipe.c revision 184536
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 184536 2008-11-01 21:56:45Z 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 152155408Srwatson u_int64_t ap_inserts; /* Records added. */ 153155408Srwatson u_int64_t ap_reads; /* Records read. */ 154155408Srwatson u_int64_t ap_drops; /* Records dropped. */ 155155408Srwatson 156159269Srwatson /* 157159269Srwatson * Fields relating to pipe interest: global masks for unmatched 158159269Srwatson * processes (attributable, non-attributable), and a list of specific 159159269Srwatson * interest specifications by auid. 160159269Srwatson */ 161159269Srwatson int ap_preselect_mode; 162159269Srwatson au_mask_t ap_preselect_flags; 163159269Srwatson au_mask_t ap_preselect_naflags; 164159269Srwatson TAILQ_HEAD(, audit_pipe_preselect) ap_preselect_list; 165159269Srwatson 166159269Srwatson /* 167184508Srwatson * Current pending record list. Protected by a combination of ap_mtx 168184508Srwatson * and ap_sx. Note particularly that *both* locks are required to 169184508Srwatson * remove a record from the head of the queue, as an in-progress read * may sleep while copying and therefore cannot hold ap_mtx. 170159269Srwatson */ 171155408Srwatson TAILQ_HEAD(, audit_pipe_entry) ap_queue; 172155408Srwatson 173159269Srwatson /* 174159269Srwatson * Global pipe list. 175159269Srwatson */ 176155408Srwatson TAILQ_ENTRY(audit_pipe) ap_list; 177155408Srwatson}; 178155408Srwatson 179184508Srwatson#define AUDIT_PIPE_LOCK(ap) mtx_lock(&(ap)->ap_mtx) 180184508Srwatson#define AUDIT_PIPE_LOCK_ASSERT(ap) mtx_assert(&(ap)->ap_mtx, MA_OWNED) 181184508Srwatson#define AUDIT_PIPE_LOCK_DESTROY(ap) mtx_destroy(&(ap)->ap_mtx) 182184508Srwatson#define AUDIT_PIPE_LOCK_INIT(ap) mtx_init(&(ap)->ap_mtx, \ 183184508Srwatson "audit_pipe_mtx", NULL, MTX_DEF) 184184508Srwatson#define AUDIT_PIPE_UNLOCK(ap) mtx_unlock(&(ap)->ap_mtx) 185184508Srwatson#define AUDIT_PIPE_MTX(ap) (&(ap)->ap_mtx) 186184488Srwatson 187184508Srwatson#define AUDIT_PIPE_SX_LOCK_DESTROY(ap) sx_destroy(&(ap)->ap_sx) 188184508Srwatson#define AUDIT_PIPE_SX_LOCK_INIT(ap) sx_init(&(ap)->ap_sx, "audit_pipe_sx") 189184508Srwatson#define AUDIT_PIPE_SX_XLOCK_ASSERT(ap) sx_assert(&(ap)->ap_sx, SA_XLOCKED) 190184508Srwatson#define AUDIT_PIPE_SX_XLOCK_SIG(ap) sx_xlock_sig(&(ap)->ap_sx) 191184508Srwatson#define AUDIT_PIPE_SX_XUNLOCK(ap) sx_xunlock(&(ap)->ap_sx) 192184508Srwatson 193155408Srwatson/* 194184488Srwatson * Global list of audit pipes, rwlock to protect it. Individual record 195184488Srwatson * queues on pipes are protected by per-pipe locks; these locks synchronize 196184488Srwatson * between threads walking the list to deliver to individual pipes and add/ 197184488Srwatson * remove of pipes, and are mostly acquired for read. 198155408Srwatson */ 199155408Srwatsonstatic TAILQ_HEAD(, audit_pipe) audit_pipe_list; 200184488Srwatsonstatic struct rwlock audit_pipe_lock; 201155408Srwatson 202184488Srwatson#define AUDIT_PIPE_LIST_LOCK_INIT() rw_init(&audit_pipe_lock, \ 203184488Srwatson "audit_pipe_list_lock") 204184488Srwatson#define AUDIT_PIPE_LIST_RLOCK() rw_rlock(&audit_pipe_lock) 205184488Srwatson#define AUDIT_PIPE_LIST_RUNLOCK() rw_runlock(&audit_pipe_lock) 206184488Srwatson#define AUDIT_PIPE_LIST_WLOCK() rw_wlock(&audit_pipe_lock) 207184488Srwatson#define AUDIT_PIPE_LIST_WLOCK_ASSERT() rw_assert(&audit_pipe_lock, \ 208184488Srwatson RA_WLOCKED) 209184488Srwatson#define AUDIT_PIPE_LIST_WUNLOCK() rw_wunlock(&audit_pipe_lock) 210155408Srwatson 211155408Srwatson/* 212155408Srwatson * Cloning related variables and constants. 213155408Srwatson */ 214155408Srwatson#define AUDIT_PIPE_NAME "auditpipe" 215155408Srwatsonstatic eventhandler_tag audit_pipe_eh_tag; 216155408Srwatsonstatic struct clonedevs *audit_pipe_clones; 217155408Srwatson 218155408Srwatson/* 219155408Srwatson * Special device methods and definition. 220155408Srwatson */ 221155408Srwatsonstatic d_open_t audit_pipe_open; 222155408Srwatsonstatic d_close_t audit_pipe_close; 223155408Srwatsonstatic d_read_t audit_pipe_read; 224155408Srwatsonstatic d_ioctl_t audit_pipe_ioctl; 225155408Srwatsonstatic d_poll_t audit_pipe_poll; 226161582Srwatsonstatic d_kqfilter_t audit_pipe_kqfilter; 227155408Srwatson 228155408Srwatsonstatic struct cdevsw audit_pipe_cdevsw = { 229155408Srwatson .d_version = D_VERSION, 230179726Sed .d_flags = D_PSEUDO | D_NEEDGIANT | D_NEEDMINOR, 231155408Srwatson .d_open = audit_pipe_open, 232155408Srwatson .d_close = audit_pipe_close, 233155408Srwatson .d_read = audit_pipe_read, 234155408Srwatson .d_ioctl = audit_pipe_ioctl, 235155408Srwatson .d_poll = audit_pipe_poll, 236161582Srwatson .d_kqfilter = audit_pipe_kqfilter, 237155408Srwatson .d_name = AUDIT_PIPE_NAME, 238155408Srwatson}; 239155408Srwatson 240161582Srwatsonstatic int audit_pipe_kqread(struct knote *note, long hint); 241161582Srwatsonstatic void audit_pipe_kqdetach(struct knote *note); 242161582Srwatson 243161582Srwatsonstatic struct filterops audit_pipe_read_filterops = { 244161582Srwatson .f_isfd = 1, 245161582Srwatson .f_attach = NULL, 246161582Srwatson .f_detach = audit_pipe_kqdetach, 247161582Srwatson .f_event = audit_pipe_kqread, 248161582Srwatson}; 249161582Srwatson 250155408Srwatson/* 251155408Srwatson * Some global statistics on audit pipes. 252155408Srwatson */ 253155408Srwatsonstatic int audit_pipe_count; /* Current number of pipes. */ 254155408Srwatsonstatic u_int64_t audit_pipe_ever; /* Pipes ever allocated. */ 255155408Srwatsonstatic u_int64_t audit_pipe_records; /* Records seen. */ 256155408Srwatsonstatic u_int64_t audit_pipe_drops; /* Global record drop count. */ 257155408Srwatson 258155408Srwatson/* 259155408Srwatson * Free an audit pipe entry. 260155408Srwatson */ 261155408Srwatsonstatic void 262155408Srwatsonaudit_pipe_entry_free(struct audit_pipe_entry *ape) 263155408Srwatson{ 264155408Srwatson 265155408Srwatson free(ape->ape_record, M_AUDIT_PIPE_ENTRY); 266155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 267155408Srwatson} 268155408Srwatson 269155408Srwatson/* 270159269Srwatson * Find an audit pipe preselection specification for an auid, if any. 271159269Srwatson */ 272159269Srwatsonstatic struct audit_pipe_preselect * 273159269Srwatsonaudit_pipe_preselect_find(struct audit_pipe *ap, au_id_t auid) 274159269Srwatson{ 275159269Srwatson struct audit_pipe_preselect *app; 276159269Srwatson 277184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 278159269Srwatson 279159269Srwatson TAILQ_FOREACH(app, &ap->ap_preselect_list, app_list) { 280159269Srwatson if (app->app_auid == auid) 281159269Srwatson return (app); 282159269Srwatson } 283159269Srwatson return (NULL); 284159269Srwatson} 285159269Srwatson 286159269Srwatson/* 287159269Srwatson * Query the per-pipe mask for a specific auid. 288159269Srwatson */ 289159269Srwatsonstatic int 290159269Srwatsonaudit_pipe_preselect_get(struct audit_pipe *ap, au_id_t auid, 291159269Srwatson au_mask_t *maskp) 292159269Srwatson{ 293159269Srwatson struct audit_pipe_preselect *app; 294159269Srwatson int error; 295159269Srwatson 296184488Srwatson AUDIT_PIPE_LOCK(ap); 297159269Srwatson app = audit_pipe_preselect_find(ap, auid); 298159269Srwatson if (app != NULL) { 299159269Srwatson *maskp = app->app_mask; 300159269Srwatson error = 0; 301159269Srwatson } else 302159269Srwatson error = ENOENT; 303184488Srwatson AUDIT_PIPE_UNLOCK(ap); 304159269Srwatson return (error); 305159269Srwatson} 306159269Srwatson 307159269Srwatson/* 308159269Srwatson * Set the per-pipe mask for a specific auid. Add a new entry if needed; 309159269Srwatson * otherwise, update the current entry. 310159269Srwatson */ 311159269Srwatsonstatic void 312159269Srwatsonaudit_pipe_preselect_set(struct audit_pipe *ap, au_id_t auid, au_mask_t mask) 313159269Srwatson{ 314159269Srwatson struct audit_pipe_preselect *app, *app_new; 315159269Srwatson 316159269Srwatson /* 317159269Srwatson * Pessimistically assume that the auid doesn't already have a mask 318159269Srwatson * set, and allocate. We will free it if it is unneeded. 319159269Srwatson */ 320159269Srwatson app_new = malloc(sizeof(*app_new), M_AUDIT_PIPE_PRESELECT, M_WAITOK); 321184488Srwatson AUDIT_PIPE_LOCK(ap); 322159269Srwatson app = audit_pipe_preselect_find(ap, auid); 323159269Srwatson if (app == NULL) { 324159269Srwatson app = app_new; 325159269Srwatson app_new = NULL; 326159269Srwatson app->app_auid = auid; 327159269Srwatson TAILQ_INSERT_TAIL(&ap->ap_preselect_list, app, app_list); 328159269Srwatson } 329159269Srwatson app->app_mask = mask; 330184488Srwatson AUDIT_PIPE_UNLOCK(ap); 331159269Srwatson if (app_new != NULL) 332159269Srwatson free(app_new, M_AUDIT_PIPE_PRESELECT); 333159269Srwatson} 334159269Srwatson 335159269Srwatson/* 336159269Srwatson * Delete a per-auid mask on an audit pipe. 337159269Srwatson */ 338159269Srwatsonstatic int 339159269Srwatsonaudit_pipe_preselect_delete(struct audit_pipe *ap, au_id_t auid) 340159269Srwatson{ 341159269Srwatson struct audit_pipe_preselect *app; 342159269Srwatson int error; 343159269Srwatson 344184488Srwatson AUDIT_PIPE_LOCK(ap); 345159269Srwatson app = audit_pipe_preselect_find(ap, auid); 346159269Srwatson if (app != NULL) { 347159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 348159269Srwatson error = 0; 349159269Srwatson } else 350159269Srwatson error = ENOENT; 351184488Srwatson AUDIT_PIPE_UNLOCK(ap); 352159269Srwatson if (app != NULL) 353159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 354159269Srwatson return (error); 355159269Srwatson} 356159269Srwatson 357159269Srwatson/* 358159269Srwatson * Delete all per-auid masks on an audit pipe. 359159269Srwatson */ 360159269Srwatsonstatic void 361159269Srwatsonaudit_pipe_preselect_flush_locked(struct audit_pipe *ap) 362159269Srwatson{ 363159269Srwatson struct audit_pipe_preselect *app; 364159269Srwatson 365184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 366159269Srwatson 367159269Srwatson while ((app = TAILQ_FIRST(&ap->ap_preselect_list)) != NULL) { 368159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 369159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 370159269Srwatson } 371159269Srwatson} 372159269Srwatson 373159269Srwatsonstatic void 374159269Srwatsonaudit_pipe_preselect_flush(struct audit_pipe *ap) 375159269Srwatson{ 376159269Srwatson 377184488Srwatson AUDIT_PIPE_LOCK(ap); 378159269Srwatson audit_pipe_preselect_flush_locked(ap); 379184488Srwatson AUDIT_PIPE_UNLOCK(ap); 380159269Srwatson} 381159269Srwatson 382170196Srwatson/*- 383159269Srwatson * Determine whether a specific audit pipe matches a record with these 384159269Srwatson * properties. Algorithm is as follows: 385159269Srwatson * 386159269Srwatson * - If the pipe is configured to track the default trail configuration, then 387159269Srwatson * use the results of global preselection matching. 388159269Srwatson * - If not, search for a specifically configured auid entry matching the 389159269Srwatson * event. If an entry is found, use that. 390159269Srwatson * - Otherwise, use the default flags or naflags configured for the pipe. 391159269Srwatson */ 392159269Srwatsonstatic int 393159269Srwatsonaudit_pipe_preselect_check(struct audit_pipe *ap, au_id_t auid, 394159269Srwatson au_event_t event, au_class_t class, int sorf, int trail_preselect) 395159269Srwatson{ 396159269Srwatson struct audit_pipe_preselect *app; 397159269Srwatson 398184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 399159269Srwatson 400159269Srwatson switch (ap->ap_preselect_mode) { 401159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 402159269Srwatson return (trail_preselect); 403159269Srwatson 404159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 405159269Srwatson app = audit_pipe_preselect_find(ap, auid); 406159269Srwatson if (app == NULL) { 407159269Srwatson if (auid == AU_DEFAUDITID) 408159269Srwatson return (au_preselect(event, class, 409159269Srwatson &ap->ap_preselect_naflags, sorf)); 410159269Srwatson else 411159269Srwatson return (au_preselect(event, class, 412159269Srwatson &ap->ap_preselect_flags, sorf)); 413159269Srwatson } else 414159269Srwatson return (au_preselect(event, class, &app->app_mask, 415159269Srwatson sorf)); 416159269Srwatson 417159269Srwatson default: 418159269Srwatson panic("audit_pipe_preselect_check: mode %d", 419159269Srwatson ap->ap_preselect_mode); 420159269Srwatson } 421159269Srwatson 422159269Srwatson return (0); 423159269Srwatson} 424159269Srwatson 425159269Srwatson/* 426159269Srwatson * Determine whether there exists a pipe interested in a record with specific 427159269Srwatson * properties. 428159269Srwatson */ 429159269Srwatsonint 430159269Srwatsonaudit_pipe_preselect(au_id_t auid, au_event_t event, au_class_t class, 431159269Srwatson int sorf, int trail_preselect) 432159269Srwatson{ 433159269Srwatson struct audit_pipe *ap; 434159269Srwatson 435184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 436159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 437184488Srwatson AUDIT_PIPE_LOCK(ap); 438159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 439159269Srwatson trail_preselect)) { 440184488Srwatson AUDIT_PIPE_UNLOCK(ap); 441184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 442159269Srwatson return (1); 443159269Srwatson } 444184488Srwatson AUDIT_PIPE_UNLOCK(ap); 445159269Srwatson } 446184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 447159269Srwatson return (0); 448159269Srwatson} 449159269Srwatson 450159269Srwatson/* 451159269Srwatson * Append individual record to a queue -- allocate queue-local buffer, and 452184489Srwatson * add to the queue. If the queue is full or we can't allocate memory, drop 453184489Srwatson * the newest record. 454155408Srwatson */ 455155408Srwatsonstatic void 456155408Srwatsonaudit_pipe_append(struct audit_pipe *ap, void *record, u_int record_len) 457155408Srwatson{ 458184489Srwatson struct audit_pipe_entry *ape; 459155408Srwatson 460184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 461155408Srwatson 462184489Srwatson if (ap->ap_qlen >= ap->ap_qlimit) { 463184489Srwatson ap->ap_drops++; 464184489Srwatson audit_pipe_drops++; 465184489Srwatson return; 466184489Srwatson } 467184489Srwatson 468155408Srwatson ape = malloc(sizeof(*ape), M_AUDIT_PIPE_ENTRY, M_NOWAIT | M_ZERO); 469155408Srwatson if (ape == NULL) { 470155408Srwatson ap->ap_drops++; 471156292Srwatson audit_pipe_drops++; 472155408Srwatson return; 473155408Srwatson } 474155408Srwatson 475155408Srwatson ape->ape_record = malloc(record_len, M_AUDIT_PIPE_ENTRY, M_NOWAIT); 476155408Srwatson if (ape->ape_record == NULL) { 477155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 478155408Srwatson ap->ap_drops++; 479155408Srwatson audit_pipe_drops++; 480155408Srwatson return; 481155408Srwatson } 482155408Srwatson 483155408Srwatson bcopy(record, ape->ape_record, record_len); 484155408Srwatson ape->ape_record_len = record_len; 485155408Srwatson 486155408Srwatson TAILQ_INSERT_TAIL(&ap->ap_queue, ape, ape_queue); 487155408Srwatson ap->ap_inserts++; 488155408Srwatson ap->ap_qlen++; 489184536Srwatson ap->ap_qbyteslen += ape->ape_record_len; 490155408Srwatson selwakeuppri(&ap->ap_selinfo, PSOCK); 491161582Srwatson KNOTE_LOCKED(&ap->ap_selinfo.si_note, 0); 492155408Srwatson if (ap->ap_flags & AUDIT_PIPE_ASYNC) 493155408Srwatson pgsigio(&ap->ap_sigio, SIGIO, 0); 494184488Srwatson cv_broadcast(&ap->ap_cv); 495155408Srwatson} 496155408Srwatson 497155408Srwatson/* 498155408Srwatson * audit_pipe_submit(): audit_worker submits audit records via this 499155408Srwatson * interface, which arranges for them to be delivered to pipe queues. 500155408Srwatson */ 501155408Srwatsonvoid 502159269Srwatsonaudit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class, int sorf, 503159269Srwatson int trail_select, void *record, u_int record_len) 504155408Srwatson{ 505155408Srwatson struct audit_pipe *ap; 506155408Srwatson 507155408Srwatson /* 508184488Srwatson * Lockless read to avoid lock overhead if pipes are not in use. 509155408Srwatson */ 510155408Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 511155408Srwatson return; 512155408Srwatson 513184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 514159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 515184488Srwatson AUDIT_PIPE_LOCK(ap); 516159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 517159269Srwatson trail_select)) 518159269Srwatson audit_pipe_append(ap, record, record_len); 519184488Srwatson AUDIT_PIPE_UNLOCK(ap); 520159269Srwatson } 521184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 522184488Srwatson 523184488Srwatson /* Unlocked increment. */ 524159269Srwatson audit_pipe_records++; 525159269Srwatson} 526159269Srwatson 527159269Srwatson/* 528159269Srwatson * audit_pipe_submit_user(): the same as audit_pipe_submit(), except that 529159269Srwatson * since we don't currently have selection information available, it is 530159269Srwatson * delivered to the pipe unconditionally. 531159269Srwatson * 532159269Srwatson * XXXRW: This is a bug. The BSM check routine for submitting a user record 533159269Srwatson * should parse that information and return it. 534159269Srwatson */ 535159269Srwatsonvoid 536159269Srwatsonaudit_pipe_submit_user(void *record, u_int record_len) 537159269Srwatson{ 538159269Srwatson struct audit_pipe *ap; 539159269Srwatson 540159269Srwatson /* 541184488Srwatson * Lockless read to avoid lock overhead if pipes are not in use. 542159269Srwatson */ 543159269Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 544159269Srwatson return; 545159269Srwatson 546184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 547184488Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 548184488Srwatson AUDIT_PIPE_LOCK(ap); 549155408Srwatson audit_pipe_append(ap, record, record_len); 550184488Srwatson AUDIT_PIPE_UNLOCK(ap); 551184488Srwatson } 552184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 553184488Srwatson 554184488Srwatson /* Unlocked increment. */ 555155408Srwatson audit_pipe_records++; 556155408Srwatson} 557155408Srwatson 558155408Srwatson/* 559155408Srwatson * Allocate a new audit pipe. Connects the pipe, on success, to the global 560155408Srwatson * list and updates statistics. 561155408Srwatson */ 562155408Srwatsonstatic struct audit_pipe * 563155408Srwatsonaudit_pipe_alloc(void) 564155408Srwatson{ 565155408Srwatson struct audit_pipe *ap; 566155408Srwatson 567184488Srwatson AUDIT_PIPE_LIST_WLOCK_ASSERT(); 568155408Srwatson 569155408Srwatson ap = malloc(sizeof(*ap), M_AUDIT_PIPE, M_NOWAIT | M_ZERO); 570155408Srwatson if (ap == NULL) 571155408Srwatson return (NULL); 572155408Srwatson ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT; 573155408Srwatson TAILQ_INIT(&ap->ap_queue); 574184488Srwatson knlist_init(&ap->ap_selinfo.si_note, AUDIT_PIPE_MTX(ap), NULL, NULL, 575161582Srwatson NULL); 576184488Srwatson AUDIT_PIPE_LOCK_INIT(ap); 577184508Srwatson AUDIT_PIPE_SX_LOCK_INIT(ap); 578184488Srwatson cv_init(&ap->ap_cv, "audit_pipe"); 579159269Srwatson 580159269Srwatson /* 581159269Srwatson * Default flags, naflags, and auid-specific preselection settings to 582159269Srwatson * 0. Initialize the mode to the global trail so that if praudit(1) 583159269Srwatson * is run on /dev/auditpipe, it sees events associated with the 584159269Srwatson * default trail. Pipe-aware application can clear the flag, set 585159269Srwatson * custom masks, and flush the pipe as needed. 586159269Srwatson */ 587159269Srwatson bzero(&ap->ap_preselect_flags, sizeof(ap->ap_preselect_flags)); 588159269Srwatson bzero(&ap->ap_preselect_naflags, sizeof(ap->ap_preselect_naflags)); 589159269Srwatson TAILQ_INIT(&ap->ap_preselect_list); 590159269Srwatson ap->ap_preselect_mode = AUDITPIPE_PRESELECT_MODE_TRAIL; 591159269Srwatson 592161582Srwatson /* 593161582Srwatson * Add to global list and update global statistics. 594161582Srwatson */ 595155408Srwatson TAILQ_INSERT_HEAD(&audit_pipe_list, ap, ap_list); 596155408Srwatson audit_pipe_count++; 597155408Srwatson audit_pipe_ever++; 598159269Srwatson 599155408Srwatson return (ap); 600155408Srwatson} 601155408Srwatson 602155408Srwatson/* 603159269Srwatson * Flush all records currently present in an audit pipe; assume mutex is held. 604155408Srwatson */ 605155408Srwatsonstatic void 606159269Srwatsonaudit_pipe_flush(struct audit_pipe *ap) 607155408Srwatson{ 608155408Srwatson struct audit_pipe_entry *ape; 609155408Srwatson 610184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 611155408Srwatson 612155408Srwatson while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL) { 613155408Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 614184536Srwatson ap->ap_qbyteslen -= ape->ape_record_len; 615155408Srwatson audit_pipe_entry_free(ape); 616155408Srwatson ap->ap_qlen--; 617155408Srwatson } 618184536Srwatson ap->ap_qoffset = 0; 619184536Srwatson 620184536Srwatson KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qbyteslen")); 621184536Srwatson KASSERT(ap->ap_qbyteslen == 0, ("audit_pipe_flush: ap_qbyteslen")); 622159269Srwatson} 623159269Srwatson 624159269Srwatson/* 625159269Srwatson * Free an audit pipe; this means freeing all preselection state and all 626184488Srwatson * records in the pipe. Assumes global write lock and pipe mutex are held to 627184488Srwatson * prevent any new records from being inserted during the free, and that the 628184488Srwatson * audit pipe is still on the global list. 629159269Srwatson */ 630159269Srwatsonstatic void 631159269Srwatsonaudit_pipe_free(struct audit_pipe *ap) 632159269Srwatson{ 633159269Srwatson 634184488Srwatson AUDIT_PIPE_LIST_WLOCK_ASSERT(); 635184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 636159269Srwatson 637159269Srwatson audit_pipe_preselect_flush_locked(ap); 638159269Srwatson audit_pipe_flush(ap); 639184488Srwatson cv_destroy(&ap->ap_cv); 640184508Srwatson AUDIT_PIPE_SX_LOCK_DESTROY(ap); 641184488Srwatson AUDIT_PIPE_LOCK_DESTROY(ap); 642161582Srwatson knlist_destroy(&ap->ap_selinfo.si_note); 643159269Srwatson TAILQ_REMOVE(&audit_pipe_list, ap, ap_list); 644155408Srwatson free(ap, M_AUDIT_PIPE); 645155408Srwatson audit_pipe_count--; 646155408Srwatson} 647155408Srwatson 648155408Srwatson/* 649155408Srwatson * Audit pipe clone routine -- provide specific requested audit pipe, or a 650155408Srwatson * fresh one if a specific one is not requested. 651155408Srwatson */ 652155408Srwatsonstatic void 653155408Srwatsonaudit_pipe_clone(void *arg, struct ucred *cred, char *name, int namelen, 654155408Srwatson struct cdev **dev) 655155408Srwatson{ 656155408Srwatson int i, u; 657155408Srwatson 658155408Srwatson if (*dev != NULL) 659155408Srwatson return; 660155408Srwatson 661155408Srwatson if (strcmp(name, AUDIT_PIPE_NAME) == 0) 662155408Srwatson u = -1; 663155408Srwatson else if (dev_stdclone(name, NULL, AUDIT_PIPE_NAME, &u) != 1) 664155408Srwatson return; 665155408Srwatson 666155408Srwatson i = clone_create(&audit_pipe_clones, &audit_pipe_cdevsw, &u, dev, 0); 667155408Srwatson if (i) { 668183381Sed *dev = make_dev(&audit_pipe_cdevsw, u, UID_ROOT, 669155408Srwatson GID_WHEEL, 0600, "%s%d", AUDIT_PIPE_NAME, u); 670155408Srwatson if (*dev != NULL) { 671155408Srwatson dev_ref(*dev); 672155408Srwatson (*dev)->si_flags |= SI_CHEAPCLONE; 673155408Srwatson } 674155408Srwatson } 675155408Srwatson} 676155408Srwatson 677155408Srwatson/* 678164033Srwatson * Audit pipe open method. Explicit privilege check isn't used as this 679164033Srwatson * allows file permissions on the special device to be used to grant audit 680164033Srwatson * review access. Those file permissions should be managed carefully. 681155408Srwatson */ 682155408Srwatsonstatic int 683155408Srwatsonaudit_pipe_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 684155408Srwatson{ 685155408Srwatson struct audit_pipe *ap; 686155408Srwatson 687184488Srwatson AUDIT_PIPE_LIST_WLOCK(); 688155408Srwatson ap = dev->si_drv1; 689155408Srwatson if (ap == NULL) { 690155408Srwatson ap = audit_pipe_alloc(); 691155408Srwatson if (ap == NULL) { 692184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 693155408Srwatson return (ENOMEM); 694155408Srwatson } 695155408Srwatson dev->si_drv1 = ap; 696155408Srwatson } else { 697155408Srwatson KASSERT(ap->ap_open, ("audit_pipe_open: ap && !ap_open")); 698184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 699155408Srwatson return (EBUSY); 700155408Srwatson } 701184488Srwatson ap->ap_open = 1; /* No lock required yet. */ 702184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 703155408Srwatson fsetown(td->td_proc->p_pid, &ap->ap_sigio); 704155408Srwatson return (0); 705155408Srwatson} 706155408Srwatson 707155408Srwatson/* 708155408Srwatson * Close audit pipe, tear down all records, etc. 709155408Srwatson */ 710155408Srwatsonstatic int 711155408Srwatsonaudit_pipe_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 712155408Srwatson{ 713155408Srwatson struct audit_pipe *ap; 714155408Srwatson 715155408Srwatson ap = dev->si_drv1; 716155408Srwatson KASSERT(ap != NULL, ("audit_pipe_close: ap == NULL")); 717155408Srwatson KASSERT(ap->ap_open, ("audit_pipe_close: !ap_open")); 718184488Srwatson 719155408Srwatson funsetown(&ap->ap_sigio); 720184488Srwatson AUDIT_PIPE_LIST_WLOCK(); 721184488Srwatson AUDIT_PIPE_LOCK(ap); 722155408Srwatson ap->ap_open = 0; 723155408Srwatson audit_pipe_free(ap); 724155408Srwatson dev->si_drv1 = NULL; 725184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 726155408Srwatson return (0); 727155408Srwatson} 728155408Srwatson 729155408Srwatson/* 730156880Srwatson * Audit pipe ioctl() routine. Handle file descriptor and audit pipe layer 731156880Srwatson * commands. 732155408Srwatson * 733155408Srwatson * Would be desirable to support filtering, although perhaps something simple 734155408Srwatson * like an event mask, as opposed to something complicated like BPF. 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