diff --git a/drivers/parisc/eisa_enumerator.c b/drivers/parisc/eisa_enumerator.c index e0a57086a8a8..011b9ac6f97b 100644 --- a/drivers/parisc/eisa_enumerator.c +++ b/drivers/parisc/eisa_enumerator.c @@ -311,6 +311,7 @@ static int configure_function(const unsigned char *buf, int *more) static int parse_slot_config(int slot, const unsigned char *buf, + unsigned int buflen, struct eeprom_eisa_slot_info *es, struct resource *io_parent, struct resource *mem_parent) @@ -333,8 +334,8 @@ static int parse_slot_config(int slot, printk(KERN_INFO "EISA slot %d: %s %s ", slot, board, es->flags&HPEE_FLAG_BOARD_IS_ISA ? "ISA" : "EISA"); - maxlen = es->config_data_length < HPEE_MAX_LENGTH ? - es->config_data_length : HPEE_MAX_LENGTH; + /* never parse beyond the data that is actually in the buffer */ + maxlen = min_t(unsigned int, es->config_data_length, buflen); while ((pos < maxlen) && (num_func <= es->num_functions)) { pos+=configure_function(buf+pos, &function_len); @@ -491,6 +492,13 @@ int eisa_enumerator(unsigned long eeprom_addr, printk(KERN_INFO "Enumerating EISA bus\n"); eh = (struct eeprom_header*)(eeprom_buf); + /* + * The EEPROM contents are not to be trusted: clamp the number of + * slots so that all slot records fit into eeprom_buf. + */ + eh->num_slots = min_t(u8, eh->num_slots, + (HPEE_MAX_LENGTH - sizeof(*eh)) / + sizeof(struct eeprom_eisa_slot_info)); for (i=0;inum_slots;i++) { struct eeprom_eisa_slot_info *es; @@ -503,7 +511,8 @@ int eisa_enumerator(unsigned long eeprom_addr, if (es->config_data_offset < HPEE_MAX_LENGTH) { if (parse_slot_config(i+1, &eeprom_buf[es->config_data_offset], - es, io_parent, mem_parent)) { + HPEE_MAX_LENGTH - es->config_data_offset, + es, io_parent, mem_parent)) { return -1; } } else {