PERFORCE change 113365 for review

Todd Miller millert at FreeBSD.org
Mon Jan 22 16:24:21 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=113365

Change 113365 by millert at millert_macbook on 2007/01/22 16:24:15

	We can't hold the spinlock to protect the avc log printf()
	for as long as we do since vn_getpath() may sleep.  Go back
	to allocating a new log struct for each avc audit message
	and only hold the spinlock for the duration of the printf(),
	which is safe.  As an optimization, keep a spare log struct
	to avoid allocating when we don't need to (and since we
	are not allowed to sleep).

Affected files ...

.. //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/avc/avc.c#19 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/avc/avc.h#9 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/avc/avc_audit.c#6 edit
.. //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/linux-compat.h#7 edit

Differences ...

==== //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/avc/avc.c#19 (text+ko) ====

@@ -270,10 +270,11 @@
 	lck_attr_setdefault(avc_lck_attr);	/* no lock debugging */
 
 	/* allocate avc locks */
-	avc_log_lock = lck_spin_alloc_init(avc_lck_grp, avc_lck_attr);
 	avc_lock = lck_rw_alloc_init(avc_lck_grp, avc_lck_attr);
 	notif_lock = lck_spin_alloc_init(avc_lck_grp, avc_lck_attr);
 
+	avc_audit_init(avc_lck_grp, avc_lck_attr);
+
 	for (i = 0; i < AVC_CACHE_SLOTS; i++) {
 		LIST_INIT(&avc_cache.slots[i]);
 	}
@@ -603,7 +604,7 @@
 			return;
 	}
 
-	ab = audit_log_start();
+	ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC);
 	if (!ab)
 		return;		/* audit_panic has been called */
 	audit_log_format(ab, "avc:  %s ", denied ? "denied" : "granted");

==== //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/avc/avc.h#9 (text+ko) ====

@@ -140,5 +140,7 @@
 DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats);
 #endif
 
+void avc_audit_init(lck_grp_t *avc_lck_grp, lck_attr_t *avc_lck_attr);
+
 #endif /* _SELINUX_AVC_H_ */
 

==== //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/avc/avc_audit.c#6 (text+ko) ====

@@ -38,8 +38,10 @@
 #include <kern/lock.h>
 
 #include <security/mac_policy.h>
+#include <security/mac_alloc.h>
 #include <sedarwin/linux-compat.h>
 #include <sedarwin/sebsd.h>
+#include <sedarwin/avc/avc.h>
 
 /*
  * Emulate Linux audit API.
@@ -52,16 +54,40 @@
 	struct sbuf sbuf;
 	char buf[1024];
 };
-static struct audit_buffer audit_buf;
+
+static zone_t avc_audit_zone;			/* audit buffer zone */
+static struct audit_buffer *spare_buf;		/* spare buffer */
+
+void
+avc_audit_init(lck_grp_t *avc_lck_grp, lck_attr_t *avc_lck_attr)
+{
+
+	avc_log_lock = lck_spin_alloc_init(avc_lck_grp, avc_lck_attr);
+	avc_audit_zone = mac_zinit(sizeof(struct audit_buffer),
+	            512 * sizeof(struct audit_buffer), 0, "avc_audit");
+	spare_buf = mac_zalloc(avc_audit_zone, M_WAITOK);
+}
 
 struct audit_buffer *
-audit_log_start(void)
+_audit_log_start(int flag)
 {
+	struct audit_buffer *ab = spare_buf;
 
-	lck_spin_lock(avc_log_lock);
-	sbuf_new(&audit_buf.sbuf, audit_buf.buf, sizeof(audit_buf.buf),
-	    SBUF_FIXEDLEN);
-	return (&audit_buf);
+	/* Use a free buffer if available, else alloc a new one. */
+	if (ab != NULL) {
+		if (OSCompareAndSwap((UInt32)ab, 0, (UInt32 *)&spare_buf) == 0)
+			ab = NULL;
+	}
+	if (ab == NULL) {
+		ab = mac_zalloc(avc_audit_zone, flag);
+		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);
+	return (ab);
 }
 
 void
@@ -69,9 +95,13 @@
 {
 
 	sbuf_finish(&ab->sbuf);
+	lck_spin_lock(avc_log_lock);
 	printf("\n%s\n", sbuf_data(&ab->sbuf));
-	sbuf_delete(&ab->sbuf);	/* XXX - not really needed */
 	lck_spin_unlock(avc_log_lock);
+	/* Always keep a free buffer around. */
+	if (spare_buf != NULL ||
+	    OSCompareAndSwap(0, (UInt32)ab, (UInt32 *)&spare_buf) == 0)
+		mac_zfree(avc_audit_zone, ab);
 }
 
 void
@@ -85,19 +115,6 @@
 }
 
 void
-sebsd_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)
 {
 

==== //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/linux-compat.h#7 (text+ko) ====

@@ -137,12 +137,18 @@
 /* emulate linux audit support */
 extern lck_spin_t *avc_log_lock;
 struct audit_buffer;
-struct audit_buffer *audit_log_start(void);
-void sebsd_log(const char *, ...);
+struct audit_buffer *_audit_log_start(int);
 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, ...)	sebsd_log(__VA_ARGS__)
+#define audit_log_start(ac, mf, af) _audit_log_start(mf)
+#define audit_log(ac, mf, af, ...) do {					\
+	lck_spin_lock(avc_log_lock);					\
+	printf(__VA_ARGS__);						\
+	printf("\n");							\
+	lck_spin_unlock(avc_log_lock);					\
+} while (0)
+#define sebsd_log(fmt, ...)	printf(fmt "\n", __VA_ARGS__)
 
 /* we don't enable the selinux netlbl support */
 #define	selinux_netlbl_cache_invalidate()


More information about the p4-projects mailing list