Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bca463e8 authored by Chin-Ran Lo's avatar Chin-Ran Lo Committed by John W. Linville
Browse files

mwifiex: fix tx_info/rx_info overlap with PCIe dma_mapping



On PCIe Tx data path, network interface specific tx_info
parameters such as bss_num and bss_type are saved at
"skb->cb + sizeof(dma_addr_t)" (returned by MWIFIEX_SKB_TXCB).
Later mwifiex_map_pci_memory() called from
mwifiex_pcie_send_data() will memcpy
sizeof(struct mwifiex_dma_mapping) bytes to save PCIe DMA
address and length information at beginning of skb->cb.
This accidently overwrites bss_num and bss_type saved in skb->cb
previously because bss_num/bss_type and mwifiex_dma_mapping data
overlap.
Similarly, on PCIe Rx data path, rx_info parameters overlaps
with PCIe DMA address and length information too.

Fix it by defining mwifiex_cb structure and having
MWIFIEX_SKB_TXCB and MWIFIEX_SKB_RXCB return the correct address
of tx_info/rx_info using the structure members.

Also add a BUILD_BUG_ON to maks sure that mwifiex_cb structure
doesn't exceed the size of skb->cb.

Reviewed-by: default avatarAaron Durbin <adurbin@chromium.org>
Signed-off-by: default avatarChin-Ran Lo <crlo@marvell.com>
Signed-off-by: default avatarBing Zhao <bzhao@marvell.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent f15ec345
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
		return -1;
	}
	mapping.len = size;
	memcpy(skb->cb, &mapping, sizeof(mapping));
	mwifiex_store_mapping(skb, &mapping);
	return 0;
}

@@ -60,7 +60,7 @@ static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter,
	struct pcie_service_card *card = adapter->card;
	struct mwifiex_dma_mapping mapping;

	MWIFIEX_SKB_PACB(skb, &mapping);
	mwifiex_get_mapping(skb, &mapping);
	pci_unmap_single(card->dev, mapping.addr, mapping.len, flags);
}

+33 −10
Original line number Diff line number Diff line
@@ -20,32 +20,55 @@
#ifndef _MWIFIEX_UTIL_H_
#define _MWIFIEX_UTIL_H_

struct mwifiex_dma_mapping {
	dma_addr_t addr;
	size_t len;
};

struct mwifiex_cb {
	struct mwifiex_dma_mapping dma_mapping;
	union {
		struct mwifiex_rxinfo rx_info;
		struct mwifiex_txinfo tx_info;
	};
};

static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb)
{
	return (struct mwifiex_rxinfo *)(skb->cb + sizeof(dma_addr_t));
	struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;

	BUILD_BUG_ON(sizeof(struct mwifiex_cb) > sizeof(skb->cb));
	return &cb->rx_info;
}

static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb)
{
	return (struct mwifiex_txinfo *)(skb->cb + sizeof(dma_addr_t));
	struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;

	return &cb->tx_info;
}

struct mwifiex_dma_mapping {
	dma_addr_t addr;
	size_t len;
};
static inline void mwifiex_store_mapping(struct sk_buff *skb,
					 struct mwifiex_dma_mapping *mapping)
{
	struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;

	memcpy(&cb->dma_mapping, mapping, sizeof(*mapping));
}

static inline void MWIFIEX_SKB_PACB(struct sk_buff *skb,
static inline void mwifiex_get_mapping(struct sk_buff *skb,
				       struct mwifiex_dma_mapping *mapping)
{
	memcpy(mapping, skb->cb, sizeof(*mapping));
	struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;

	memcpy(mapping, &cb->dma_mapping, sizeof(*mapping));
}

static inline dma_addr_t MWIFIEX_SKB_DMA_ADDR(struct sk_buff *skb)
{
	struct mwifiex_dma_mapping mapping;

	MWIFIEX_SKB_PACB(skb, &mapping);
	mwifiex_get_mapping(skb, &mapping);

	return mapping.addr;
}