DF-4321 / fix.diff
--- a/sys/dev/netif/ath/ath_hal/ah.c +++ b/sys/dev/netif/ath/ath_hal/ah.c @@ -852,17 +852,24 @@ uint32_t *dp = dstbuf; int i; - for (i = 0; space >= 2*sizeof(uint32_t); i++) { + /* + * NB: space is a signed int; compare against signed constants. + * Comparing against sizeof() (size_t) converts negative space to + * a huge unsigned value and defeats these bounds checks, turning + * a truncated register dump into an uncontrolled heap overflow + * (DF-4321). Also check space before the first value write. + */ + for (i = 0; space >= (int)(2*sizeof(uint32_t)); i++) { uint32_t r = regs[i].start; uint32_t e = regs[i].end; *dp++ = r; *dp++ = e; - space -= 2*sizeof(uint32_t); - do { + space -= (int)(2*sizeof(uint32_t)); + while (r <= e && space >= (int)sizeof(uint32_t)) { *dp++ = OS_REG_READ(ah, r); r += sizeof(uint32_t); - space -= sizeof(uint32_t); - } while (r <= e && space >= sizeof(uint32_t)); + space -= (int)sizeof(uint32_t); + } } return (char *) dp - (char *) dstbuf; } |