Date: Tue, 2 May 2006 22:03:22 GMT From: Robert Watson <rwatson@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 96570 for review Message-ID: <200605022203.k42M3M4b038414@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=96570 Change 96570 by rwatson@rwatson_peppercorn on 2006/05/02 22:03:11 Early pass at per-pipe preselection: - Add new fields to struct audit_pipe to describe the preselection preferences for the pipe. Currently, this consists of two masks, flags and naflags, with similar meanings to those used for trails. In addition, a linked list of audit_pipe_preselect structures provides similar functionality to audit_user, assigning masks to specific auids. The details here need refinement. - Add two new functions, audit_pipe_preselect_check(), which checks whether a record with the passed {auid, event, class, sorf} is matched, and audit_pipe_preselect(), which iterates over available pipes. This will be called by the system preselection mechanisms to poll the audit pipe subsystem for interest in a particular record. - Modify audit_pipe_submit() to accept additional fields auid, class, sorf for a BSM record, so that preselection can be performed when delivering to pipes. The old preselection-free audit_pipe_submit() continues to exist, for now, as audit_pipe_submit_user(), to be called on user records since we don't currently extract sufficient information from user submitted records to perform full preselection. - Modify audit worker code to pass additional record properties into audit_pipe_submit(). This almost certainly doesn't work yet. Affected files ... .. //depot/projects/trustedbsd/audit3/sys/security/audit/audit_pipe.c#14 edit .. //depot/projects/trustedbsd/audit3/sys/security/audit/audit_private.h#25 edit .. //depot/projects/trustedbsd/audit3/sys/security/audit/audit_worker.c#9 edit Differences ... ==== //depot/projects/trustedbsd/audit3/sys/security/audit/audit_pipe.c#14 (text+ko) ==== @@ -82,6 +82,19 @@ }; /* + * Audit pipes allow processes to express "interest" in the set of records + * that are delivered via the pipe. They do this in a similar manner to the + * mechanism for audit trail configuration, by expressing two global masks, + * and optionally expressing per-auid masks. The following data structures + * define by the global masks for each pipe, and a list of per-auid masks. + */ +struct audit_pipe_preselect { + au_id_t app_auid; + au_mask_t app_mask; + TAILQ_ENTRY(audit_pipe_preselect) app_list; +}; + +/* * Description of an individual audit_pipe. Consists largely of a bounded * length queue. */ @@ -102,8 +115,24 @@ u_int64_t ap_drops; /* Records dropped. */ u_int64_t ap_truncates; /* Records too long. */ + + /* + * Fields relating to pipe interest: global masks for unmatched + * processes (attributable, non-attributable), and a list of specific + * interest specifications by auid. + */ + au_mask_t ap_preselect_flags; + au_mask_t ap_preselect_naflags; + TAILQ_HEAD(, audit_pipe_preselect) ap_preselect_list; + + /* + * Record list. + */ TAILQ_HEAD(, audit_pipe_entry) ap_queue; + /* + * Global pipe list. + */ TAILQ_ENTRY(audit_pipe) ap_list; }; @@ -167,6 +196,49 @@ } /* + * Determine whether a specific audit pipe matches a record with these + * properties. + */ +static int +audit_pipe_preselect_check(struct audit_pipe *ap, au_id_t auid, + au_event_t event, au_class_t class, int sorf) +{ + struct audit_pipe_preselect *app; + + TAILQ_FOREACH(app, &ap->ap_preselect_list, app_list) { + if (app->app_auid == auid) + break; + } + if (app == NULL) { + if (auid == AU_DEFAUDITID) + return (au_preselect(event, &ap->ap_preselect_naflags, + sorf)); + else + return (au_preselect(event, &ap->ap_preselect_flags, + sorf)); + } else + return (au_preselect(event, &app->app_mask, sorf)); + return (0); +} + +/* + * Determine whether there exists a pipe interested in a record with these + * properties. + */ +int +audit_pipe_preselect(au_id_t auid, au_event_t event, au_class_t class, + int sorf) +{ + struct audit_pipe *ap; + + TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { + if (audit_pipe_preselect_check(ap, auid, event, class, sorf)) + return (1); + } + return (0); +} + +/* * Apparent individual record to a queue -- allocate queue-local buffer, and * add to the queue. We try to drop from the head of the queue so that more * recent events take precedence over older ones, but if allocation fails we @@ -219,7 +291,37 @@ * interface, which arranges for them to be delivered to pipe queues. */ void -audit_pipe_submit(void *record, u_int record_len) +audit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class, int sorf, + void *record, u_int record_len) +{ + struct audit_pipe *ap; + + /* + * Lockless read to avoid mutex overhead if pipes are not in use. + */ + if (TAILQ_FIRST(&audit_pipe_list) == NULL) + return; + + mtx_lock(&audit_pipe_mtx); + TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { + if (audit_pipe_preselect_check(ap, auid, event, class, sorf)) + audit_pipe_append(ap, record, record_len); + } + audit_pipe_records++; + mtx_unlock(&audit_pipe_mtx); + cv_signal(&audit_pipe_cv); +} + +/* + * audit_pipe_submit_user(): the same as audit_pipe_submit(), except that + * since we don't currently have selection information available, it is + * delivered to the pipe unconditionally. + * + * XXXRW: This is a bug. The BSM check routine for submitting a user record + * should parse that information and return it. + */ +void +audit_pipe_submit_user(void *record, u_int record_len) { struct audit_pipe *ap; @@ -237,6 +339,7 @@ cv_signal(&audit_pipe_cv); } + /* * Read the next record off of an audit pipe. */ @@ -273,9 +376,14 @@ return (NULL); ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT; TAILQ_INIT(&ap->ap_queue); + bzero(&ap->ap_preselect_flags, sizeof(ap->ap_preselect_flags)); + bzero(&ap->ap_preselect_naflags, sizeof(ap->ap_preselect_naflags)); + TAILQ_INIT(&ap->ap_preselect_list); + TAILQ_INSERT_HEAD(&audit_pipe_list, ap, ap_list); audit_pipe_count++; audit_pipe_ever++; + return (ap); } ==== //depot/projects/trustedbsd/audit3/sys/security/audit/audit_private.h#25 (text+ko) ==== @@ -337,6 +337,10 @@ /* * Audit pipe functions. */ -void audit_pipe_submit(void *record, u_int record_len); +int audit_pipe_preselect(au_id_t auid, au_event_t event, + au_class_t class, int sorf); +void audit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class, + int sorf, void *record, u_int record_len); +void audit_pipe_submit_user(void *record, u_int record_len); #endif /* ! _SECURITY_AUDIT_PRIVATE_H_ */ ==== //depot/projects/trustedbsd/audit3/sys/security/audit/audit_worker.c#9 (text+ko) ==== @@ -315,7 +315,11 @@ struct thread *audit_td, struct kaudit_record *ar) { struct au_record *bsm; + au_class_t class; + au_event_t event; int error, ret; + au_id_t auid; + int sorf; if (ar->k_ar_commit & AR_COMMIT_USER) { error = audit_record_write(audit_vp, audit_cred, audit_td, @@ -324,10 +328,18 @@ panic("audit_worker: write error %d\n", error); else if (error) printf("audit_worker: write error %d\n", error); - audit_pipe_submit(ar->k_udata, ar->k_ulen); + audit_pipe_submit_user(ar->k_udata, ar->k_ulen); } if (ar->k_ar_commit & AR_COMMIT_KERNEL) { + auid = ar->k_ar.ar_subj_auid; + event = ar->k_ar.ar_event; + class = au_event_class(event); + if (ar->k_ar.ar_errno == 0) + sorf = AU_PRS_SUCCESS; + else + sorf = AU_PRS_FAILURE; + ret = kaudit_to_bsm(ar, &bsm); switch (ret) { case BSM_NOAUDIT: @@ -346,7 +358,8 @@ else if (error) printf("audit_worker: write error %d\n", error); - audit_pipe_submit(bsm->data, bsm->len); + audit_pipe_submit(auid, event, class, sorf, + bsm->data, bsm->len); kau_free(bsm); break;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200605022203.k42M3M4b038414>