Author: rwatson
Date: Wed Feb 25 13:21:28 2009
New Revision: 189035
URL: http://svn.freebsd.org/changeset/base/189035

Log:
  Merge r184536 from head to stable/7:
  
    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.
  
    Sponsored by: Apple, Inc.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/security/audit/audit_pipe.c

Modified: stable/7/sys/security/audit/audit_pipe.c
==============================================================================
--- stable/7/sys/security/audit/audit_pipe.c    Wed Feb 25 13:17:46 2009        
(r189034)
+++ stable/7/sys/security/audit/audit_pipe.c    Wed Feb 25 13:21:28 2009        
(r189035)
@@ -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. */
@@ -478,11 +486,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)
@@ -607,10 +615,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"));
 }
 
 /*
@@ -756,12 +768,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;
@@ -981,11 +988,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);
@@ -998,11 +1007,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);
@@ -1075,7 +1088,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;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to