From owner-svn-src-user@FreeBSD.ORG Fri Oct 31 18:40:35 2008 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D4E911065670; Fri, 31 Oct 2008 18:40:35 +0000 (UTC) (envelope-from imp@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id C1F218FC22; Fri, 31 Oct 2008 18:40:35 +0000 (UTC) (envelope-from imp@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9VIeZbV087591; Fri, 31 Oct 2008 18:40:35 GMT (envelope-from imp@svn.freebsd.org) Received: (from imp@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9VIeZ6F087584; Fri, 31 Oct 2008 18:40:35 GMT (envelope-from imp@svn.freebsd.org) Message-Id: <200810311840.m9VIeZ6F087584@svn.freebsd.org> From: Warner Losh Date: Fri, 31 Oct 2008 18:40:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184514 - in user/imp/newcard/sys: . amd64/amd64 compat/linux geom i386/i386 security/audit security/mac security/mac_bsdextended X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 31 Oct 2008 18:40:35 -0000 Author: imp Date: Fri Oct 31 18:40:35 2008 New Revision: 184514 URL: http://svn.freebsd.org/changeset/base/184514 Log: Merging r184495 through r184513 Modified: user/imp/newcard/sys/ (props changed) user/imp/newcard/sys/amd64/amd64/dump_machdep.c user/imp/newcard/sys/amd64/amd64/minidump_machdep.c user/imp/newcard/sys/compat/linux/linux_emul.c user/imp/newcard/sys/geom/geom_disk.c user/imp/newcard/sys/i386/i386/dump_machdep.c user/imp/newcard/sys/i386/i386/minidump_machdep.c user/imp/newcard/sys/security/audit/audit_pipe.c user/imp/newcard/sys/security/mac/mac_cred.c (props changed) user/imp/newcard/sys/security/mac_bsdextended/ugidfw_system.c (props changed) user/imp/newcard/sys/security/mac_bsdextended/ugidfw_vnode.c (props changed) Modified: user/imp/newcard/sys/amd64/amd64/dump_machdep.c ============================================================================== --- user/imp/newcard/sys/amd64/amd64/dump_machdep.c Fri Oct 31 18:27:30 2008 (r184513) +++ user/imp/newcard/sys/amd64/amd64/dump_machdep.c Fri Oct 31 18:40:35 2008 (r184514) @@ -165,7 +165,7 @@ cb_dumpdata(struct md_pa *mdp, int seqnr va = 0; pgs = mdp->md_size / PAGE_SIZE; pa = mdp->md_start; - maxdumppgs = di->maxiosize / PAGE_SIZE; + maxdumppgs = min(di->maxiosize / PAGE_SIZE, MAXDUMPPGS); if (maxdumppgs == 0) /* seatbelt */ maxdumppgs = 1; Modified: user/imp/newcard/sys/amd64/amd64/minidump_machdep.c ============================================================================== --- user/imp/newcard/sys/amd64/amd64/minidump_machdep.c Fri Oct 31 18:27:30 2008 (r184513) +++ user/imp/newcard/sys/amd64/amd64/minidump_machdep.c Fri Oct 31 18:40:35 2008 (r184514) @@ -104,7 +104,7 @@ blk_write(struct dumperinfo *di, char *p int error, i, c; u_int maxdumpsz; - maxdumpsz = di->maxiosize; + maxdumpsz = min(di->maxiosize, MAXDUMPPGS * PAGE_SIZE); if (maxdumpsz == 0) /* seatbelt */ maxdumpsz = PAGE_SIZE; error = 0; Modified: user/imp/newcard/sys/compat/linux/linux_emul.c ============================================================================== --- user/imp/newcard/sys/compat/linux/linux_emul.c Fri Oct 31 18:27:30 2008 (r184513) +++ user/imp/newcard/sys/compat/linux/linux_emul.c Fri Oct 31 18:40:35 2008 (r184514) @@ -235,11 +235,11 @@ linux_proc_exit(void *arg __unused, stru continue; em = em_find(q, EMUL_DOLOCK); KASSERT(em != NULL, ("linux_reparent: emuldata not found: %i\n", q->p_pid)); - if (em->pdeath_signal != 0) { - PROC_LOCK(q); + PROC_LOCK(q); + if ((q->p_flag & P_WEXIT) == 0 && em->pdeath_signal != 0) { psignal(q, em->pdeath_signal); - PROC_UNLOCK(q); } + PROC_UNLOCK(q); EMUL_UNLOCK(&emul_lock); } sx_xunlock(&proctree_lock); Modified: user/imp/newcard/sys/geom/geom_disk.c ============================================================================== --- user/imp/newcard/sys/geom/geom_disk.c Fri Oct 31 18:27:30 2008 (r184513) +++ user/imp/newcard/sys/geom/geom_disk.c Fri Oct 31 18:40:35 2008 (r184514) @@ -179,7 +179,7 @@ g_disk_kerneldump(struct bio *bp, struct di.dumper = dp->d_dump; di.priv = dp; di.blocksize = dp->d_sectorsize; - di.maxiosize = min(dp->d_maxsize, MAXDUMPPGS * PAGE_SIZE); + di.maxiosize = dp->d_maxsize; di.mediaoffset = gkd->offset; if ((gkd->offset + gkd->length) > dp->d_mediasize) gkd->length = dp->d_mediasize - gkd->offset; Modified: user/imp/newcard/sys/i386/i386/dump_machdep.c ============================================================================== --- user/imp/newcard/sys/i386/i386/dump_machdep.c Fri Oct 31 18:27:30 2008 (r184513) +++ user/imp/newcard/sys/i386/i386/dump_machdep.c Fri Oct 31 18:40:35 2008 (r184514) @@ -165,7 +165,7 @@ cb_dumpdata(struct md_pa *mdp, int seqnr va = 0; pgs = mdp->md_size / PAGE_SIZE; pa = mdp->md_start; - maxdumppgs = di->maxiosize / PAGE_SIZE; + maxdumppgs = min(di->maxiosize / PAGE_SIZE, MAXDUMPPGS); if (maxdumppgs == 0) /* seatbelt */ maxdumppgs = 1; Modified: user/imp/newcard/sys/i386/i386/minidump_machdep.c ============================================================================== --- user/imp/newcard/sys/i386/i386/minidump_machdep.c Fri Oct 31 18:27:30 2008 (r184513) +++ user/imp/newcard/sys/i386/i386/minidump_machdep.c Fri Oct 31 18:40:35 2008 (r184514) @@ -102,7 +102,7 @@ blk_write(struct dumperinfo *di, char *p int error, i, c; u_int maxdumpsz; - maxdumpsz = di->maxiosize; + maxdumpsz = min(di->maxiosize, MAXDUMPPGS * PAGE_SIZE); if (maxdumpsz == 0) /* seatbelt */ maxdumpsz = PAGE_SIZE; error = 0; Modified: user/imp/newcard/sys/security/audit/audit_pipe.c ============================================================================== --- user/imp/newcard/sys/security/audit/audit_pipe.c Fri Oct 31 18:27:30 2008 (r184513) +++ user/imp/newcard/sys/security/audit/audit_pipe.c Fri Oct 31 18:40:35 2008 (r184514) @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -84,6 +85,7 @@ 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; }; @@ -120,7 +122,15 @@ struct audit_pipe { /* * Per-pipe mutex protecting most fields in this data structure. */ - struct mtx ap_lock; + struct mtx ap_mtx; + + /* + * Per-pipe sleep lock serializing user-generated reads and flushes. + * uiomove() is called to copy out the current head record's data + * while the record remains in the queue, so we prevent other threads + * from removing it using this lock. + */ + struct sx ap_sx; /* * Condition variable to signal when data has been delivered to a @@ -134,7 +144,6 @@ struct audit_pipe { u_int64_t ap_inserts; /* Records added. */ u_int64_t ap_reads; /* Records read. */ u_int64_t ap_drops; /* Records dropped. */ - u_int64_t ap_truncates; /* Records too long. */ /* * Fields relating to pipe interest: global masks for unmatched @@ -147,7 +156,9 @@ struct audit_pipe { TAILQ_HEAD(, audit_pipe_preselect) ap_preselect_list; /* - * Current pending record list. + * Current pending record list. Protected by a combination of ap_mtx + * and ap_sx. Note particularly that *both* locks are required to + * remove a record from the head of the queue, as an in-progress read * may sleep while copying and therefore cannot hold ap_mtx. */ TAILQ_HEAD(, audit_pipe_entry) ap_queue; @@ -157,13 +168,19 @@ struct audit_pipe { TAILQ_ENTRY(audit_pipe) ap_list; }; -#define AUDIT_PIPE_LOCK(ap) mtx_lock(&(ap)->ap_lock) -#define AUDIT_PIPE_LOCK_ASSERT(ap) mtx_assert(&(ap)->ap_lock, MA_OWNED) -#define AUDIT_PIPE_LOCK_DESTROY(ap) mtx_destroy(&(ap)->ap_lock) -#define AUDIT_PIPE_LOCK_INIT(ap) mtx_init(&(ap)->ap_lock, \ - "audit_pipe_lock", NULL, MTX_DEF) -#define AUDIT_PIPE_UNLOCK(ap) mtx_unlock(&(ap)->ap_lock) -#define AUDIT_PIPE_MTX(ap) (&(ap)->ap_lock) +#define AUDIT_PIPE_LOCK(ap) mtx_lock(&(ap)->ap_mtx) +#define AUDIT_PIPE_LOCK_ASSERT(ap) mtx_assert(&(ap)->ap_mtx, MA_OWNED) +#define AUDIT_PIPE_LOCK_DESTROY(ap) mtx_destroy(&(ap)->ap_mtx) +#define AUDIT_PIPE_LOCK_INIT(ap) mtx_init(&(ap)->ap_mtx, \ + "audit_pipe_mtx", NULL, MTX_DEF) +#define AUDIT_PIPE_UNLOCK(ap) mtx_unlock(&(ap)->ap_mtx) +#define AUDIT_PIPE_MTX(ap) (&(ap)->ap_mtx) + +#define AUDIT_PIPE_SX_LOCK_DESTROY(ap) sx_destroy(&(ap)->ap_sx) +#define AUDIT_PIPE_SX_LOCK_INIT(ap) sx_init(&(ap)->ap_sx, "audit_pipe_sx") +#define AUDIT_PIPE_SX_XLOCK_ASSERT(ap) sx_assert(&(ap)->ap_sx, SA_XLOCKED) +#define AUDIT_PIPE_SX_XLOCK_SIG(ap) sx_xlock_sig(&(ap)->ap_sx) +#define AUDIT_PIPE_SX_XUNLOCK(ap) sx_xunlock(&(ap)->ap_sx) /* * Global list of audit pipes, rwlock to protect it. Individual record @@ -457,6 +474,7 @@ 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++; @@ -530,26 +548,6 @@ audit_pipe_submit_user(void *record, u_i } /* - * Pop the next record off of an audit pipe. - */ -static struct audit_pipe_entry * -audit_pipe_pop(struct audit_pipe *ap) -{ - struct audit_pipe_entry *ape; - - AUDIT_PIPE_LOCK_ASSERT(ap); - - ape = TAILQ_FIRST(&ap->ap_queue); - KASSERT((ape == NULL && ap->ap_qlen == 0) || - (ape != NULL && ap->ap_qlen != 0), ("audit_pipe_pop: qlen")); - if (ape == NULL) - return (NULL); - TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); - ap->ap_qlen--; - return (ape); -} - -/* * Allocate a new audit pipe. Connects the pipe, on success, to the global * list and updates statistics. */ @@ -568,6 +566,7 @@ audit_pipe_alloc(void) knlist_init(&ap->ap_selinfo.si_note, AUDIT_PIPE_MTX(ap), NULL, NULL, NULL); AUDIT_PIPE_LOCK_INIT(ap); + AUDIT_PIPE_SX_LOCK_INIT(ap); cv_init(&ap->ap_cv, "audit_pipe"); /* @@ -626,6 +625,7 @@ audit_pipe_free(struct audit_pipe *ap) audit_pipe_preselect_flush_locked(ap); audit_pipe_flush(ap); cv_destroy(&ap->ap_cv); + AUDIT_PIPE_SX_LOCK_DESTROY(ap); AUDIT_PIPE_LOCK_DESTROY(ap); knlist_destroy(&ap->ap_selinfo.si_note); TAILQ_REMOVE(&audit_pipe_list, ap, ap_list); @@ -754,7 +754,8 @@ audit_pipe_ioctl(struct cdev *dev, u_lon 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_len - + TAILQ_FIRST(&ap->ap_queue)->ape_record_offset; else *(int *)data = 0; AUDIT_PIPE_UNLOCK(ap); @@ -888,9 +889,12 @@ audit_pipe_ioctl(struct cdev *dev, u_lon break; case AUDITPIPE_FLUSH: + if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) + return (EINTR); AUDIT_PIPE_LOCK(ap); audit_pipe_flush(ap); AUDIT_PIPE_UNLOCK(ap); + AUDIT_PIPE_SX_XUNLOCK(ap); error = 0; break; @@ -915,7 +919,7 @@ audit_pipe_ioctl(struct cdev *dev, u_lon break; case AUDITPIPE_GET_TRUNCATES: - *(u_int *)data = ap->ap_truncates; + *(u_int *)data = 0; error = 0; break; @@ -945,45 +949,68 @@ audit_pipe_read(struct cdev *dev, struct { struct audit_pipe_entry *ape; struct audit_pipe *ap; + u_int toread; int error; ap = dev->si_drv1; KASSERT(ap != NULL, ("audit_pipe_read: ap == NULL")); + /* + * We hold an sx(9) lock over read and flush because we rely on the + * stability of a record in the queue during uiomove(9). + */ + if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) + return (EINTR); AUDIT_PIPE_LOCK(ap); - do { - /* - * Wait for a record that fits into the read buffer, dropping - * records that would be truncated if actually passed to the - * process. This helps maintain the discreet record read - * interface. - */ - while ((ape = audit_pipe_pop(ap)) == NULL) { - if (ap->ap_flags & AUDIT_PIPE_NBIO) { - AUDIT_PIPE_UNLOCK(ap); - return (EAGAIN); - } - error = cv_wait_sig(&ap->ap_cv, AUDIT_PIPE_MTX(ap)); - if (error) { - AUDIT_PIPE_UNLOCK(ap); - return (error); - } + while (TAILQ_EMPTY(&ap->ap_queue)) { + if (ap->ap_flags & AUDIT_PIPE_NBIO) { + AUDIT_PIPE_UNLOCK(ap); + AUDIT_PIPE_SX_XUNLOCK(ap); + return (EAGAIN); } - if (ape->ape_record_len <= uio->uio_resid) - break; - audit_pipe_entry_free(ape); - ap->ap_truncates++; - } while (1); + error = cv_wait_sig(&ap->ap_cv, AUDIT_PIPE_MTX(ap)); + if (error) { + AUDIT_PIPE_UNLOCK(ap); + AUDIT_PIPE_SX_XUNLOCK(ap); + return (error); + } + } + + /* + * Copy as many remaining bytes from the current record to userspace + * as we can. + * + * Note: we rely on the SX lock to maintain ape's stability here. + */ ap->ap_reads++; + ape = TAILQ_FIRST(&ap->ap_queue); + toread = MIN(ape->ape_record_len - ape->ape_record_offset, + uio->uio_resid); AUDIT_PIPE_UNLOCK(ap); + error = uiomove((char *)ape->ape_record + ape->ape_record_offset, + toread, uio); + if (error) { + AUDIT_PIPE_SX_XUNLOCK(ap); + return (error); + } /* - * Now read record to user space memory. Even if the read is short, - * we abandon the remainder of the record, supporting only discreet - * record reads. + * If the copy succeeded, update book-keeping, and if no bytes remain + * in the current record, free it. */ - error = uiomove(ape->ape_record, ape->ape_record_len, uio); - audit_pipe_entry_free(ape); + 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) { + TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); + ap->ap_qlen--; + } else + ape = NULL; + AUDIT_PIPE_UNLOCK(ap); + AUDIT_PIPE_SX_XUNLOCK(ap); + if (ape != NULL) + audit_pipe_entry_free(ape); return (error); } @@ -1052,7 +1079,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; + kn->kn_data = ape->ape_record_len - ape->ape_record_offset; return (1); } else { kn->kn_data = 0;