From owner-freebsd-bugs@FreeBSD.ORG Wed Apr 4 15:00:10 2012 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id E76551065674 for ; Wed, 4 Apr 2012 15:00:10 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 2FB918FC16 for ; Wed, 4 Apr 2012 15:00:10 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.5/8.14.5) with ESMTP id q34F0AU5098079 for ; Wed, 4 Apr 2012 15:00:10 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.5/8.14.5/Submit) id q34F0A4f098078; Wed, 4 Apr 2012 15:00:10 GMT (envelope-from gnats) Resent-Date: Wed, 4 Apr 2012 15:00:10 GMT Resent-Message-Id: <201204041500.q34F0A4f098078@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Andrew Atrens Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 48DCE1065672 for ; Wed, 4 Apr 2012 14:59:52 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22]) by mx1.freebsd.org (Postfix) with ESMTP id 1AF9D8FC08 for ; Wed, 4 Apr 2012 14:59:52 +0000 (UTC) Received: from red.freebsd.org (localhost [127.0.0.1]) by red.freebsd.org (8.14.4/8.14.4) with ESMTP id q34ExpsM042991 for ; Wed, 4 Apr 2012 14:59:51 GMT (envelope-from nobody@red.freebsd.org) Received: (from nobody@localhost) by red.freebsd.org (8.14.4/8.14.4/Submit) id q34ExpRS042990; Wed, 4 Apr 2012 14:59:51 GMT (envelope-from nobody) Message-Id: <201204041459.q34ExpRS042990@red.freebsd.org> Date: Wed, 4 Apr 2012 14:59:51 GMT From: Andrew Atrens To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/166641: mbuf/cluster leak in AP mode in 802.11 power saving support X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 04 Apr 2012 15:00:11 -0000 >Number: 166641 >Category: kern >Synopsis: mbuf/cluster leak in AP mode in 802.11 power saving support >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Apr 04 15:00:09 UTC 2012 >Closed-Date: >Last-Modified: >Originator: Andrew Atrens >Release: trunk >Organization: >Environment: generic - will affect all supported platforms. >Description: If one has a FreeBSD AP and clients (like iPods and macbooks) that are constantly going into/out-of power saving mode, the AP will leak mbufs for fragmented packets added to the sleeping node's power saving queue. Eventually (depending on activity, available kvm) the AP will run out of mbuf/clusters and become incommunicado. --Andrew >How-To-Repeat: See above. >Fix: Here's my patch - $ svn diff ieee80211_power.c Index: ieee80211_power.c =================================================================== --- ieee80211_power.c (revision 233759) +++ ieee80211_power.c (working copy) @@ -323,6 +323,7 @@ struct ieee80211com *ic = ni->ni_ic; struct ieee80211_psq_head *qhead; int qlen, age; + struct mbuf *m0; IEEE80211_PSQ_LOCK(psq); if (psq->psq_len >= psq->psq_maxlen) { @@ -336,7 +337,9 @@ ieee80211_dump_pkt(ni->ni_ic, mtod(m, caddr_t), m->m_len, -1, -1); #endif - psq_mfree(m); + for (m0 = m; (m0=m) != NULL ; m = m->m_nextpkt) { + psq_mfree(m0); + } return ENOSPC; } /* @@ -386,10 +389,25 @@ } KASSERT(age >= 0, ("age %d", age)); M_AGE_SET(m, age); qhead->tail = m; qhead->len++; qlen = ++(psq->psq_len); + + /* + * We could have a fragmented frame that has multiple packets. + * In that case we want to enqueue them all. + * + * Make sure they're all tagged with the same age. + */ + + while ((m = m->m_nextpkt)) { + M_AGE_SET(m, age); + qhead->len++; + qlen = ++(psq->psq_len); + if (!m->m_nextpkt) + qhead->tail = m; + } + IEEE80211_PSQ_UNLOCK(psq); IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni, >Release-Note: >Audit-Trail: >Unformatted: