From owner-trustedbsd-cvs@FreeBSD.ORG Tue May 2 22:03:25 2006 Return-Path: X-Original-To: trustedbsd-cvs@freebsd.org Delivered-To: trustedbsd-cvs@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 6E54316A408 for ; Tue, 2 May 2006 22:03:25 +0000 (UTC) (envelope-from owner-perforce@freebsd.org) Received: from cyrus.watson.org (cyrus.watson.org [209.31.154.42]) by mx1.FreeBSD.org (Postfix) with ESMTP id CCA7643D45 for ; Tue, 2 May 2006 22:03:24 +0000 (GMT) (envelope-from owner-perforce@freebsd.org) Received: from mx2.freebsd.org (mx2.freebsd.org [216.136.204.119]) by cyrus.watson.org (Postfix) with ESMTP id EEF9846CE5 for ; Tue, 2 May 2006 18:03:23 -0400 (EDT) Received: from hub.freebsd.org (hub.freebsd.org [216.136.204.18]) by mx2.freebsd.org (Postfix) with ESMTP id 5D861556D9; Tue, 2 May 2006 22:03:23 +0000 (GMT) (envelope-from owner-perforce@freebsd.org) Received: by hub.freebsd.org (Postfix, from userid 32767) id 5881316A407; Tue, 2 May 2006 22:03:23 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 16E1416A403 for ; Tue, 2 May 2006 22:03:23 +0000 (UTC) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id C0E9F43D45 for ; Tue, 2 May 2006 22:03:22 +0000 (GMT) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id k42M3Mi4038420 for ; Tue, 2 May 2006 22:03:22 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id k42M3M4b038414 for perforce@freebsd.org; Tue, 2 May 2006 22:03:22 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Date: Tue, 2 May 2006 22:03:22 GMT Message-Id: <200605022203.k42M3M4b038414@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to bb+lists.freebsd.perforce@cyrus.watson.org using -f From: Robert Watson To: Perforce Change Reviews Cc: Subject: PERFORCE change 96570 for review X-BeenThere: trustedbsd-cvs@FreeBSD.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: TrustedBSD CVS and Perforce commit message list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 02 May 2006 22:03:25 -0000 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;