audit_pipe.c (156884) | audit_pipe.c (159269) |
---|---|
1/*- 2 * Copyright (c) 2006 Robert N. M. Watson 3 * All rights reserved. 4 * 5 * This software was developed by Robert Watson for the TrustedBSD Project. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 11 unchanged lines hidden (view full) --- 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * | 1/*- 2 * Copyright (c) 2006 Robert N. M. Watson 3 * All rights reserved. 4 * 5 * This software was developed by Robert Watson for the TrustedBSD Project. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 11 unchanged lines hidden (view full) --- 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * |
28 * $FreeBSD: head/sys/security/audit/audit_pipe.c 156884 2006-03-19 15:39:03Z rwatson $ | 28 * $FreeBSD: head/sys/security/audit/audit_pipe.c 159269 2006-06-05 14:48:17Z rwatson $ |
29 */ 30 31#include <sys/param.h> 32#include <sys/condvar.h> 33#include <sys/conf.h> 34#include <sys/eventhandler.h> 35#include <sys/filio.h> 36#include <sys/kernel.h> --- 13 unchanged lines hidden (view full) --- 50#include <security/audit/audit.h> 51#include <security/audit/audit_ioctl.h> 52#include <security/audit/audit_private.h> 53 54/* 55 * Implementation of a clonable special device providing a live stream of BSM 56 * audit data. This is a "tee" of the data going to the file. It provides 57 * unreliable but timely access to audit events. Consumers of this interface | 29 */ 30 31#include <sys/param.h> 32#include <sys/condvar.h> 33#include <sys/conf.h> 34#include <sys/eventhandler.h> 35#include <sys/filio.h> 36#include <sys/kernel.h> --- 13 unchanged lines hidden (view full) --- 50#include <security/audit/audit.h> 51#include <security/audit/audit_ioctl.h> 52#include <security/audit/audit_private.h> 53 54/* 55 * Implementation of a clonable special device providing a live stream of BSM 56 * audit data. This is a "tee" of the data going to the file. It provides 57 * unreliable but timely access to audit events. Consumers of this interface |
58 * should be very careful to avoid introducing event cycles. | 58 * should be very careful to avoid introducing event cycles. Consumers may 59 * express interest via a set of preselection ioctls. |
59 */ 60 61/* 62 * Memory types. 63 */ 64static MALLOC_DEFINE(M_AUDIT_PIPE, "audit_pipe", "Audit pipes"); 65static MALLOC_DEFINE(M_AUDIT_PIPE_ENTRY, "audit_pipeent", 66 "Audit pipe entries and buffers"); | 60 */ 61 62/* 63 * Memory types. 64 */ 65static MALLOC_DEFINE(M_AUDIT_PIPE, "audit_pipe", "Audit pipes"); 66static MALLOC_DEFINE(M_AUDIT_PIPE_ENTRY, "audit_pipeent", 67 "Audit pipe entries and buffers"); |
68static MALLOC_DEFINE(M_AUDIT_PIPE_PRESELECT, "audit_pipe_preselect", 69 "Audit pipe preselection structure"); |
|
67 68/* 69 * Audit pipe buffer parameters. 70 */ 71#define AUDIT_PIPE_QLIMIT_DEFAULT (128) 72#define AUDIT_PIPE_QLIMIT_MIN (0) 73#define AUDIT_PIPE_QLIMIT_MAX (1024) 74 75/* 76 * Description of an entry in an audit_pipe. 77 */ 78struct audit_pipe_entry { 79 void *ape_record; 80 u_int ape_record_len; 81 TAILQ_ENTRY(audit_pipe_entry) ape_queue; 82}; 83 84/* | 70 71/* 72 * Audit pipe buffer parameters. 73 */ 74#define AUDIT_PIPE_QLIMIT_DEFAULT (128) 75#define AUDIT_PIPE_QLIMIT_MIN (0) 76#define AUDIT_PIPE_QLIMIT_MAX (1024) 77 78/* 79 * Description of an entry in an audit_pipe. 80 */ 81struct audit_pipe_entry { 82 void *ape_record; 83 u_int ape_record_len; 84 TAILQ_ENTRY(audit_pipe_entry) ape_queue; 85}; 86 87/* |
88 * Audit pipes allow processes to express "interest" in the set of records 89 * that are delivered via the pipe. They do this in a similar manner to the 90 * mechanism for audit trail configuration, by expressing two global masks, 91 * and optionally expressing per-auid masks. The following data structure is 92 * the per-auid mask description. The global state is stored in the audit 93 * pipe data structure. 94 * 95 * We may want to consider a more space/time-efficient data structure once 96 * usage patterns for per-auid specifications are clear. 97 */ 98struct audit_pipe_preselect { 99 au_id_t app_auid; 100 au_mask_t app_mask; 101 TAILQ_ENTRY(audit_pipe_preselect) app_list; 102}; 103 104/* |
|
85 * Description of an individual audit_pipe. Consists largely of a bounded 86 * length queue. 87 */ 88#define AUDIT_PIPE_ASYNC 0x00000001 89#define AUDIT_PIPE_NBIO 0x00000002 90struct audit_pipe { 91 int ap_open; /* Device open? */ 92 u_int ap_flags; --- 4 unchanged lines hidden (view full) --- 97 u_int ap_qlen; 98 u_int ap_qlimit; 99 100 u_int64_t ap_inserts; /* Records added. */ 101 u_int64_t ap_reads; /* Records read. */ 102 u_int64_t ap_drops; /* Records dropped. */ 103 u_int64_t ap_truncates; /* Records too long. */ 104 | 105 * Description of an individual audit_pipe. Consists largely of a bounded 106 * length queue. 107 */ 108#define AUDIT_PIPE_ASYNC 0x00000001 109#define AUDIT_PIPE_NBIO 0x00000002 110struct audit_pipe { 111 int ap_open; /* Device open? */ 112 u_int ap_flags; --- 4 unchanged lines hidden (view full) --- 117 u_int ap_qlen; 118 u_int ap_qlimit; 119 120 u_int64_t ap_inserts; /* Records added. */ 121 u_int64_t ap_reads; /* Records read. */ 122 u_int64_t ap_drops; /* Records dropped. */ 123 u_int64_t ap_truncates; /* Records too long. */ 124 |
125 /* 126 * Fields relating to pipe interest: global masks for unmatched 127 * processes (attributable, non-attributable), and a list of specific 128 * interest specifications by auid. 129 */ 130 int ap_preselect_mode; 131 au_mask_t ap_preselect_flags; 132 au_mask_t ap_preselect_naflags; 133 TAILQ_HEAD(, audit_pipe_preselect) ap_preselect_list; 134 135 /* 136 * Current pending record list. 137 */ |
|
105 TAILQ_HEAD(, audit_pipe_entry) ap_queue; 106 | 138 TAILQ_HEAD(, audit_pipe_entry) ap_queue; 139 |
140 /* 141 * Global pipe list. 142 */ |
|
107 TAILQ_ENTRY(audit_pipe) ap_list; 108}; 109 110/* | 143 TAILQ_ENTRY(audit_pipe) ap_list; 144}; 145 146/* |
111 * Global list of audit pipes, mutex to protect it and the pipes. Finder | 147 * Global list of audit pipes, mutex to protect it and the pipes. Finer |
112 * grained locking may be desirable at some point. 113 */ 114static TAILQ_HEAD(, audit_pipe) audit_pipe_list; 115static struct mtx audit_pipe_mtx; 116 117/* | 148 * grained locking may be desirable at some point. 149 */ 150static TAILQ_HEAD(, audit_pipe) audit_pipe_list; 151static struct mtx audit_pipe_mtx; 152 153/* |
118 * This CV is used to wakeup on an audit record write. Eventually, it should 119 * probably be per-pipe. | 154 * This CV is used to wakeup on an audit record write. Eventually, it might 155 * be per-pipe to avoid unnecessary wakeups when several pipes with different 156 * preselection masks are present. |
120 */ 121static struct cv audit_pipe_cv; 122 123/* 124 * Cloning related variables and constants. 125 */ 126#define AUDIT_PIPE_NAME "auditpipe" 127static eventhandler_tag audit_pipe_eh_tag; --- 5 unchanged lines hidden (view full) --- 133static d_open_t audit_pipe_open; 134static d_close_t audit_pipe_close; 135static d_read_t audit_pipe_read; 136static d_ioctl_t audit_pipe_ioctl; 137static d_poll_t audit_pipe_poll; 138 139static struct cdevsw audit_pipe_cdevsw = { 140 .d_version = D_VERSION, | 157 */ 158static struct cv audit_pipe_cv; 159 160/* 161 * Cloning related variables and constants. 162 */ 163#define AUDIT_PIPE_NAME "auditpipe" 164static eventhandler_tag audit_pipe_eh_tag; --- 5 unchanged lines hidden (view full) --- 170static d_open_t audit_pipe_open; 171static d_close_t audit_pipe_close; 172static d_read_t audit_pipe_read; 173static d_ioctl_t audit_pipe_ioctl; 174static d_poll_t audit_pipe_poll; 175 176static struct cdevsw audit_pipe_cdevsw = { 177 .d_version = D_VERSION, |
141 .d_flags = D_PSEUDO, | 178 .d_flags = D_PSEUDO | D_NEEDGIANT, |
142 .d_open = audit_pipe_open, 143 .d_close = audit_pipe_close, 144 .d_read = audit_pipe_read, 145 .d_ioctl = audit_pipe_ioctl, 146 .d_poll = audit_pipe_poll, 147 .d_name = AUDIT_PIPE_NAME, 148}; 149 --- 12 unchanged lines hidden (view full) --- 162audit_pipe_entry_free(struct audit_pipe_entry *ape) 163{ 164 165 free(ape->ape_record, M_AUDIT_PIPE_ENTRY); 166 free(ape, M_AUDIT_PIPE_ENTRY); 167} 168 169/* | 179 .d_open = audit_pipe_open, 180 .d_close = audit_pipe_close, 181 .d_read = audit_pipe_read, 182 .d_ioctl = audit_pipe_ioctl, 183 .d_poll = audit_pipe_poll, 184 .d_name = AUDIT_PIPE_NAME, 185}; 186 --- 12 unchanged lines hidden (view full) --- 199audit_pipe_entry_free(struct audit_pipe_entry *ape) 200{ 201 202 free(ape->ape_record, M_AUDIT_PIPE_ENTRY); 203 free(ape, M_AUDIT_PIPE_ENTRY); 204} 205 206/* |
170 * Apparent individual record to a queue -- allocate queue-local buffer, and | 207 * Find an audit pipe preselection specification for an auid, if any. 208 */ 209static struct audit_pipe_preselect * 210audit_pipe_preselect_find(struct audit_pipe *ap, au_id_t auid) 211{ 212 struct audit_pipe_preselect *app; 213 214 mtx_assert(&audit_pipe_mtx, MA_OWNED); 215 216 TAILQ_FOREACH(app, &ap->ap_preselect_list, app_list) { 217 if (app->app_auid == auid) 218 return (app); 219 } 220 return (NULL); 221} 222 223/* 224 * Query the per-pipe mask for a specific auid. 225 */ 226static int 227audit_pipe_preselect_get(struct audit_pipe *ap, au_id_t auid, 228 au_mask_t *maskp) 229{ 230 struct audit_pipe_preselect *app; 231 int error; 232 233 mtx_lock(&audit_pipe_mtx); 234 app = audit_pipe_preselect_find(ap, auid); 235 if (app != NULL) { 236 *maskp = app->app_mask; 237 error = 0; 238 } else 239 error = ENOENT; 240 mtx_unlock(&audit_pipe_mtx); 241 return (error); 242} 243 244/* 245 * Set the per-pipe mask for a specific auid. Add a new entry if needed; 246 * otherwise, update the current entry. 247 */ 248static void 249audit_pipe_preselect_set(struct audit_pipe *ap, au_id_t auid, au_mask_t mask) 250{ 251 struct audit_pipe_preselect *app, *app_new; 252 253 /* 254 * Pessimistically assume that the auid doesn't already have a mask 255 * set, and allocate. We will free it if it is unneeded. 256 */ 257 app_new = malloc(sizeof(*app_new), M_AUDIT_PIPE_PRESELECT, M_WAITOK); 258 mtx_lock(&audit_pipe_mtx); 259 app = audit_pipe_preselect_find(ap, auid); 260 if (app == NULL) { 261 app = app_new; 262 app_new = NULL; 263 app->app_auid = auid; 264 TAILQ_INSERT_TAIL(&ap->ap_preselect_list, app, app_list); 265 } 266 app->app_mask = mask; 267 mtx_unlock(&audit_pipe_mtx); 268 if (app_new != NULL) 269 free(app_new, M_AUDIT_PIPE_PRESELECT); 270} 271 272/* 273 * Delete a per-auid mask on an audit pipe. 274 */ 275static int 276audit_pipe_preselect_delete(struct audit_pipe *ap, au_id_t auid) 277{ 278 struct audit_pipe_preselect *app; 279 int error; 280 281 mtx_lock(&audit_pipe_mtx); 282 app = audit_pipe_preselect_find(ap, auid); 283 if (app != NULL) { 284 TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 285 error = 0; 286 } else 287 error = ENOENT; 288 mtx_unlock(&audit_pipe_mtx); 289 if (app != NULL) 290 free(app, M_AUDIT_PIPE_PRESELECT); 291 return (error); 292} 293 294/* 295 * Delete all per-auid masks on an audit pipe. 296 */ 297static void 298audit_pipe_preselect_flush_locked(struct audit_pipe *ap) 299{ 300 struct audit_pipe_preselect *app; 301 302 mtx_assert(&audit_pipe_mtx, MA_OWNED); 303 304 while ((app = TAILQ_FIRST(&ap->ap_preselect_list)) != NULL) { 305 TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); 306 free(app, M_AUDIT_PIPE_PRESELECT); 307 } 308} 309 310static void 311audit_pipe_preselect_flush(struct audit_pipe *ap) 312{ 313 314 mtx_lock(&audit_pipe_mtx); 315 audit_pipe_preselect_flush_locked(ap); 316 mtx_unlock(&audit_pipe_mtx); 317} 318 319/* 320 * Determine whether a specific audit pipe matches a record with these 321 * properties. Algorithm is as follows: 322 * 323 * - If the pipe is configured to track the default trail configuration, then 324 * use the results of global preselection matching. 325 * - If not, search for a specifically configured auid entry matching the 326 * event. If an entry is found, use that. 327 * - Otherwise, use the default flags or naflags configured for the pipe. 328 */ 329static int 330audit_pipe_preselect_check(struct audit_pipe *ap, au_id_t auid, 331 au_event_t event, au_class_t class, int sorf, int trail_preselect) 332{ 333 struct audit_pipe_preselect *app; 334 335 mtx_assert(&audit_pipe_mtx, MA_OWNED); 336 337 switch (ap->ap_preselect_mode) { 338 case AUDITPIPE_PRESELECT_MODE_TRAIL: 339 return (trail_preselect); 340 341 case AUDITPIPE_PRESELECT_MODE_LOCAL: 342 app = audit_pipe_preselect_find(ap, auid); 343 if (app == NULL) { 344 if (auid == AU_DEFAUDITID) 345 return (au_preselect(event, class, 346 &ap->ap_preselect_naflags, sorf)); 347 else 348 return (au_preselect(event, class, 349 &ap->ap_preselect_flags, sorf)); 350 } else 351 return (au_preselect(event, class, &app->app_mask, 352 sorf)); 353 354 default: 355 panic("audit_pipe_preselect_check: mode %d", 356 ap->ap_preselect_mode); 357 } 358 359 return (0); 360} 361 362/* 363 * Determine whether there exists a pipe interested in a record with specific 364 * properties. 365 */ 366int 367audit_pipe_preselect(au_id_t auid, au_event_t event, au_class_t class, 368 int sorf, int trail_preselect) 369{ 370 struct audit_pipe *ap; 371 372 mtx_lock(&audit_pipe_mtx); 373 TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 374 if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 375 trail_preselect)) { 376 mtx_unlock(&audit_pipe_mtx); 377 return (1); 378 } 379 } 380 mtx_unlock(&audit_pipe_mtx); 381 return (0); 382} 383 384/* 385 * Append individual record to a queue -- allocate queue-local buffer, and |
171 * add to the queue. We try to drop from the head of the queue so that more 172 * recent events take precedence over older ones, but if allocation fails we 173 * do drop the new event. 174 */ 175static void 176audit_pipe_append(struct audit_pipe *ap, void *record, u_int record_len) 177{ 178 struct audit_pipe_entry *ape, *ape_remove; --- 35 unchanged lines hidden (view full) --- 214 pgsigio(&ap->ap_sigio, SIGIO, 0); 215} 216 217/* 218 * audit_pipe_submit(): audit_worker submits audit records via this 219 * interface, which arranges for them to be delivered to pipe queues. 220 */ 221void | 386 * add to the queue. We try to drop from the head of the queue so that more 387 * recent events take precedence over older ones, but if allocation fails we 388 * do drop the new event. 389 */ 390static void 391audit_pipe_append(struct audit_pipe *ap, void *record, u_int record_len) 392{ 393 struct audit_pipe_entry *ape, *ape_remove; --- 35 unchanged lines hidden (view full) --- 429 pgsigio(&ap->ap_sigio, SIGIO, 0); 430} 431 432/* 433 * audit_pipe_submit(): audit_worker submits audit records via this 434 * interface, which arranges for them to be delivered to pipe queues. 435 */ 436void |
222audit_pipe_submit(void *record, u_int record_len) | 437audit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class, int sorf, 438 int trail_select, void *record, u_int record_len) |
223{ 224 struct audit_pipe *ap; 225 226 /* 227 * Lockless read to avoid mutex overhead if pipes are not in use. 228 */ 229 if (TAILQ_FIRST(&audit_pipe_list) == NULL) 230 return; 231 232 mtx_lock(&audit_pipe_mtx); | 439{ 440 struct audit_pipe *ap; 441 442 /* 443 * Lockless read to avoid mutex overhead if pipes are not in use. 444 */ 445 if (TAILQ_FIRST(&audit_pipe_list) == NULL) 446 return; 447 448 mtx_lock(&audit_pipe_mtx); |
449 TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { 450 if (audit_pipe_preselect_check(ap, auid, event, class, sorf, 451 trail_select)) 452 audit_pipe_append(ap, record, record_len); 453 } 454 audit_pipe_records++; 455 mtx_unlock(&audit_pipe_mtx); 456 cv_signal(&audit_pipe_cv); 457} 458 459/* 460 * audit_pipe_submit_user(): the same as audit_pipe_submit(), except that 461 * since we don't currently have selection information available, it is 462 * delivered to the pipe unconditionally. 463 * 464 * XXXRW: This is a bug. The BSM check routine for submitting a user record 465 * should parse that information and return it. 466 */ 467void 468audit_pipe_submit_user(void *record, u_int record_len) 469{ 470 struct audit_pipe *ap; 471 472 /* 473 * Lockless read to avoid mutex overhead if pipes are not in use. 474 */ 475 if (TAILQ_FIRST(&audit_pipe_list) == NULL) 476 return; 477 478 mtx_lock(&audit_pipe_mtx); |
|
233 TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) 234 audit_pipe_append(ap, record, record_len); 235 audit_pipe_records++; 236 mtx_unlock(&audit_pipe_mtx); 237 cv_signal(&audit_pipe_cv); 238} 239 | 479 TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) 480 audit_pipe_append(ap, record, record_len); 481 audit_pipe_records++; 482 mtx_unlock(&audit_pipe_mtx); 483 cv_signal(&audit_pipe_cv); 484} 485 |
486 |
|
240/* | 487/* |
241 * Read the next record off of an audit pipe. | 488 * Pop the next record off of an audit pipe. |
242 */ 243static struct audit_pipe_entry * 244audit_pipe_pop(struct audit_pipe *ap) 245{ 246 struct audit_pipe_entry *ape; 247 248 mtx_assert(&audit_pipe_mtx, MA_OWNED); 249 --- 18 unchanged lines hidden (view full) --- 268 269 mtx_assert(&audit_pipe_mtx, MA_OWNED); 270 271 ap = malloc(sizeof(*ap), M_AUDIT_PIPE, M_NOWAIT | M_ZERO); 272 if (ap == NULL) 273 return (NULL); 274 ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT; 275 TAILQ_INIT(&ap->ap_queue); | 489 */ 490static struct audit_pipe_entry * 491audit_pipe_pop(struct audit_pipe *ap) 492{ 493 struct audit_pipe_entry *ape; 494 495 mtx_assert(&audit_pipe_mtx, MA_OWNED); 496 --- 18 unchanged lines hidden (view full) --- 515 516 mtx_assert(&audit_pipe_mtx, MA_OWNED); 517 518 ap = malloc(sizeof(*ap), M_AUDIT_PIPE, M_NOWAIT | M_ZERO); 519 if (ap == NULL) 520 return (NULL); 521 ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT; 522 TAILQ_INIT(&ap->ap_queue); |
523 524 /* 525 * Default flags, naflags, and auid-specific preselection settings to 526 * 0. Initialize the mode to the global trail so that if praudit(1) 527 * is run on /dev/auditpipe, it sees events associated with the 528 * default trail. Pipe-aware application can clear the flag, set 529 * custom masks, and flush the pipe as needed. 530 */ 531 bzero(&ap->ap_preselect_flags, sizeof(ap->ap_preselect_flags)); 532 bzero(&ap->ap_preselect_naflags, sizeof(ap->ap_preselect_naflags)); 533 TAILQ_INIT(&ap->ap_preselect_list); 534 ap->ap_preselect_mode = AUDITPIPE_PRESELECT_MODE_TRAIL; 535 |
|
276 TAILQ_INSERT_HEAD(&audit_pipe_list, ap, ap_list); 277 audit_pipe_count++; 278 audit_pipe_ever++; | 536 TAILQ_INSERT_HEAD(&audit_pipe_list, ap, ap_list); 537 audit_pipe_count++; 538 audit_pipe_ever++; |
539 |
|
279 return (ap); 280} 281 282/* | 540 return (ap); 541} 542 543/* |
283 * Free an audit pipe. Assumes mutex is held, audit_pipe is still on the 284 * global list. Frees any audit pipe entries in the queue. | 544 * Flush all records currently present in an audit pipe; assume mutex is held. |
285 */ 286static void | 545 */ 546static void |
287audit_pipe_free(struct audit_pipe *ap) | 547audit_pipe_flush(struct audit_pipe *ap) |
288{ 289 struct audit_pipe_entry *ape; 290 291 mtx_assert(&audit_pipe_mtx, MA_OWNED); 292 | 548{ 549 struct audit_pipe_entry *ape; 550 551 mtx_assert(&audit_pipe_mtx, MA_OWNED); 552 |
293 TAILQ_REMOVE(&audit_pipe_list, ap, ap_list); | |
294 while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL) { 295 TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 296 audit_pipe_entry_free(ape); 297 ap->ap_qlen--; 298 } 299 KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qlen")); | 553 while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL) { 554 TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); 555 audit_pipe_entry_free(ape); 556 ap->ap_qlen--; 557 } 558 KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qlen")); |
559} 560 561/* 562 * Free an audit pipe; this means freeing all preselection state and all 563 * records in the pipe. Assumes mutex is held to prevent any new records 564 * from being inserted during the free, and that the audit pipe is still on 565 * the global list. 566 */ 567static void 568audit_pipe_free(struct audit_pipe *ap) 569{ 570 571 mtx_assert(&audit_pipe_mtx, MA_OWNED); 572 573 audit_pipe_preselect_flush_locked(ap); 574 audit_pipe_flush(ap); 575 TAILQ_REMOVE(&audit_pipe_list, ap, ap_list); |
|
300 free(ap, M_AUDIT_PIPE); 301 audit_pipe_count--; 302} 303 304/* 305 * Audit pipe clone routine -- provide specific requested audit pipe, or a 306 * fresh one if a specific one is not requested. 307 */ --- 78 unchanged lines hidden (view full) --- 386 * 387 * Would be desirable to support filtering, although perhaps something simple 388 * like an event mask, as opposed to something complicated like BPF. 389 */ 390static int 391audit_pipe_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, 392 struct thread *td) 393{ | 576 free(ap, M_AUDIT_PIPE); 577 audit_pipe_count--; 578} 579 580/* 581 * Audit pipe clone routine -- provide specific requested audit pipe, or a 582 * fresh one if a specific one is not requested. 583 */ --- 78 unchanged lines hidden (view full) --- 662 * 663 * Would be desirable to support filtering, although perhaps something simple 664 * like an event mask, as opposed to something complicated like BPF. 665 */ 666static int 667audit_pipe_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, 668 struct thread *td) 669{ |
670 struct auditpipe_ioctl_preselect *aip; |
|
394 struct audit_pipe *ap; | 671 struct audit_pipe *ap; |
395 int error; | 672 au_mask_t *maskp; 673 int error, mode; 674 au_id_t auid; |
396 397 ap = dev->si_drv1; 398 KASSERT(ap != NULL, ("audit_pipe_ioctl: ap == NULL")); | 675 676 ap = dev->si_drv1; 677 KASSERT(ap != NULL, ("audit_pipe_ioctl: ap == NULL")); |
678 679 /* 680 * Audit pipe ioctls: first come standard device node ioctls, then 681 * manipulation of pipe settings, and finally, statistics query 682 * ioctls. 683 */ |
|
399 switch (cmd) { 400 case FIONBIO: 401 mtx_lock(&audit_pipe_mtx); 402 if (*(int *)data) 403 ap->ap_flags |= AUDIT_PIPE_NBIO; 404 else 405 ap->ap_flags &= ~AUDIT_PIPE_NBIO; 406 mtx_unlock(&audit_pipe_mtx); --- 55 unchanged lines hidden (view full) --- 462 error = 0; 463 break; 464 465 case AUDITPIPE_GET_QLIMIT_MAX: 466 *(u_int *)data = AUDIT_PIPE_QLIMIT_MAX; 467 error = 0; 468 break; 469 | 684 switch (cmd) { 685 case FIONBIO: 686 mtx_lock(&audit_pipe_mtx); 687 if (*(int *)data) 688 ap->ap_flags |= AUDIT_PIPE_NBIO; 689 else 690 ap->ap_flags &= ~AUDIT_PIPE_NBIO; 691 mtx_unlock(&audit_pipe_mtx); --- 55 unchanged lines hidden (view full) --- 747 error = 0; 748 break; 749 750 case AUDITPIPE_GET_QLIMIT_MAX: 751 *(u_int *)data = AUDIT_PIPE_QLIMIT_MAX; 752 error = 0; 753 break; 754 |
755 case AUDITPIPE_GET_PRESELECT_FLAGS: 756 mtx_lock(&audit_pipe_mtx); 757 maskp = (au_mask_t *)data; 758 *maskp = ap->ap_preselect_flags; 759 mtx_unlock(&audit_pipe_mtx); 760 error = 0; 761 break; 762 763 case AUDITPIPE_SET_PRESELECT_FLAGS: 764 mtx_lock(&audit_pipe_mtx); 765 maskp = (au_mask_t *)data; 766 ap->ap_preselect_flags = *maskp; 767 mtx_unlock(&audit_pipe_mtx); 768 error = 0; 769 break; 770 771 case AUDITPIPE_GET_PRESELECT_NAFLAGS: 772 mtx_lock(&audit_pipe_mtx); 773 maskp = (au_mask_t *)data; 774 *maskp = ap->ap_preselect_naflags; 775 mtx_unlock(&audit_pipe_mtx); 776 error = 0; 777 break; 778 779 case AUDITPIPE_SET_PRESELECT_NAFLAGS: 780 mtx_lock(&audit_pipe_mtx); 781 maskp = (au_mask_t *)data; 782 ap->ap_preselect_naflags = *maskp; 783 mtx_unlock(&audit_pipe_mtx); 784 error = 0; 785 break; 786 787 case AUDITPIPE_GET_PRESELECT_AUID: 788 aip = (struct auditpipe_ioctl_preselect *)data; 789 error = audit_pipe_preselect_get(ap, aip->aip_auid, 790 &aip->aip_mask); 791 break; 792 793 case AUDITPIPE_SET_PRESELECT_AUID: 794 aip = (struct auditpipe_ioctl_preselect *)data; 795 audit_pipe_preselect_set(ap, aip->aip_auid, aip->aip_mask); 796 error = 0; 797 break; 798 799 case AUDITPIPE_DELETE_PRESELECT_AUID: 800 auid = *(au_id_t *)data; 801 error = audit_pipe_preselect_delete(ap, auid); 802 break; 803 804 case AUDITPIPE_FLUSH_PRESELECT_AUID: 805 audit_pipe_preselect_flush(ap); 806 error = 0; 807 break; 808 809 case AUDITPIPE_GET_PRESELECT_MODE: 810 mtx_lock(&audit_pipe_mtx); 811 *(int *)data = ap->ap_preselect_mode; 812 mtx_unlock(&audit_pipe_mtx); 813 error = 0; 814 break; 815 816 case AUDITPIPE_SET_PRESELECT_MODE: 817 mode = *(int *)data; 818 switch (mode) { 819 case AUDITPIPE_PRESELECT_MODE_TRAIL: 820 case AUDITPIPE_PRESELECT_MODE_LOCAL: 821 mtx_lock(&audit_pipe_mtx); 822 ap->ap_preselect_mode = mode; 823 mtx_unlock(&audit_pipe_mtx); 824 error = 0; 825 break; 826 827 default: 828 error = EINVAL; 829 } 830 break; 831 832 case AUDITPIPE_FLUSH: 833 mtx_lock(&audit_pipe_mtx); 834 audit_pipe_flush(ap); 835 mtx_unlock(&audit_pipe_mtx); 836 error = 0; 837 break; 838 |
|
470 case AUDITPIPE_GET_INSERTS: 471 *(u_int *)data = ap->ap_inserts; 472 error = 0; 473 break; 474 475 case AUDITPIPE_GET_READS: 476 *(u_int *)data = ap->ap_reads; 477 error = 0; --- 13 unchanged lines hidden (view full) --- 491 error = ENOTTY; 492 } 493 return (error); 494} 495 496/* 497 * Audit pipe read. Pull one record off the queue and copy to user space. 498 * On error, the record is dropped. | 839 case AUDITPIPE_GET_INSERTS: 840 *(u_int *)data = ap->ap_inserts; 841 error = 0; 842 break; 843 844 case AUDITPIPE_GET_READS: 845 *(u_int *)data = ap->ap_reads; 846 error = 0; --- 13 unchanged lines hidden (view full) --- 860 error = ENOTTY; 861 } 862 return (error); 863} 864 865/* 866 * Audit pipe read. Pull one record off the queue and copy to user space. 867 * On error, the record is dropped. |
868 * 869 * Providing more sophisticated behavior, such as partial reads, is tricky 870 * due to the potential for parallel I/O. If partial read support is 871 * required, it will require a per-pipe "current record being read" along 872 * with an offset into that trecord which has already been read. Threads 873 * performing partial reads will need to allocate per-thread copies of the 874 * data so that if another thread completes the read of the record, it can be 875 * freed without adding reference count logic. If this is added, a flag to 876 * indicate that only atomic record reads are desired would be useful, as if 877 * different threads are all waiting for records on the pipe, they will want 878 * independent record reads, which is currently the behavior. |
|
499 */ 500static int 501audit_pipe_read(struct cdev *dev, struct uio *uio, int flag) 502{ 503 struct audit_pipe_entry *ape; 504 struct audit_pipe *ap; 505 int error; 506 --- 81 unchanged lines hidden --- | 879 */ 880static int 881audit_pipe_read(struct cdev *dev, struct uio *uio, int flag) 882{ 883 struct audit_pipe_entry *ape; 884 struct audit_pipe *ap; 885 int error; 886 --- 81 unchanged lines hidden --- |