diff options
author | Finn Thain <fthain@telegraphics.com.au> | 2018-01-13 17:37:13 -0500 |
---|---|---|
committer | Geert Uytterhoeven <geert@linux-m68k.org> | 2018-01-16 10:47:29 -0500 |
commit | 2f828fb21df42058084b16d5e07cecdc30dbc3a5 (patch) | |
tree | e4dd00df654ccc5b3119ea6b93ef94f326daf1c0 /drivers/nubus | |
parent | 955999c9023290da18230b57df1f04187a43a4c0 (diff) |
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>
Diffstat (limited to 'drivers/nubus')
-rw-r--r-- | drivers/nubus/nubus.c | 29 | ||||
-rw-r--r-- | drivers/nubus/proc.c | 12 |
2 files changed, 23 insertions, 18 deletions
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c index b793727cd4f7..b6c97e07f15e 100644 --- a/drivers/nubus/nubus.c +++ b/drivers/nubus/nubus.c | |||
@@ -161,7 +161,7 @@ static unsigned char *nubus_dirptr(const struct nubus_dirent *nd) | |||
161 | pointed to with offsets) out of the card ROM. */ | 161 | pointed to with offsets) out of the card ROM. */ |
162 | 162 | ||
163 | void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, | 163 | void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, |
164 | int len) | 164 | unsigned int len) |
165 | { | 165 | { |
166 | unsigned char *t = (unsigned char *)dest; | 166 | unsigned char *t = (unsigned char *)dest; |
167 | unsigned char *p = nubus_dirptr(dirent); | 167 | unsigned char *p = nubus_dirptr(dirent); |
@@ -173,18 +173,22 @@ void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, | |||
173 | } | 173 | } |
174 | EXPORT_SYMBOL(nubus_get_rsrc_mem); | 174 | EXPORT_SYMBOL(nubus_get_rsrc_mem); |
175 | 175 | ||
176 | void nubus_get_rsrc_str(void *dest, const struct nubus_dirent *dirent, | 176 | void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, |
177 | int len) | 177 | unsigned int len) |
178 | { | 178 | { |
179 | unsigned char *t = (unsigned char *)dest; | 179 | char *t = dest; |
180 | unsigned char *p = nubus_dirptr(dirent); | 180 | unsigned char *p = nubus_dirptr(dirent); |
181 | 181 | ||
182 | while (len) { | 182 | while (len > 1) { |
183 | *t = nubus_get_rom(&p, 1, dirent->mask); | 183 | unsigned char c = nubus_get_rom(&p, 1, dirent->mask); |
184 | if (!*t++) | 184 | |
185 | if (!c) | ||
185 | break; | 186 | break; |
187 | *t++ = c; | ||
186 | len--; | 188 | len--; |
187 | } | 189 | } |
190 | if (len > 0) | ||
191 | *t = '\0'; | ||
188 | } | 192 | } |
189 | EXPORT_SYMBOL(nubus_get_rsrc_str); | 193 | EXPORT_SYMBOL(nubus_get_rsrc_str); |
190 | 194 | ||
@@ -468,7 +472,7 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, | |||
468 | } | 472 | } |
469 | case NUBUS_RESID_NAME: | 473 | case NUBUS_RESID_NAME: |
470 | { | 474 | { |
471 | nubus_get_rsrc_str(dev->name, &ent, 64); | 475 | nubus_get_rsrc_str(dev->name, &ent, sizeof(dev->name)); |
472 | pr_info(" name: %s\n", dev->name); | 476 | pr_info(" name: %s\n", dev->name); |
473 | break; | 477 | break; |
474 | } | 478 | } |
@@ -528,7 +532,7 @@ static int __init nubus_get_vidnames(struct nubus_board *board, | |||
528 | /* Don't know what this is yet */ | 532 | /* Don't know what this is yet */ |
529 | u16 id; | 533 | u16 id; |
530 | /* Longest one I've seen so far is 26 characters */ | 534 | /* Longest one I've seen so far is 26 characters */ |
531 | char name[32]; | 535 | char name[36]; |
532 | }; | 536 | }; |
533 | 537 | ||
534 | pr_info(" video modes supported:\n"); | 538 | pr_info(" video modes supported:\n"); |
@@ -598,8 +602,8 @@ static int __init nubus_get_vendorinfo(struct nubus_board *board, | |||
598 | char name[64]; | 602 | char name[64]; |
599 | 603 | ||
600 | /* These are all strings, we think */ | 604 | /* These are all strings, we think */ |
601 | nubus_get_rsrc_str(name, &ent, 64); | 605 | nubus_get_rsrc_str(name, &ent, sizeof(name)); |
602 | if (ent.type > 5) | 606 | if (ent.type < 1 || ent.type > 5) |
603 | ent.type = 5; | 607 | ent.type = 5; |
604 | pr_info(" %s: %s\n", vendor_fields[ent.type - 1], name); | 608 | pr_info(" %s: %s\n", vendor_fields[ent.type - 1], name); |
605 | } | 609 | } |
@@ -633,7 +637,8 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot, | |||
633 | break; | 637 | break; |
634 | } | 638 | } |
635 | case NUBUS_RESID_NAME: | 639 | case NUBUS_RESID_NAME: |
636 | nubus_get_rsrc_str(board->name, &ent, 64); | 640 | nubus_get_rsrc_str(board->name, &ent, |
641 | sizeof(board->name)); | ||
637 | pr_info(" name: %s\n", board->name); | 642 | pr_info(" name: %s\n", board->name); |
638 | break; | 643 | break; |
639 | case NUBUS_RESID_ICON: | 644 | case NUBUS_RESID_ICON: |
diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c index 004a122ac0ff..fc20dbcd3b9a 100644 --- a/drivers/nubus/proc.c +++ b/drivers/nubus/proc.c | |||
@@ -73,10 +73,10 @@ static void nubus_proc_subdir(struct nubus_dev* dev, | |||
73 | 73 | ||
74 | /* Some of these are directories, others aren't */ | 74 | /* Some of these are directories, others aren't */ |
75 | while (nubus_readdir(dir, &ent) != -1) { | 75 | while (nubus_readdir(dir, &ent) != -1) { |
76 | char name[8]; | 76 | char name[9]; |
77 | struct proc_dir_entry* e; | 77 | struct proc_dir_entry* e; |
78 | 78 | ||
79 | sprintf(name, "%x", ent.type); | 79 | snprintf(name, sizeof(name), "%x", ent.type); |
80 | e = proc_create(name, S_IFREG | S_IRUGO | S_IWUSR, parent, | 80 | e = proc_create(name, S_IFREG | S_IRUGO | S_IWUSR, parent, |
81 | &nubus_proc_subdir_fops); | 81 | &nubus_proc_subdir_fops); |
82 | if (!e) | 82 | if (!e) |
@@ -95,11 +95,11 @@ static void nubus_proc_populate(struct nubus_dev* dev, | |||
95 | /* We know these are all directories (board resource + one or | 95 | /* We know these are all directories (board resource + one or |
96 | more functional resources) */ | 96 | more functional resources) */ |
97 | while (nubus_readdir(root, &ent) != -1) { | 97 | while (nubus_readdir(root, &ent) != -1) { |
98 | char name[8]; | 98 | char name[9]; |
99 | struct proc_dir_entry* e; | 99 | struct proc_dir_entry* e; |
100 | struct nubus_dir dir; | 100 | struct nubus_dir dir; |
101 | 101 | ||
102 | sprintf(name, "%x", ent.type); | 102 | snprintf(name, sizeof(name), "%x", ent.type); |
103 | e = proc_mkdir(name, parent); | 103 | e = proc_mkdir(name, parent); |
104 | if (!e) return; | 104 | if (!e) return; |
105 | 105 | ||
@@ -119,7 +119,7 @@ int nubus_proc_attach_device(struct nubus_dev *dev) | |||
119 | { | 119 | { |
120 | struct proc_dir_entry *e; | 120 | struct proc_dir_entry *e; |
121 | struct nubus_dir root; | 121 | struct nubus_dir root; |
122 | char name[8]; | 122 | char name[9]; |
123 | 123 | ||
124 | if (dev == NULL) { | 124 | if (dev == NULL) { |
125 | printk(KERN_ERR | 125 | printk(KERN_ERR |
@@ -135,7 +135,7 @@ int nubus_proc_attach_device(struct nubus_dev *dev) | |||
135 | } | 135 | } |
136 | 136 | ||
137 | /* Create a directory */ | 137 | /* Create a directory */ |
138 | sprintf(name, "%x", dev->board->slot); | 138 | snprintf(name, sizeof(name), "%x", dev->board->slot); |
139 | e = dev->procdir = proc_mkdir(name, proc_bus_nubus_dir); | 139 | e = dev->procdir = proc_mkdir(name, proc_bus_nubus_dir); |
140 | if (!e) | 140 | if (!e) |
141 | return -ENOMEM; | 141 | return -ENOMEM; |