diff options
author | simokawa <simokawa@FreeBSD.org> | 2003-06-16 08:43:22 +0000 |
---|---|---|
committer | simokawa <simokawa@FreeBSD.org> | 2003-06-16 08:43:22 +0000 |
commit | 34a8115079a045c0f679b0e6d8ac5301662062f9 (patch) | |
tree | 420fb983b86b8deceba0db36ae0bf7b202d2b1dd /sys/dev/firewire/fwcrom.c | |
parent | 2efdcd558c180476006bb5886c13e6f094b4cf32 (diff) | |
download | FreeBSD-src-34a8115079a045c0f679b0e6d8ac5301662062f9.zip FreeBSD-src-34a8115079a045c0f679b0e6d8ac5301662062f9.tar.gz |
Bound check for broken Configuration ROM.
Diffstat (limited to 'sys/dev/firewire/fwcrom.c')
-rw-r--r-- | sys/dev/firewire/fwcrom.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/sys/dev/firewire/fwcrom.c b/sys/dev/firewire/fwcrom.c index bf85ae2..24ab07c 100644 --- a/sys/dev/firewire/fwcrom.c +++ b/sys/dev/firewire/fwcrom.c @@ -52,6 +52,9 @@ #include <dev/firewire/firewire.h> #include <dev/firewire/iec13213.h> +#define MAX_ROM (1024 - sizeof(u_int32_t) * 5) +#define CROM_END(cc) ((vm_offset_t)(cc)->stack[0].dir + MAX_ROM - 1) + void crom_init_context(struct crom_context *cc, u_int32_t *p) { @@ -93,12 +96,12 @@ crom_next(struct crom_context *cc) return; reg = crom_get(cc); if ((reg->key & CSRTYPE_MASK) == CSRTYPE_D) { - cc->depth ++; - if (cc->depth > CROM_MAX_DEPTH) { + if (cc->depth >= CROM_MAX_DEPTH) { printf("crom_next: too deep\n"); - cc->depth --; goto again; } + cc->depth ++; + ptr = &cc->stack[cc->depth]; ptr->dir = (struct csrdirectory *) (reg + reg->val); ptr->index = 0; @@ -108,8 +111,13 @@ again: ptr = &cc->stack[cc->depth]; ptr->index ++; check: - if (ptr->index < ptr->dir->crc_len) + if (ptr->index < ptr->dir->crc_len && + (vm_offset_t)crom_get(cc) <= CROM_END(cc)) return; + + if (ptr->index < ptr->dir->crc_len) + printf("crom_next: bound check failed\n"); + if (cc->depth > 0) { cc->depth--; goto again; @@ -173,12 +181,18 @@ crom_parse_text(struct crom_context *cc, char *buf, int len) return; reg = crom_get(cc); - if (reg->key != CROM_TEXTLEAF) { + if (reg->key != CROM_TEXTLEAF || + (vm_offset_t)(reg + reg->val) > CROM_END(cc)) { strncpy(buf, nullstr, len); return; } textleaf = (struct csrtext *)(reg + reg->val); + if ((vm_offset_t)textleaf + textleaf->crc_len > CROM_END(cc)) { + strncpy(buf, nullstr, len); + return; + } + /* XXX should check spec and type */ bp = (u_int32_t *)&buf[0]; |