Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144467059
D11786.id31683.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D11786.id31683.diff
View Options
Index: sys/dev/usb/wlan/if_uath.c
===================================================================
--- sys/dev/usb/wlan/if_uath.c
+++ sys/dev/usb/wlan/if_uath.c
@@ -2201,17 +2201,19 @@
#undef UATH_SYSCTL_STAT_ADD32
+CTASSERT(sizeof(u_int) >= sizeof(uint32_t));
+
static void
uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
{
struct uath_cmd_hdr *hdr;
- int dlen;
+ uint32_t dlen;
hdr = (struct uath_cmd_hdr *)cmd->buf;
/* NB: msgid is passed thru w/o byte swapping */
#ifdef UATH_DEBUG
if (sc->sc_debug & UATH_DEBUG_CMDS) {
- int len = be32toh(hdr->len);
+ uint32_t len = be32toh(hdr->len);
printf("%s: %s [ix %u] len %u status %u\n",
__func__, uath_codename(be32toh(hdr->code)),
hdr->msgid, len, be32toh(hdr->magic));
@@ -2228,11 +2230,7 @@
/* reply to a read command */
default:
dlen = hdr->len - sizeof(*hdr);
- if (dlen < 0) {
- device_printf(sc->sc_dev,
- "Invalid header length %d\n", dlen);
- return;
- }
+
DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL,
"%s: code %d data len %u\n",
__func__, hdr->code & 0xff, dlen);
@@ -2258,7 +2256,7 @@
* number of bytes--unless it's 0 in which
* case a single 32-bit word should be present.
*/
- if (dlen >= (int)sizeof(uint32_t)) {
+ if (dlen >= sizeof(uint32_t)) {
olen = be32toh(rp[0]);
dlen -= sizeof(uint32_t);
if (olen == 0) {
@@ -2278,7 +2276,7 @@
cmd->olen);
olen = cmd->olen;
}
- if (olen > (u_int)dlen) {
+ if (olen > dlen) {
/* XXX complain, shouldn't happen */
device_printf(sc->sc_dev,
"%s: cmd 0x%x olen %u dlen %u\n",
@@ -2300,8 +2298,10 @@
return;
}
dlen = hdr->len - sizeof(*hdr);
- if (dlen != (int)sizeof(uint32_t)) {
- /* XXX something wrong */
+ if (dlen != sizeof(uint32_t)) {
+ device_printf(sc->sc_dev,
+ "%s: dlen (%u) != %zu!\n",
+ __func__, dlen, sizeof(uint32_t));
return;
}
/* XXX have submitter do this */
@@ -2330,6 +2330,7 @@
{
struct uath_softc *sc = usbd_xfer_softc(xfer);
struct uath_cmd *cmd;
+ struct uath_cmd_hdr *hdr;
struct usb_page_cache *pc;
int actlen;
@@ -2347,10 +2348,25 @@
STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next);
UATH_STAT_INC(sc, st_cmd_inactive);
- KASSERT(actlen >= (int)sizeof(struct uath_cmd_hdr),
- ("short xfer error"));
+ if (actlen < sizeof(struct uath_cmd_hdr)) {
+ device_printf(sc->sc_dev,
+ "%s: short xfer error (actlen %d)\n",
+ __func__, actlen);
+ goto setup;
+ }
+
pc = usbd_xfer_get_frame(xfer, 0);
usbd_copy_out(pc, 0, cmd->buf, actlen);
+
+ hdr = (struct uath_cmd_hdr *)cmd->buf;
+ hdr->len = be32toh(hdr->len);
+ if (hdr->len > actlen) {
+ device_printf(sc->sc_dev,
+ "%s: truncated xfer (len %u, actlen %d)\n",
+ __func__, hdr->len, actlen);
+ goto setup;
+ }
+
uath_cmdeof(sc, cmd);
case USB_ST_SETUP:
setup:
@@ -2473,13 +2489,24 @@
}
chunk = (struct uath_chunk *)data->buf;
- if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) {
+ chunklen = be16toh(chunk->length);
+ if (chunk->seqnum == 0 && chunk->flags == 0 && chunklen == 0) {
device_printf(sc->sc_dev, "%s: strange response\n", __func__);
counter_u64_add(ic->ic_ierrors, 1);
UATH_RESET_INTRX(sc);
return (NULL);
}
+ if (chunklen > actlen) {
+ device_printf(sc->sc_dev,
+ "%s: invalid chunk length (len %u > actlen %d)\n",
+ __func__, chunklen, actlen);
+ counter_u64_add(ic->ic_ierrors, 1);
+ /* XXX cleanup? */
+ UATH_RESET_INTRX(sc);
+ return (NULL);
+ }
+
if (chunk->seqnum != sc->sc_intrx_nextnum) {
DPRINTF(sc, UATH_DEBUG_XMIT, "invalid seqnum %d, expected %d\n",
chunk->seqnum, sc->sc_intrx_nextnum);
@@ -2496,9 +2523,19 @@
chunk->flags & UATH_CFLAGS_RXMSG)
UATH_STAT_INC(sc, st_multichunk);
- chunklen = be16toh(chunk->length);
- if (chunk->flags & UATH_CFLAGS_FINAL)
+ if (chunk->flags & UATH_CFLAGS_FINAL) {
+ if (chunklen < sizeof(struct uath_rx_desc)) {
+ device_printf(sc->sc_dev,
+ "%s: invalid chunk length %d\n",
+ __func__, chunklen);
+ counter_u64_add(ic->ic_ierrors, 1);
+ if (sc->sc_intrx_head != NULL)
+ m_freem(sc->sc_intrx_head);
+ UATH_RESET_INTRX(sc);
+ return (NULL);
+ }
chunklen -= sizeof(struct uath_rx_desc);
+ }
if (chunklen > 0 &&
(!(chunk->flags & UATH_CFLAGS_FINAL) || !(chunk->seqnum == 0))) {
@@ -2559,6 +2596,19 @@
(struct uath_rx_desc *)(((uint8_t *)chunk) +
sizeof(struct uath_chunk) + be16toh(chunk->length) -
sizeof(struct uath_rx_desc));
+ if ((uint8_t *)chunk + actlen - sizeof(struct uath_rx_desc) <
+ (uint8_t *)desc) {
+ device_printf(sc->sc_dev,
+ "%s: wrong Rx descriptor pointer "
+ "(desc %p chunk %p actlen %d)\n",
+ __func__, desc, chunk, actlen);
+ counter_u64_add(ic->ic_ierrors, 1);
+ if (sc->sc_intrx_head != NULL)
+ m_freem(sc->sc_intrx_head);
+ UATH_RESET_INTRX(sc);
+ return (NULL);
+ }
+
*pdesc = desc;
DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
@@ -2586,8 +2636,21 @@
/* finalize mbuf */
if (sc->sc_intrx_head == NULL) {
- m->m_pkthdr.len = m->m_len =
- be32toh(desc->framelen) - UATH_RX_DUMMYSIZE;
+ uint32_t framelen;
+
+ framelen = be32toh(desc->framelen) - UATH_RX_DUMMYSIZE;
+ if (framelen > actlen - sizeof(struct uath_chunk)) {
+ device_printf(sc->sc_dev,
+ "%s: wrong frame length (%u, actlen %d)!\n",
+ __func__, framelen, actlen);
+ counter_u64_add(ic->ic_ierrors, 1);
+ if (sc->sc_intrx_head != NULL)
+ m_freem(sc->sc_intrx_head);
+ UATH_RESET_INTRX(sc);
+ return (NULL);
+ }
+
+ m->m_pkthdr.len = m->m_len = framelen;
m->m_data += sizeof(struct uath_chunk);
} else {
mp = sc->sc_intrx_head;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 9, 2:30 PM (12 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28589325
Default Alt Text
D11786.id31683.diff (5 KB)
Attached To
Mode
D11786: uath: fix varible types, add checks for descriptor / command header structure fields.
Attached
Detach File
Event Timeline
Log In to Comment