>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:
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to