PERFORCE change 96570 for review
Robert Watson
rwatson at FreeBSD.org
Tue May 2 22:03:25 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=96570
Change 96570 by rwatson at 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;
More information about the trustedbsd-cvs
mailing list