Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 1 Nov 2008 21:56:45 +0000 (UTC)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r184536 - head/sys/security/audit
Message-ID:  <200811012156.mA1Lujju019836@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rwatson
Date: Sat Nov  1 21:56:45 2008
New Revision: 184536
URL: http://svn.freebsd.org/changeset/base/184536

Log:
  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.

Modified:
  head/sys/security/audit/audit_pipe.c

Modified: head/sys/security/audit/audit_pipe.c
==============================================================================
--- head/sys/security/audit/audit_pipe.c	Sat Nov  1 21:49:32 2008	(r184535)
+++ head/sys/security/audit/audit_pipe.c	Sat Nov  1 21:56:45 2008	(r184536)
@@ -85,7 +85,6 @@ static MALLOC_DEFINE(M_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,
 
 	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_lon
 
 	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_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
 		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
 		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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200811012156.mA1Lujju019836>