Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F147888579
D11785.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D11785.diff
View Options
Index: sys/dev/usb/wlan/if_upgt.c
===================================================================
--- sys/dev/usb/wlan/if_upgt.c
+++ sys/dev/usb/wlan/if_upgt.c
@@ -118,7 +118,7 @@
static struct mbuf *
upgt_rxeof(struct usb_xfer *, struct upgt_data *, int *);
static struct mbuf *
- upgt_rx(struct upgt_softc *, uint8_t *, int, int *);
+ upgt_rx(struct upgt_softc *, uint8_t *, uint16_t, int *);
static void upgt_txeof(struct usb_xfer *, struct upgt_data *);
static int upgt_eeprom_read(struct upgt_softc *);
static int upgt_eeprom_parse(struct upgt_softc *);
@@ -306,7 +306,9 @@
DPRINTF(sc, UPGT_DEBUG_FW, "memory address rx start=0x%08x\n",
sc->sc_memaddr_rx_start);
- upgt_mem_init(sc);
+ error = upgt_mem_init(sc);
+ if (error)
+ goto fail4;
/* Load the firmware. */
error = upgt_fw_load(sc);
@@ -1043,7 +1045,7 @@
struct ieee80211com *ic = &sc->sc_ic;
struct upgt_eeprom_header *eeprom_header;
struct upgt_eeprom_option *eeprom_option;
- uint16_t option_len;
+ uint32_t option_len;
uint16_t option_type;
uint16_t preamble_len;
int option_end = 0;
@@ -1058,7 +1060,9 @@
/* sanity check */
if (eeprom_option >= (struct upgt_eeprom_option *)
- (sc->sc_eeprom + UPGT_EEPROM_SIZE)) {
+ (sc->sc_eeprom + UPGT_EEPROM_SIZE) ||
+ eeprom_option < (struct upgt_eeprom_option *)
+ sc->sc_eeprom) {
return (EINVAL);
}
@@ -1345,7 +1349,7 @@
struct upgt_lmac_header *header;
struct upgt_lmac_eeprom *eeprom;
uint8_t h1_type;
- uint16_t h2_type;
+ uint16_t h2_type, pkglen;
int actlen, sumlen;
usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
@@ -1378,13 +1382,22 @@
eeprom = (struct upgt_lmac_eeprom *)(data->buf + 4);
uint16_t eeprom_offset = le16toh(eeprom->offset);
uint16_t eeprom_len = le16toh(eeprom->len);
+ int buf_offset = sizeof(struct upgt_lmac_eeprom) + 4;
+ if (eeprom_len > actlen - buf_offset ||
+ eeprom_len > sizeof(sc->sc_eeprom) - eeprom_offset) {
+ device_printf(sc->sc_dev,
+ "%s: wrong eeprom length (%u) / offset (%u)!\n",
+ __func__, eeprom_len, eeprom_offset);
+ return (NULL);
+ }
+
DPRINTF(sc, UPGT_DEBUG_FW,
"received EEPROM block (offset=%d, len=%d)\n",
eeprom_offset, eeprom_len);
memcpy(sc->sc_eeprom + eeprom_offset,
- data->buf + sizeof(struct upgt_lmac_eeprom) + 4,
+ data->buf + buf_offset,
eeprom_len);
/* EEPROM data has arrived in time, wakeup. */
@@ -1398,8 +1411,16 @@
h1_type == UPGT_H1_TYPE_RX_DATA_MGMT) {
DPRINTF(sc, UPGT_DEBUG_RECV, "%s: received 802.11 RX data\n",
__func__);
- m = upgt_rx(sc, data->buf + 4, le16toh(header->header1.len),
- rssi);
+
+ pkglen = le16toh(header->header1.len);
+ if (actlen - 4 < pkglen) {
+ device_printf(sc->sc_dev,
+ "%s: actlen - 4 (%d) < pkglen (%d)!\n",
+ __func__, actlen - 4, pkglen);
+ return (NULL);
+ }
+
+ m = upgt_rx(sc, data->buf + 4, pkglen, rssi);
} else if (h1_type == UPGT_H1_TYPE_CTRL &&
h2_type == UPGT_H2_TYPE_STATS) {
DPRINTF(sc, UPGT_DEBUG_STAT, "%s: received statistic data\n",
@@ -1433,7 +1454,7 @@
}
static struct mbuf *
-upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
+upgt_rx(struct upgt_softc *sc, uint8_t *data, uint16_t pkglen, int *rssi)
{
struct ieee80211com *ic = &sc->sc_ic;
struct upgt_lmac_rx_desc *rxdesc;
@@ -1449,9 +1470,21 @@
/* access RX packet descriptor */
rxdesc = (struct upgt_lmac_rx_desc *)data;
+ if (pkglen < IEEE80211_ACK_LEN) {
+ device_printf(sc->sc_dev,
+ "%s: frame is too short! (pkglen %d)\n",
+ __func__, pkglen);
+ return (NULL);
+ }
+
+ if (pkglen >= MCLBYTES - ETHER_ALIGN) {
+ device_printf(sc->sc_dev,
+ "%s: A current mbuf storage is small (%d)\n",
+ __func__, pkglen + ETHER_ALIGN);
+ return (NULL);
+ }
+
/* create mbuf which is suitable for strict alignment archs */
- KASSERT((pkglen + ETHER_ALIGN) < MCLBYTES,
- ("A current mbuf storage is small (%d)", pkglen + ETHER_ALIGN));
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (m == NULL) {
device_printf(sc->sc_dev, "could not create RX mbuf\n");
@@ -1701,6 +1734,15 @@
{
int i;
+ if ((uint64_t)(sc->sc_memaddr_frame_start + MCLBYTES) >
+ sc->sc_memaddr_frame_end) {
+ device_printf(sc->sc_dev,
+ "%s: start (%u) + MCLBYTES > end (%u)!\n",
+ __func__, sc->sc_memaddr_frame_start,
+ sc->sc_memaddr_frame_end);
+ return (EINVAL);
+ }
+
for (i = 0; i < UPGT_MEMORY_MAX_PAGES; i++) {
sc->sc_memory.page[i].used = 0;
@@ -1716,6 +1758,14 @@
sc->sc_memory.page[i - 1].addr + MCLBYTES;
}
+ /* Memory wrap check. */
+ if (sc->sc_memaddr_frame_start > sc->sc_memory.page[i].addr) {
+ device_printf(sc->sc_dev,
+ "%s: frame_start (%u) is too large!\n",
+ __func__, sc->sc_memaddr_frame_start);
+ return (EINVAL);
+ }
+
if (sc->sc_memory.page[i].addr + MCLBYTES >=
sc->sc_memaddr_frame_end)
break;
@@ -1753,17 +1803,19 @@
/*
* Seek to beginning of Boot Record Area (BRA).
*/
- for (offset = 0; offset < fw->datasize; offset += sizeof(*uc)) {
+ for (offset = 0;
+ offset + sizeof(*uc) <= fw->datasize;
+ offset += sizeof(*uc)) {
uc = (const uint32_t *)((const uint8_t *)fw->data + offset);
if (*uc == 0)
break;
}
- for (; offset < fw->datasize; offset += sizeof(*uc)) {
+ for (; offset + sizeof(*uc) <= fw->datasize; offset += sizeof(*uc)) {
uc = (const uint32_t *)((const uint8_t *)fw->data + offset);
if (*uc != 0)
break;
}
- if (offset == fw->datasize) {
+ if (offset + sizeof(*uc) > fw->datasize) {
device_printf(sc->sc_dev,
"firmware Boot Record Area not found\n");
error = EIO;
@@ -1776,13 +1828,21 @@
/*
* Parse Boot Record Area (BRA) options.
*/
- while (offset < fw->datasize && bra_end == 0) {
+ while (offset <= fw->datasize - sizeof(*bra_opt) && bra_end == 0) {
/* get current BRA option */
p = (const uint8_t *)fw->data + offset;
bra_opt = (const struct upgt_fw_bra_option *)p;
bra_option_type = le32toh(bra_opt->type);
bra_option_len = le32toh(bra_opt->len) * sizeof(*uc);
+ if (bra_option_len > (size_t)(fw->datasize - offset -
+ sizeof(*bra_opt)) ||
+ bra_option_len / sizeof(*uc) != le32toh(bra_opt->len)) {
+ device_printf(sc->sc_dev, "bra_option_len overflow\n");
+ error = EINVAL;
+ goto fail;
+ }
+
switch (bra_option_type) {
case UPGT_BRA_TYPE_FW:
DPRINTF(sc, UPGT_DEBUG_FW, "UPGT_BRA_TYPE_FW len=%d\n",
@@ -1821,6 +1881,18 @@
"UPGT_BRA_TYPE_EXPIF len=%d\n", bra_option_len);
break;
case UPGT_BRA_TYPE_DESCR:
+ if (sizeof(*descr) > fw->datasize - offset -
+ sizeof(*bra_opt) ||
+ sizeof(*descr) > bra_option_len) {
+ device_printf(sc->sc_dev, "%s: no place for"
+ "'struct upgt_fw_bra_descr' (%zu / %u)\n",
+ __func__,
+ fw->datasize - offset - sizeof(*bra_opt),
+ bra_option_len);
+ error = EIO;
+ goto fail;
+ }
+
DPRINTF(sc, UPGT_DEBUG_FW,
"UPGT_BRA_TYPE_DESCR len=%d\n", bra_option_len);
@@ -2111,14 +2183,28 @@
struct upgt_data *data)
{
struct ieee80211vap *vap = ni->ni_vap;
- int error = 0, len;
+ int error = 0;
struct ieee80211_frame *wh;
struct ieee80211_key *k;
struct upgt_lmac_mem *mem;
struct upgt_lmac_tx_desc *txdesc;
+ uint32_t len;
UPGT_ASSERT_LOCKED(sc);
+ /* Calculate frame size. */
+ len = sizeof(*mem) + sizeof(*txdesc) + m->m_pkthdr.len;
+ /* We need to align the frame to a 4 byte boundary. */
+ len = (len + 3) & ~3;
+
+ if (len > MCLBYTES) {
+ device_printf(sc->sc_dev,
+ "%s: the frame %p is too big (%d)\n",
+ __func__, m, m->m_pkthdr.len);
+ error = EINVAL;
+ goto done;
+ }
+
upgt_set_led(sc, UPGT_LED_BLINK);
/*
@@ -2175,19 +2261,14 @@
/* copy frame below our TX descriptor header */
m_copydata(m, 0, m->m_pkthdr.len,
data->buf + (sizeof(*mem) + sizeof(*txdesc)));
- /* calculate frame size */
- len = sizeof(*mem) + sizeof(*txdesc) + m->m_pkthdr.len;
- /* we need to align the frame to a 4 byte boundary */
- len = (len + 3) & ~3;
/* calculate frame checksum */
mem->chksum = upgt_chksum_le((uint32_t *)txdesc, len - sizeof(*mem));
data->ni = ni;
data->m = m;
data->buflen = len;
- DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: TX start data sending (%d bytes)\n",
+ DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: TX start data sending (%u bytes)\n",
__func__, len);
- KASSERT(len <= MCLBYTES, ("mbuf is small for saving data"));
upgt_bulk_tx(sc, data);
done:
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 15, 10:50 AM (9 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29697372
Default Alt Text
D11785.diff (8 KB)
Attached To
Mode
D11785: upgt: add some overflow checks
Attached
Detach File
Event Timeline
Log In to Comment