audit_pipe.c revision 161582
1155408Srwatson/*- 2155408Srwatson * Copyright (c) 2006 Robert N. M. Watson 3155408Srwatson * All rights reserved. 4155408Srwatson * 5155408Srwatson * This software was developed by Robert Watson for the TrustedBSD Project. 6155408Srwatson * 7155408Srwatson * Redistribution and use in source and binary forms, with or without 8155408Srwatson * modification, are permitted provided that the following conditions 9155408Srwatson * are met: 10155408Srwatson * 1. Redistributions of source code must retain the above copyright 11155408Srwatson * notice, this list of conditions and the following disclaimer. 12155408Srwatson * 2. Redistributions in binary form must reproduce the above copyright 13155408Srwatson * notice, this list of conditions and the following disclaimer in the 14155408Srwatson * documentation and/or other materials provided with the distribution. 15155408Srwatson * 16155408Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17155408Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18155408Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19155408Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20155408Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21155408Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22155408Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23155408Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24155408Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25155408Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26155408Srwatson * SUCH DAMAGE. 27155408Srwatson * 28155408Srwatson * $FreeBSD: head/sys/security/audit/audit_pipe.c 161582 2006-08-24 17:42:38Z rwatson $ 29155408Srwatson */ 30155408Srwatson 31155408Srwatson#include <sys/param.h> 32155408Srwatson#include <sys/condvar.h> 33155408Srwatson#include <sys/conf.h> 34155408Srwatson#include <sys/eventhandler.h> 35155408Srwatson#include <sys/filio.h> 36155408Srwatson#include <sys/kernel.h> 37155408Srwatson#include <sys/lock.h> 38155408Srwatson#include <sys/malloc.h> 39155408Srwatson#include <sys/mutex.h> 40155408Srwatson#include <sys/poll.h> 41155408Srwatson#include <sys/proc.h> 42155408Srwatson#include <sys/queue.h> 43155408Srwatson#include <sys/selinfo.h> 44155408Srwatson#include <sys/sigio.h> 45155408Srwatson#include <sys/signal.h> 46155408Srwatson#include <sys/signalvar.h> 47155408Srwatson#include <sys/systm.h> 48155408Srwatson#include <sys/uio.h> 49155408Srwatson 50155408Srwatson#include <security/audit/audit.h> 51156880Srwatson#include <security/audit/audit_ioctl.h> 52155408Srwatson#include <security/audit/audit_private.h> 53155408Srwatson 54155408Srwatson/* 55155408Srwatson * Implementation of a clonable special device providing a live stream of BSM 56155408Srwatson * audit data. This is a "tee" of the data going to the file. It provides 57155408Srwatson * unreliable but timely access to audit events. Consumers of this interface 58159269Srwatson * should be very careful to avoid introducing event cycles. Consumers may 59159269Srwatson * express interest via a set of preselection ioctls. 60155408Srwatson */ 61155408Srwatson 62155408Srwatson/* 63155408Srwatson * Memory types. 64155408Srwatson */ 65155408Srwatsonstatic MALLOC_DEFINE(M_AUDIT_PIPE, "audit_pipe", "Audit pipes"); 66155408Srwatsonstatic MALLOC_DEFINE(M_AUDIT_PIPE_ENTRY, "audit_pipeent", 67155408Srwatson "Audit pipe entries and buffers"); 68159269Srwatsonstatic MALLOC_DEFINE(M_AUDIT_PIPE_PRESELECT, "audit_pipe_preselect", 69159269Srwatson "Audit pipe preselection structure"); 70155408Srwatson 71155408Srwatson/* 72155408Srwatson * Audit pipe buffer parameters. 73155408Srwatson */ 74156883Srwatson#define AUDIT_PIPE_QLIMIT_DEFAULT (128) 75156880Srwatson#define AUDIT_PIPE_QLIMIT_MIN (0) 76155408Srwatson#define AUDIT_PIPE_QLIMIT_MAX (1024) 77155408Srwatson 78155408Srwatson/* 79155408Srwatson * Description of an entry in an audit_pipe. 80155408Srwatson */ 81155408Srwatsonstruct audit_pipe_entry { 82155408Srwatson void *ape_record; 83155408Srwatson u_int ape_record_len; 84155408Srwatson TAILQ_ENTRY(audit_pipe_entry) ape_queue; 85155408Srwatson}; 86155408Srwatson 87155408Srwatson/* 88159269Srwatson * Audit pipes allow processes to express "interest" in the set of records 89159269Srwatson * that are delivered via the pipe. They do this in a similar manner to the 90159269Srwatson * mechanism for audit trail configuration, by expressing two global masks, 91159269Srwatson * and optionally expressing per-auid masks. The following data structure is 92159269Srwatson * the per-auid mask description. The global state is stored in the audit 93159269Srwatson * pipe data structure. 94159269Srwatson * 95159269Srwatson * We may want to consider a more space/time-efficient data structure once 96159269Srwatson * usage patterns for per-auid specifications are clear. 97159269Srwatson */ 98159269Srwatsonstruct audit_pipe_preselect { 99159269Srwatson au_id_t app_auid; 100159269Srwatson au_mask_t app_mask; 101159269Srwatson TAILQ_ENTRY(audit_pipe_preselect) app_list; 102159269Srwatson}; 103159269Srwatson 104159269Srwatson/* 105155408Srwatson * Description of an individual audit_pipe. Consists largely of a bounded 106155408Srwatson * length queue. 107155408Srwatson */ 108155408Srwatson#define AUDIT_PIPE_ASYNC 0x00000001 109155408Srwatson#define AUDIT_PIPE_NBIO 0x00000002 110155408Srwatsonstruct audit_pipe { 111155408Srwatson int ap_open; /* Device open? */ 112155408Srwatson u_int ap_flags; 113155408Srwatson 114155408Srwatson struct selinfo ap_selinfo; 115155408Srwatson struct sigio *ap_sigio; 116155408Srwatson 117155408Srwatson u_int ap_qlen; 118155408Srwatson u_int ap_qlimit; 119155408Srwatson 120155408Srwatson u_int64_t ap_inserts; /* Records added. */ 121155408Srwatson u_int64_t ap_reads; /* Records read. */ 122155408Srwatson u_int64_t ap_drops; /* Records dropped. */ 123155408Srwatson u_int64_t ap_truncates; /* Records too long. */ 124155408Srwatson 125159269Srwatson /* 126159269Srwatson * Fields relating to pipe interest: global masks for unmatched 127159269Srwatson * processes (attributable, non-attributable), and a list of specific 128159269Srwatson * interest specifications by auid. 129159269Srwatson */ 130159269Srwatson int ap_preselect_mode; 131159269Srwatson au_mask_t ap_preselect_flags; 132159269Srwatson au_mask_t ap_preselect_naflags; 133159269Srwatson TAILQ_HEAD(, audit_pipe_preselect) ap_preselect_list; 134159269Srwatson 135159269Srwatson /* 136159269Srwatson * Current pending record list. 137159269Srwatson */ 138155408Srwatson TAILQ_HEAD(, audit_pipe_entry) ap_queue; 139155408Srwatson 140159269Srwatson /* 141159269Srwatson * Global pipe list. 142159269Srwatson */ 143155408Srwatson TAILQ_ENTRY(audit_pipe) ap_list; 144155408Srwatson}; 145155408Srwatson 146155408Srwatson/* 147159269Srwatson * Global list of audit pipes, mutex to protect it and the pipes. Finer 148155408Srwatson * grained locking may be desirable at some point. 149155408Srwatson */ 150155408Srwatsonstatic TAILQ_HEAD(, audit_pipe) audit_pipe_list; 151155408Srwatsonstatic struct mtx audit_pipe_mtx; 152155408Srwatson 153155408Srwatson/* 154159269Srwatson * This CV is used to wakeup on an audit record write. Eventually, it might 155159269Srwatson * be per-pipe to avoid unnecessary wakeups when several pipes with different 156159269Srwatson * preselection masks are present. 157155408Srwatson */ 158155408Srwatsonstatic struct cv audit_pipe_cv; 159155408Srwatson 160155408Srwatson/* 161155408Srwatson * Cloning related variables and constants. 162155408Srwatson */ 163155408Srwatson#define AUDIT_PIPE_NAME "auditpipe" 164155408Srwatsonstatic eventhandler_tag audit_pipe_eh_tag; 165155408Srwatsonstatic struct clonedevs *audit_pipe_clones; 166155408Srwatson 167155408Srwatson/* 168155408Srwatson * Special device methods and definition. 169155408Srwatson */ 170155408Srwatsonstatic d_open_t audit_pipe_open; 171155408Srwatsonstatic d_close_t audit_pipe_close; 172155408Srwatsonstatic d_read_t audit_pipe_read; 173155408Srwatsonstatic d_ioctl_t audit_pipe_ioctl; 174155408Srwatsonstatic d_poll_t audit_pipe_poll; 175161582Srwatsonstatic d_kqfilter_t audit_pipe_kqfilter; 176155408Srwatson 177155408Srwatsonstatic struct cdevsw audit_pipe_cdevsw = { 178155408Srwatson .d_version = D_VERSION, 179159269Srwatson .d_flags = D_PSEUDO | D_NEEDGIANT, 180155408Srwatson .d_open = audit_pipe_open, 181155408Srwatson .d_close = audit_pipe_close, 182155408Srwatson .d_read = audit_pipe_read, 183155408Srwatson .d_ioctl = audit_pipe_ioctl, 184155408Srwatson .d_poll = audit_pipe_poll, 185161582Srwatson .d_kqfilter = audit_pipe_kqfilter, 186155408Srwatson .d_name = AUDIT_PIPE_NAME, 187155408Srwatson}; 188155408Srwatson 189161582Srwatsonstatic int audit_pipe_kqread(struct knote *note, long hint); 190161582Srwatsonstatic void audit_pipe_kqdetach(struct knote *note); 191161582Srwatson 192161582Srwatsonstatic struct filterops audit_pipe_read_filterops = { 193161582Srwatson .f_isfd = 1, 194161582Srwatson .f_attach = NULL, 195161582Srwatson .f_detach = audit_pipe_kqdetach, 196161582Srwatson .f_event = audit_pipe_kqread, 197161582Srwatson}; 198161582Srwatson 199155408Srwatson/* 200155408Srwatson * Some global statistics on audit pipes. 201155408Srwatson */ 202155408Srwatsonstatic int audit_pipe_count; /* Current number of pipes. */ 203155408Srwatsonstatic u_int64_t audit_pipe_ever; /* Pipes ever allocated. */ 204155408Srwatsonstatic u_int64_t audit_pipe_records; /* Records seen. */ 205155408Srwatsonstatic u_int64_t audit_pipe_drops; /* Global record drop count. */ 206155408Srwatson 207155408Srwatson/* 208155408Srwatson * Free an audit pipe entry. 209155408Srwatson */ 210155408Srwatsonstatic void 211155408Srwatsonaudit_pipe_entry_free(struct audit_pipe_entry *ape) 212155408Srwatson{ 213155408Srwatson 214155408Srwatson free(ape->ape_record, M_AUDIT_PIPE_ENTRY); 215155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 216155408Srwatson} 217155408Srwatson 218155408Srwatson/* 219159269Srwatson * Find an audit pipe preselection specification for an auid, if any. 220159269Srwatson */ 221159269Srwatsonstatic struct audit_pipe_preselect * 222159269Srwatsonaudit_pipe_preselect_find(struct audit_pipe *ap, au_id_t auid) 223159269Srwatson{ 224159269Srwatson struct audit_pipe_preselect *app; 225159269Srwatson 226159269Srwatson mtx_assert(&audit_pipe_mtx, MA_OWNED); 227159269Srwatson 228159269Srwatson TAILQ_FOREACH(app, &ap->ap_preselect_list, app_list) { 229159269Srwatson if (app->app_auid == auid) 230159269Srwatson return (app); 231159269Srwatson } 232159269Srwatson return (NULL); 233159269Srwatson} 234159269Srwatson 235159269Srwatson/* 236159269Srwatson * Query the per-pipe mask for a specific auid. 237159269Srwatson */ 238159269Srwatsonstatic int 239159269Srwatsonaudit_pipe_preselect_get(struct audit_pipe *ap, au_id_t auid, 240159269Srwatson au_mask_t *maskp) 241159269Srwatson{ 242159269Srwatson struct audit_pipe_preselect *app; 243159269Srwatson int error; 244159269Srwatson 245159269Srwatson mtx_lock(&audit_pipe_mtx); 246159269Srwatson app = audit_pipe_preselect_find(ap, auid); 247159269Srwatson if (app != NULL) { 248159269Srwatson *maskp = app->app_mask; 249159269Srwatson error = 0; 250159269Srwatson } else 251159269Srwatson error = ENOENT; 252159269Srwatson mtx_unlock(&audit_pipe_mtx); 253159269Srwatson return (error); 254159269Srwatson} 255159269Srwatson 256159269Srwatson/* 257159269Srwatson * Set the per-pipe mask for a specific auid. Add a new entry if needed; 258159269Srwatson * otherwise, update the current entry. 259159269Srwatson */ 260159269Srwatsonstatic void 261159269Srwatsonaudit_pipe_preselect_set(struct audit_pipe *ap, au_id_t auid, au_mask_t mask) 262159269Srwatson{ 263159269Srwatson struct audit_pipe_preselect *app, *app_new; 264159269Srwatson 265159269Srwatson /* 266159269Srwatson * Pessimistically assume that the auid doesn't already have a mask 267159269Srwatson * set, and allocate. We will free it if it is unneeded. 268159269Srwatson */ 269159269Srwatson app_new = malloc(sizeof(*app_new), M_AUDIT_PIPE_PRESELECT, M_WAITOK); 270159269Srwatson mtx_lock(&audit_pipe_mtx); 271159269Srwatson app = audit_pipe_preselect_find(ap, auid); 272159269Srwatson if (app == NULL) { 273159269Srwatson app = app_new; 274159269Srwatson app_new = NULL; 275159269Srwatson app->app_auid = auid; 276159269Srwatson TAILQ_INSERT_TAIL(&ap->ap_preselect_list, app, app_list); 277159269Srwatson } 278159269Srwatson app->app_mask = mask; 279159269Srwatson mtx_unlock(&audit_pipe_mtx); 280159269Srwatson if (app_new != NULL) 281159269Srwatson free(app_new, M_AUDIT_PIPE_PRESELECT); 282159269Srwatson} 283159269Srwatson 284159269Srwatson/* 285159269Srwatson * Delete a per-auid mask on an audit pipe. 286159269Srwatson */ 287159269Srwatsonstatic int 288159269Srwatsonaudit_pipe_preselect_delete(struct audit_pipe *ap, au_id_t auid) 289159269Srwatson{ 290159269Srwatson struct audit_pipe_preselect *app; 291159269Srwatson int error; 292159269Srwatson 293159269Srwatson mtx_lock(&audit_pipe_mtx); 294159269Srwatson app = audit_pipe_preselect_find(ap, auid); 295159269Srwatson if (app != NULL) { 296159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 297159269Srwatson error = 0; 298159269Srwatson } else 299159269Srwatson error = ENOENT; 300159269Srwatson mtx_unlock(&audit_pipe_mtx); 301159269Srwatson if (app != NULL) 302159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 303159269Srwatson return (error); 304159269Srwatson} 305159269Srwatson 306159269Srwatson/* 307159269Srwatson * Delete all per-auid masks on an audit pipe. 308159269Srwatson */ 309159269Srwatsonstatic void 310159269Srwatsonaudit_pipe_preselect_flush_locked(struct audit_pipe *ap) 311159269Srwatson{ 312159269Srwatson struct audit_pipe_preselect *app; 313159269Srwatson 314159269Srwatson mtx_assert(&audit_pipe_mtx, MA_OWNED); 315159269Srwatson 316159269Srwatson while ((app = TAILQ_FIRST(&ap->ap_preselect_list)) != NULL) { 317159269Srwatson TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 318159269Srwatson free(app, M_AUDIT_PIPE_PRESELECT); 319159269Srwatson } 320159269Srwatson} 321159269Srwatson 322159269Srwatsonstatic void 323159269Srwatsonaudit_pipe_preselect_flush(struct audit_pipe *ap) 324159269Srwatson{ 325159269Srwatson 326159269Srwatson mtx_lock(&audit_pipe_mtx); 327159269Srwatson audit_pipe_preselect_flush_locked(ap); 328159269Srwatson mtx_unlock(&audit_pipe_mtx); 329159269Srwatson} 330159269Srwatson 331159269Srwatson/* 332159269Srwatson * Determine whether a specific audit pipe matches a record with these 333159269Srwatson * properties. Algorithm is as follows: 334159269Srwatson * 335159269Srwatson * - If the pipe is configured to track the default trail configuration, then 336159269Srwatson * use the results of global preselection matching. 337159269Srwatson * - If not, search for a specifically configured auid entry matching the 338159269Srwatson * event. If an entry is found, use that. 339159269Srwatson * - Otherwise, use the default flags or naflags configured for the pipe. 340159269Srwatson */ 341159269Srwatsonstatic int 342159269Srwatsonaudit_pipe_preselect_check(struct audit_pipe *ap, au_id_t auid, 343159269Srwatson au_event_t event, au_class_t class, int sorf, int trail_preselect) 344159269Srwatson{ 345159269Srwatson struct audit_pipe_preselect *app; 346159269Srwatson 347159269Srwatson mtx_assert(&audit_pipe_mtx, MA_OWNED); 348159269Srwatson 349159269Srwatson switch (ap->ap_preselect_mode) { 350159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 351159269Srwatson return (trail_preselect); 352159269Srwatson 353159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 354159269Srwatson app = audit_pipe_preselect_find(ap, auid); 355159269Srwatson if (app == NULL) { 356159269Srwatson if (auid == AU_DEFAUDITID) 357159269Srwatson return (au_preselect(event, class, 358159269Srwatson &ap->ap_preselect_naflags, sorf)); 359159269Srwatson else 360159269Srwatson return (au_preselect(event, class, 361159269Srwatson &ap->ap_preselect_flags, sorf)); 362159269Srwatson } else 363159269Srwatson return (au_preselect(event, class, &app->app_mask, 364159269Srwatson sorf)); 365159269Srwatson 366159269Srwatson default: 367159269Srwatson panic("audit_pipe_preselect_check: mode %d", 368159269Srwatson ap->ap_preselect_mode); 369159269Srwatson } 370159269Srwatson 371159269Srwatson return (0); 372159269Srwatson} 373159269Srwatson 374159269Srwatson/* 375159269Srwatson * Determine whether there exists a pipe interested in a record with specific 376159269Srwatson * properties. 377159269Srwatson */ 378159269Srwatsonint 379159269Srwatsonaudit_pipe_preselect(au_id_t auid, au_event_t event, au_class_t class, 380159269Srwatson int sorf, int trail_preselect) 381159269Srwatson{ 382159269Srwatson struct audit_pipe *ap; 383159269Srwatson 384159269Srwatson mtx_lock(&audit_pipe_mtx); 385159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 386159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 387159269Srwatson trail_preselect)) { 388159269Srwatson mtx_unlock(&audit_pipe_mtx); 389159269Srwatson return (1); 390159269Srwatson } 391159269Srwatson } 392159269Srwatson mtx_unlock(&audit_pipe_mtx); 393159269Srwatson return (0); 394159269Srwatson} 395159269Srwatson 396159269Srwatson/* 397159269Srwatson * Append individual record to a queue -- allocate queue-local buffer, and 398155408Srwatson * add to the queue. We try to drop from the head of the queue so that more 399155408Srwatson * recent events take precedence over older ones, but if allocation fails we 400155408Srwatson * do drop the new event. 401155408Srwatson */ 402155408Srwatsonstatic void 403155408Srwatsonaudit_pipe_append(struct audit_pipe *ap, void *record, u_int record_len) 404155408Srwatson{ 405155408Srwatson struct audit_pipe_entry *ape, *ape_remove; 406155408Srwatson 407155408Srwatson mtx_assert(&audit_pipe_mtx, MA_OWNED); 408155408Srwatson 409155408Srwatson ape = malloc(sizeof(*ape), M_AUDIT_PIPE_ENTRY, M_NOWAIT | M_ZERO); 410155408Srwatson if (ape == NULL) { 411155408Srwatson ap->ap_drops++; 412156292Srwatson audit_pipe_drops++; 413155408Srwatson return; 414155408Srwatson } 415155408Srwatson 416155408Srwatson ape->ape_record = malloc(record_len, M_AUDIT_PIPE_ENTRY, M_NOWAIT); 417155408Srwatson if (ape->ape_record == NULL) { 418155408Srwatson free(ape, M_AUDIT_PIPE_ENTRY); 419155408Srwatson ap->ap_drops++; 420155408Srwatson audit_pipe_drops++; 421155408Srwatson return; 422155408Srwatson } 423155408Srwatson 424155408Srwatson bcopy(record, ape->ape_record, record_len); 425155408Srwatson ape->ape_record_len = record_len; 426155408Srwatson 427155408Srwatson if (ap->ap_qlen >= ap->ap_qlimit) { 428155408Srwatson ape_remove = TAILQ_FIRST(&ap->ap_queue); 429155408Srwatson TAILQ_REMOVE(&ap->ap_queue, ape_remove, ape_queue); 430155408Srwatson audit_pipe_entry_free(ape_remove); 431155428Srwatson ap->ap_qlen--; 432155408Srwatson ap->ap_drops++; 433155408Srwatson audit_pipe_drops++; 434155408Srwatson } 435155408Srwatson 436155408Srwatson TAILQ_INSERT_TAIL(&ap->ap_queue, ape, ape_queue); 437155408Srwatson ap->ap_inserts++; 438155408Srwatson ap->ap_qlen++; 439155408Srwatson selwakeuppri(&ap->ap_selinfo, PSOCK); 440161582Srwatson KNOTE_LOCKED(&ap->ap_selinfo.si_note, 0); 441155408Srwatson if (ap->ap_flags & AUDIT_PIPE_ASYNC) 442155408Srwatson pgsigio(&ap->ap_sigio, SIGIO, 0); 443155408Srwatson} 444155408Srwatson 445155408Srwatson/* 446155408Srwatson * audit_pipe_submit(): audit_worker submits audit records via this 447155408Srwatson * interface, which arranges for them to be delivered to pipe queues. 448155408Srwatson */ 449155408Srwatsonvoid 450159269Srwatsonaudit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class, int sorf, 451159269Srwatson int trail_select, void *record, u_int record_len) 452155408Srwatson{ 453155408Srwatson struct audit_pipe *ap; 454155408Srwatson 455155408Srwatson /* 456155408Srwatson * Lockless read to avoid mutex overhead if pipes are not in use. 457155408Srwatson */ 458155408Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 459155408Srwatson return; 460155408Srwatson 461155408Srwatson mtx_lock(&audit_pipe_mtx); 462159269Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 463159269Srwatson if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 464159269Srwatson trail_select)) 465159269Srwatson audit_pipe_append(ap, record, record_len); 466159269Srwatson } 467159269Srwatson audit_pipe_records++; 468159269Srwatson mtx_unlock(&audit_pipe_mtx); 469159269Srwatson cv_signal(&audit_pipe_cv); 470159269Srwatson} 471159269Srwatson 472159269Srwatson/* 473159269Srwatson * audit_pipe_submit_user(): the same as audit_pipe_submit(), except that 474159269Srwatson * since we don't currently have selection information available, it is 475159269Srwatson * delivered to the pipe unconditionally. 476159269Srwatson * 477159269Srwatson * XXXRW: This is a bug. The BSM check routine for submitting a user record 478159269Srwatson * should parse that information and return it. 479159269Srwatson */ 480159269Srwatsonvoid 481159269Srwatsonaudit_pipe_submit_user(void *record, u_int record_len) 482159269Srwatson{ 483159269Srwatson struct audit_pipe *ap; 484159269Srwatson 485159269Srwatson /* 486159269Srwatson * Lockless read to avoid mutex overhead if pipes are not in use. 487159269Srwatson */ 488159269Srwatson if (TAILQ_FIRST(&audit_pipe_list) == NULL) 489159269Srwatson return; 490159269Srwatson 491159269Srwatson mtx_lock(&audit_pipe_mtx); 492155408Srwatson TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) 493155408Srwatson audit_pipe_append(ap, record, record_len); 494155408Srwatson audit_pipe_records++; 495155408Srwatson mtx_unlock(&audit_pipe_mtx); 496155408Srwatson cv_signal(&audit_pipe_cv); 497155408Srwatson} 498155408Srwatson 499159269Srwatson 500155408Srwatson/* 501159269Srwatson * Pop the next record off of an audit pipe. 502155408Srwatson */ 503155408Srwatsonstatic struct audit_pipe_entry * 504155408Srwatsonaudit_pipe_pop(struct audit_pipe *ap) 505155408Srwatson{ 506155408Srwatson struct audit_pipe_entry *ape; 507155408Srwatson 508155408Srwatson mtx_assert(&audit_pipe_mtx, MA_OWNED); 509155408Srwatson 510155408Srwatson ape = TAILQ_FIRST(&ap->ap_queue); 511155408Srwatson KASSERT((ape == NULL && ap->ap_qlen == 0) || 512155408Srwatson (ape != NULL && ap->ap_qlen != 0), ("audit_pipe_pop: qlen")); 513155408Srwatson if (ape == NULL) 514155408Srwatson return (NULL); 515155408Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 516155408Srwatson ap->ap_qlen--; 517155408Srwatson return (ape); 518155408Srwatson} 519155408Srwatson 520155408Srwatson/* 521155408Srwatson * Allocate a new audit pipe. Connects the pipe, on success, to the global 522155408Srwatson * list and updates statistics. 523155408Srwatson */ 524155408Srwatsonstatic struct audit_pipe * 525155408Srwatsonaudit_pipe_alloc(void) 526155408Srwatson{ 527155408Srwatson struct audit_pipe *ap; 528155408Srwatson 529155408Srwatson mtx_assert(&audit_pipe_mtx, MA_OWNED); 530155408Srwatson 531155408Srwatson ap = malloc(sizeof(*ap), M_AUDIT_PIPE, M_NOWAIT | M_ZERO); 532155408Srwatson if (ap == NULL) 533155408Srwatson return (NULL); 534155408Srwatson ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT; 535155408Srwatson TAILQ_INIT(&ap->ap_queue); 536161582Srwatson knlist_init(&ap->ap_selinfo.si_note, &audit_pipe_mtx, NULL, NULL, 537161582Srwatson NULL); 538159269Srwatson 539159269Srwatson /* 540159269Srwatson * Default flags, naflags, and auid-specific preselection settings to 541159269Srwatson * 0. Initialize the mode to the global trail so that if praudit(1) 542159269Srwatson * is run on /dev/auditpipe, it sees events associated with the 543159269Srwatson * default trail. Pipe-aware application can clear the flag, set 544159269Srwatson * custom masks, and flush the pipe as needed. 545159269Srwatson */ 546159269Srwatson bzero(&ap->ap_preselect_flags, sizeof(ap->ap_preselect_flags)); 547159269Srwatson bzero(&ap->ap_preselect_naflags, sizeof(ap->ap_preselect_naflags)); 548159269Srwatson TAILQ_INIT(&ap->ap_preselect_list); 549159269Srwatson ap->ap_preselect_mode = AUDITPIPE_PRESELECT_MODE_TRAIL; 550159269Srwatson 551161582Srwatson /* 552161582Srwatson * Add to global list and update global statistics. 553161582Srwatson */ 554155408Srwatson TAILQ_INSERT_HEAD(&audit_pipe_list, ap, ap_list); 555155408Srwatson audit_pipe_count++; 556155408Srwatson audit_pipe_ever++; 557159269Srwatson 558155408Srwatson return (ap); 559155408Srwatson} 560155408Srwatson 561155408Srwatson/* 562159269Srwatson * Flush all records currently present in an audit pipe; assume mutex is held. 563155408Srwatson */ 564155408Srwatsonstatic void 565159269Srwatsonaudit_pipe_flush(struct audit_pipe *ap) 566155408Srwatson{ 567155408Srwatson struct audit_pipe_entry *ape; 568155408Srwatson 569155408Srwatson mtx_assert(&audit_pipe_mtx, MA_OWNED); 570155408Srwatson 571155408Srwatson while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL) { 572155408Srwatson TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 573155408Srwatson audit_pipe_entry_free(ape); 574155408Srwatson ap->ap_qlen--; 575155408Srwatson } 576155408Srwatson KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qlen")); 577159269Srwatson} 578159269Srwatson 579159269Srwatson/* 580159269Srwatson * Free an audit pipe; this means freeing all preselection state and all 581159269Srwatson * records in the pipe. Assumes mutex is held to prevent any new records 582159269Srwatson * from being inserted during the free, and that the audit pipe is still on 583159269Srwatson * the global list. 584159269Srwatson */ 585159269Srwatsonstatic void 586159269Srwatsonaudit_pipe_free(struct audit_pipe *ap) 587159269Srwatson{ 588159269Srwatson 589159269Srwatson mtx_assert(&audit_pipe_mtx, MA_OWNED); 590159269Srwatson 591159269Srwatson audit_pipe_preselect_flush_locked(ap); 592159269Srwatson audit_pipe_flush(ap); 593161582Srwatson knlist_destroy(&ap->ap_selinfo.si_note); 594159269Srwatson TAILQ_REMOVE(&audit_pipe_list, ap, ap_list); 595155408Srwatson free(ap, M_AUDIT_PIPE); 596155408Srwatson audit_pipe_count--; 597155408Srwatson} 598155408Srwatson 599155408Srwatson/* 600155408Srwatson * Audit pipe clone routine -- provide specific requested audit pipe, or a 601155408Srwatson * fresh one if a specific one is not requested. 602155408Srwatson */ 603155408Srwatsonstatic void 604155408Srwatsonaudit_pipe_clone(void *arg, struct ucred *cred, char *name, int namelen, 605155408Srwatson struct cdev **dev) 606155408Srwatson{ 607155408Srwatson int i, u; 608155408Srwatson 609155408Srwatson if (*dev != NULL) 610155408Srwatson return; 611155408Srwatson 612155408Srwatson if (strcmp(name, AUDIT_PIPE_NAME) == 0) 613155408Srwatson u = -1; 614155408Srwatson else if (dev_stdclone(name, NULL, AUDIT_PIPE_NAME, &u) != 1) 615155408Srwatson return; 616155408Srwatson 617155408Srwatson i = clone_create(&audit_pipe_clones, &audit_pipe_cdevsw, &u, dev, 0); 618155408Srwatson if (i) { 619155408Srwatson *dev = make_dev(&audit_pipe_cdevsw, unit2minor(u), UID_ROOT, 620155408Srwatson GID_WHEEL, 0600, "%s%d", AUDIT_PIPE_NAME, u); 621155408Srwatson if (*dev != NULL) { 622155408Srwatson dev_ref(*dev); 623155408Srwatson (*dev)->si_flags |= SI_CHEAPCLONE; 624155408Srwatson } 625155408Srwatson } 626155408Srwatson} 627155408Srwatson 628155408Srwatson/* 629155408Srwatson * Audit pipe open method. Explicit suser check isn't used as this allows 630155408Srwatson * file permissions on the special device to be used to grant audit review 631155408Srwatson * access. 632155408Srwatson */ 633155408Srwatsonstatic int 634155408Srwatsonaudit_pipe_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 635155408Srwatson{ 636155408Srwatson struct audit_pipe *ap; 637155408Srwatson 638155408Srwatson mtx_lock(&audit_pipe_mtx); 639155408Srwatson ap = dev->si_drv1; 640155408Srwatson if (ap == NULL) { 641155408Srwatson ap = audit_pipe_alloc(); 642155408Srwatson if (ap == NULL) { 643155408Srwatson mtx_unlock(&audit_pipe_mtx); 644155408Srwatson return (ENOMEM); 645155408Srwatson } 646155408Srwatson dev->si_drv1 = ap; 647155408Srwatson } else { 648155408Srwatson KASSERT(ap->ap_open, ("audit_pipe_open: ap && !ap_open")); 649155408Srwatson mtx_unlock(&audit_pipe_mtx); 650155408Srwatson return (EBUSY); 651155408Srwatson } 652155408Srwatson ap->ap_open = 1; 653155408Srwatson mtx_unlock(&audit_pipe_mtx); 654155408Srwatson fsetown(td->td_proc->p_pid, &ap->ap_sigio); 655155408Srwatson return (0); 656155408Srwatson} 657155408Srwatson 658155408Srwatson/* 659155408Srwatson * Close audit pipe, tear down all records, etc. 660155408Srwatson */ 661155408Srwatsonstatic int 662155408Srwatsonaudit_pipe_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 663155408Srwatson{ 664155408Srwatson struct audit_pipe *ap; 665155408Srwatson 666155408Srwatson ap = dev->si_drv1; 667155408Srwatson KASSERT(ap != NULL, ("audit_pipe_close: ap == NULL")); 668155408Srwatson KASSERT(ap->ap_open, ("audit_pipe_close: !ap_open")); 669155408Srwatson funsetown(&ap->ap_sigio); 670155408Srwatson mtx_lock(&audit_pipe_mtx); 671155408Srwatson ap->ap_open = 0; 672155408Srwatson audit_pipe_free(ap); 673155408Srwatson dev->si_drv1 = NULL; 674155408Srwatson mtx_unlock(&audit_pipe_mtx); 675155408Srwatson return (0); 676155408Srwatson} 677155408Srwatson 678155408Srwatson/* 679156880Srwatson * Audit pipe ioctl() routine. Handle file descriptor and audit pipe layer 680156880Srwatson * commands. 681155408Srwatson * 682155408Srwatson * Would be desirable to support filtering, although perhaps something simple 683155408Srwatson * like an event mask, as opposed to something complicated like BPF. 684155408Srwatson */ 685155408Srwatsonstatic int 686155408Srwatsonaudit_pipe_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, 687155408Srwatson struct thread *td) 688155408Srwatson{ 689159269Srwatson struct auditpipe_ioctl_preselect *aip; 690155408Srwatson struct audit_pipe *ap; 691159269Srwatson au_mask_t *maskp; 692159269Srwatson int error, mode; 693159269Srwatson au_id_t auid; 694155408Srwatson 695155408Srwatson ap = dev->si_drv1; 696155408Srwatson KASSERT(ap != NULL, ("audit_pipe_ioctl: ap == NULL")); 697159269Srwatson 698159269Srwatson /* 699159269Srwatson * Audit pipe ioctls: first come standard device node ioctls, then 700159269Srwatson * manipulation of pipe settings, and finally, statistics query 701159269Srwatson * ioctls. 702159269Srwatson */ 703155408Srwatson switch (cmd) { 704155408Srwatson case FIONBIO: 705155408Srwatson mtx_lock(&audit_pipe_mtx); 706155408Srwatson if (*(int *)data) 707155408Srwatson ap->ap_flags |= AUDIT_PIPE_NBIO; 708155408Srwatson else 709155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_NBIO; 710155408Srwatson mtx_unlock(&audit_pipe_mtx); 711155408Srwatson error = 0; 712155408Srwatson break; 713155408Srwatson 714155408Srwatson case FIONREAD: 715155408Srwatson mtx_lock(&audit_pipe_mtx); 716155408Srwatson if (TAILQ_FIRST(&ap->ap_queue) != NULL) 717155408Srwatson *(int *)data = 718155408Srwatson TAILQ_FIRST(&ap->ap_queue)->ape_record_len; 719155408Srwatson else 720155408Srwatson *(int *)data = 0; 721155408Srwatson mtx_unlock(&audit_pipe_mtx); 722155408Srwatson error = 0; 723155408Srwatson break; 724155408Srwatson 725155408Srwatson case FIOASYNC: 726155408Srwatson mtx_lock(&audit_pipe_mtx); 727155408Srwatson if (*(int *)data) 728155408Srwatson ap->ap_flags |= AUDIT_PIPE_ASYNC; 729155408Srwatson else 730155408Srwatson ap->ap_flags &= ~AUDIT_PIPE_ASYNC; 731155408Srwatson mtx_unlock(&audit_pipe_mtx); 732155408Srwatson error = 0; 733155408Srwatson break; 734155408Srwatson 735155408Srwatson case FIOSETOWN: 736155408Srwatson error = fsetown(*(int *)data, &ap->ap_sigio); 737155408Srwatson break; 738155408Srwatson 739155408Srwatson case FIOGETOWN: 740155408Srwatson *(int *)data = fgetown(&ap->ap_sigio); 741155408Srwatson error = 0; 742156880Srwatson break; 743155408Srwatson 744156880Srwatson case AUDITPIPE_GET_QLEN: 745156880Srwatson *(u_int *)data = ap->ap_qlen; 746156880Srwatson error = 0; 747156880Srwatson break; 748156880Srwatson 749156880Srwatson case AUDITPIPE_GET_QLIMIT: 750156880Srwatson *(u_int *)data = ap->ap_qlimit; 751156880Srwatson error = 0; 752156880Srwatson break; 753156880Srwatson 754156880Srwatson case AUDITPIPE_SET_QLIMIT: 755156880Srwatson /* Lockless integer write. */ 756156880Srwatson if (*(u_int *)data >= AUDIT_PIPE_QLIMIT_MIN || 757156880Srwatson *(u_int *)data <= AUDIT_PIPE_QLIMIT_MAX) { 758156880Srwatson ap->ap_qlimit = *(u_int *)data; 759156880Srwatson error = 0; 760156880Srwatson } else 761156880Srwatson error = EINVAL; 762156880Srwatson break; 763156880Srwatson 764156884Srwatson case AUDITPIPE_GET_QLIMIT_MIN: 765156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MIN; 766156884Srwatson error = 0; 767156884Srwatson break; 768156884Srwatson 769156884Srwatson case AUDITPIPE_GET_QLIMIT_MAX: 770156884Srwatson *(u_int *)data = AUDIT_PIPE_QLIMIT_MAX; 771156884Srwatson error = 0; 772156884Srwatson break; 773156884Srwatson 774159269Srwatson case AUDITPIPE_GET_PRESELECT_FLAGS: 775159269Srwatson mtx_lock(&audit_pipe_mtx); 776159269Srwatson maskp = (au_mask_t *)data; 777159269Srwatson *maskp = ap->ap_preselect_flags; 778159269Srwatson mtx_unlock(&audit_pipe_mtx); 779159269Srwatson error = 0; 780159269Srwatson break; 781159269Srwatson 782159269Srwatson case AUDITPIPE_SET_PRESELECT_FLAGS: 783159269Srwatson mtx_lock(&audit_pipe_mtx); 784159269Srwatson maskp = (au_mask_t *)data; 785159269Srwatson ap->ap_preselect_flags = *maskp; 786159269Srwatson mtx_unlock(&audit_pipe_mtx); 787159269Srwatson error = 0; 788159269Srwatson break; 789159269Srwatson 790159269Srwatson case AUDITPIPE_GET_PRESELECT_NAFLAGS: 791159269Srwatson mtx_lock(&audit_pipe_mtx); 792159269Srwatson maskp = (au_mask_t *)data; 793159269Srwatson *maskp = ap->ap_preselect_naflags; 794159269Srwatson mtx_unlock(&audit_pipe_mtx); 795159269Srwatson error = 0; 796159269Srwatson break; 797159269Srwatson 798159269Srwatson case AUDITPIPE_SET_PRESELECT_NAFLAGS: 799159269Srwatson mtx_lock(&audit_pipe_mtx); 800159269Srwatson maskp = (au_mask_t *)data; 801159269Srwatson ap->ap_preselect_naflags = *maskp; 802159269Srwatson mtx_unlock(&audit_pipe_mtx); 803159269Srwatson error = 0; 804159269Srwatson break; 805159269Srwatson 806159269Srwatson case AUDITPIPE_GET_PRESELECT_AUID: 807159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 808159269Srwatson error = audit_pipe_preselect_get(ap, aip->aip_auid, 809159269Srwatson &aip->aip_mask); 810159269Srwatson break; 811159269Srwatson 812159269Srwatson case AUDITPIPE_SET_PRESELECT_AUID: 813159269Srwatson aip = (struct auditpipe_ioctl_preselect *)data; 814159269Srwatson audit_pipe_preselect_set(ap, aip->aip_auid, aip->aip_mask); 815159269Srwatson error = 0; 816159269Srwatson break; 817159269Srwatson 818159269Srwatson case AUDITPIPE_DELETE_PRESELECT_AUID: 819159269Srwatson auid = *(au_id_t *)data; 820159269Srwatson error = audit_pipe_preselect_delete(ap, auid); 821159269Srwatson break; 822159269Srwatson 823159269Srwatson case AUDITPIPE_FLUSH_PRESELECT_AUID: 824159269Srwatson audit_pipe_preselect_flush(ap); 825159269Srwatson error = 0; 826159269Srwatson break; 827159269Srwatson 828159269Srwatson case AUDITPIPE_GET_PRESELECT_MODE: 829159269Srwatson mtx_lock(&audit_pipe_mtx); 830159269Srwatson *(int *)data = ap->ap_preselect_mode; 831159269Srwatson mtx_unlock(&audit_pipe_mtx); 832159269Srwatson error = 0; 833159269Srwatson break; 834159269Srwatson 835159269Srwatson case AUDITPIPE_SET_PRESELECT_MODE: 836159269Srwatson mode = *(int *)data; 837159269Srwatson switch (mode) { 838159269Srwatson case AUDITPIPE_PRESELECT_MODE_TRAIL: 839159269Srwatson case AUDITPIPE_PRESELECT_MODE_LOCAL: 840159269Srwatson mtx_lock(&audit_pipe_mtx); 841159269Srwatson ap->ap_preselect_mode = mode; 842159269Srwatson mtx_unlock(&audit_pipe_mtx); 843159269Srwatson error = 0; 844159269Srwatson break; 845159269Srwatson 846159269Srwatson default: 847159269Srwatson error = EINVAL; 848159269Srwatson } 849159269Srwatson break; 850159269Srwatson 851159269Srwatson case AUDITPIPE_FLUSH: 852159269Srwatson mtx_lock(&audit_pipe_mtx); 853159269Srwatson audit_pipe_flush(ap); 854159269Srwatson mtx_unlock(&audit_pipe_mtx); 855159269Srwatson error = 0; 856159269Srwatson break; 857159269Srwatson 858156880Srwatson case AUDITPIPE_GET_INSERTS: 859156880Srwatson *(u_int *)data = ap->ap_inserts; 860156880Srwatson error = 0; 861156880Srwatson break; 862156880Srwatson 863156880Srwatson case AUDITPIPE_GET_READS: 864156880Srwatson *(u_int *)data = ap->ap_reads; 865156880Srwatson error = 0; 866156880Srwatson break; 867156880Srwatson 868156880Srwatson case AUDITPIPE_GET_DROPS: 869156880Srwatson *(u_int *)data = ap->ap_drops; 870156880Srwatson error = 0; 871156880Srwatson break; 872156880Srwatson 873156880Srwatson case AUDITPIPE_GET_TRUNCATES: 874156880Srwatson *(u_int *)data = ap->ap_truncates; 875156880Srwatson error = 0; 876156880Srwatson break; 877156880Srwatson 878155408Srwatson default: 879155408Srwatson error = ENOTTY; 880155408Srwatson } 881155408Srwatson return (error); 882155408Srwatson} 883155408Srwatson 884155408Srwatson/* 885155408Srwatson * Audit pipe read. Pull one record off the queue and copy to user space. 886155408Srwatson * On error, the record is dropped. 887159269Srwatson * 888159269Srwatson * Providing more sophisticated behavior, such as partial reads, is tricky 889159269Srwatson * due to the potential for parallel I/O. If partial read support is 890159269Srwatson * required, it will require a per-pipe "current record being read" along 891159269Srwatson * with an offset into that trecord which has already been read. Threads 892159269Srwatson * performing partial reads will need to allocate per-thread copies of the 893159269Srwatson * data so that if another thread completes the read of the record, it can be 894159269Srwatson * freed without adding reference count logic. If this is added, a flag to 895159269Srwatson * indicate that only atomic record reads are desired would be useful, as if 896159269Srwatson * different threads are all waiting for records on the pipe, they will want 897159269Srwatson * independent record reads, which is currently the behavior. 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; 904155408Srwatson int error; 905155408Srwatson 906155408Srwatson ap = dev->si_drv1; 907155408Srwatson KASSERT(ap != NULL, ("audit_pipe_read: ap == NULL")); 908155408Srwatson mtx_lock(&audit_pipe_mtx); 909155408Srwatson do { 910155408Srwatson /* 911155408Srwatson * Wait for a record that fits into the read buffer, dropping 912155408Srwatson * records that would be truncated if actually passed to the 913155408Srwatson * process. This helps maintain the discreet record read 914155408Srwatson * interface. 915155408Srwatson */ 916155408Srwatson while ((ape = audit_pipe_pop(ap)) == NULL) { 917155408Srwatson if (ap->ap_flags & AUDIT_PIPE_NBIO) { 918155408Srwatson mtx_unlock(&audit_pipe_mtx); 919155408Srwatson return (EAGAIN); 920155408Srwatson } 921155408Srwatson error = cv_wait_sig(&audit_pipe_cv, &audit_pipe_mtx); 922155408Srwatson if (error) { 923155408Srwatson mtx_unlock(&audit_pipe_mtx); 924155408Srwatson return (error); 925155408Srwatson } 926155408Srwatson } 927155408Srwatson if (ape->ape_record_len <= uio->uio_resid) 928155408Srwatson break; 929155408Srwatson audit_pipe_entry_free(ape); 930155408Srwatson ap->ap_truncates++; 931155408Srwatson } while (1); 932155408Srwatson mtx_unlock(&audit_pipe_mtx); 933155408Srwatson 934155408Srwatson /* 935155408Srwatson * Now read record to user space memory. Even if the read is short, 936155408Srwatson * we abandon the remainder of the record, supporting only discreet 937155408Srwatson * record reads. 938155408Srwatson */ 939155408Srwatson error = uiomove(ape->ape_record, ape->ape_record_len, uio); 940155408Srwatson audit_pipe_entry_free(ape); 941155408Srwatson return (error); 942155408Srwatson} 943155408Srwatson 944155408Srwatson/* 945155408Srwatson * Audit pipe poll. 946155408Srwatson */ 947155408Srwatsonstatic int 948155408Srwatsonaudit_pipe_poll(struct cdev *dev, int events, struct thread *td) 949155408Srwatson{ 950155408Srwatson struct audit_pipe *ap; 951155408Srwatson int revents; 952155408Srwatson 953155408Srwatson revents = 0; 954155408Srwatson ap = dev->si_drv1; 955155408Srwatson KASSERT(ap != NULL, ("audit_pipe_poll: ap == NULL")); 956155408Srwatson if (events & (POLLIN | POLLRDNORM)) { 957155408Srwatson mtx_lock(&audit_pipe_mtx); 958155408Srwatson if (TAILQ_FIRST(&ap->ap_queue) != NULL) 959155408Srwatson revents |= events & (POLLIN | POLLRDNORM); 960155408Srwatson else 961155408Srwatson selrecord(td, &ap->ap_selinfo); 962155408Srwatson mtx_unlock(&audit_pipe_mtx); 963155408Srwatson } 964155408Srwatson return (revents); 965155408Srwatson} 966155408Srwatson 967155408Srwatson/* 968161582Srwatson * Audit pipe kqfilter. 969161582Srwatson */ 970161582Srwatsonstatic int 971161582Srwatsonaudit_pipe_kqfilter(struct cdev *dev, struct knote *kn) 972161582Srwatson{ 973161582Srwatson struct audit_pipe *ap; 974161582Srwatson 975161582Srwatson ap = dev->si_drv1; 976161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqfilter: ap == NULL")); 977161582Srwatson 978161582Srwatson if (kn->kn_filter != EVFILT_READ) 979161582Srwatson return (EINVAL); 980161582Srwatson 981161582Srwatson kn->kn_fop = &audit_pipe_read_filterops; 982161582Srwatson kn->kn_hook = ap; 983161582Srwatson 984161582Srwatson mtx_lock(&audit_pipe_mtx); 985161582Srwatson knlist_add(&ap->ap_selinfo.si_note, kn, 1); 986161582Srwatson mtx_unlock(&audit_pipe_mtx); 987161582Srwatson return (0); 988161582Srwatson} 989161582Srwatson 990161582Srwatson/* 991161582Srwatson * Return true if there are records available for reading on the pipe. 992161582Srwatson */ 993161582Srwatsonstatic int 994161582Srwatsonaudit_pipe_kqread(struct knote *kn, long hint) 995161582Srwatson{ 996161582Srwatson struct audit_pipe_entry *ape; 997161582Srwatson struct audit_pipe *ap; 998161582Srwatson 999161582Srwatson mtx_assert(&audit_pipe_mtx, MA_OWNED); 1000161582Srwatson 1001161582Srwatson ap = (struct audit_pipe *)kn->kn_hook; 1002161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqread: ap == NULL")); 1003161582Srwatson 1004161582Srwatson if (ap->ap_qlen != 0) { 1005161582Srwatson ape = TAILQ_FIRST(&ap->ap_queue); 1006161582Srwatson KASSERT(ape != NULL, ("audit_pipe_kqread: ape == NULL")); 1007161582Srwatson 1008161582Srwatson kn->kn_data = ape->ape_record_len; 1009161582Srwatson return (1); 1010161582Srwatson } else { 1011161582Srwatson kn->kn_data = 0; 1012161582Srwatson return (0); 1013161582Srwatson } 1014161582Srwatson} 1015161582Srwatson 1016161582Srwatson/* 1017161582Srwatson * Detach kqueue state from audit pipe. 1018161582Srwatson */ 1019161582Srwatsonstatic void 1020161582Srwatsonaudit_pipe_kqdetach(struct knote *kn) 1021161582Srwatson{ 1022161582Srwatson struct audit_pipe *ap; 1023161582Srwatson 1024161582Srwatson ap = (struct audit_pipe *)kn->kn_hook; 1025161582Srwatson KASSERT(ap != NULL, ("audit_pipe_kqdetach: ap == NULL")); 1026161582Srwatson 1027161582Srwatson mtx_lock(&audit_pipe_mtx); 1028161582Srwatson knlist_remove(&ap->ap_selinfo.si_note, kn, 1); 1029161582Srwatson mtx_unlock(&audit_pipe_mtx); 1030161582Srwatson} 1031161582Srwatson 1032161582Srwatson/* 1033155408Srwatson * Initialize the audit pipe system. 1034155408Srwatson */ 1035155408Srwatsonstatic void 1036155408Srwatsonaudit_pipe_init(void *unused) 1037155408Srwatson{ 1038155408Srwatson 1039155408Srwatson TAILQ_INIT(&audit_pipe_list); 1040155408Srwatson mtx_init(&audit_pipe_mtx, "audit_pipe_mtx", NULL, MTX_DEF); 1041155408Srwatson cv_init(&audit_pipe_cv, "audit_pipe_cv"); 1042155408Srwatson 1043155408Srwatson clone_setup(&audit_pipe_clones); 1044155408Srwatson audit_pipe_eh_tag = EVENTHANDLER_REGISTER(dev_clone, 1045155408Srwatson audit_pipe_clone, 0, 1000); 1046155408Srwatson if (audit_pipe_eh_tag == NULL) 1047155408Srwatson panic("audit_pipe_init: EVENTHANDLER_REGISTER"); 1048155408Srwatson} 1049155408Srwatson 1050155408SrwatsonSYSINIT(audit_pipe_init, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, audit_pipe_init, 1051155408Srwatson NULL); 1052