PERFORCE change 111048 for review
Todd Miller
millert at FreeBSD.org
Mon Dec 4 10:38:36 PST 2006
http://perforce.freebsd.org/chv.cgi?CH=111048
Change 111048 by millert at millert_g5tower on 2006/12/04 18:38:23
When logging avc audit info, fill in an array of struct
audit_buffer which are later processed by audit_log_process()
via sebsd_thread_userret(). This lets us log audit data
without blocking during the actual syscall (atomic operations
are used as needed). We use a spin lock to keep the printf()s
from overlapping.
Fixes a problem on dual CPU machines.
Affected files ...
.. //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/avc/avc.c#13 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/avc/avc_audit.c#3 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/linux-compat.h#4 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/sebsd.c#49 edit
Differences ...
==== //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/avc/avc.c#13 (text+ko) ====
@@ -270,7 +270,7 @@
lck_attr_setdefault(avc_lck_attr); /* no lock debugging */
/* allocate avc mutexes */
- avc_log_lock = lck_mtx_alloc_init(avc_lck_grp, avc_lck_attr);
+ avc_log_lock = lck_spin_alloc_init(avc_lck_grp, avc_lck_attr);
notif_lock = lck_mtx_alloc_init(avc_lck_grp, avc_lck_attr);
for (i = 0; i < AVC_CACHE_SLOTS; i++) {
==== //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/avc/avc_audit.c#3 (text+ko) ====
@@ -43,46 +43,80 @@
/*
* Emulate Linux audit API.
- * In the future we may wish to use the BSD audit support instead.
- * TBD: use a freelist so we don't have to mallc/free so much.
+ * In the future we may wish to use the BSM audit support instead.
*/
-lck_mtx_t *avc_log_lock;
-
-extern void conslog_putc(char);
-
struct audit_buffer {
struct sbuf sbuf;
char buf[1024];
};
+#define AUDIT_SLOT_MAX 256
+static SInt32 nslots;
+struct audit_buffer *audit_slots[AUDIT_SLOT_MAX];
+
+lck_spin_t *avc_log_lock;
+
struct audit_buffer *
audit_log_start(void)
{
struct audit_buffer *ab;
ab = sebsd_malloc(sizeof(*ab), M_SEBSD, M_NOWAIT);
- if (ab == NULL) {
- printf("%s: unable to allocate audit buffer\n", __func__);
- return (NULL);
- }
- sbuf_new(&ab->sbuf, ab->buf, sizeof(ab->buf), SBUF_FIXEDLEN);
+ if (ab != NULL)
+ sbuf_new(&ab->sbuf, ab->buf, sizeof(ab->buf), SBUF_FIXEDLEN);
+
return (ab);
}
void
audit_log_end(struct audit_buffer *ab)
{
+ int i;
+ UInt32 oldval;
sbuf_finish(&ab->sbuf);
- lck_mtx_lock(avc_log_lock);
- printf("\n%s\n", sbuf_data(&ab->sbuf));
- lck_mtx_unlock(avc_log_lock);
- sbuf_delete(&ab->sbuf);
+
+ /*
+ * Find and claim an audit slot (assumes 32bit pointers).
+ */
+ for (i = 0; i < AUDIT_SLOT_MAX; i++) {
+ oldval = (UInt32)audit_slots[i];
+ if (oldval == 0 && OSCompareAndSwap(oldval, (UInt32)ab,
+ (UInt32 *)&audit_slots[i])) {
+ OSIncrementAtomic(&nslots);
+ return;
+ }
+ }
+ /* No free slots, drop record. */
sebsd_free(ab, M_SEBSD);
}
void
+audit_log_process(void)
+{
+ struct audit_buffer *ab;
+ int i;
+
+ /*
+ * Print and free all existing (finished) audit records.
+ */
+ lck_spin_lock(avc_log_lock);
+ for (i = 0; nslots != 0 && i < AUDIT_SLOT_MAX; i++) {
+ ab = audit_slots[i];
+ if (ab != NULL) {
+ if (OSCompareAndSwap((UInt32)ab, 0,
+ (UInt32 *)&audit_slots[i])) {
+ OSDecrementAtomic(&nslots);
+ printf("\n%s\n", sbuf_data(&ab->sbuf));
+ sebsd_free(ab, M_SEBSD);
+ }
+ }
+ }
+ lck_spin_unlock(avc_log_lock);
+}
+
+void
audit_log_format(struct audit_buffer *ab, const char *fmt, ...)
{
va_list ap;
@@ -93,8 +127,21 @@
}
void
+_audit_log(const char *fmt, ...)
+{
+ struct audit_buffer *ab;
+ va_list ap;
+
+ ab = audit_log_start();
+ va_start(ap, fmt);
+ sbuf_vprintf(&ab->sbuf, fmt, ap);
+ va_end(ap);
+ audit_log_end(ab);
+}
+
+void
audit_log_untrustedstring(struct audit_buffer *ab, const char *s)
{
- sbuf_cat(&ab->sbuf, s);
+ sbuf_cat(&ab->sbuf, s); /* XXX - wants vis(3) support */
}
==== //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/linux-compat.h#4 (text+ko) ====
@@ -135,18 +135,15 @@
#define TUNABLE_INT_FETCH(str,var)
/* emulate linux audit support */
-extern lck_mtx_t *avc_log_lock;
+extern lck_spin_t *avc_log_lock;
struct audit_buffer;
struct audit_buffer *audit_log_start(void);
+void _audit_log(const char *, ...);
void audit_log_end(struct audit_buffer *);
void audit_log_format(struct audit_buffer *, const char *, ...);
void audit_log_untrustedstring(struct audit_buffer *, const char *);
-#define audit_log(ac, mf, af, ...) do { \
- lck_mtx_lock(avc_log_lock); \
- printf(__VA_ARGS__); \
- printf("\n"); \
- lck_mtx_unlock(avc_log_lock); \
-} while (0)
+void audit_log_process(void);
+#define audit_log(ac, mf, af, ...) _audit_log(__VA_ARGS__)
/* we don't enable the selinux netlbl support */
#define selinux_netlbl_cache_invalidate()
==== //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/sebsd.c#49 (text+ko) ====
@@ -3527,6 +3527,14 @@
return (ipc_has_perm(cred, pshmlabel, SHM__DESTROY));
}
+static void
+sebsd_thread_userret(struct thread *thread)
+{
+
+ /* Process any pending audit log records at syscall exit. */
+ audit_log_process();
+}
+
static struct mac_policy_ops sebsd_ops = {
.mpo_cred_check_label_update =sebsd_cred_check_label_update,
.mpo_cred_check_label_update_execve = sebsd_cred_check_label_update_execve,
@@ -3706,6 +3714,7 @@
.mpo_task_label_init = sebsd_cred_label_init,
.mpo_task_label_internalize = sebsd_cred_label_internalize,
.mpo_task_label_update = sebsd_task_label_update,
+ .mpo_thread_userret = sebsd_thread_userret,
.mpo_vnode_check_access = sebsd_vnode_check_access,
.mpo_vnode_check_chdir = sebsd_vnode_check_chdir,
.mpo_vnode_check_chroot = sebsd_vnode_check_chroot,
More information about the trustedbsd-cvs
mailing list