1155408Srwatson/*- 2155408Srwatson * Copyright (c) 2006 Robert N. M. Watson 3188315Srwatson * Copyright (c) 2008-2009 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: stable/11/sys/security/audit/audit_pipe.c 337122 2018-08-02 09:31:50Z avg $"); 32178186Srwatson 33155408Srwatson#include <sys/param.h> 34155408Srwatson#include <sys/condvar.h> 35155408Srwatson#include <sys/conf.h> 36155408Srwatson#include <sys/eventhandler.h> 37155408Srwatson#include <sys/filio.h> 38155408Srwatson#include <sys/kernel.h> 39155408Srwatson#include <sys/lock.h> 40155408Srwatson#include <sys/malloc.h> 41155408Srwatson#include <sys/mutex.h> 42155408Srwatson#include <sys/poll.h> 43155408Srwatson#include <sys/proc.h> 44155408Srwatson#include <sys/queue.h> 45184488Srwatson#include <sys/rwlock.h> 46155408Srwatson#include <sys/selinfo.h> 47155408Srwatson#include <sys/sigio.h> 48155408Srwatson#include <sys/signal.h> 49155408Srwatson#include <sys/signalvar.h> 50184508Srwatson#include <sys/sx.h> 51155408Srwatson#include <sys/systm.h> 52155408Srwatson#include <sys/uio.h> 53155408Srwatson 54155408Srwatson#include <security/audit/audit.h> 55156880Srwatson#include <security/audit/audit_ioctl.h> 56155408Srwatson#include <security/audit/audit_private.h> 57155408Srwatson 58155408Srwatson/* 59155408Srwatson * Implementation of a clonable special device providing a live stream of BSM 60184545Srwatson * audit data. Consumers receive a "tee" of the system audit trail by 61184545Srwatson * default, but may also define alternative event selections using ioctls. 62184545Srwatson * This interface provides unreliable but timely access to audit events. 63184545Srwatson * Consumers should be very careful to avoid introducing event cycles. 64155408Srwatson */ 65155408Srwatson 66155408Srwatson/* 67155408Srwatson * Memory types. 68155408Srwatson */ 69155408Srwatsonstatic MALLOC_DEFINE(M_AUDIT_PIPE, "audit_pipe", "Audit pipes"); 70155408Srwatsonstatic MALLOC_DEFINE(M_AUDIT_PIPE_ENTRY, "audit_pipeent", 71155408Srwatson "Audit pipe entries and buffers"); 72174894Swkoszekstatic MALLOC_DEFINE(M_AUDIT_PIPE_PRESELECT, "audit_pipe_presel", 73159269Srwatson "Audit pipe preselection structure"); 74155408Srwatson 75155408Srwatson/* 76155408Srwatson * Audit pipe buffer parameters. 77155408Srwatson */ 78156883Srwatson#define AUDIT_PIPE_QLIMIT_DEFAULT (128) 79188315Srwatson#define AUDIT_PIPE_QLIMIT_MIN (1) 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 u_int ap_flags; 116155408Srwatson 117155408Srwatson struct selinfo ap_selinfo; 118155408Srwatson struct sigio *ap_sigio; 119155408Srwatson 120184488Srwatson /* 121184488Srwatson * Per-pipe mutex protecting most fields in this data structure. 122184488Srwatson */ 123184508Srwatson struct mtx ap_mtx; 124184488Srwatson 125184488Srwatson /* 126184508Srwatson * Per-pipe sleep lock serializing user-generated reads and flushes. 127184508Srwatson * uiomove() is called to copy out the current head record's data 128184508Srwatson * while the record remains in the queue, so we prevent other threads 129184508Srwatson * from removing it using this lock. 130184508Srwatson */ 131184508Srwatson struct sx ap_sx; 132184508Srwatson 133184508Srwatson /* 134184488Srwatson * Condition variable to signal when data has been delivered to a 135184488Srwatson * pipe. 136184488Srwatson */ 137184488Srwatson struct cv ap_cv; 138184488Srwatson 139184536Srwatson /* 140184536Srwatson * Various queue-reated variables: qlen and qlimit are a count of 141184536Srwatson * records in the queue; qbyteslen is the number of bytes of data 142184536Srwatson * across all records, and qoffset is the amount read so far of the 143184536Srwatson * first record in the queue. The number of bytes available for 144184536Srwatson * reading in the queue is qbyteslen - qoffset. 145184536Srwatson */ 146155408Srwatson u_int ap_qlen; 147155408Srwatson u_int ap_qlimit; 148184536Srwatson u_int ap_qbyteslen; 149184536Srwatson u_int ap_qoffset; 150155408Srwatson 151184540Srwatson /* 152184540Srwatson * Per-pipe operation statistics. 153184540Srwatson */ 154155408Srwatson u_int64_t ap_inserts; /* Records added. */ 155155408Srwatson u_int64_t ap_reads; /* Records read. */ 156155408Srwatson u_int64_t ap_drops; /* Records dropped. */ 157155408Srwatson 158159269Srwatson /* 159159269Srwatson * Fields relating to pipe interest: global masks for unmatched 160159269Srwatson * processes (attributable, non-attributable), and a list of specific 161159269Srwatson * interest specifications by auid. 162159269Srwatson */ 163159269Srwatson int ap_preselect_mode; 164159269Srwatson au_mask_t ap_preselect_flags; 165159269Srwatson au_mask_t ap_preselect_naflags; 166159269Srwatson TAILQ_HEAD(, audit_pipe_preselect) ap_preselect_list; 167159269Srwatson 168159269Srwatson /* 169184508Srwatson * Current pending record list. Protected by a combination of ap_mtx 170184508Srwatson * and ap_sx. Note particularly that *both* locks are required to 171186662Srwatson * remove a record from the head of the queue, as an in-progress read 172186662Srwatson * may sleep while copying and therefore cannot hold ap_mtx. 173159269Srwatson */ 174155408Srwatson TAILQ_HEAD(, audit_pipe_entry) ap_queue; 175155408Srwatson 176159269Srwatson /* 177159269Srwatson * Global pipe list. 178159269Srwatson */ 179155408Srwatson TAILQ_ENTRY(audit_pipe) ap_list; 180155408Srwatson}; 181155408Srwatson 182184508Srwatson#define AUDIT_PIPE_LOCK(ap) mtx_lock(&(ap)->ap_mtx) 183184508Srwatson#define AUDIT_PIPE_LOCK_ASSERT(ap) mtx_assert(&(ap)->ap_mtx, MA_OWNED) 184184508Srwatson#define AUDIT_PIPE_LOCK_DESTROY(ap) mtx_destroy(&(ap)->ap_mtx) 185184508Srwatson#define AUDIT_PIPE_LOCK_INIT(ap) mtx_init(&(ap)->ap_mtx, \ 186184508Srwatson "audit_pipe_mtx", NULL, MTX_DEF) 187184508Srwatson#define AUDIT_PIPE_UNLOCK(ap) mtx_unlock(&(ap)->ap_mtx) 188184508Srwatson#define AUDIT_PIPE_MTX(ap) (&(ap)->ap_mtx) 189184488Srwatson 190184508Srwatson#define AUDIT_PIPE_SX_LOCK_DESTROY(ap) sx_destroy(&(ap)->ap_sx) 191184508Srwatson#define AUDIT_PIPE_SX_LOCK_INIT(ap) sx_init(&(ap)->ap_sx, "audit_pipe_sx") 192184508Srwatson#define AUDIT_PIPE_SX_XLOCK_ASSERT(ap) sx_assert(&(ap)->ap_sx, SA_XLOCKED) 193184508Srwatson#define AUDIT_PIPE_SX_XLOCK_SIG(ap) sx_xlock_sig(&(ap)->ap_sx) 194184508Srwatson#define AUDIT_PIPE_SX_XUNLOCK(ap) sx_xunlock(&(ap)->ap_sx) 195184508Srwatson 196155408Srwatson/* 197184488Srwatson * Global list of audit pipes, rwlock to protect it. Individual record 198184488Srwatson * queues on pipes are protected by per-pipe locks; these locks synchronize 199184488Srwatson * between threads walking the list to deliver to individual pipes and add/ 200184488Srwatson * remove of pipes, and are mostly acquired for read. 201155408Srwatson */ 202155408Srwatsonstatic TAILQ_HEAD(, audit_pipe) audit_pipe_list; 203184488Srwatsonstatic struct rwlock audit_pipe_lock; 204155408Srwatson 205184488Srwatson#define AUDIT_PIPE_LIST_LOCK_INIT() rw_init(&audit_pipe_lock, \ 206184488Srwatson "audit_pipe_list_lock") 207270221Sdavide#define AUDIT_PIPE_LIST_LOCK_DESTROY() rw_destroy(&audit_pipe_lock) 208184488Srwatson#define AUDIT_PIPE_LIST_RLOCK() rw_rlock(&audit_pipe_lock) 209184488Srwatson#define AUDIT_PIPE_LIST_RUNLOCK() rw_runlock(&audit_pipe_lock) 210184488Srwatson#define AUDIT_PIPE_LIST_WLOCK() rw_wlock(&audit_pipe_lock) 211184488Srwatson#define AUDIT_PIPE_LIST_WLOCK_ASSERT() rw_assert(&audit_pipe_lock, \ 212184488Srwatson RA_WLOCKED) 213184488Srwatson#define AUDIT_PIPE_LIST_WUNLOCK() rw_wunlock(&audit_pipe_lock) 214155408Srwatson 215155408Srwatson/* 216270221Sdavide * Audit pipe device. 217155408Srwatson */ 218270221Sdavidestatic struct cdev *audit_pipe_dev; 219155408Srwatson 220270221Sdavide#define AUDIT_PIPE_NAME "auditpipe" 221270221Sdavide 222155408Srwatson/* 223155408Srwatson * Special device methods and definition. 224155408Srwatson */ 225155408Srwatsonstatic d_open_t audit_pipe_open; 226155408Srwatsonstatic d_read_t audit_pipe_read; 227155408Srwatsonstatic d_ioctl_t audit_pipe_ioctl; 228155408Srwatsonstatic d_poll_t audit_pipe_poll; 229161582Srwatsonstatic d_kqfilter_t audit_pipe_kqfilter; 230155408Srwatson 231155408Srwatsonstatic struct cdevsw audit_pipe_cdevsw = { 232155408Srwatson .d_version = D_VERSION, 233155408Srwatson .d_open = audit_pipe_open, 234155408Srwatson .d_read = audit_pipe_read, 235155408Srwatson .d_ioctl = audit_pipe_ioctl, 236155408Srwatson .d_poll = audit_pipe_poll, 237161582Srwatson .d_kqfilter = audit_pipe_kqfilter, 238155408Srwatson .d_name = AUDIT_PIPE_NAME, 239155408Srwatson}; 240155408Srwatson 241161582Srwatsonstatic int audit_pipe_kqread(struct knote *note, long hint); 242161582Srwatsonstatic void audit_pipe_kqdetach(struct knote *note); 243161582Srwatson 244161582Srwatsonstatic struct filterops audit_pipe_read_filterops = { 245161582Srwatson .f_isfd = 1, 246161582Srwatson .f_attach = NULL, 247161582Srwatson .f_detach = audit_pipe_kqdetach, 248161582Srwatson .f_event = audit_pipe_kqread, 249161582Srwatson}; 250161582Srwatson 251155408Srwatson/* 252155408Srwatson * Some global statistics on audit pipes. 253155408Srwatson */ 254155408Srwatsonstatic int audit_pipe_count; /* Current number of pipes. */ 255155408Srwatsonstatic u_int64_t audit_pipe_ever; /* Pipes ever allocated. */ 256155408Srwatsonstatic u_int64_t audit_pipe_records; /* Records seen. */ 257155408Srwatsonstatic u_int64_t audit_pipe_drops; /* Global record drop count. */ 258155408Srwatson 259155408Srwatson/* 260155408Srwatson * Free an audit pipe entry. 261155408Srwatson */ 262155408Srwatsonstatic void 263155408Srwatsonaudit_pipe_entry_free(struct audit_pipe_entry *ape) 264155408Srwatson{ 265155408Srwatson 266155408Srwatson free(ape->ape_record, M_AUDIT_PIPE_ENTRY); 267155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 268155408Srwatson} 269155408Srwatson 270155408Srwatson/* 271159269Srwatson * Find an audit pipe preselection specification for an auid, if any. 272159269Srwatson */ 273159269Srwatsonstatic struct audit_pipe_preselect * 274159269Srwatsonaudit_pipe_preselect_find(struct audit_pipe *ap, au_id_t auid) 275159269Srwatson{ 276159269Srwatson struct audit_pipe_preselect *app; 277159269Srwatson 278184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 279159269Srwatson 280159269Srwatson TAILQ_FOREACH(app, &ap->ap_preselect_list, app_list) { 281159269Srwatson if (app->app_auid == auid) 282159269Srwatson return (app); 283159269Srwatson } 284159269Srwatson return (NULL); 285159269Srwatson} 286159269Srwatson 287159269Srwatson/* 288159269Srwatson * Query the per-pipe mask for a specific auid. 289159269Srwatson */ 290159269Srwatsonstatic int 291159269Srwatsonaudit_pipe_preselect_get(struct audit_pipe *ap, au_id_t auid, 292159269Srwatson au_mask_t *maskp) 293159269Srwatson{ 294159269Srwatson struct audit_pipe_preselect *app; 295159269Srwatson int error; 296159269Srwatson 297184488Srwatson AUDIT_PIPE_LOCK(ap); 298159269Srwatson app = audit_pipe_preselect_find(ap, auid); 299159269Srwatson if (app != NULL) { 300159269Srwatson *maskp = app->app_mask; 301159269Srwatson error = 0; 302159269Srwatson } else 303159269Srwatson error = ENOENT; 304184488Srwatson AUDIT_PIPE_UNLOCK(ap); 305159269Srwatson return (error); 306159269Srwatson} 307159269Srwatson 308159269Srwatson/* 309159269Srwatson * Set the per-pipe mask for a specific auid. Add a new entry if needed; 310159269Srwatson * otherwise, update the current entry. 311159269Srwatson */ 312159269Srwatsonstatic void 313159269Srwatsonaudit_pipe_preselect_set(struct audit_pipe *ap, au_id_t auid, au_mask_t mask) 314159269Srwatson{ 315159269Srwatson struct audit_pipe_preselect *app, *app_new; 316159269Srwatson 317159269Srwatson /* 318159269Srwatson * Pessimistically assume that the auid doesn't already have a mask 319159269Srwatson * set, and allocate. We will free it if it is unneeded. 320159269Srwatson */ 321159269Srwatson app_new = malloc(sizeof(*app_new), M_AUDIT_PIPE_PRESELECT, M_WAITOK); 322184488Srwatson AUDIT_PIPE_LOCK(ap); 323159269Srwatson app = audit_pipe_preselect_find(ap, auid); 324159269Srwatson if (app == NULL) { 325159269Srwatson app = app_new; 326159269Srwatson app_new = NULL; 327159269Srwatson app->app_auid = auid; 328159269Srwatson TAILQ_INSERT_TAIL(&ap->ap_preselect_list, app, app_list); 329159269Srwatson } 330159269Srwatson app->app_mask = mask; 331184488Srwatson AUDIT_PIPE_UNLOCK(ap); 332159269Srwatson if (app_new != NULL) 333159269Srwatson free(app_new, M_AUDIT_PIPE_PRESELECT); 334159269Srwatson} 335159269Srwatson 336159269Srwatson/* 337159269Srwatson * Delete a per-auid mask on an audit pipe. 338159269Srwatson */ 339159269Srwatsonstatic int 340159269Srwatsonaudit_pipe_preselect_delete(struct audit_pipe *ap, au_id_t auid) 341159269Srwatson{ 342159269Srwatson struct audit_pipe_preselect *app; 343159269Srwatson int error; 344159269Srwatson 345184488Srwatson AUDIT_PIPE_LOCK(ap); 346159269Srwatson app = audit_pipe_preselect_find(ap, auid); 347159269Srwatson if (app != NULL) { 348159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 349159269Srwatson error = 0; 350159269Srwatson } else 351159269Srwatson error = ENOENT; 352184488Srwatson AUDIT_PIPE_UNLOCK(ap); 353159269Srwatson if (app != NULL) 354159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 355159269Srwatson return (error); 356159269Srwatson} 357159269Srwatson 358159269Srwatson/* 359159269Srwatson * Delete all per-auid masks on an audit pipe. 360159269Srwatson */ 361159269Srwatsonstatic void 362159269Srwatsonaudit_pipe_preselect_flush_locked(struct audit_pipe *ap) 363159269Srwatson{ 364159269Srwatson struct audit_pipe_preselect *app; 365159269Srwatson 366184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 367159269Srwatson 368159269Srwatson while ((app = TAILQ_FIRST(&ap->ap_preselect_list)) != NULL) { 369159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 370159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 371159269Srwatson } 372159269Srwatson} 373159269Srwatson 374159269Srwatsonstatic void 375159269Srwatsonaudit_pipe_preselect_flush(struct audit_pipe *ap) 376159269Srwatson{ 377159269Srwatson 378184488Srwatson AUDIT_PIPE_LOCK(ap); 379159269Srwatson audit_pipe_preselect_flush_locked(ap); 380184488Srwatson AUDIT_PIPE_UNLOCK(ap); 381159269Srwatson} 382159269Srwatson 383170196Srwatson/*- 384159269Srwatson * Determine whether a specific audit pipe matches a record with these 385159269Srwatson * properties. Algorithm is as follows: 386159269Srwatson * 387159269Srwatson * - If the pipe is configured to track the default trail configuration, then 388159269Srwatson * use the results of global preselection matching. 389159269Srwatson * - If not, search for a specifically configured auid entry matching the 390159269Srwatson * event. If an entry is found, use that. 391159269Srwatson * - Otherwise, use the default flags or naflags configured for the pipe. 392159269Srwatson */ 393159269Srwatsonstatic int 394159269Srwatsonaudit_pipe_preselect_check(struct audit_pipe *ap, au_id_t auid, 395159269Srwatson au_event_t event, au_class_t class, int sorf, int trail_preselect) 396159269Srwatson{ 397159269Srwatson struct audit_pipe_preselect *app; 398159269Srwatson 399184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 400159269Srwatson 401159269Srwatson switch (ap->ap_preselect_mode) { 402159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 403159269Srwatson return (trail_preselect); 404159269Srwatson 405159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 406159269Srwatson app = audit_pipe_preselect_find(ap, auid); 407159269Srwatson if (app == NULL) { 408159269Srwatson if (auid == AU_DEFAUDITID) 409159269Srwatson return (au_preselect(event, class, 410159269Srwatson &ap->ap_preselect_naflags, sorf)); 411159269Srwatson else 412159269Srwatson return (au_preselect(event, class, 413159269Srwatson &ap->ap_preselect_flags, sorf)); 414159269Srwatson } else 415159269Srwatson return (au_preselect(event, class, &app->app_mask, 416159269Srwatson sorf)); 417159269Srwatson 418159269Srwatson default: 419159269Srwatson panic("audit_pipe_preselect_check: mode %d", 420159269Srwatson ap->ap_preselect_mode); 421159269Srwatson } 422159269Srwatson 423159269Srwatson return (0); 424159269Srwatson} 425159269Srwatson 426159269Srwatson/* 427159269Srwatson * Determine whether there exists a pipe interested in a record with specific 428159269Srwatson * properties. 429159269Srwatson */ 430159269Srwatsonint 431159269Srwatsonaudit_pipe_preselect(au_id_t auid, au_event_t event, au_class_t class, 432159269Srwatson int sorf, int trail_preselect) 433159269Srwatson{ 434159269Srwatson struct audit_pipe *ap; 435159269Srwatson 436186825Srwatson /* Lockless read to avoid acquiring the global lock if not needed. */ 437186825Srwatson if (TAILQ_EMPTY(&audit_pipe_list)) 438186825Srwatson return (0); 439186825Srwatson 440184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 441159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 442184488Srwatson AUDIT_PIPE_LOCK(ap); 443159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 444159269Srwatson trail_preselect)) { 445184488Srwatson AUDIT_PIPE_UNLOCK(ap); 446184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 447159269Srwatson return (1); 448159269Srwatson } 449184488Srwatson AUDIT_PIPE_UNLOCK(ap); 450159269Srwatson } 451184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 452159269Srwatson return (0); 453159269Srwatson} 454159269Srwatson 455159269Srwatson/* 456159269Srwatson * Append individual record to a queue -- allocate queue-local buffer, and 457184489Srwatson * add to the queue. If the queue is full or we can't allocate memory, drop 458184489Srwatson * the newest record. 459155408Srwatson */ 460155408Srwatsonstatic void 461155408Srwatsonaudit_pipe_append(struct audit_pipe *ap, void *record, u_int record_len) 462155408Srwatson{ 463184489Srwatson struct audit_pipe_entry *ape; 464155408Srwatson 465184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 466155408Srwatson 467184489Srwatson if (ap->ap_qlen >= ap->ap_qlimit) { 468184489Srwatson ap->ap_drops++; 469184489Srwatson audit_pipe_drops++; 470184489Srwatson return; 471184489Srwatson } 472184489Srwatson 473155408Srwatson ape = malloc(sizeof(*ape), M_AUDIT_PIPE_ENTRY, M_NOWAIT | M_ZERO); 474155408Srwatson if (ape == NULL) { 475155408Srwatson ap->ap_drops++; 476156292Srwatson audit_pipe_drops++; 477155408Srwatson return; 478155408Srwatson } 479155408Srwatson 480155408Srwatson ape->ape_record = malloc(record_len, M_AUDIT_PIPE_ENTRY, M_NOWAIT); 481155408Srwatson if (ape->ape_record == NULL) { 482155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 483155408Srwatson ap->ap_drops++; 484155408Srwatson audit_pipe_drops++; 485155408Srwatson return; 486155408Srwatson } 487155408Srwatson 488155408Srwatson bcopy(record, ape->ape_record, record_len); 489155408Srwatson ape->ape_record_len = record_len; 490155408Srwatson 491155408Srwatson TAILQ_INSERT_TAIL(&ap->ap_queue, ape, ape_queue); 492155408Srwatson ap->ap_inserts++; 493155408Srwatson ap->ap_qlen++; 494184536Srwatson ap->ap_qbyteslen += ape->ape_record_len; 495155408Srwatson selwakeuppri(&ap->ap_selinfo, PSOCK); 496161582Srwatson KNOTE_LOCKED(&ap->ap_selinfo.si_note, 0); 497155408Srwatson if (ap->ap_flags & AUDIT_PIPE_ASYNC) 498155408Srwatson pgsigio(&ap->ap_sigio, SIGIO, 0); 499184488Srwatson cv_broadcast(&ap->ap_cv); 500155408Srwatson} 501155408Srwatson 502155408Srwatson/* 503155408Srwatson * audit_pipe_submit(): audit_worker submits audit records via this 504155408Srwatson * interface, which arranges for them to be delivered to pipe queues. 505155408Srwatson */ 506155408Srwatsonvoid 507159269Srwatsonaudit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class, int sorf, 508159269Srwatson int trail_select, void *record, u_int record_len) 509155408Srwatson{ 510155408Srwatson struct audit_pipe *ap; 511155408Srwatson 512155408Srwatson /* 513184488Srwatson * Lockless read to avoid lock overhead if pipes are not in use. 514155408Srwatson */ 515155408Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 516155408Srwatson return; 517155408Srwatson 518184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 519159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 520184488Srwatson AUDIT_PIPE_LOCK(ap); 521159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 522159269Srwatson trail_select)) 523159269Srwatson audit_pipe_append(ap, record, record_len); 524184488Srwatson AUDIT_PIPE_UNLOCK(ap); 525159269Srwatson } 526184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 527184488Srwatson 528184488Srwatson /* Unlocked increment. */ 529159269Srwatson audit_pipe_records++; 530159269Srwatson} 531159269Srwatson 532159269Srwatson/* 533159269Srwatson * audit_pipe_submit_user(): the same as audit_pipe_submit(), except that 534159269Srwatson * since we don't currently have selection information available, it is 535159269Srwatson * delivered to the pipe unconditionally. 536159269Srwatson * 537159269Srwatson * XXXRW: This is a bug. The BSM check routine for submitting a user record 538159269Srwatson * should parse that information and return it. 539159269Srwatson */ 540159269Srwatsonvoid 541159269Srwatsonaudit_pipe_submit_user(void *record, u_int record_len) 542159269Srwatson{ 543159269Srwatson struct audit_pipe *ap; 544159269Srwatson 545159269Srwatson /* 546184488Srwatson * Lockless read to avoid lock overhead if pipes are not in use. 547159269Srwatson */ 548159269Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 549159269Srwatson return; 550159269Srwatson 551184488Srwatson AUDIT_PIPE_LIST_RLOCK(); 552184488Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 553184488Srwatson AUDIT_PIPE_LOCK(ap); 554155408Srwatson audit_pipe_append(ap, record, record_len); 555184488Srwatson AUDIT_PIPE_UNLOCK(ap); 556184488Srwatson } 557184488Srwatson AUDIT_PIPE_LIST_RUNLOCK(); 558184488Srwatson 559184488Srwatson /* Unlocked increment. */ 560155408Srwatson audit_pipe_records++; 561155408Srwatson} 562155408Srwatson 563155408Srwatson/* 564155408Srwatson * Allocate a new audit pipe. Connects the pipe, on success, to the global 565155408Srwatson * list and updates statistics. 566155408Srwatson */ 567155408Srwatsonstatic struct audit_pipe * 568155408Srwatsonaudit_pipe_alloc(void) 569155408Srwatson{ 570155408Srwatson struct audit_pipe *ap; 571155408Srwatson 572155408Srwatson ap = malloc(sizeof(*ap), M_AUDIT_PIPE, M_NOWAIT | M_ZERO); 573155408Srwatson if (ap == NULL) 574155408Srwatson return (NULL); 575155408Srwatson ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT; 576155408Srwatson TAILQ_INIT(&ap->ap_queue); 577193951Skib knlist_init_mtx(&ap->ap_selinfo.si_note, AUDIT_PIPE_MTX(ap)); 578184488Srwatson AUDIT_PIPE_LOCK_INIT(ap); 579184508Srwatson AUDIT_PIPE_SX_LOCK_INIT(ap); 580184488Srwatson cv_init(&ap->ap_cv, "audit_pipe"); 581159269Srwatson 582159269Srwatson /* 583159269Srwatson * Default flags, naflags, and auid-specific preselection settings to 584159269Srwatson * 0. Initialize the mode to the global trail so that if praudit(1) 585159269Srwatson * is run on /dev/auditpipe, it sees events associated with the 586159269Srwatson * default trail. Pipe-aware application can clear the flag, set 587159269Srwatson * custom masks, and flush the pipe as needed. 588159269Srwatson */ 589159269Srwatson bzero(&ap->ap_preselect_flags, sizeof(ap->ap_preselect_flags)); 590159269Srwatson bzero(&ap->ap_preselect_naflags, sizeof(ap->ap_preselect_naflags)); 591159269Srwatson TAILQ_INIT(&ap->ap_preselect_list); 592159269Srwatson ap->ap_preselect_mode = AUDITPIPE_PRESELECT_MODE_TRAIL; 593159269Srwatson 594161582Srwatson /* 595161582Srwatson * Add to global list and update global statistics. 596161582Srwatson */ 597270221Sdavide AUDIT_PIPE_LIST_WLOCK(); 598155408Srwatson TAILQ_INSERT_HEAD(&audit_pipe_list, ap, ap_list); 599155408Srwatson audit_pipe_count++; 600155408Srwatson audit_pipe_ever++; 601270221Sdavide AUDIT_PIPE_LIST_WUNLOCK(); 602159269Srwatson 603155408Srwatson return (ap); 604155408Srwatson} 605155408Srwatson 606155408Srwatson/* 607159269Srwatson * Flush all records currently present in an audit pipe; assume mutex is held. 608155408Srwatson */ 609155408Srwatsonstatic void 610159269Srwatsonaudit_pipe_flush(struct audit_pipe *ap) 611155408Srwatson{ 612155408Srwatson struct audit_pipe_entry *ape; 613155408Srwatson 614184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 615155408Srwatson 616155408Srwatson while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL) { 617155408Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 618184536Srwatson ap->ap_qbyteslen -= ape->ape_record_len; 619155408Srwatson audit_pipe_entry_free(ape); 620155408Srwatson ap->ap_qlen--; 621155408Srwatson } 622184536Srwatson ap->ap_qoffset = 0; 623184536Srwatson 624184536Srwatson KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qbyteslen")); 625184536Srwatson KASSERT(ap->ap_qbyteslen == 0, ("audit_pipe_flush: ap_qbyteslen")); 626159269Srwatson} 627159269Srwatson 628159269Srwatson/* 629159269Srwatson * Free an audit pipe; this means freeing all preselection state and all 630184488Srwatson * records in the pipe. Assumes global write lock and pipe mutex are held to 631184488Srwatson * prevent any new records from being inserted during the free, and that the 632184488Srwatson * audit pipe is still on the global list. 633159269Srwatson */ 634159269Srwatsonstatic void 635159269Srwatsonaudit_pipe_free(struct audit_pipe *ap) 636159269Srwatson{ 637159269Srwatson 638184488Srwatson AUDIT_PIPE_LIST_WLOCK_ASSERT(); 639184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 640159269Srwatson 641159269Srwatson audit_pipe_preselect_flush_locked(ap); 642159269Srwatson audit_pipe_flush(ap); 643184488Srwatson cv_destroy(&ap->ap_cv); 644184508Srwatson AUDIT_PIPE_SX_LOCK_DESTROY(ap); 645184488Srwatson AUDIT_PIPE_LOCK_DESTROY(ap); 646225177Sattilio seldrain(&ap->ap_selinfo); 647161582Srwatson knlist_destroy(&ap->ap_selinfo.si_note); 648159269Srwatson TAILQ_REMOVE(&audit_pipe_list, ap, ap_list); 649155408Srwatson free(ap, M_AUDIT_PIPE); 650155408Srwatson audit_pipe_count--; 651155408Srwatson} 652155408Srwatson 653155408Srwatsonstatic void 654270221Sdavideaudit_pipe_dtor(void *arg) 655155408Srwatson{ 656270221Sdavide struct audit_pipe *ap; 657155408Srwatson 658270221Sdavide ap = arg; 659293826Skib funsetown(&ap->ap_sigio); 660270221Sdavide AUDIT_PIPE_LIST_WLOCK(); 661270221Sdavide AUDIT_PIPE_LOCK(ap); 662270221Sdavide audit_pipe_free(ap); 663270221Sdavide AUDIT_PIPE_LIST_WUNLOCK(); 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; 675270221Sdavide int error; 676155408Srwatson 677270221Sdavide ap = audit_pipe_alloc(); 678293826Skib if (ap == NULL) 679270221Sdavide return (ENOMEM); 680270221Sdavide fsetown(td->td_proc->p_pid, &ap->ap_sigio); 681270221Sdavide error = devfs_set_cdevpriv(ap, audit_pipe_dtor); 682270221Sdavide if (error != 0) 683293826Skib audit_pipe_dtor(ap); 684293826Skib return (error); 685155408Srwatson} 686155408Srwatson 687155408Srwatson/* 688156880Srwatson * Audit pipe ioctl() routine. Handle file descriptor and audit pipe layer 689156880Srwatson * commands. 690155408Srwatson */ 691155408Srwatsonstatic int 692155408Srwatsonaudit_pipe_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, 693155408Srwatson struct thread *td) 694155408Srwatson{ 695159269Srwatson struct auditpipe_ioctl_preselect *aip; 696155408Srwatson struct audit_pipe *ap; 697159269Srwatson au_mask_t *maskp; 698159269Srwatson int error, mode; 699159269Srwatson au_id_t auid; 700155408Srwatson 701270221Sdavide error = devfs_get_cdevpriv((void **)&ap); 702270221Sdavide if (error != 0) 703270221Sdavide return (error); 704159269Srwatson 705159269Srwatson /* 706159269Srwatson * Audit pipe ioctls: first come standard device node ioctls, then 707159269Srwatson * manipulation of pipe settings, and finally, statistics query 708159269Srwatson * ioctls. 709159269Srwatson */ 710155408Srwatson switch (cmd) { 711155408Srwatson case FIONBIO: 712184488Srwatson AUDIT_PIPE_LOCK(ap); 713155408Srwatson if (*(int *)data) 714155408Srwatson ap->ap_flags |= AUDIT_PIPE_NBIO; 715155408Srwatson else 716155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_NBIO; 717184488Srwatson AUDIT_PIPE_UNLOCK(ap); 718155408Srwatson error = 0; 719155408Srwatson break; 720155408Srwatson 721155408Srwatson case FIONREAD: 722184488Srwatson AUDIT_PIPE_LOCK(ap); 723184536Srwatson *(int *)data = ap->ap_qbyteslen - ap->ap_qoffset; 724184488Srwatson AUDIT_PIPE_UNLOCK(ap); 725155408Srwatson error = 0; 726155408Srwatson break; 727155408Srwatson 728155408Srwatson case FIOASYNC: 729184488Srwatson AUDIT_PIPE_LOCK(ap); 730155408Srwatson if (*(int *)data) 731155408Srwatson ap->ap_flags |= AUDIT_PIPE_ASYNC; 732155408Srwatson else 733155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_ASYNC; 734184488Srwatson AUDIT_PIPE_UNLOCK(ap); 735155408Srwatson error = 0; 736155408Srwatson break; 737155408Srwatson 738155408Srwatson case FIOSETOWN: 739155408Srwatson error = fsetown(*(int *)data, &ap->ap_sigio); 740155408Srwatson break; 741155408Srwatson 742155408Srwatson case FIOGETOWN: 743155408Srwatson *(int *)data = fgetown(&ap->ap_sigio); 744155408Srwatson error = 0; 745156880Srwatson break; 746155408Srwatson 747156880Srwatson case AUDITPIPE_GET_QLEN: 748156880Srwatson *(u_int *)data = ap->ap_qlen; 749156880Srwatson error = 0; 750156880Srwatson break; 751156880Srwatson 752156880Srwatson case AUDITPIPE_GET_QLIMIT: 753156880Srwatson *(u_int *)data = ap->ap_qlimit; 754156880Srwatson error = 0; 755156880Srwatson break; 756156880Srwatson 757156880Srwatson case AUDITPIPE_SET_QLIMIT: 758156880Srwatson /* Lockless integer write. */ 759337122Savg if (*(u_int *)data >= AUDIT_PIPE_QLIMIT_MIN && 760156880Srwatson *(u_int *)data <= AUDIT_PIPE_QLIMIT_MAX) { 761156880Srwatson ap->ap_qlimit = *(u_int *)data; 762156880Srwatson error = 0; 763156880Srwatson } else 764156880Srwatson error = EINVAL; 765156880Srwatson break; 766156880Srwatson 767156884Srwatson case AUDITPIPE_GET_QLIMIT_MIN: 768156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MIN; 769156884Srwatson error = 0; 770156884Srwatson break; 771156884Srwatson 772156884Srwatson case AUDITPIPE_GET_QLIMIT_MAX: 773156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MAX; 774156884Srwatson error = 0; 775156884Srwatson break; 776156884Srwatson 777159269Srwatson case AUDITPIPE_GET_PRESELECT_FLAGS: 778184488Srwatson AUDIT_PIPE_LOCK(ap); 779159269Srwatson maskp = (au_mask_t *)data; 780159269Srwatson *maskp = ap->ap_preselect_flags; 781184488Srwatson AUDIT_PIPE_UNLOCK(ap); 782159269Srwatson error = 0; 783159269Srwatson break; 784159269Srwatson 785159269Srwatson case AUDITPIPE_SET_PRESELECT_FLAGS: 786184488Srwatson AUDIT_PIPE_LOCK(ap); 787159269Srwatson maskp = (au_mask_t *)data; 788159269Srwatson ap->ap_preselect_flags = *maskp; 789184488Srwatson AUDIT_PIPE_UNLOCK(ap); 790159269Srwatson error = 0; 791159269Srwatson break; 792159269Srwatson 793159269Srwatson case AUDITPIPE_GET_PRESELECT_NAFLAGS: 794184488Srwatson AUDIT_PIPE_LOCK(ap); 795159269Srwatson maskp = (au_mask_t *)data; 796159269Srwatson *maskp = ap->ap_preselect_naflags; 797184488Srwatson AUDIT_PIPE_UNLOCK(ap); 798159269Srwatson error = 0; 799159269Srwatson break; 800159269Srwatson 801159269Srwatson case AUDITPIPE_SET_PRESELECT_NAFLAGS: 802184488Srwatson AUDIT_PIPE_LOCK(ap); 803159269Srwatson maskp = (au_mask_t *)data; 804159269Srwatson ap->ap_preselect_naflags = *maskp; 805184488Srwatson AUDIT_PIPE_UNLOCK(ap); 806159269Srwatson error = 0; 807159269Srwatson break; 808159269Srwatson 809159269Srwatson case AUDITPIPE_GET_PRESELECT_AUID: 810159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 811159269Srwatson error = audit_pipe_preselect_get(ap, aip->aip_auid, 812159269Srwatson &aip->aip_mask); 813159269Srwatson break; 814159269Srwatson 815159269Srwatson case AUDITPIPE_SET_PRESELECT_AUID: 816159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 817159269Srwatson audit_pipe_preselect_set(ap, aip->aip_auid, aip->aip_mask); 818159269Srwatson error = 0; 819159269Srwatson break; 820159269Srwatson 821159269Srwatson case AUDITPIPE_DELETE_PRESELECT_AUID: 822159269Srwatson auid = *(au_id_t *)data; 823159269Srwatson error = audit_pipe_preselect_delete(ap, auid); 824159269Srwatson break; 825159269Srwatson 826159269Srwatson case AUDITPIPE_FLUSH_PRESELECT_AUID: 827159269Srwatson audit_pipe_preselect_flush(ap); 828159269Srwatson error = 0; 829159269Srwatson break; 830159269Srwatson 831159269Srwatson case AUDITPIPE_GET_PRESELECT_MODE: 832184488Srwatson AUDIT_PIPE_LOCK(ap); 833159269Srwatson *(int *)data = ap->ap_preselect_mode; 834184488Srwatson AUDIT_PIPE_UNLOCK(ap); 835159269Srwatson error = 0; 836159269Srwatson break; 837159269Srwatson 838159269Srwatson case AUDITPIPE_SET_PRESELECT_MODE: 839159269Srwatson mode = *(int *)data; 840159269Srwatson switch (mode) { 841159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 842159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 843184488Srwatson AUDIT_PIPE_LOCK(ap); 844159269Srwatson ap->ap_preselect_mode = mode; 845184488Srwatson AUDIT_PIPE_UNLOCK(ap); 846159269Srwatson error = 0; 847159269Srwatson break; 848159269Srwatson 849159269Srwatson default: 850159269Srwatson error = EINVAL; 851159269Srwatson } 852159269Srwatson break; 853159269Srwatson 854159269Srwatson case AUDITPIPE_FLUSH: 855184508Srwatson if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) 856184508Srwatson return (EINTR); 857184488Srwatson AUDIT_PIPE_LOCK(ap); 858159269Srwatson audit_pipe_flush(ap); 859184488Srwatson AUDIT_PIPE_UNLOCK(ap); 860184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 861159269Srwatson error = 0; 862159269Srwatson break; 863159269Srwatson 864161646Srwatson case AUDITPIPE_GET_MAXAUDITDATA: 865161646Srwatson *(u_int *)data = MAXAUDITDATA; 866161646Srwatson error = 0; 867161646Srwatson break; 868161646Srwatson 869156880Srwatson case AUDITPIPE_GET_INSERTS: 870156880Srwatson *(u_int *)data = ap->ap_inserts; 871156880Srwatson error = 0; 872156880Srwatson break; 873156880Srwatson 874156880Srwatson case AUDITPIPE_GET_READS: 875156880Srwatson *(u_int *)data = ap->ap_reads; 876156880Srwatson error = 0; 877156880Srwatson break; 878156880Srwatson 879156880Srwatson case AUDITPIPE_GET_DROPS: 880156880Srwatson *(u_int *)data = ap->ap_drops; 881156880Srwatson error = 0; 882156880Srwatson break; 883156880Srwatson 884156880Srwatson case AUDITPIPE_GET_TRUNCATES: 885184510Srwatson *(u_int *)data = 0; 886156880Srwatson error = 0; 887156880Srwatson break; 888156880Srwatson 889155408Srwatson default: 890155408Srwatson error = ENOTTY; 891155408Srwatson } 892155408Srwatson return (error); 893155408Srwatson} 894155408Srwatson 895155408Srwatson/* 896184534Srwatson * Audit pipe read. Read one or more partial or complete records to user 897184534Srwatson * memory. 898155408Srwatson */ 899155408Srwatsonstatic int 900155408Srwatsonaudit_pipe_read(struct cdev *dev, struct uio *uio, int flag) 901155408Srwatson{ 902155408Srwatson struct audit_pipe_entry *ape; 903155408Srwatson struct audit_pipe *ap; 904184508Srwatson u_int toread; 905155408Srwatson int error; 906155408Srwatson 907270221Sdavide error = devfs_get_cdevpriv((void **)&ap); 908270221Sdavide if (error != 0) 909270221Sdavide return (error); 910184488Srwatson 911184508Srwatson /* 912184508Srwatson * We hold an sx(9) lock over read and flush because we rely on the 913184508Srwatson * stability of a record in the queue during uiomove(9). 914184508Srwatson */ 915184508Srwatson if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) 916184508Srwatson return (EINTR); 917184488Srwatson AUDIT_PIPE_LOCK(ap); 918184508Srwatson while (TAILQ_EMPTY(&ap->ap_queue)) { 919184508Srwatson if (ap->ap_flags & AUDIT_PIPE_NBIO) { 920184508Srwatson AUDIT_PIPE_UNLOCK(ap); 921184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 922184508Srwatson return (EAGAIN); 923155408Srwatson } 924184508Srwatson error = cv_wait_sig(&ap->ap_cv, AUDIT_PIPE_MTX(ap)); 925184508Srwatson if (error) { 926184508Srwatson AUDIT_PIPE_UNLOCK(ap); 927184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 928184508Srwatson return (error); 929184508Srwatson } 930184508Srwatson } 931184508Srwatson 932184508Srwatson /* 933184508Srwatson * Copy as many remaining bytes from the current record to userspace 934184534Srwatson * as we can. Keep processing records until we run out of records in 935184534Srwatson * the queue, or until the user buffer runs out of space. 936184508Srwatson * 937184508Srwatson * Note: we rely on the SX lock to maintain ape's stability here. 938184508Srwatson */ 939173083Scsjp ap->ap_reads++; 940184534Srwatson while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL && 941184534Srwatson uio->uio_resid > 0) { 942184534Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 943184534Srwatson 944184536Srwatson KASSERT(ape->ape_record_len > ap->ap_qoffset, 945184536Srwatson ("audit_pipe_read: record_len > qoffset (1)")); 946184536Srwatson toread = MIN(ape->ape_record_len - ap->ap_qoffset, 947184534Srwatson uio->uio_resid); 948184534Srwatson AUDIT_PIPE_UNLOCK(ap); 949184536Srwatson error = uiomove((char *)ape->ape_record + ap->ap_qoffset, 950184536Srwatson toread, uio); 951184534Srwatson if (error) { 952184534Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 953184534Srwatson return (error); 954184534Srwatson } 955184534Srwatson 956184534Srwatson /* 957184534Srwatson * If the copy succeeded, update book-keeping, and if no 958184534Srwatson * bytes remain in the current record, free it. 959184534Srwatson */ 960184534Srwatson AUDIT_PIPE_LOCK(ap); 961184534Srwatson KASSERT(TAILQ_FIRST(&ap->ap_queue) == ape, 962184534Srwatson ("audit_pipe_read: queue out of sync after uiomove")); 963184536Srwatson ap->ap_qoffset += toread; 964184536Srwatson KASSERT(ape->ape_record_len >= ap->ap_qoffset, 965184536Srwatson ("audit_pipe_read: record_len >= qoffset (2)")); 966184536Srwatson if (ap->ap_qoffset == ape->ape_record_len) { 967184534Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 968184536Srwatson ap->ap_qbyteslen -= ape->ape_record_len; 969184534Srwatson audit_pipe_entry_free(ape); 970184534Srwatson ap->ap_qlen--; 971184536Srwatson ap->ap_qoffset = 0; 972184534Srwatson } 973184508Srwatson } 974184508Srwatson AUDIT_PIPE_UNLOCK(ap); 975184508Srwatson AUDIT_PIPE_SX_XUNLOCK(ap); 976184534Srwatson return (0); 977155408Srwatson} 978155408Srwatson 979155408Srwatson/* 980155408Srwatson * Audit pipe poll. 981155408Srwatson */ 982155408Srwatsonstatic int 983155408Srwatsonaudit_pipe_poll(struct cdev *dev, int events, struct thread *td) 984155408Srwatson{ 985155408Srwatson struct audit_pipe *ap; 986270221Sdavide int error, revents; 987155408Srwatson 988155408Srwatson revents = 0; 989270221Sdavide error = devfs_get_cdevpriv((void **)&ap); 990270221Sdavide if (error != 0) 991270221Sdavide return (error); 992155408Srwatson if (events & (POLLIN | POLLRDNORM)) { 993184488Srwatson AUDIT_PIPE_LOCK(ap); 994155408Srwatson if (TAILQ_FIRST(&ap->ap_queue) != NULL) 995155408Srwatson revents |= events & (POLLIN | POLLRDNORM); 996155408Srwatson else 997155408Srwatson selrecord(td, &ap->ap_selinfo); 998184488Srwatson AUDIT_PIPE_UNLOCK(ap); 999155408Srwatson } 1000155408Srwatson return (revents); 1001155408Srwatson} 1002155408Srwatson 1003155408Srwatson/* 1004161582Srwatson * Audit pipe kqfilter. 1005161582Srwatson */ 1006161582Srwatsonstatic int 1007161582Srwatsonaudit_pipe_kqfilter(struct cdev *dev, struct knote *kn) 1008161582Srwatson{ 1009161582Srwatson struct audit_pipe *ap; 1010270221Sdavide int error; 1011161582Srwatson 1012270221Sdavide error = devfs_get_cdevpriv((void **)&ap); 1013270221Sdavide if (error != 0) 1014270221Sdavide return (error); 1015161582Srwatson if (kn->kn_filter != EVFILT_READ) 1016161582Srwatson return (EINVAL); 1017161582Srwatson 1018161582Srwatson kn->kn_fop = &audit_pipe_read_filterops; 1019161582Srwatson kn->kn_hook = ap; 1020161582Srwatson 1021184488Srwatson AUDIT_PIPE_LOCK(ap); 1022161582Srwatson knlist_add(&ap->ap_selinfo.si_note, kn, 1); 1023184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1024161582Srwatson return (0); 1025161582Srwatson} 1026161582Srwatson 1027161582Srwatson/* 1028161582Srwatson * Return true if there are records available for reading on the pipe. 1029161582Srwatson */ 1030161582Srwatsonstatic int 1031161582Srwatsonaudit_pipe_kqread(struct knote *kn, long hint) 1032161582Srwatson{ 1033161582Srwatson struct audit_pipe *ap; 1034161582Srwatson 1035161582Srwatson ap = (struct audit_pipe *)kn->kn_hook; 1036184488Srwatson AUDIT_PIPE_LOCK_ASSERT(ap); 1037184488Srwatson 1038161582Srwatson if (ap->ap_qlen != 0) { 1039184536Srwatson kn->kn_data = ap->ap_qbyteslen - ap->ap_qoffset; 1040161582Srwatson return (1); 1041161582Srwatson } else { 1042161582Srwatson kn->kn_data = 0; 1043161582Srwatson return (0); 1044161582Srwatson } 1045161582Srwatson} 1046161582Srwatson 1047161582Srwatson/* 1048161582Srwatson * Detach kqueue state from audit pipe. 1049161582Srwatson */ 1050161582Srwatsonstatic void 1051161582Srwatsonaudit_pipe_kqdetach(struct knote *kn) 1052161582Srwatson{ 1053161582Srwatson struct audit_pipe *ap; 1054161582Srwatson 1055161582Srwatson ap = (struct audit_pipe *)kn->kn_hook; 1056184488Srwatson AUDIT_PIPE_LOCK(ap); 1057161582Srwatson knlist_remove(&ap->ap_selinfo.si_note, kn, 1); 1058184488Srwatson AUDIT_PIPE_UNLOCK(ap); 1059161582Srwatson} 1060161582Srwatson 1061161582Srwatson/* 1062155408Srwatson * Initialize the audit pipe system. 1063155408Srwatson */ 1064155408Srwatsonstatic void 1065155408Srwatsonaudit_pipe_init(void *unused) 1066155408Srwatson{ 1067155408Srwatson 1068155408Srwatson TAILQ_INIT(&audit_pipe_list); 1069184488Srwatson AUDIT_PIPE_LIST_LOCK_INIT(); 1070270221Sdavide audit_pipe_dev = make_dev(&audit_pipe_cdevsw, 0, UID_ROOT, 1071270221Sdavide GID_WHEEL, 0600, "%s", AUDIT_PIPE_NAME); 1072270221Sdavide if (audit_pipe_dev == NULL) { 1073270221Sdavide AUDIT_PIPE_LIST_LOCK_DESTROY(); 1074270221Sdavide panic("Can't initialize audit pipe subsystem"); 1075270221Sdavide } 1076155408Srwatson} 1077155408Srwatson 1078155408SrwatsonSYSINIT(audit_pipe_init, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, audit_pipe_init, 1079155408Srwatson NULL); 1080