audit_pipe.c revision 184508
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 184508 2008-10-31 14:40:21Z rwatson $"); 32178186Srwatson 33155408Srwatson#include <sys/param.h> 34155408Srwatson#include <sys/condvar.h> 35155408Srwatson#include <sys/conf.h> 36155408Srwatson#include <sys/eventhandler.h> 37155408Srwatson#include <sys/filio.h> 38155408Srwatson#include <sys/kernel.h> 39155408Srwatson#include <sys/lock.h> 40155408Srwatson#include <sys/malloc.h> 41155408Srwatson#include <sys/mutex.h> 42155408Srwatson#include <sys/poll.h> 43155408Srwatson#include <sys/proc.h> 44155408Srwatson#include <sys/queue.h> 45184488Srwatson#include <sys/rwlock.h> 46155408Srwatson#include <sys/selinfo.h> 47155408Srwatson#include <sys/sigio.h> 48155408Srwatson#include <sys/signal.h> 49155408Srwatson#include <sys/signalvar.h> 50184508Srwatson#include <sys/sx.h> 51155408Srwatson#include <sys/systm.h> 52155408Srwatson#include <sys/uio.h> 53155408Srwatson 54155408Srwatson#include <security/audit/audit.h> 55156880Srwatson#include <security/audit/audit_ioctl.h> 56155408Srwatson#include <security/audit/audit_private.h> 57155408Srwatson 58155408Srwatson/* 59155408Srwatson * Implementation of a clonable special device providing a live stream of BSM 60155408Srwatson * audit data. This is a "tee" of the data going to the file. It provides 61155408Srwatson * unreliable but timely access to audit events. Consumers of this interface 62159269Srwatson * should be very careful to avoid introducing event cycles. Consumers may 63159269Srwatson * express interest via a set of preselection ioctls. 64155408Srwatson */ 65155408Srwatson 66155408Srwatson/* 67155408Srwatson * Memory types. 68155408Srwatson */ 69155408Srwatsonstatic MALLOC_DEFINE(M_AUDIT_PIPE, "audit_pipe", "Audit pipes"); 70155408Srwatsonstatic MALLOC_DEFINE(M_AUDIT_PIPE_ENTRY, "audit_pipeent", 71155408Srwatson "Audit pipe entries and buffers"); 72174894Swkoszekstatic MALLOC_DEFINE(M_AUDIT_PIPE_PRESELECT, "audit_pipe_presel", 73159269Srwatson "Audit pipe preselection structure"); 74155408Srwatson 75155408Srwatson/* 76155408Srwatson * Audit pipe buffer parameters. 77155408Srwatson */ 78156883Srwatson#define AUDIT_PIPE_QLIMIT_DEFAULT (128) 79156880Srwatson#define AUDIT_PIPE_QLIMIT_MIN (0) 80155408Srwatson#define AUDIT_PIPE_QLIMIT_MAX (1024) 81155408Srwatson 82155408Srwatson/* 83155408Srwatson * Description of an entry in an audit_pipe. 84155408Srwatson */ 85155408Srwatsonstruct audit_pipe_entry { 86155408Srwatson void *ape_record; 87155408Srwatson u_int ape_record_len; 88184508Srwatson u_int ape_record_offset; 89155408Srwatson TAILQ_ENTRY(audit_pipe_entry) ape_queue; 90155408Srwatson}; 91155408Srwatson 92155408Srwatson/* 93159269Srwatson * Audit pipes allow processes to express "interest" in the set of records 94159269Srwatson * that are delivered via the pipe. They do this in a similar manner to the 95159269Srwatson * mechanism for audit trail configuration, by expressing two global masks, 96159269Srwatson * and optionally expressing per-auid masks. The following data structure is 97159269Srwatson * the per-auid mask description. The global state is stored in the audit 98159269Srwatson * pipe data structure. 99159269Srwatson * 100159269Srwatson * We may want to consider a more space/time-efficient data structure once 101159269Srwatson * usage patterns for per-auid specifications are clear. 102159269Srwatson */ 103159269Srwatsonstruct audit_pipe_preselect { 104159269Srwatson au_id_t app_auid; 105159269Srwatson au_mask_t app_mask; 106159269Srwatson TAILQ_ENTRY(audit_pipe_preselect) app_list; 107159269Srwatson}; 108159269Srwatson 109159269Srwatson/* 110155408Srwatson * Description of an individual audit_pipe. Consists largely of a bounded 111155408Srwatson * length queue. 112155408Srwatson */ 113155408Srwatson#define AUDIT_PIPE_ASYNC 0x00000001 114155408Srwatson#define AUDIT_PIPE_NBIO 0x00000002 115155408Srwatsonstruct audit_pipe { 116155408Srwatson int ap_open; /* Device open? */ 117155408Srwatson u_int ap_flags; 118155408Srwatson 119155408Srwatson struct selinfo ap_selinfo; 120155408Srwatson struct sigio *ap_sigio; 121155408Srwatson 122184488Srwatson /* 123184488Srwatson * Per-pipe mutex protecting most fields in this data structure. 124184488Srwatson */ 125184508Srwatson struct mtx ap_mtx; 126184488Srwatson 127184488Srwatson /* 128184508Srwatson * Per-pipe sleep lock serializing user-generated reads and flushes. 129184508Srwatson * uiomove() is called to copy out the current head record's data 130184508Srwatson * while the record remains in the queue, so we prevent other threads 131184508Srwatson * from removing it using this lock. 132184508Srwatson */ 133184508Srwatson struct sx ap_sx; 134184508Srwatson 135184508Srwatson /* 136184488Srwatson * Condition variable to signal when data has been delivered to a 137184488Srwatson * pipe. 138184488Srwatson */ 139184488Srwatson struct cv ap_cv; 140184488Srwatson 141155408Srwatson u_int ap_qlen; 142155408Srwatson u_int ap_qlimit; 143155408Srwatson 144155408Srwatson u_int64_t ap_inserts; /* Records added. */ 145155408Srwatson u_int64_t ap_reads; /* Records read. */ 146155408Srwatson u_int64_t ap_drops; /* Records dropped. */ 147155408Srwatson u_int64_t ap_truncates; /* Records too long. */ 148155408Srwatson 149159269Srwatson /* 150159269Srwatson * Fields relating to pipe interest: global masks for unmatched 151159269Srwatson * processes (attributable, non-attributable), and a list of specific 152159269Srwatson * interest specifications by auid. 153159269Srwatson */ 154159269Srwatson int ap_preselect_mode; 155159269Srwatson au_mask_t ap_preselect_flags; 156159269Srwatson au_mask_t ap_preselect_naflags; 157159269Srwatson TAILQ_HEAD(, audit_pipe_preselect) ap_preselect_list; 158159269Srwatson 159159269Srwatson /* 160184508Srwatson * Current pending record list. Protected by a combination of ap_mtx 161184508Srwatson * and ap_sx. Note particularly that *both* locks are required to 162184508Srwatson * remove a record from the head of the queue, as an in-progress read * may sleep while copying and therefore cannot hold ap_mtx. 163159269Srwatson */ 164155408Srwatson TAILQ_HEAD(, audit_pipe_entry) ap_queue; 165155408Srwatson 166159269Srwatson /* 167159269Srwatson * Global pipe list. 168159269Srwatson */ 169155408Srwatson TAILQ_ENTRY(audit_pipe) ap_list; 170155408Srwatson}; 171155408Srwatson 172184508Srwatson#define AUDIT_PIPE_LOCK(ap) mtx_lock(&(ap)->ap_mtx) 173184508Srwatson#define AUDIT_PIPE_LOCK_ASSERT(ap) mtx_assert(&(ap)->ap_mtx, MA_OWNED) 174184508Srwatson#define AUDIT_PIPE_LOCK_DESTROY(ap) mtx_destroy(&(ap)->ap_mtx) 175184508Srwatson#define AUDIT_PIPE_LOCK_INIT(ap) mtx_init(&(ap)->ap_mtx, \ 176184508Srwatson "audit_pipe_mtx", NULL, MTX_DEF) 177184508Srwatson#define AUDIT_PIPE_UNLOCK(ap) mtx_unlock(&(ap)->ap_mtx) 178184508Srwatson#define AUDIT_PIPE_MTX(ap) (&(ap)->ap_mtx) 179184488Srwatson 180184508Srwatson#define AUDIT_PIPE_SX_LOCK_DESTROY(ap) sx_destroy(&(ap)->ap_sx) 181184508Srwatson#define AUDIT_PIPE_SX_LOCK_INIT(ap) sx_init(&(ap)->ap_sx, "audit_pipe_sx") 182184508Srwatson#define AUDIT_PIPE_SX_XLOCK_ASSERT(ap) sx_assert(&(ap)->ap_sx, SA_XLOCKED) 183184508Srwatson#define AUDIT_PIPE_SX_XLOCK_SIG(ap) sx_xlock_sig(&(ap)->ap_sx) 184184508Srwatson#define AUDIT_PIPE_SX_XUNLOCK(ap) sx_xunlock(&(ap)->ap_sx) 185184508Srwatson 186155408Srwatson/* 187184488Srwatson * Global list of audit pipes, rwlock to protect it. Individual record 188184488Srwatson * queues on pipes are protected by per-pipe locks; these locks synchronize 189184488Srwatson * between threads walking the list to deliver to individual pipes and add/ 190184488Srwatson * remove of pipes, and are mostly acquired for read. 191155408Srwatson */ 192155408Srwatsonstatic TAILQ_HEAD(, audit_pipe) audit_pipe_list; 193184488Srwatsonstatic struct rwlock audit_pipe_lock; 194155408Srwatson 195184488Srwatson#define AUDIT_PIPE_LIST_LOCK_INIT() rw_init(&audit_pipe_lock, \ 196184488Srwatson "audit_pipe_list_lock") 197184488Srwatson#define AUDIT_PIPE_LIST_RLOCK() rw_rlock(&audit_pipe_lock) 198184488Srwatson#define AUDIT_PIPE_LIST_RUNLOCK() rw_runlock(&audit_pipe_lock) 199184488Srwatson#define AUDIT_PIPE_LIST_WLOCK() rw_wlock(&audit_pipe_lock) 200184488Srwatson#define AUDIT_PIPE_LIST_WLOCK_ASSERT() rw_assert(&audit_pipe_lock, \ 201184488Srwatson RA_WLOCKED) 202184488Srwatson#define AUDIT_PIPE_LIST_WUNLOCK() rw_wunlock(&audit_pipe_lock) 203155408Srwatson 204155408Srwatson/* 205155408Srwatson * Cloning related variables and constants. 206155408Srwatson */ 207155408Srwatson#define AUDIT_PIPE_NAME "auditpipe" 208155408Srwatsonstatic eventhandler_tag audit_pipe_eh_tag; 209155408Srwatsonstatic struct clonedevs *audit_pipe_clones; 210155408Srwatson 211155408Srwatson/* 212155408Srwatson * Special device methods and definition. 213155408Srwatson */ 214155408Srwatsonstatic d_open_t audit_pipe_open; 215155408Srwatsonstatic d_close_t audit_pipe_close; 216155408Srwatsonstatic d_read_t audit_pipe_read; 217155408Srwatsonstatic d_ioctl_t audit_pipe_ioctl; 218155408Srwatsonstatic d_poll_t audit_pipe_poll; 219161582Srwatsonstatic d_kqfilter_t audit_pipe_kqfilter; 220155408Srwatson 221155408Srwatsonstatic struct cdevsw audit_pipe_cdevsw = { 222155408Srwatson .d_version = D_VERSION, 223179726Sed .d_flags = D_PSEUDO | D_NEEDGIANT | D_NEEDMINOR, 224155408Srwatson .d_open = audit_pipe_open, 225155408Srwatson .d_close = audit_pipe_close, 226155408Srwatson .d_read = audit_pipe_read, 227155408Srwatson .d_ioctl = audit_pipe_ioctl, 228155408Srwatson .d_poll = audit_pipe_poll, 229161582Srwatson .d_kqfilter = audit_pipe_kqfilter, 230155408Srwatson .d_name = AUDIT_PIPE_NAME, 231155408Srwatson}; 232155408Srwatson 233161582Srwatsonstatic int audit_pipe_kqread(struct knote *note, long hint); 234161582Srwatsonstatic void audit_pipe_kqdetach(struct knote *note); 235161582Srwatson 236161582Srwatsonstatic struct filterops audit_pipe_read_filterops = { 237161582Srwatson .f_isfd = 1, 238161582Srwatson .f_attach = NULL, 239161582Srwatson .f_detach = audit_pipe_kqdetach, 240161582Srwatson .f_event = audit_pipe_kqread, 241161582Srwatson}; 242161582Srwatson 243155408Srwatson/* 244155408Srwatson * Some global statistics on audit pipes. 245155408Srwatson */ 246155408Srwatsonstatic int audit_pipe_count; /* Current number of pipes. */ 247155408Srwatsonstatic u_int64_t audit_pipe_ever; /* Pipes ever allocated. */ 248155408Srwatsonstatic u_int64_t audit_pipe_records; /* Records seen. */ 249155408Srwatsonstatic u_int64_t audit_pipe_drops; /* Global record drop count. */ 250155408Srwatson 251155408Srwatson/* 252155408Srwatson * Free an audit pipe entry. 253155408Srwatson */ 254155408Srwatsonstatic void 255155408Srwatsonaudit_pipe_entry_free(struct audit_pipe_entry *ape) 256155408Srwatson{ 257155408Srwatson 258155408Srwatson free(ape->ape_record, M_AUDIT_PIPE_ENTRY); 259155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 260155408Srwatson} 261155408Srwatson 262155408Srwatson/* 263159269Srwatson * Find an audit pipe preselection specification for an auid, if any. 264159269Srwatson */ 265159269Srwatsonstatic struct audit_pipe_preselect * 266159269Srwatsonaudit_pipe_preselect_find(struct audit_pipe *ap, au_id_t auid) 267159269Srwatson{ 268159269Srwatson struct audit_pipe_preselect *app; 269159269Srwatson 270184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 271159269Srwatson 272159269Srwatson TAILQ_FOREACH(app, &ap->ap_preselect_list, app_list) { 273159269Srwatson if (app->app_auid == auid) 274159269Srwatson return (app); 275159269Srwatson } 276159269Srwatson return (NULL); 277159269Srwatson} 278159269Srwatson 279159269Srwatson/* 280159269Srwatson * Query the per-pipe mask for a specific auid. 281159269Srwatson */ 282159269Srwatsonstatic int 283159269Srwatsonaudit_pipe_preselect_get(struct audit_pipe *ap, au_id_t auid, 284159269Srwatson au_mask_t *maskp) 285159269Srwatson{ 286159269Srwatson struct audit_pipe_preselect *app; 287159269Srwatson int error; 288159269Srwatson 289184488Srwatson AUDIT_PIPE_LOCK(ap); 290159269Srwatson app = audit_pipe_preselect_find(ap, auid); 291159269Srwatson if (app != NULL) { 292159269Srwatson *maskp = app->app_mask; 293159269Srwatson error = 0; 294159269Srwatson } else 295159269Srwatson error = ENOENT; 296184488Srwatson AUDIT_PIPE_UNLOCK(ap); 297159269Srwatson return (error); 298159269Srwatson} 299159269Srwatson 300159269Srwatson/* 301159269Srwatson * Set the per-pipe mask for a specific auid. Add a new entry if needed; 302159269Srwatson * otherwise, update the current entry. 303159269Srwatson */ 304159269Srwatsonstatic void 305159269Srwatsonaudit_pipe_preselect_set(struct audit_pipe *ap, au_id_t auid, au_mask_t mask) 306159269Srwatson{ 307159269Srwatson struct audit_pipe_preselect *app, *app_new; 308159269Srwatson 309159269Srwatson /* 310159269Srwatson * Pessimistically assume that the auid doesn't already have a mask 311159269Srwatson * set, and allocate. We will free it if it is unneeded. 312159269Srwatson */ 313159269Srwatson app_new = malloc(sizeof(*app_new), M_AUDIT_PIPE_PRESELECT, M_WAITOK); 314184488Srwatson AUDIT_PIPE_LOCK(ap); 315159269Srwatson app = audit_pipe_preselect_find(ap, auid); 316159269Srwatson if (app == NULL) { 317159269Srwatson app = app_new; 318159269Srwatson app_new = NULL; 319159269Srwatson app->app_auid = auid; 320159269Srwatson TAILQ_INSERT_TAIL(&ap->ap_preselect_list, app, app_list); 321159269Srwatson } 322159269Srwatson app->app_mask = mask; 323184488Srwatson AUDIT_PIPE_UNLOCK(ap); 324159269Srwatson if (app_new != NULL) 325159269Srwatson free(app_new, M_AUDIT_PIPE_PRESELECT); 326159269Srwatson} 327159269Srwatson 328159269Srwatson/* 329159269Srwatson * Delete a per-auid mask on an audit pipe. 330159269Srwatson */ 331159269Srwatsonstatic int 332159269Srwatsonaudit_pipe_preselect_delete(struct audit_pipe *ap, au_id_t auid) 333159269Srwatson{ 334159269Srwatson struct audit_pipe_preselect *app; 335159269Srwatson int error; 336159269Srwatson 337184488Srwatson AUDIT_PIPE_LOCK(ap); 338159269Srwatson app = audit_pipe_preselect_find(ap, auid); 339159269Srwatson if (app != NULL) { 340159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 341159269Srwatson error = 0; 342159269Srwatson } else 343159269Srwatson error = ENOENT; 344184488Srwatson AUDIT_PIPE_UNLOCK(ap); 345159269Srwatson if (app != NULL) 346159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 347159269Srwatson return (error); 348159269Srwatson} 349159269Srwatson 350159269Srwatson/* 351159269Srwatson * Delete all per-auid masks on an audit pipe. 352159269Srwatson */ 353159269Srwatsonstatic void 354159269Srwatsonaudit_pipe_preselect_flush_locked(struct audit_pipe *ap) 355159269Srwatson{ 356159269Srwatson struct audit_pipe_preselect *app; 357159269Srwatson 358184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 359159269Srwatson 360159269Srwatson while ((app = TAILQ_FIRST(&ap->ap_preselect_list)) != NULL) { 361159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 362159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 363159269Srwatson } 364159269Srwatson} 365159269Srwatson 366159269Srwatsonstatic void 367159269Srwatsonaudit_pipe_preselect_flush(struct audit_pipe *ap) 368159269Srwatson{ 369159269Srwatson 370184488Srwatson AUDIT_PIPE_LOCK(ap); 371159269Srwatson audit_pipe_preselect_flush_locked(ap); 372184488Srwatson AUDIT_PIPE_UNLOCK(ap); 373159269Srwatson} 374159269Srwatson 375170196Srwatson/*- 376159269Srwatson * Determine whether a specific audit pipe matches a record with these 377159269Srwatson * properties. Algorithm is as follows: 378159269Srwatson * 379159269Srwatson * - If the pipe is configured to track the default trail configuration, then 380159269Srwatson * use the results of global preselection matching. 381159269Srwatson * - If not, search for a specifically configured auid entry matching the 382159269Srwatson * event. If an entry is found, use that. 383159269Srwatson * - Otherwise, use the default flags or naflags configured for the pipe. 384159269Srwatson */ 385159269Srwatsonstatic int 386159269Srwatsonaudit_pipe_preselect_check(struct audit_pipe *ap, au_id_t auid, 387159269Srwatson au_event_t event, au_class_t class, int sorf, int trail_preselect) 388159269Srwatson{ 389159269Srwatson struct audit_pipe_preselect *app; 390159269Srwatson 391184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 392159269Srwatson 393159269Srwatson switch (ap->ap_preselect_mode) { 394159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 395159269Srwatson return (trail_preselect); 396159269Srwatson 397159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 398159269Srwatson app = audit_pipe_preselect_find(ap, auid); 399159269Srwatson if (app == NULL) { 400159269Srwatson if (auid == AU_DEFAUDITID) 401159269Srwatson return (au_preselect(event, class, 402159269Srwatson &ap->ap_preselect_naflags, sorf)); 403159269Srwatson else 404159269Srwatson return (au_preselect(event, class, 405159269Srwatson &ap->ap_preselect_flags, sorf)); 406159269Srwatson } else 407159269Srwatson return (au_preselect(event, class, &app->app_mask, 408159269Srwatson sorf)); 409159269Srwatson 410159269Srwatson default: 411159269Srwatson panic("audit_pipe_preselect_check: mode %d", 412159269Srwatson ap->ap_preselect_mode); 413159269Srwatson } 414159269Srwatson 415159269Srwatson return (0); 416159269Srwatson} 417159269Srwatson 418159269Srwatson/* 419159269Srwatson * Determine whether there exists a pipe interested in a record with specific 420159269Srwatson * properties. 421159269Srwatson */ 422159269Srwatsonint 423159269Srwatsonaudit_pipe_preselect(au_id_t auid, au_event_t event, au_class_t class, 424159269Srwatson int sorf, int trail_preselect) 425159269Srwatson{ 426159269Srwatson struct audit_pipe *ap; 427159269Srwatson 428184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 429159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 430184488Srwatson AUDIT_PIPE_LOCK(ap); 431159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 432159269Srwatson trail_preselect)) { 433184488Srwatson AUDIT_PIPE_UNLOCK(ap); 434184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 435159269Srwatson return (1); 436159269Srwatson } 437184488Srwatson AUDIT_PIPE_UNLOCK(ap); 438159269Srwatson } 439184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 440159269Srwatson return (0); 441159269Srwatson} 442159269Srwatson 443159269Srwatson/* 444159269Srwatson * Append individual record to a queue -- allocate queue-local buffer, and 445184489Srwatson * add to the queue. If the queue is full or we can't allocate memory, drop 446184489Srwatson * the newest record. 447155408Srwatson */ 448155408Srwatsonstatic void 449155408Srwatsonaudit_pipe_append(struct audit_pipe *ap, void *record, u_int record_len) 450155408Srwatson{ 451184489Srwatson struct audit_pipe_entry *ape; 452155408Srwatson 453184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 454155408Srwatson 455184489Srwatson if (ap->ap_qlen >= ap->ap_qlimit) { 456184489Srwatson ap->ap_drops++; 457184489Srwatson audit_pipe_drops++; 458184489Srwatson return; 459184489Srwatson } 460184489Srwatson 461155408Srwatson ape = malloc(sizeof(*ape), M_AUDIT_PIPE_ENTRY, M_NOWAIT | M_ZERO); 462155408Srwatson if (ape == NULL) { 463155408Srwatson ap->ap_drops++; 464156292Srwatson audit_pipe_drops++; 465155408Srwatson return; 466155408Srwatson } 467155408Srwatson 468155408Srwatson ape->ape_record = malloc(record_len, M_AUDIT_PIPE_ENTRY, M_NOWAIT); 469155408Srwatson if (ape->ape_record == NULL) { 470155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 471155408Srwatson ap->ap_drops++; 472155408Srwatson audit_pipe_drops++; 473155408Srwatson return; 474155408Srwatson } 475155408Srwatson 476155408Srwatson bcopy(record, ape->ape_record, record_len); 477155408Srwatson ape->ape_record_len = record_len; 478184508Srwatson ape->ape_record_offset = 0; 479155408Srwatson 480155408Srwatson TAILQ_INSERT_TAIL(&ap->ap_queue, ape, ape_queue); 481155408Srwatson ap->ap_inserts++; 482155408Srwatson ap->ap_qlen++; 483155408Srwatson selwakeuppri(&ap->ap_selinfo, PSOCK); 484161582Srwatson KNOTE_LOCKED(&ap->ap_selinfo.si_note, 0); 485155408Srwatson if (ap->ap_flags & AUDIT_PIPE_ASYNC) 486155408Srwatson pgsigio(&ap->ap_sigio, SIGIO, 0); 487184488Srwatson cv_broadcast(&ap->ap_cv); 488155408Srwatson} 489155408Srwatson 490155408Srwatson/* 491155408Srwatson * audit_pipe_submit(): audit_worker submits audit records via this 492155408Srwatson * interface, which arranges for them to be delivered to pipe queues. 493155408Srwatson */ 494155408Srwatsonvoid 495159269Srwatsonaudit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class, int sorf, 496159269Srwatson int trail_select, void *record, u_int record_len) 497155408Srwatson{ 498155408Srwatson struct audit_pipe *ap; 499155408Srwatson 500155408Srwatson /* 501184488Srwatson * Lockless read to avoid lock overhead if pipes are not in use. 502155408Srwatson */ 503155408Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 504155408Srwatson return; 505155408Srwatson 506184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 507159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 508184488Srwatson AUDIT_PIPE_LOCK(ap); 509159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 510159269Srwatson trail_select)) 511159269Srwatson audit_pipe_append(ap, record, record_len); 512184488Srwatson AUDIT_PIPE_UNLOCK(ap); 513159269Srwatson } 514184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 515184488Srwatson 516184488Srwatson /* Unlocked increment. */ 517159269Srwatson audit_pipe_records++; 518159269Srwatson} 519159269Srwatson 520159269Srwatson/* 521159269Srwatson * audit_pipe_submit_user(): the same as audit_pipe_submit(), except that 522159269Srwatson * since we don't currently have selection information available, it is 523159269Srwatson * delivered to the pipe unconditionally. 524159269Srwatson * 525159269Srwatson * XXXRW: This is a bug. The BSM check routine for submitting a user record 526159269Srwatson * should parse that information and return it. 527159269Srwatson */ 528159269Srwatsonvoid 529159269Srwatsonaudit_pipe_submit_user(void *record, u_int record_len) 530159269Srwatson{ 531159269Srwatson struct audit_pipe *ap; 532159269Srwatson 533159269Srwatson /* 534184488Srwatson * Lockless read to avoid lock overhead if pipes are not in use. 535159269Srwatson */ 536159269Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 537159269Srwatson return; 538159269Srwatson 539184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 540184488Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 541184488Srwatson AUDIT_PIPE_LOCK(ap); 542155408Srwatson audit_pipe_append(ap, record, record_len); 543184488Srwatson AUDIT_PIPE_UNLOCK(ap); 544184488Srwatson } 545184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 546184488Srwatson 547184488Srwatson /* Unlocked increment. */ 548155408Srwatson audit_pipe_records++; 549155408Srwatson} 550155408Srwatson 551155408Srwatson/* 552155408Srwatson * Allocate a new audit pipe. Connects the pipe, on success, to the global 553155408Srwatson * list and updates statistics. 554155408Srwatson */ 555155408Srwatsonstatic struct audit_pipe * 556155408Srwatsonaudit_pipe_alloc(void) 557155408Srwatson{ 558155408Srwatson struct audit_pipe *ap; 559155408Srwatson 560184488Srwatson AUDIT_PIPE_LIST_WLOCK_ASSERT(); 561155408Srwatson 562155408Srwatson ap = malloc(sizeof(*ap), M_AUDIT_PIPE, M_NOWAIT | M_ZERO); 563155408Srwatson if (ap == NULL) 564155408Srwatson return (NULL); 565155408Srwatson ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT; 566155408Srwatson TAILQ_INIT(&ap->ap_queue); 567184488Srwatson knlist_init(&ap->ap_selinfo.si_note, AUDIT_PIPE_MTX(ap), NULL, NULL, 568161582Srwatson NULL); 569184488Srwatson AUDIT_PIPE_LOCK_INIT(ap); 570184508Srwatson AUDIT_PIPE_SX_LOCK_INIT(ap); 571184488Srwatson cv_init(&ap->ap_cv, "audit_pipe"); 572159269Srwatson 573159269Srwatson /* 574159269Srwatson * Default flags, naflags, and auid-specific preselection settings to 575159269Srwatson * 0. Initialize the mode to the global trail so that if praudit(1) 576159269Srwatson * is run on /dev/auditpipe, it sees events associated with the 577159269Srwatson * default trail. Pipe-aware application can clear the flag, set 578159269Srwatson * custom masks, and flush the pipe as needed. 579159269Srwatson */ 580159269Srwatson bzero(&ap->ap_preselect_flags, sizeof(ap->ap_preselect_flags)); 581159269Srwatson bzero(&ap->ap_preselect_naflags, sizeof(ap->ap_preselect_naflags)); 582159269Srwatson TAILQ_INIT(&ap->ap_preselect_list); 583159269Srwatson ap->ap_preselect_mode = AUDITPIPE_PRESELECT_MODE_TRAIL; 584159269Srwatson 585161582Srwatson /* 586161582Srwatson * Add to global list and update global statistics. 587161582Srwatson */ 588155408Srwatson TAILQ_INSERT_HEAD(&audit_pipe_list, ap, ap_list); 589155408Srwatson audit_pipe_count++; 590155408Srwatson audit_pipe_ever++; 591159269Srwatson 592155408Srwatson return (ap); 593155408Srwatson} 594155408Srwatson 595155408Srwatson/* 596159269Srwatson * Flush all records currently present in an audit pipe; assume mutex is held. 597155408Srwatson */ 598155408Srwatsonstatic void 599159269Srwatsonaudit_pipe_flush(struct audit_pipe *ap) 600155408Srwatson{ 601155408Srwatson struct audit_pipe_entry *ape; 602155408Srwatson 603184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 604155408Srwatson 605155408Srwatson while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL) { 606155408Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 607155408Srwatson audit_pipe_entry_free(ape); 608155408Srwatson ap->ap_qlen--; 609155408Srwatson } 610155408Srwatson KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qlen")); 611159269Srwatson} 612159269Srwatson 613159269Srwatson/* 614159269Srwatson * Free an audit pipe; this means freeing all preselection state and all 615184488Srwatson * records in the pipe. Assumes global write lock and pipe mutex are held to 616184488Srwatson * prevent any new records from being inserted during the free, and that the 617184488Srwatson * audit pipe is still on the global list. 618159269Srwatson */ 619159269Srwatsonstatic void 620159269Srwatsonaudit_pipe_free(struct audit_pipe *ap) 621159269Srwatson{ 622159269Srwatson 623184488Srwatson AUDIT_PIPE_LIST_WLOCK_ASSERT(); 624184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 625159269Srwatson 626159269Srwatson audit_pipe_preselect_flush_locked(ap); 627159269Srwatson audit_pipe_flush(ap); 628184488Srwatson cv_destroy(&ap->ap_cv); 629184508Srwatson AUDIT_PIPE_SX_LOCK_DESTROY(ap); 630184488Srwatson AUDIT_PIPE_LOCK_DESTROY(ap); 631161582Srwatson knlist_destroy(&ap->ap_selinfo.si_note); 632159269Srwatson TAILQ_REMOVE(&audit_pipe_list, ap, ap_list); 633155408Srwatson free(ap, M_AUDIT_PIPE); 634155408Srwatson audit_pipe_count--; 635155408Srwatson} 636155408Srwatson 637155408Srwatson/* 638155408Srwatson * Audit pipe clone routine -- provide specific requested audit pipe, or a 639155408Srwatson * fresh one if a specific one is not requested. 640155408Srwatson */ 641155408Srwatsonstatic void 642155408Srwatsonaudit_pipe_clone(void *arg, struct ucred *cred, char *name, int namelen, 643155408Srwatson struct cdev **dev) 644155408Srwatson{ 645155408Srwatson int i, u; 646155408Srwatson 647155408Srwatson if (*dev != NULL) 648155408Srwatson return; 649155408Srwatson 650155408Srwatson if (strcmp(name, AUDIT_PIPE_NAME) == 0) 651155408Srwatson u = -1; 652155408Srwatson else if (dev_stdclone(name, NULL, AUDIT_PIPE_NAME, &u) != 1) 653155408Srwatson return; 654155408Srwatson 655155408Srwatson i = clone_create(&audit_pipe_clones, &audit_pipe_cdevsw, &u, dev, 0); 656155408Srwatson if (i) { 657183381Sed *dev = make_dev(&audit_pipe_cdevsw, u, UID_ROOT, 658155408Srwatson GID_WHEEL, 0600, "%s%d", AUDIT_PIPE_NAME, u); 659155408Srwatson if (*dev != NULL) { 660155408Srwatson dev_ref(*dev); 661155408Srwatson (*dev)->si_flags |= SI_CHEAPCLONE; 662155408Srwatson } 663155408Srwatson } 664155408Srwatson} 665155408Srwatson 666155408Srwatson/* 667164033Srwatson * Audit pipe open method. Explicit privilege check isn't used as this 668164033Srwatson * allows file permissions on the special device to be used to grant audit 669164033Srwatson * review access. Those file permissions should be managed carefully. 670155408Srwatson */ 671155408Srwatsonstatic int 672155408Srwatsonaudit_pipe_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 673155408Srwatson{ 674155408Srwatson struct audit_pipe *ap; 675155408Srwatson 676184488Srwatson AUDIT_PIPE_LIST_WLOCK(); 677155408Srwatson ap = dev->si_drv1; 678155408Srwatson if (ap == NULL) { 679155408Srwatson ap = audit_pipe_alloc(); 680155408Srwatson if (ap == NULL) { 681184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 682155408Srwatson return (ENOMEM); 683155408Srwatson } 684155408Srwatson dev->si_drv1 = ap; 685155408Srwatson } else { 686155408Srwatson KASSERT(ap->ap_open, ("audit_pipe_open: ap && !ap_open")); 687184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 688155408Srwatson return (EBUSY); 689155408Srwatson } 690184488Srwatson ap->ap_open = 1; /* No lock required yet. */ 691184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 692155408Srwatson fsetown(td->td_proc->p_pid, &ap->ap_sigio); 693155408Srwatson return (0); 694155408Srwatson} 695155408Srwatson 696155408Srwatson/* 697155408Srwatson * Close audit pipe, tear down all records, etc. 698155408Srwatson */ 699155408Srwatsonstatic int 700155408Srwatsonaudit_pipe_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 701155408Srwatson{ 702155408Srwatson struct audit_pipe *ap; 703155408Srwatson 704155408Srwatson ap = dev->si_drv1; 705155408Srwatson KASSERT(ap != NULL, ("audit_pipe_close: ap == NULL")); 706155408Srwatson KASSERT(ap->ap_open, ("audit_pipe_close: !ap_open")); 707184488Srwatson 708155408Srwatson funsetown(&ap->ap_sigio); 709184488Srwatson AUDIT_PIPE_LIST_WLOCK(); 710184488Srwatson AUDIT_PIPE_LOCK(ap); 711155408Srwatson ap->ap_open = 0; 712155408Srwatson audit_pipe_free(ap); 713155408Srwatson dev->si_drv1 = NULL; 714184488Srwatson AUDIT_PIPE_LIST_WUNLOCK(); 715155408Srwatson return (0); 716155408Srwatson} 717155408Srwatson 718155408Srwatson/* 719156880Srwatson * Audit pipe ioctl() routine. Handle file descriptor and audit pipe layer 720156880Srwatson * commands. 721155408Srwatson * 722155408Srwatson * Would be desirable to support filtering, although perhaps something simple 723155408Srwatson * like an event mask, as opposed to something complicated like BPF. 724155408Srwatson */ 725155408Srwatsonstatic int 726155408Srwatsonaudit_pipe_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, 727155408Srwatson struct thread *td) 728155408Srwatson{ 729159269Srwatson struct auditpipe_ioctl_preselect *aip; 730155408Srwatson struct audit_pipe *ap; 731159269Srwatson au_mask_t *maskp; 732159269Srwatson int error, mode; 733159269Srwatson au_id_t auid; 734155408Srwatson 735155408Srwatson ap = dev->si_drv1; 736155408Srwatson KASSERT(ap != NULL, ("audit_pipe_ioctl: ap == NULL")); 737159269Srwatson 738159269Srwatson /* 739159269Srwatson * Audit pipe ioctls: first come standard device node ioctls, then 740159269Srwatson * manipulation of pipe settings, and finally, statistics query 741159269Srwatson * ioctls. 742159269Srwatson */ 743155408Srwatson switch (cmd) { 744155408Srwatson case FIONBIO: 745184488Srwatson AUDIT_PIPE_LOCK(ap); 746155408Srwatson if (*(int *)data) 747155408Srwatson ap->ap_flags |= AUDIT_PIPE_NBIO; 748155408Srwatson else 749155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_NBIO; 750184488Srwatson AUDIT_PIPE_UNLOCK(ap); 751155408Srwatson error = 0; 752155408Srwatson break; 753155408Srwatson 754155408Srwatson case FIONREAD: 755184488Srwatson AUDIT_PIPE_LOCK(ap); 756155408Srwatson if (TAILQ_FIRST(&ap->ap_queue) != NULL) 757155408Srwatson *(int *)data = 758184508Srwatson TAILQ_FIRST(&ap->ap_queue)->ape_record_len - 759184508Srwatson TAILQ_FIRST(&ap->ap_queue)->ape_record_offset; 760155408Srwatson else 761155408Srwatson *(int *)data = 0; 762184488Srwatson AUDIT_PIPE_UNLOCK(ap); 763155408Srwatson error = 0; 764155408Srwatson break; 765155408Srwatson 766155408Srwatson case FIOASYNC: 767184488Srwatson AUDIT_PIPE_LOCK(ap); 768155408Srwatson if (*(int *)data) 769155408Srwatson ap->ap_flags |= AUDIT_PIPE_ASYNC; 770155408Srwatson else 771155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_ASYNC; 772184488Srwatson AUDIT_PIPE_UNLOCK(ap); 773155408Srwatson error = 0; 774155408Srwatson break; 775155408Srwatson 776155408Srwatson case FIOSETOWN: 777155408Srwatson error = fsetown(*(int *)data, &ap->ap_sigio); 778155408Srwatson break; 779155408Srwatson 780155408Srwatson case FIOGETOWN: 781155408Srwatson *(int *)data = fgetown(&ap->ap_sigio); 782155408Srwatson error = 0; 783156880Srwatson break; 784155408Srwatson 785156880Srwatson case AUDITPIPE_GET_QLEN: 786156880Srwatson *(u_int *)data = ap->ap_qlen; 787156880Srwatson error = 0; 788156880Srwatson break; 789156880Srwatson 790156880Srwatson case AUDITPIPE_GET_QLIMIT: 791156880Srwatson *(u_int *)data = ap->ap_qlimit; 792156880Srwatson error = 0; 793156880Srwatson break; 794156880Srwatson 795156880Srwatson case AUDITPIPE_SET_QLIMIT: 796156880Srwatson /* Lockless integer write. */ 797156880Srwatson if (*(u_int *)data >= AUDIT_PIPE_QLIMIT_MIN || 798156880Srwatson *(u_int *)data <= AUDIT_PIPE_QLIMIT_MAX) { 799156880Srwatson ap->ap_qlimit = *(u_int *)data; 800156880Srwatson error = 0; 801156880Srwatson } else 802156880Srwatson error = EINVAL; 803156880Srwatson break; 804156880Srwatson 805156884Srwatson case AUDITPIPE_GET_QLIMIT_MIN: 806156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MIN; 807156884Srwatson error = 0; 808156884Srwatson break; 809156884Srwatson 810156884Srwatson case AUDITPIPE_GET_QLIMIT_MAX: 811156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MAX; 812156884Srwatson error = 0; 813156884Srwatson break; 814156884Srwatson 815159269Srwatson case AUDITPIPE_GET_PRESELECT_FLAGS: 816184488Srwatson AUDIT_PIPE_LOCK(ap); 817159269Srwatson maskp = (au_mask_t *)data; 818159269Srwatson *maskp = ap->ap_preselect_flags; 819184488Srwatson AUDIT_PIPE_UNLOCK(ap); 820159269Srwatson error = 0; 821159269Srwatson break; 822159269Srwatson 823159269Srwatson case AUDITPIPE_SET_PRESELECT_FLAGS: 824184488Srwatson AUDIT_PIPE_LOCK(ap); 825159269Srwatson maskp = (au_mask_t *)data; 826159269Srwatson ap->ap_preselect_flags = *maskp; 827184488Srwatson AUDIT_PIPE_UNLOCK(ap); 828159269Srwatson error = 0; 829159269Srwatson break; 830159269Srwatson 831159269Srwatson case AUDITPIPE_GET_PRESELECT_NAFLAGS: 832184488Srwatson AUDIT_PIPE_LOCK(ap); 833159269Srwatson maskp = (au_mask_t *)data; 834159269Srwatson *maskp = ap->ap_preselect_naflags; 835184488Srwatson AUDIT_PIPE_UNLOCK(ap); 836159269Srwatson error = 0; 837159269Srwatson break; 838159269Srwatson 839159269Srwatson case AUDITPIPE_SET_PRESELECT_NAFLAGS: 840184488Srwatson AUDIT_PIPE_LOCK(ap); 841159269Srwatson maskp = (au_mask_t *)data; 842159269Srwatson ap->ap_preselect_naflags = *maskp; 843184488Srwatson AUDIT_PIPE_UNLOCK(ap); 844159269Srwatson error = 0; 845159269Srwatson break; 846159269Srwatson 847159269Srwatson case AUDITPIPE_GET_PRESELECT_AUID: 848159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 849159269Srwatson error = audit_pipe_preselect_get(ap, aip->aip_auid, 850159269Srwatson &aip->aip_mask); 851159269Srwatson break; 852159269Srwatson 853159269Srwatson case AUDITPIPE_SET_PRESELECT_AUID: 854159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 855159269Srwatson audit_pipe_preselect_set(ap, aip->aip_auid, aip->aip_mask); 856159269Srwatson error = 0; 857159269Srwatson break; 858159269Srwatson 859159269Srwatson case AUDITPIPE_DELETE_PRESELECT_AUID: 860159269Srwatson auid = *(au_id_t *)data; 861159269Srwatson error = audit_pipe_preselect_delete(ap, auid); 862159269Srwatson break; 863159269Srwatson 864159269Srwatson case AUDITPIPE_FLUSH_PRESELECT_AUID: 865159269Srwatson audit_pipe_preselect_flush(ap); 866159269Srwatson error = 0; 867159269Srwatson break; 868159269Srwatson 869159269Srwatson case AUDITPIPE_GET_PRESELECT_MODE: 870184488Srwatson AUDIT_PIPE_LOCK(ap); 871159269Srwatson *(int *)data = ap->ap_preselect_mode; 872184488Srwatson AUDIT_PIPE_UNLOCK(ap); 873159269Srwatson error = 0; 874159269Srwatson break; 875159269Srwatson 876159269Srwatson case AUDITPIPE_SET_PRESELECT_MODE: 877159269Srwatson mode = *(int *)data; 878159269Srwatson switch (mode) { 879159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 880159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 881184488Srwatson AUDIT_PIPE_LOCK(ap); 882159269Srwatson ap->ap_preselect_mode = mode; 883184488Srwatson AUDIT_PIPE_UNLOCK(ap); 884159269Srwatson error = 0; 885159269Srwatson break; 886159269Srwatson 887159269Srwatson default: 888159269Srwatson error = EINVAL; 889159269Srwatson } 890159269Srwatson break; 891159269Srwatson 892159269Srwatson case AUDITPIPE_FLUSH: 893184508Srwatson if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) 894184508Srwatson return (EINTR); 895184488Srwatson AUDIT_PIPE_LOCK(ap); 896159269Srwatson audit_pipe_flush(ap); 897184488Srwatson AUDIT_PIPE_UNLOCK(ap); 898184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 899159269Srwatson error = 0; 900159269Srwatson break; 901159269Srwatson 902161646Srwatson case AUDITPIPE_GET_MAXAUDITDATA: 903161646Srwatson *(u_int *)data = MAXAUDITDATA; 904161646Srwatson error = 0; 905161646Srwatson break; 906161646Srwatson 907156880Srwatson case AUDITPIPE_GET_INSERTS: 908156880Srwatson *(u_int *)data = ap->ap_inserts; 909156880Srwatson error = 0; 910156880Srwatson break; 911156880Srwatson 912156880Srwatson case AUDITPIPE_GET_READS: 913156880Srwatson *(u_int *)data = ap->ap_reads; 914156880Srwatson error = 0; 915156880Srwatson break; 916156880Srwatson 917156880Srwatson case AUDITPIPE_GET_DROPS: 918156880Srwatson *(u_int *)data = ap->ap_drops; 919156880Srwatson error = 0; 920156880Srwatson break; 921156880Srwatson 922156880Srwatson case AUDITPIPE_GET_TRUNCATES: 923156880Srwatson *(u_int *)data = ap->ap_truncates; 924156880Srwatson error = 0; 925156880Srwatson break; 926156880Srwatson 927155408Srwatson default: 928155408Srwatson error = ENOTTY; 929155408Srwatson } 930155408Srwatson return (error); 931155408Srwatson} 932155408Srwatson 933155408Srwatson/* 934155408Srwatson * Audit pipe read. Pull one record off the queue and copy to user space. 935155408Srwatson * On error, the record is dropped. 936159269Srwatson * 937159269Srwatson * Providing more sophisticated behavior, such as partial reads, is tricky 938159269Srwatson * due to the potential for parallel I/O. If partial read support is 939159269Srwatson * required, it will require a per-pipe "current record being read" along 940159269Srwatson * with an offset into that trecord which has already been read. Threads 941159269Srwatson * performing partial reads will need to allocate per-thread copies of the 942159269Srwatson * data so that if another thread completes the read of the record, it can be 943159269Srwatson * freed without adding reference count logic. If this is added, a flag to 944159269Srwatson * indicate that only atomic record reads are desired would be useful, as if 945159269Srwatson * different threads are all waiting for records on the pipe, they will want 946159269Srwatson * independent record reads, which is currently the behavior. 947155408Srwatson */ 948155408Srwatsonstatic int 949155408Srwatsonaudit_pipe_read(struct cdev *dev, struct uio *uio, int flag) 950155408Srwatson{ 951155408Srwatson struct audit_pipe_entry *ape; 952155408Srwatson struct audit_pipe *ap; 953184508Srwatson u_int toread; 954155408Srwatson int error; 955155408Srwatson 956155408Srwatson ap = dev->si_drv1; 957155408Srwatson KASSERT(ap != NULL, ("audit_pipe_read: ap == NULL")); 958184488Srwatson 959184508Srwatson /* 960184508Srwatson * We hold an sx(9) lock over read and flush because we rely on the 961184508Srwatson * stability of a record in the queue during uiomove(9). 962184508Srwatson */ 963184508Srwatson if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) 964184508Srwatson return (EINTR); 965184488Srwatson AUDIT_PIPE_LOCK(ap); 966184508Srwatson while (TAILQ_EMPTY(&ap->ap_queue)) { 967184508Srwatson if (ap->ap_flags & AUDIT_PIPE_NBIO) { 968184508Srwatson AUDIT_PIPE_UNLOCK(ap); 969184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 970184508Srwatson return (EAGAIN); 971155408Srwatson } 972184508Srwatson error = cv_wait_sig(&ap->ap_cv, AUDIT_PIPE_MTX(ap)); 973184508Srwatson if (error) { 974184508Srwatson AUDIT_PIPE_UNLOCK(ap); 975184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 976184508Srwatson return (error); 977184508Srwatson } 978184508Srwatson } 979184508Srwatson 980184508Srwatson /* 981184508Srwatson * Copy as many remaining bytes from the current record to userspace 982184508Srwatson * as we can. 983184508Srwatson * 984184508Srwatson * Note: we rely on the SX lock to maintain ape's stability here. 985184508Srwatson */ 986173083Scsjp ap->ap_reads++; 987184508Srwatson ape = TAILQ_FIRST(&ap->ap_queue); 988184508Srwatson toread = MIN(ape->ape_record_len - ape->ape_record_offset, 989184508Srwatson uio->uio_resid); 990184488Srwatson AUDIT_PIPE_UNLOCK(ap); 991184508Srwatson error = uiomove((char *)ape->ape_record + ape->ape_record_offset, 992184508Srwatson toread, uio); 993184508Srwatson if (error) { 994184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 995184508Srwatson return (error); 996184508Srwatson } 997155408Srwatson 998155408Srwatson /* 999184508Srwatson * If the copy succeeded, update book-keeping, and if no bytes remain 1000184508Srwatson * in the current record, free it. 1001155408Srwatson */ 1002184508Srwatson AUDIT_PIPE_LOCK(ap); 1003184508Srwatson KASSERT(TAILQ_FIRST(&ap->ap_queue) == ape, 1004184508Srwatson ("audit_pipe_read: queue out of sync after uiomove")); 1005184508Srwatson ape->ape_record_offset += toread; 1006184508Srwatson if (ape->ape_record_offset == ape->ape_record_len) { 1007184508Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 1008184508Srwatson ap->ap_qlen--; 1009184508Srwatson } else 1010184508Srwatson ape = NULL; 1011184508Srwatson AUDIT_PIPE_UNLOCK(ap); 1012184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 1013184508Srwatson if (ape != NULL) 1014184508Srwatson audit_pipe_entry_free(ape); 1015155408Srwatson return (error); 1016155408Srwatson} 1017155408Srwatson 1018155408Srwatson/* 1019155408Srwatson * Audit pipe poll. 1020155408Srwatson */ 1021155408Srwatsonstatic int 1022155408Srwatsonaudit_pipe_poll(struct cdev *dev, int events, struct thread *td) 1023155408Srwatson{ 1024155408Srwatson struct audit_pipe *ap; 1025155408Srwatson int revents; 1026155408Srwatson 1027155408Srwatson revents = 0; 1028155408Srwatson ap = dev->si_drv1; 1029155408Srwatson KASSERT(ap != NULL, ("audit_pipe_poll: ap == NULL")); 1030184488Srwatson 1031155408Srwatson if (events & (POLLIN | POLLRDNORM)) { 1032184488Srwatson AUDIT_PIPE_LOCK(ap); 1033155408Srwatson if (TAILQ_FIRST(&ap->ap_queue) != NULL) 1034155408Srwatson revents |= events & (POLLIN | POLLRDNORM); 1035155408Srwatson else 1036155408Srwatson selrecord(td, &ap->ap_selinfo); 1037184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1038155408Srwatson } 1039155408Srwatson return (revents); 1040155408Srwatson} 1041155408Srwatson 1042155408Srwatson/* 1043161582Srwatson * Audit pipe kqfilter. 1044161582Srwatson */ 1045161582Srwatsonstatic int 1046161582Srwatsonaudit_pipe_kqfilter(struct cdev *dev, struct knote *kn) 1047161582Srwatson{ 1048161582Srwatson struct audit_pipe *ap; 1049161582Srwatson 1050161582Srwatson ap = dev->si_drv1; 1051161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqfilter: ap == NULL")); 1052161582Srwatson 1053161582Srwatson if (kn->kn_filter != EVFILT_READ) 1054161582Srwatson return (EINVAL); 1055161582Srwatson 1056161582Srwatson kn->kn_fop = &audit_pipe_read_filterops; 1057161582Srwatson kn->kn_hook = ap; 1058161582Srwatson 1059184488Srwatson AUDIT_PIPE_LOCK(ap); 1060161582Srwatson knlist_add(&ap->ap_selinfo.si_note, kn, 1); 1061184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1062161582Srwatson return (0); 1063161582Srwatson} 1064161582Srwatson 1065161582Srwatson/* 1066161582Srwatson * Return true if there are records available for reading on the pipe. 1067161582Srwatson */ 1068161582Srwatsonstatic int 1069161582Srwatsonaudit_pipe_kqread(struct knote *kn, long hint) 1070161582Srwatson{ 1071161582Srwatson struct audit_pipe_entry *ape; 1072161582Srwatson struct audit_pipe *ap; 1073161582Srwatson 1074161582Srwatson ap = (struct audit_pipe *)kn->kn_hook; 1075161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqread: ap == NULL")); 1076161582Srwatson 1077184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 1078184488Srwatson 1079161582Srwatson if (ap->ap_qlen != 0) { 1080161582Srwatson ape = TAILQ_FIRST(&ap->ap_queue); 1081161582Srwatson KASSERT(ape != NULL, ("audit_pipe_kqread: ape == NULL")); 1082161582Srwatson 1083184508Srwatson kn->kn_data = ape->ape_record_len - ape->ape_record_offset; 1084161582Srwatson return (1); 1085161582Srwatson } else { 1086161582Srwatson kn->kn_data = 0; 1087161582Srwatson return (0); 1088161582Srwatson } 1089161582Srwatson} 1090161582Srwatson 1091161582Srwatson/* 1092161582Srwatson * Detach kqueue state from audit pipe. 1093161582Srwatson */ 1094161582Srwatsonstatic void 1095161582Srwatsonaudit_pipe_kqdetach(struct knote *kn) 1096161582Srwatson{ 1097161582Srwatson struct audit_pipe *ap; 1098161582Srwatson 1099161582Srwatson ap = (struct audit_pipe *)kn->kn_hook; 1100161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqdetach: ap == NULL")); 1101161582Srwatson 1102184488Srwatson AUDIT_PIPE_LOCK(ap); 1103161582Srwatson knlist_remove(&ap->ap_selinfo.si_note, kn, 1); 1104184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1105161582Srwatson} 1106161582Srwatson 1107161582Srwatson/* 1108155408Srwatson * Initialize the audit pipe system. 1109155408Srwatson */ 1110155408Srwatsonstatic void 1111155408Srwatsonaudit_pipe_init(void *unused) 1112155408Srwatson{ 1113155408Srwatson 1114155408Srwatson TAILQ_INIT(&audit_pipe_list); 1115184488Srwatson AUDIT_PIPE_LIST_LOCK_INIT(); 1116155408Srwatson 1117155408Srwatson clone_setup(&audit_pipe_clones); 1118155408Srwatson audit_pipe_eh_tag = EVENTHANDLER_REGISTER(dev_clone, 1119155408Srwatson audit_pipe_clone, 0, 1000); 1120155408Srwatson if (audit_pipe_eh_tag == NULL) 1121155408Srwatson panic("audit_pipe_init: EVENTHANDLER_REGISTER"); 1122155408Srwatson} 1123155408Srwatson 1124155408SrwatsonSYSINIT(audit_pipe_init, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, audit_pipe_init, 1125155408Srwatson NULL); 1126