Changeset 2296

Show
Ignore:
Timestamp:
04/26/07 23:46:12 (5 years ago)
Author:
mentor
Message:

Have athff_decap check that there is enough data in the frame for the headers it tries to use.

This patch changes the variable frame_len to an unsigned variable for safety. This variable is referenced 4 times, including declaration; all expect an unsigned values, and there are no cross-type comparisons. The code type-checks and compiles with gcc-4.1 and linux-2.6.20.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/net80211/ieee80211_input.c

    r2069 r2296  
    126126 
    127127#ifdef ATH_SUPERG_FF 
    128 static void athff_decap(struct sk_buff *); 
     128static int athff_decap(struct sk_buff *); 
    129129#endif 
    130130#ifdef USE_HEADERLEN_RESV 
     
    690690                        struct ether_header *eh_tmp; 
    691691                        struct athl2p_tunnel_hdr *ath_hdr; 
    692                         int frame_len; 
     692                        unsigned int frame_len; 
    693693 
    694694                        /* NB: assumes linear (i.e., non-fragmented) skb */ 
     
    715715                        /* move past the tunneled header, with alignment */ 
    716716                        skb_pull(skb, roundup(sizeof(struct athl2p_tunnel_hdr) - 2, 4) + 2); 
     717                        eh_tmp = (struct ether_header *)skb->data; 
     718                         
     719                        /* ether_type must be length as FF frames are always LLC/SNAP encap'd */ 
     720                        frame_len = ntohs(eh_tmp->ether_type); 
    717721 
    718722                        skb1 = skb_clone(skb, GFP_ATOMIC); /* XXX: GFP_ATOMIC is overkill? */ 
    719                         eh_tmp = (struct ether_header *)skb->data; 
    720  
    721                         /* ether_type must be length*/ 
    722                         frame_len = ntohs(eh_tmp->ether_type); 
    723  
    724                         /* we now have 802.3 MAC hdr followed by 802.2 LLC/SNAP. convert to DIX */ 
     723 
     724                        /* we now have 802.3 MAC hdr followed by 802.2 LLC/SNAP; convert to EthernetII. 
     725                         * Not that the frame is at least IEEE80211_MIN_LEN, due to the driver code. */ 
    725726                        athff_decap(skb); 
    726727 
     
    730731                        /* prepare second tunneled frame */ 
    731732                        skb_pull(skb1, roundup(sizeof(struct ether_header) + frame_len, 4)); 
    732                         eh_tmp = (struct ether_header *)skb1->data; 
    733                         frame_len = ntohs(eh_tmp->ether_type); 
    734                         athff_decap(skb1); 
     733                         
     734                        /* Fail if there is no space left for at least the necessary headers */ 
     735                        if (athff_decap(skb1)) 
     736                        { 
     737                                IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, 
     738                                                ni->ni_macaddr, "data", "%s", "Decapsulation error"); 
     739                                vap->iv_stats.is_rx_decap++; 
     740                                IEEE80211_NODE_STAT(ni, rx_decap); 
     741                                goto err; 
     742                        } 
    735743 
    736744                        /* deliver the frames */ 
     
    11531161} 
    11541162 
     1163/* This function removes the 802.11 header, including LLC/SNAP headers and  
     1164 * replaces it with an Ethernet II header. */ 
    11551165static struct sk_buff * 
    11561166ieee80211_decap(struct ieee80211vap *vap, struct sk_buff *skb, int hdrlen) 
     
    11611171        __be16 ether_type = 0; 
    11621172 
    1163         memcpy(&wh, skb->data, hdrlen); /* Only copy hdrlen over */ 
     1173        memcpy(&wh, skb->data, hdrlen); /* Make a copy of the variably sized .11 header */ 
     1174         
    11641175        llc = (struct llc *) skb_pull(skb, hdrlen); 
    11651176        if (skb->len >= LLC_SNAPFRAMELEN && 
     
    11671178            llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 && 
    11681179            llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0) { 
     1180                 
    11691181                ether_type = llc->llc_un.type_snap.ether_type; 
    11701182                skb_pull(skb, LLC_SNAPFRAMELEN); 
    11711183                llc = NULL; 
    11721184        } 
     1185 
    11731186        eh = (struct ether_header *) skb_push(skb, sizeof(struct ether_header)); 
    11741187        switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) { 
     
    11901203                break; 
    11911204        } 
     1205 
     1206        if (llc != NULL) 
     1207                eh->ether_type = ether_type; 
     1208        else 
     1209                eh->ether_type = htons(skb->len - sizeof(*eh)); 
     1210         
    11921211        if (!ALIGNED_POINTER(skb->data + sizeof(*eh), u_int32_t)) { 
    1193                 struct sk_buff *n
    1194  
    1195                 /* XXX does this always work? */ 
    1196                 n = skb_copy(skb, GFP_ATOMIC); 
     1212                struct sk_buff *tskb
     1213 
     1214                /* XXX: does this always work? */ 
     1215                tskb = skb_copy(skb, GFP_ATOMIC); 
    11971216                dev_kfree_skb(skb); 
    1198                 if (n == NULL) 
    1199                         return NULL; 
    1200                 skb = n; 
    1201                 eh = (struct ether_header *) skb->data; 
    1202         } 
    1203         if (llc != NULL) 
    1204                 eh->ether_type = htons(skb->len - sizeof(*eh)); 
    1205         else 
    1206                 eh->ether_type = ether_type; 
     1217                skb = tskb; 
     1218        } 
    12071219        return skb; 
    12081220} 
     
    36653677 
    36663678#ifdef ATH_SUPERG_FF 
    3667 static void 
     3679static int 
    36683680athff_decap(struct sk_buff *skb) 
    36693681{ 
    36703682        struct ether_header eh_src, *eh_dst; 
    36713683        struct llc *llc; 
     3684 
     3685        if (skb->len < (sizeof(struct ether_header) + LLC_SNAPFRAMELEN)) 
     3686                return -1; 
    36723687 
    36733688        memcpy(&eh_src, skb->data, sizeof(struct ether_header)); 
     
    36783693        eh_dst = (struct ether_header *) skb_push(skb, sizeof(struct ether_header)); 
    36793694        memcpy(eh_dst, &eh_src, sizeof(struct ether_header)); 
     3695 
     3696        return 0; 
    36803697} 
    36813698#endif