PERFORCE change 91247 for review
Robert Watson
rwatson at FreeBSD.org
Mon Feb 6 18:25:46 GMT 2006
http://perforce.freebsd.org/chv.cgi?CH=91247
Change 91247 by rwatson at rwatson_zoo on 2006/02/06 18:25:03
Add support for asynchronous I/O (sigio), non-blocking I/O, and
select()/poll() to the audit pipe psuedo-device.
Rename the audit pipe entry memory type so it is a bit shorter and
aligns more nicely in vmstat -m output.
Don't need to use audit_pipe_mtx to protect dev->si_drv1
references while the device is open, only during open, close, and
when accessing fields in struct audit_pipe.
Affected files ...
.. //depot/projects/trustedbsd/audit3/sys/security/audit/audit_pipe.c#5 edit
Differences ...
==== //depot/projects/trustedbsd/audit3/sys/security/audit/audit_pipe.c#5 (text+ko) ====
@@ -32,11 +32,18 @@
#include <sys/condvar.h>
#include <sys/conf.h>
#include <sys/eventhandler.h>
+#include <sys/filio.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
+#include <sys/poll.h>
+#include <sys/proc.h>
#include <sys/queue.h>
+#include <sys/selinfo.h>
+#include <sys/sigio.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
#include <sys/systm.h>
#include <sys/uio.h>
@@ -54,7 +61,7 @@
* Memory types.
*/
static MALLOC_DEFINE(M_AUDIT_PIPE, "audit_pipe", "Audit pipes");
-static MALLOC_DEFINE(M_AUDIT_PIPE_ENTRY, "audit_pipe_entry",
+static MALLOC_DEFINE(M_AUDIT_PIPE_ENTRY, "audit_pipeent",
"Audit pipe entries and buffers");
/*
@@ -76,8 +83,14 @@
* Description of an individual audit_pipe. Consists largely of a bounded
* length queue.
*/
+#define AUDIT_PIPE_ASYNC 0x00000001
+#define AUDIT_PIPE_NBIO 0x00000002
struct audit_pipe {
int ap_open; /* Device open? */
+ u_int ap_flags;
+
+ struct selinfo ap_selinfo;
+ struct sigio *ap_sigio;
u_int ap_qlen;
u_int ap_qlimit;
@@ -192,6 +205,9 @@
TAILQ_INSERT_TAIL(&ap->ap_queue, ape, ape_queue);
ap->ap_inserts++;
ap->ap_qlen++;
+ selwakeuppri(&ap->ap_selinfo, PSOCK);
+ if (ap->ap_flags & AUDIT_PIPE_ASYNC)
+ pgsigio(&ap->ap_sigio, SIGIO, 0);
}
/*
@@ -314,8 +330,6 @@
* Audit pipe open method. Explicit suser check isn't used as this allows
* file permissions on the special device to be used to grant audit review
* access.
- *
- * XXXRW: SIGIO/select/etc support?
*/
static int
audit_pipe_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
@@ -331,12 +345,14 @@
return (ENOMEM);
}
dev->si_drv1 = ap;
- } else if (ap->ap_open) {
+ } else {
+ KASSERT(ap->ap_open, ("audit_pipe_open: ap && !ap_open"));
mtx_unlock(&audit_pipe_mtx);
return (EBUSY);
}
- ap->ap_open++;
+ ap->ap_open = 1;
mtx_unlock(&audit_pipe_mtx);
+ fsetown(td->td_proc->p_pid, &ap->ap_sigio);
return (0);
}
@@ -348,12 +364,12 @@
{
struct audit_pipe *ap;
- mtx_lock(&audit_pipe_mtx);
ap = dev->si_drv1;
KASSERT(ap != NULL, ("audit_pipe_close: ap == NULL"));
KASSERT(ap->ap_open, ("audit_pipe_close: !ap_open"));
- ap->ap_open--;
- KASSERT(ap->ap_open == 0, ("audit_pipe_close: ap_open"));
+ funsetown(&ap->ap_sigio);
+ mtx_lock(&audit_pipe_mtx);
+ ap->ap_open = 0;
audit_pipe_free(ap);
dev->si_drv1 = NULL;
mtx_unlock(&audit_pipe_mtx);
@@ -366,27 +382,65 @@
*
* Would be desirable to support filtering, although perhaps something simple
* like an event mask, as opposed to something complicated like BPF.
- *
- * XXXRW: SIGIO/select/etc support?
*/
static int
audit_pipe_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
struct thread *td)
{
struct audit_pipe *ap;
+ int error;
- mtx_lock(&audit_pipe_mtx);
ap = dev->si_drv1;
KASSERT(ap != NULL, ("audit_pipe_ioctl: ap == NULL"));
- mtx_unlock(&audit_pipe_mtx);
- return (ENOTTY);
+ switch (cmd) {
+ case FIONBIO:
+ mtx_lock(&audit_pipe_mtx);
+ if (*(int *)data)
+ ap->ap_flags |= AUDIT_PIPE_NBIO;
+ else
+ ap->ap_flags &= ~AUDIT_PIPE_NBIO;
+ mtx_unlock(&audit_pipe_mtx);
+ error = 0;
+ break;
+
+ case FIONREAD:
+ mtx_lock(&audit_pipe_mtx);
+ if (TAILQ_FIRST(&ap->ap_queue) != NULL)
+ *(int *)data =
+ TAILQ_FIRST(&ap->ap_queue)->ape_record_len;
+ else
+ *(int *)data = 0;
+ mtx_unlock(&audit_pipe_mtx);
+ error = 0;
+ break;
+
+ case FIOASYNC:
+ mtx_lock(&audit_pipe_mtx);
+ if (*(int *)data)
+ ap->ap_flags |= AUDIT_PIPE_ASYNC;
+ else
+ ap->ap_flags &= ~AUDIT_PIPE_ASYNC;
+ mtx_unlock(&audit_pipe_mtx);
+ error = 0;
+ break;
+
+ case FIOSETOWN:
+ error = fsetown(*(int *)data, &ap->ap_sigio);
+ break;
+
+ case FIOGETOWN:
+ *(int *)data = fgetown(&ap->ap_sigio);
+ error = 0;
+
+ default:
+ error = ENOTTY;
+ }
+ return (error);
}
/*
* Audit pipe read. Pull one record off the queue and copy to user space.
* On error, the record is dropped.
- *
- * XXXRW: SIGIO/select/etc support?
*/
static int
audit_pipe_read(struct cdev *dev, struct uio *uio, int flag)
@@ -395,10 +449,9 @@
struct audit_pipe *ap;
int error;
- mtx_lock(&audit_pipe_mtx);
ap = dev->si_drv1;
KASSERT(ap != NULL, ("audit_pipe_read: ap == NULL"));
- ape = audit_pipe_pop(ap);
+ mtx_lock(&audit_pipe_mtx);
do {
/*
* Wait for a record that fits into the read buffer, dropping
@@ -407,6 +460,10 @@
* interface.
*/
while ((ape = audit_pipe_pop(ap)) == NULL) {
+ if (ap->ap_flags & AUDIT_PIPE_NBIO) {
+ mtx_unlock(&audit_pipe_mtx);
+ return (EAGAIN);
+ }
error = cv_wait_sig(&audit_pipe_cv, &audit_pipe_mtx);
if (error) {
mtx_unlock(&audit_pipe_mtx);
@@ -425,22 +482,32 @@
* we abandon the remainder of the record, supporting only discreet
* record reads.
*/
- if (ape != NULL) {
- error = uiomove(ape->ape_record, ape->ape_record_len, uio);
- audit_pipe_entry_free(ape);
- } else
- error = 0;
+ error = uiomove(ape->ape_record, ape->ape_record_len, uio);
+ audit_pipe_entry_free(ape);
return (error);
}
/*
- * Audit pipe poll. Not currently supported.
+ * Audit pipe poll.
*/
static int
audit_pipe_poll(struct cdev *dev, int events, struct thread *td)
{
+ struct audit_pipe *ap;
+ int revents;
- return (EOPNOTSUPP);
+ revents = 0;
+ ap = dev->si_drv1;
+ KASSERT(ap != NULL, ("audit_pipe_poll: ap == NULL"));
+ if (events & (POLLIN | POLLRDNORM)) {
+ mtx_lock(&audit_pipe_mtx);
+ if (TAILQ_FIRST(&ap->ap_queue) != NULL)
+ revents |= events & (POLLIN | POLLRDNORM);
+ else
+ selrecord(td, &ap->ap_selinfo);
+ mtx_unlock(&audit_pipe_mtx);
+ }
+ return (revents);
}
/*
To Unsubscribe: send mail to majordomo at trustedbsd.org
with "unsubscribe trustedbsd-cvs" in the body of the message
More information about the trustedbsd-cvs
mailing list