int CVE_2007_4997_linux2_6_16_ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, struct CVE_2007_4997_linux2_6_16_ieee80211_rx_stats *rx_stats) { struct net_device *dev = ieee->dev; struct ieee80211_hdr_4addr *hdr; size_t hdrlen; u16 fc, type, stype, sc; struct net_device_stats *stats; unsigned int frag; u8 *payload; u16 ethertype; #ifdef NOT_YET struct net_device *wds = NULL; struct sk_buff *skb2 = NULL; struct net_device *wds = NULL; int frame_authorized = 0; int from_assoc_ap = 0; void *sta = NULL; #endif u8 dst[ETH_ALEN]; u8 src[ETH_ALEN]; struct ieee80211_crypt_data *crypt = NULL; int keyidx = 0; int can_be_decrypted = 0; hdr = (struct ieee80211_hdr_4addr *)skb->data; stats = &ieee->stats; if (skb->len < 10) { printk(KERN_INFO "%s: SKB length < 10\n", dev->name); goto rx_dropped; } fc = le16_to_cpu(hdr->frame_ctl); type = WLAN_FC_GET_TYPE(fc); stype = WLAN_FC_GET_STYPE(fc); sc = le16_to_cpu(hdr->seq_ctl); frag = WLAN_GET_SEQ_FRAG(sc); hdrlen = ieee80211_get_hdrlen(fc); /* Put this code here so that we avoid duplicating it in all * Rx paths. - Jean II */ #ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ #ifdef CONFIG_NET_RADIO /* If spy monitoring on */ if (ieee->spy_data.spy_number > 0) { struct iw_quality wstats; wstats.updated = 0; if (rx_stats->mask & IEEE80211_STATMASK_RSSI) { wstats.level = rx_stats->rssi; wstats.updated |= IW_QUAL_LEVEL_UPDATED; } else wstats.updated |= IW_QUAL_LEVEL_INVALID; if (rx_stats->mask & IEEE80211_STATMASK_NOISE) { wstats.noise = rx_stats->noise; wstats.updated |= IW_QUAL_NOISE_UPDATED; } else wstats.updated |= IW_QUAL_NOISE_INVALID; if (rx_stats->mask & IEEE80211_STATMASK_SIGNAL) { wstats.qual = rx_stats->signal; wstats.updated |= IW_QUAL_QUAL_UPDATED; } else wstats.updated |= IW_QUAL_QUAL_INVALID; /* Update spy records */ wireless_spy_update(ieee->dev, hdr->addr2, &wstats); } #endif /* CONFIG_NET_RADIO */ #endif /* IW_WIRELESS_SPY */ #ifdef NOT_YET hostap_update_rx_stats(local->ap, hdr, rx_stats); #endif if (ieee->iw_mode == IW_MODE_MONITOR) { ieee80211_monitor_rx(ieee, skb, rx_stats); stats->rx_packets++; stats->rx_bytes += skb->len; return 1; } can_be_decrypted = (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr2)) ? ieee->host_mc_decrypt : ieee->host_decrypt; if (can_be_decrypted) { int idx = 0; if (skb->len >= hdrlen + 3) { /* Top two-bits of byte 3 are the key index */ idx = skb->data[hdrlen + 3] >> 6; } /* ieee->crypt[] is WEP_KEY (4) in length. Given that idx * is only allowed 2-bits of storage, no value of idx can * be provided via above code that would result in idx * being out of range */ crypt = ieee->crypt[idx]; #ifdef NOT_YET sta = NULL; /* Use station specific key to override default keys if the * receiver address is a unicast address ("individual RA"). If * bcrx_sta_key parameter is set, station specific key is used * even with broad/multicast targets (this is against IEEE * 802.11, but makes it easier to use different keys with * stations that do not support WEP key mapping). */ if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key) (void)hostap_handle_sta_crypto(local, hdr, &crypt, &sta); #endif /* allow NULL decrypt to indicate an station specific override * for default encryption */ if (crypt && (crypt->ops == NULL || crypt->ops->decrypt_mpdu == NULL)) crypt = NULL; if (!crypt && (fc & IEEE80211_FCTL_PROTECTED)) { /* This seems to be triggered by some (multicast?) * frames from other than current BSS, so just drop the * frames silently instead of filling system log with * these reports. */ IEEE80211_DEBUG_DROP("Decryption failed (not set)" " (SA=" MAC_FMT ")\n", MAC_ARG(hdr->addr2)); ieee->ieee_stats.rx_discards_undecryptable++; goto rx_dropped; } }
int islpci_eth_receive(islpci_private *priv) { struct net_device *ndev = priv->ndev; isl38xx_control_block *control_block = priv->control_block; struct sk_buff *skb; u16 size; u32 index, offset; unsigned char *src; int discard = 0; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_receive \n"); #endif /* the device has written an Ethernet frame in the data area * of the sk_buff without updating the structure, do it now */ index = priv->free_data_rx % ISL38XX_CB_RX_QSIZE; size = le16_to_cpu(control_block->rx_data_low[index].size); skb = priv->data_low_rx[index]; offset = ((unsigned long) le32_to_cpu(control_block->rx_data_low[index].address) - (unsigned long) skb->data) & 3; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "frq->addr %x skb->data %p skb->len %u offset %u truesize %u\n ", control_block->rx_data_low[priv->free_data_rx].address, skb->data, skb->len, offset, skb->truesize); #endif /* delete the streaming DMA mapping before processing the skb */ pci_unmap_single(priv->pdev, priv->pci_map_rx_address[index], MAX_FRAGMENT_SIZE_RX + 2, PCI_DMA_FROMDEVICE); /* update the skb structure and allign the buffer */ skb_put(skb, size); if (offset) { /* shift the buffer allocation offset bytes to get the right frame */ skb_pull(skb, 2); skb_put(skb, 2); } #if VERBOSE > SHOW_ERROR_MESSAGES /* display the buffer contents for debugging */ DEBUG(SHOW_BUFFER_CONTENTS, "\nrx %p ", skb->data); display_buffer((char *) skb->data, skb->len); #endif /* check whether WDS is enabled and whether the data frame is a WDS frame */ if (init_wds) { /* WDS enabled, check for the wds address on the first 6 bytes of the buffer */ src = skb->data + 6; memmove(skb->data, src, skb->len - 6); skb_trim(skb, skb->len - 6); } #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Fragment size %i in skb at %p\n", size, skb); DEBUG(SHOW_TRACING, "Skb data at %p, length %i\n", skb->data, skb->len); /* display the buffer contents for debugging */ DEBUG(SHOW_BUFFER_CONTENTS, "\nrx %p ", skb->data); display_buffer((char *) skb->data, skb->len); #endif /* take care of monitor mode and spy monitoring. */ if (unlikely(priv->iw_mode == IW_MODE_MONITOR)) discard = islpci_monitor_rx(priv, &skb); else { if (unlikely(skb->data[2 * ETH_ALEN] == 0)) { /* The packet has a rx_annex. Read it for spy monitoring, Then * remove it, while keeping the 2 leading MAC addr. */ struct iw_quality wstats; struct rx_annex_header *annex = (struct rx_annex_header *) skb->data; wstats.level = annex->rfmon.rssi; /* The noise value can be a bit outdated if nobody's * reading wireless stats... */ wstats.noise = priv->local_iwstatistics.qual.noise; wstats.qual = wstats.level - wstats.noise; wstats.updated = 0x07; /* Update spy records */ wireless_spy_update(ndev, annex->addr2, &wstats); memcpy(skb->data + sizeof (struct rfmon_header), skb->data, 2 * ETH_ALEN); skb_pull(skb, sizeof (struct rfmon_header)); } skb->protocol = eth_type_trans(skb, ndev); } skb->ip_summed = CHECKSUM_NONE; priv->statistics.rx_packets++; priv->statistics.rx_bytes += size; /* deliver the skb to the network layer */ #ifdef ISLPCI_ETH_DEBUG printk ("islpci_eth_receive:netif_rx %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4], skb->data[5]); #endif if (unlikely(discard)) { dev_kfree_skb_irq(skb); skb = NULL; } else netif_rx(skb); /* increment the read index for the rx data low queue */ priv->free_data_rx++; /* add one or more sk_buff structures */ while (index = le32_to_cpu(control_block-> driver_curr_frag[ISL38XX_CB_RX_DATA_LQ]), index - priv->free_data_rx < ISL38XX_CB_RX_QSIZE) { /* allocate an sk_buff for received data frames storage * include any required allignment operations */ skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2); if (unlikely(skb == NULL)) { /* error allocating an sk_buff structure elements */ DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb \n"); break; } skb_reserve(skb, (4 - (long) skb->data) & 0x03); /* store the new skb structure pointer */ index = index % ISL38XX_CB_RX_QSIZE; priv->data_low_rx[index] = skb; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "new alloc skb %p skb->data %p skb->len %u index %u truesize %u\n ", skb, skb->data, skb->len, index, skb->truesize); #endif /* set the streaming DMA mapping for proper PCI bus operation */ priv->pci_map_rx_address[index] = pci_map_single(priv->pdev, (void *) skb->data, MAX_FRAGMENT_SIZE_RX + 2, PCI_DMA_FROMDEVICE); if (unlikely(priv->pci_map_rx_address[index] == (dma_addr_t) NULL)) { /* error mapping the buffer to device accessable memory address */ DEBUG(SHOW_ERROR_MESSAGES, "Error mapping DMA address\n"); /* free the skbuf structure before aborting */ dev_kfree_skb_irq((struct sk_buff *) skb); skb = NULL; break; } /* update the fragment address */ control_block->rx_data_low[index].address = cpu_to_le32((u32)priv->pci_map_rx_address[index]); wmb(); /* increment the driver read pointer */ add_le32p((u32 *) &control_block-> driver_curr_frag[ISL38XX_CB_RX_DATA_LQ], 1); } /* trigger the device */ islpci_trigger(priv); return 0; }