summaryrefslogtreecommitdiffstats
path: root/sys/security
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2008-11-01 21:56:45 +0000
committerrwatson <rwatson@FreeBSD.org>2008-11-01 21:56:45 +0000
commit64f6525f93aaf3375acf5c10f724b11708632ab6 (patch)
tree9450e5ce5419f4fd0ee3d5aeb995043a5e76ff69 /sys/security
parentf8873b326d65638e8a5788f7e2e2df467c54e558 (diff)
downloadFreeBSD-src-64f6525f93aaf3375acf5c10f724b11708632ab6.zip
FreeBSD-src-64f6525f93aaf3375acf5c10f724b11708632ab6.tar.gz
We only allow a partial read of the first record in an audit pipe
record queue, so move the offset field from the per-record audit_pipe_entry structure to the audit_pipe structure. Now that we support reading more than one record at a time, add a new summary field to audit_pipe, ap_qbyteslen, which tracks the total number of bytes present in a pipe, and return that (minus the current offset) via FIONREAD and kqueue's data variable for the pending byte count rather than the number of bytes remaining in only the first record. Add a number of asserts to confirm that these counts and offsets following the expected rules. MFC after: 2 months Sponsored by: Apple, Inc.
Diffstat (limited to 'sys/security')
-rw-r--r--sys/security/audit/audit_pipe.c43
1 files changed, 28 insertions, 15 deletions
diff --git a/sys/security/audit/audit_pipe.c b/sys/security/audit/audit_pipe.c
index d86123e..3abdc71 100644
--- a/sys/security/audit/audit_pipe.c
+++ b/sys/security/audit/audit_pipe.c
@@ -85,7 +85,6 @@ static MALLOC_DEFINE(M_AUDIT_PIPE_PRESELECT, "audit_pipe_presel",
struct audit_pipe_entry {
void *ape_record;
u_int ape_record_len;
- u_int ape_record_offset;
TAILQ_ENTRY(audit_pipe_entry) ape_queue;
};
@@ -138,8 +137,17 @@ struct audit_pipe {
*/
struct cv ap_cv;
+ /*
+ * Various queue-reated variables: qlen and qlimit are a count of
+ * records in the queue; qbyteslen is the number of bytes of data
+ * across all records, and qoffset is the amount read so far of the
+ * first record in the queue. The number of bytes available for
+ * reading in the queue is qbyteslen - qoffset.
+ */
u_int ap_qlen;
u_int ap_qlimit;
+ u_int ap_qbyteslen;
+ u_int ap_qoffset;
u_int64_t ap_inserts; /* Records added. */
u_int64_t ap_reads; /* Records read. */
@@ -474,11 +482,11 @@ audit_pipe_append(struct audit_pipe *ap, void *record, u_int record_len)
bcopy(record, ape->ape_record, record_len);
ape->ape_record_len = record_len;
- ape->ape_record_offset = 0;
TAILQ_INSERT_TAIL(&ap->ap_queue, ape, ape_queue);
ap->ap_inserts++;
ap->ap_qlen++;
+ ap->ap_qbyteslen += ape->ape_record_len;
selwakeuppri(&ap->ap_selinfo, PSOCK);
KNOTE_LOCKED(&ap->ap_selinfo.si_note, 0);
if (ap->ap_flags & AUDIT_PIPE_ASYNC)
@@ -603,10 +611,14 @@ audit_pipe_flush(struct audit_pipe *ap)
while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL) {
TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue);
+ ap->ap_qbyteslen -= ape->ape_record_len;
audit_pipe_entry_free(ape);
ap->ap_qlen--;
}
- KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qlen"));
+ ap->ap_qoffset = 0;
+
+ KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qbyteslen"));
+ KASSERT(ap->ap_qbyteslen == 0, ("audit_pipe_flush: ap_qbyteslen"));
}
/*
@@ -752,12 +764,7 @@ audit_pipe_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
case FIONREAD:
AUDIT_PIPE_LOCK(ap);
- if (TAILQ_FIRST(&ap->ap_queue) != NULL)
- *(int *)data =
- TAILQ_FIRST(&ap->ap_queue)->ape_record_len -
- TAILQ_FIRST(&ap->ap_queue)->ape_record_offset;
- else
- *(int *)data = 0;
+ *(int *)data = ap->ap_qbyteslen - ap->ap_qoffset;
AUDIT_PIPE_UNLOCK(ap);
error = 0;
break;
@@ -977,11 +984,13 @@ audit_pipe_read(struct cdev *dev, struct uio *uio, int flag)
uio->uio_resid > 0) {
AUDIT_PIPE_LOCK_ASSERT(ap);
- toread = MIN(ape->ape_record_len - ape->ape_record_offset,
+ KASSERT(ape->ape_record_len > ap->ap_qoffset,
+ ("audit_pipe_read: record_len > qoffset (1)"));
+ toread = MIN(ape->ape_record_len - ap->ap_qoffset,
uio->uio_resid);
AUDIT_PIPE_UNLOCK(ap);
- error = uiomove((char *)ape->ape_record +
- ape->ape_record_offset, toread, uio);
+ error = uiomove((char *)ape->ape_record + ap->ap_qoffset,
+ toread, uio);
if (error) {
AUDIT_PIPE_SX_XUNLOCK(ap);
return (error);
@@ -994,11 +1003,15 @@ audit_pipe_read(struct cdev *dev, struct uio *uio, int flag)
AUDIT_PIPE_LOCK(ap);
KASSERT(TAILQ_FIRST(&ap->ap_queue) == ape,
("audit_pipe_read: queue out of sync after uiomove"));
- ape->ape_record_offset += toread;
- if (ape->ape_record_offset == ape->ape_record_len) {
+ ap->ap_qoffset += toread;
+ KASSERT(ape->ape_record_len >= ap->ap_qoffset,
+ ("audit_pipe_read: record_len >= qoffset (2)"));
+ if (ap->ap_qoffset == ape->ape_record_len) {
TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue);
+ ap->ap_qbyteslen -= ape->ape_record_len;
audit_pipe_entry_free(ape);
ap->ap_qlen--;
+ ap->ap_qoffset = 0;
}
}
AUDIT_PIPE_UNLOCK(ap);
@@ -1071,7 +1084,7 @@ audit_pipe_kqread(struct knote *kn, long hint)
ape = TAILQ_FIRST(&ap->ap_queue);
KASSERT(ape != NULL, ("audit_pipe_kqread: ape == NULL"));
- kn->kn_data = ape->ape_record_len - ape->ape_record_offset;
+ kn->kn_data = ap->ap_qbyteslen - ap->ap_qoffset;
return (1);
} else {
kn->kn_data = 0;
OpenPOWER on IntegriCloud