Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nubus: Avoid array underflow and overflow

Check array indices. Avoid sprintf. Use buffers of sufficient size.
Use appropriate types for array length parameters.

Tested-by: Stan Johnson <userm57@yahoo.com>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>

authored by

Finn Thain and committed by
Geert Uytterhoeven
2f828fb2 955999c9

+27 -24
+17 -12
drivers/nubus/nubus.c
··· 161 161 pointed to with offsets) out of the card ROM. */ 162 162 163 163 void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, 164 - int len) 164 + unsigned int len) 165 165 { 166 166 unsigned char *t = (unsigned char *)dest; 167 167 unsigned char *p = nubus_dirptr(dirent); ··· 173 173 } 174 174 EXPORT_SYMBOL(nubus_get_rsrc_mem); 175 175 176 - void nubus_get_rsrc_str(void *dest, const struct nubus_dirent *dirent, 177 - int len) 176 + void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, 177 + unsigned int len) 178 178 { 179 - unsigned char *t = (unsigned char *)dest; 179 + char *t = dest; 180 180 unsigned char *p = nubus_dirptr(dirent); 181 181 182 - while (len) { 183 - *t = nubus_get_rom(&p, 1, dirent->mask); 184 - if (!*t++) 182 + while (len > 1) { 183 + unsigned char c = nubus_get_rom(&p, 1, dirent->mask); 184 + 185 + if (!c) 185 186 break; 187 + *t++ = c; 186 188 len--; 187 189 } 190 + if (len > 0) 191 + *t = '\0'; 188 192 } 189 193 EXPORT_SYMBOL(nubus_get_rsrc_str); 190 194 ··· 472 468 } 473 469 case NUBUS_RESID_NAME: 474 470 { 475 - nubus_get_rsrc_str(dev->name, &ent, 64); 471 + nubus_get_rsrc_str(dev->name, &ent, sizeof(dev->name)); 476 472 pr_info(" name: %s\n", dev->name); 477 473 break; 478 474 } ··· 532 528 /* Don't know what this is yet */ 533 529 u16 id; 534 530 /* Longest one I've seen so far is 26 characters */ 535 - char name[32]; 531 + char name[36]; 536 532 }; 537 533 538 534 pr_info(" video modes supported:\n"); ··· 602 598 char name[64]; 603 599 604 600 /* These are all strings, we think */ 605 - nubus_get_rsrc_str(name, &ent, 64); 606 - if (ent.type > 5) 601 + nubus_get_rsrc_str(name, &ent, sizeof(name)); 602 + if (ent.type < 1 || ent.type > 5) 607 603 ent.type = 5; 608 604 pr_info(" %s: %s\n", vendor_fields[ent.type - 1], name); 609 605 } ··· 637 633 break; 638 634 } 639 635 case NUBUS_RESID_NAME: 640 - nubus_get_rsrc_str(board->name, &ent, 64); 636 + nubus_get_rsrc_str(board->name, &ent, 637 + sizeof(board->name)); 641 638 pr_info(" name: %s\n", board->name); 642 639 break; 643 640 case NUBUS_RESID_ICON:
+6 -6
drivers/nubus/proc.c
··· 73 73 74 74 /* Some of these are directories, others aren't */ 75 75 while (nubus_readdir(dir, &ent) != -1) { 76 - char name[8]; 76 + char name[9]; 77 77 struct proc_dir_entry* e; 78 78 79 - sprintf(name, "%x", ent.type); 79 + snprintf(name, sizeof(name), "%x", ent.type); 80 80 e = proc_create(name, S_IFREG | S_IRUGO | S_IWUSR, parent, 81 81 &nubus_proc_subdir_fops); 82 82 if (!e) ··· 95 95 /* We know these are all directories (board resource + one or 96 96 more functional resources) */ 97 97 while (nubus_readdir(root, &ent) != -1) { 98 - char name[8]; 98 + char name[9]; 99 99 struct proc_dir_entry* e; 100 100 struct nubus_dir dir; 101 101 102 - sprintf(name, "%x", ent.type); 102 + snprintf(name, sizeof(name), "%x", ent.type); 103 103 e = proc_mkdir(name, parent); 104 104 if (!e) return; 105 105 ··· 119 119 { 120 120 struct proc_dir_entry *e; 121 121 struct nubus_dir root; 122 - char name[8]; 122 + char name[9]; 123 123 124 124 if (dev == NULL) { 125 125 printk(KERN_ERR ··· 135 135 } 136 136 137 137 /* Create a directory */ 138 - sprintf(name, "%x", dev->board->slot); 138 + snprintf(name, sizeof(name), "%x", dev->board->slot); 139 139 e = dev->procdir = proc_mkdir(name, proc_bus_nubus_dir); 140 140 if (!e) 141 141 return -ENOMEM;
+4 -6
include/linux/nubus.h
··· 126 126 /* Things to do with directory entries */ 127 127 int nubus_get_subdir(const struct nubus_dirent* ent, 128 128 struct nubus_dir* dir); 129 - void nubus_get_rsrc_mem(void* dest, 130 - const struct nubus_dirent *dirent, 131 - int len); 132 - void nubus_get_rsrc_str(void* dest, 133 - const struct nubus_dirent *dirent, 134 - int maxlen); 129 + void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, 130 + unsigned int len); 131 + void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, 132 + unsigned int maxlen); 135 133 #endif /* LINUX_NUBUS_H */