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 16:47:29 +0100 |
commit | 2f828fb21df42058084b16d5e07cecdc30dbc3a5 (patch) | |
tree | e4dd00df654ccc5b3119ea6b93ef94f326daf1c0 | |
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>
-rw-r--r-- | drivers/nubus/nubus.c | 29 | ||||
-rw-r--r-- | drivers/nubus/proc.c | 12 | ||||
-rw-r--r-- | include/linux/nubus.h | 10 |
3 files changed, 27 insertions, 24 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) pointed to with offsets) out of the card ROM. */ void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, - int len) + unsigned int len) { unsigned char *t = (unsigned char *)dest; unsigned char *p = nubus_dirptr(dirent); @@ -173,18 +173,22 @@ void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, } EXPORT_SYMBOL(nubus_get_rsrc_mem); -void nubus_get_rsrc_str(void *dest, const struct nubus_dirent *dirent, - int len) +void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, + unsigned int len) { - unsigned char *t = (unsigned char *)dest; + char *t = dest; unsigned char *p = nubus_dirptr(dirent); - while (len) { - *t = nubus_get_rom(&p, 1, dirent->mask); - if (!*t++) + while (len > 1) { + unsigned char c = nubus_get_rom(&p, 1, dirent->mask); + + if (!c) break; + *t++ = c; len--; } + if (len > 0) + *t = '\0'; } EXPORT_SYMBOL(nubus_get_rsrc_str); @@ -468,7 +472,7 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, } case NUBUS_RESID_NAME: { - nubus_get_rsrc_str(dev->name, &ent, 64); + nubus_get_rsrc_str(dev->name, &ent, sizeof(dev->name)); pr_info(" name: %s\n", dev->name); break; } @@ -528,7 +532,7 @@ static int __init nubus_get_vidnames(struct nubus_board *board, /* Don't know what this is yet */ u16 id; /* Longest one I've seen so far is 26 characters */ - char name[32]; + char name[36]; }; pr_info(" video modes supported:\n"); @@ -598,8 +602,8 @@ static int __init nubus_get_vendorinfo(struct nubus_board *board, char name[64]; /* These are all strings, we think */ - nubus_get_rsrc_str(name, &ent, 64); - if (ent.type > 5) + nubus_get_rsrc_str(name, &ent, sizeof(name)); + if (ent.type < 1 || ent.type > 5) ent.type = 5; pr_info(" %s: %s\n", vendor_fields[ent.type - 1], name); } @@ -633,7 +637,8 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot, break; } case NUBUS_RESID_NAME: - nubus_get_rsrc_str(board->name, &ent, 64); + nubus_get_rsrc_str(board->name, &ent, + sizeof(board->name)); pr_info(" name: %s\n", board->name); break; 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, /* Some of these are directories, others aren't */ while (nubus_readdir(dir, &ent) != -1) { - char name[8]; + char name[9]; struct proc_dir_entry* e; - sprintf(name, "%x", ent.type); + snprintf(name, sizeof(name), "%x", ent.type); e = proc_create(name, S_IFREG | S_IRUGO | S_IWUSR, parent, &nubus_proc_subdir_fops); if (!e) @@ -95,11 +95,11 @@ static void nubus_proc_populate(struct nubus_dev* dev, /* We know these are all directories (board resource + one or more functional resources) */ while (nubus_readdir(root, &ent) != -1) { - char name[8]; + char name[9]; struct proc_dir_entry* e; struct nubus_dir dir; - sprintf(name, "%x", ent.type); + snprintf(name, sizeof(name), "%x", ent.type); e = proc_mkdir(name, parent); if (!e) return; @@ -119,7 +119,7 @@ int nubus_proc_attach_device(struct nubus_dev *dev) { struct proc_dir_entry *e; struct nubus_dir root; - char name[8]; + char name[9]; if (dev == NULL) { printk(KERN_ERR @@ -135,7 +135,7 @@ int nubus_proc_attach_device(struct nubus_dev *dev) } /* Create a directory */ - sprintf(name, "%x", dev->board->slot); + snprintf(name, sizeof(name), "%x", dev->board->slot); e = dev->procdir = proc_mkdir(name, proc_bus_nubus_dir); if (!e) return -ENOMEM; diff --git a/include/linux/nubus.h b/include/linux/nubus.h index 11ce6b1117a8..d8d63370a28c 100644 --- a/include/linux/nubus.h +++ b/include/linux/nubus.h @@ -126,10 +126,8 @@ int nubus_rewinddir(struct nubus_dir* dir); /* Things to do with directory entries */ int nubus_get_subdir(const struct nubus_dirent* ent, struct nubus_dir* dir); -void nubus_get_rsrc_mem(void* dest, - const struct nubus_dirent *dirent, - int len); -void nubus_get_rsrc_str(void* dest, - const struct nubus_dirent *dirent, - int maxlen); +void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, + unsigned int len); +void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, + unsigned int maxlen); #endif /* LINUX_NUBUS_H */ |