From 132c970f89a6b52e7c6d4ba5d7ff94193bf9b9c0 Mon Sep 17 00:00:00 2001 From: cperciva Date: Wed, 24 Jun 2009 05:28:09 +0000 Subject: [PATCH] MFS r192477: Fix packet length calculation in bce(4). [EN-09:02] MFS r191867: Correctly set IP packet length for TSO in fxp(4). [EN-09:03] MFS r191767: Fix a lock order reversal bug that could cause deadlock during fork(2). [EN-09:04] Submitted by: re (kensmith) Approved by: so (cperciva) Errata: FreeBSD-SA-09:02.bce Errata: FreeBSD-SA-09:03.fxp Errata: FreeBSD-SA-09:04.fork git-svn-id: svn://svn.freebsd.org/base/releng/7.2@194808 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- UPDATING | 9 ++++++++ lib/libc/stdlib/malloc.c | 48 +++++++++++++++++++++++++++++++--------- sys/conf/newvers.sh | 2 +- sys/dev/bce/if_bce.c | 3 +++ sys/dev/fxp/if_fxp.c | 3 ++- 5 files changed, 52 insertions(+), 13 deletions(-) diff --git a/UPDATING b/UPDATING index 3b4c08ae..6a921b20 100644 --- a/UPDATING +++ b/UPDATING @@ -8,6 +8,15 @@ Items affecting the ports and packages system can be found in /usr/ports/UPDATING. Please read that file before running portupgrade. +20090624: p2 FreeBSD-EN-09:02.bce, FreeBSD-EN-09:03.fxp, + FreeBSD-EN-09:04.fork + Fix packet length calculation in bce(4). [EN-09:02] + + Correctly set IP packet length for TSO in fxp(4). [EN-09:03] + + Fix a lock order reversal bug that could cause deadlock during + fork(2). [EN-09:04] + 20090610: p1 FreeBSD-SA-09:09.pipe, FreeBSD-SA-09:10.ipv6, FreeBSD-SA-09:11.ntpd Prevent integer overflow in direct pipe write code from circumventing diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c index c07e38bd..9328c27f 100644 --- a/lib/libc/stdlib/malloc.c +++ b/lib/libc/stdlib/malloc.c @@ -4715,16 +4715,41 @@ _malloc_thread_cleanup(void) void _malloc_prefork(void) { - unsigned i; + bool again; + unsigned i, j; + arena_t *larenas[narenas], *tarenas[narenas]; /* Acquire all mutexes in a safe order. */ - malloc_spin_lock(&arenas_lock); - for (i = 0; i < narenas; i++) { - if (arenas[i] != NULL) - malloc_spin_lock(&arenas[i]->lock); - } - malloc_spin_unlock(&arenas_lock); + /* + * arenas_lock must be acquired after all of the arena mutexes, in + * order to avoid potential deadlock with arena_lock_balance[_hard](). + * Since arenas_lock protects the arenas array, the following code has + * to race with arenas_extend() callers until it succeeds in locking + * all arenas before locking arenas_lock. + */ + memset(larenas, 0, sizeof(arena_t *) * narenas); + do { + again = false; + + malloc_spin_lock(&arenas_lock); + for (i = 0; i < narenas; i++) { + if (arenas[i] != larenas[i]) { + memcpy(tarenas, arenas, sizeof(arena_t *) * + narenas); + malloc_spin_unlock(&arenas_lock); + for (j = 0; j < narenas; j++) { + if (larenas[j] != tarenas[j]) { + larenas[j] = tarenas[j]; + malloc_spin_lock( + &larenas[j]->lock); + } + } + again = true; + break; + } + } + } while (again); malloc_mutex_lock(&base_mtx); @@ -4739,6 +4764,7 @@ void _malloc_postfork(void) { unsigned i; + arena_t *larenas[narenas]; /* Release all mutexes, now that fork() has completed. */ @@ -4750,12 +4776,12 @@ _malloc_postfork(void) malloc_mutex_unlock(&base_mtx); - malloc_spin_lock(&arenas_lock); + memcpy(larenas, arenas, sizeof(arena_t *) * narenas); + malloc_spin_unlock(&arenas_lock); for (i = 0; i < narenas; i++) { - if (arenas[i] != NULL) - malloc_spin_unlock(&arenas[i]->lock); + if (larenas[i] != NULL) + malloc_spin_unlock(&larenas[i]->lock); } - malloc_spin_unlock(&arenas_lock); } /* diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh index 76848bf3..22ebb11e 100644 --- a/sys/conf/newvers.sh +++ b/sys/conf/newvers.sh @@ -32,7 +32,7 @@ TYPE="FreeBSD" REVISION="7.2" -BRANCH="RELEASE-p1" +BRANCH="RELEASE-p2" if [ "X${BRANCH_OVERRIDE}" != "X" ]; then BRANCH=${BRANCH_OVERRIDE} fi diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c index 7c772e13..c725611c 100644 --- a/sys/dev/bce/if_bce.c +++ b/sys/dev/bce/if_bce.c @@ -5895,6 +5895,9 @@ bce_rx_intr(struct bce_softc *sc) /* Set the total packet length. */ m0->m_pkthdr.len = m0->m_len = pkt_len; } +#else + /* Set the total packet length. */ + m0->m_pkthdr.len = m0->m_len = pkt_len; #endif /* Remove the trailing Ethernet FCS. */ diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c index ca1a6141..39c36a87 100644 --- a/sys/dev/fxp/if_fxp.c +++ b/sys/dev/fxp/if_fxp.c @@ -1486,7 +1486,8 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head) * checksum in the first frame driver should compute it. */ ip->ip_sum = 0; - ip->ip_len = htons(ifp->if_mtu); + ip->ip_len = htons(m->m_pkthdr.tso_segsz + (ip->ip_hl << 2) + + (tcp->th_off << 2)); tcp->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, htons(IPPROTO_TCP + (tcp->th_off << 2) + m->m_pkthdr.tso_segsz)); -- 2.42.0