Skip to content

Commit

Permalink
kbuild: make modpost detect unterminated device id lists
Browse files Browse the repository at this point in the history
Cause modpost to fail if any device id lists are incorrectly terminated,
after reporting the offender.
Improved reporting by akpm

Signed-off-by: Kees Cook <kees@ubuntu.com>
Cc: Greg KH <greg@kroah.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Jeff Garzik <jeff@garzik.org>
Cc: Ben Collins <bcollins@ubuntu.com>
Cc: Michael Wu <flamingice@sourmilk.net>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
  • Loading branch information
kees authored and Sam Ravnborg committed Oct 12, 2007
1 parent 295ac05 commit e004982
Showing 1 changed file with 33 additions and 7 deletions.
40 changes: 33 additions & 7 deletions scripts/mod/file2alias.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,35 @@ do { \
* Check that sizeof(device_id type) are consistent with size of section
* in .o file. If in-consistent then userspace and kernel does not agree
* on actual size which is a bug.
* Also verify that the final entry in the table is all zeros.
**/
static void device_id_size_check(const char *modname, const char *device_id,
unsigned long size, unsigned long id_size)
static void device_id_check(const char *modname, const char *device_id,
unsigned long size, unsigned long id_size,
void *symval)
{
int i;

if (size % id_size || size < id_size) {
fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
"of the size of section __mod_%s_device_table=%lu.\n"
"Fix definition of struct %s_device_id "
"in mod_devicetable.h\n",
modname, device_id, id_size, device_id, size, device_id);
}
/* Verify last one is a terminator */
for (i = 0; i < id_size; i++ ) {
if (*(uint8_t*)(symval+size-id_size+i)) {
fprintf(stderr,"%s: struct %s_device_id is %lu bytes. "
"The last of %lu is:\n",
modname, device_id, id_size, size / id_size);
for (i = 0; i < id_size; i++ )
fprintf(stderr,"0x%02x ",
*(uint8_t*)(symval+size-id_size+i) );
fprintf(stderr,"\n");
fatal("%s: struct %s_device_id is not terminated "
"with a NULL entry!\n", modname, device_id);
}
}
}

/* USB is special because the bcdDevice can be matched against a numeric range */
Expand Down Expand Up @@ -168,7 +186,7 @@ static void do_usb_table(void *symval, unsigned long size,
unsigned int i;
const unsigned long id_size = sizeof(struct usb_device_id);

device_id_size_check(mod->name, "usb", size, id_size);
device_id_check(mod->name, "usb", size, id_size, symval);

/* Leave last one: it's the terminator. */
size -= id_size;
Expand Down Expand Up @@ -535,7 +553,7 @@ static void do_table(void *symval, unsigned long size,
char alias[500];
int (*do_entry)(const char *, void *entry, char *alias) = function;

device_id_size_check(mod->name, device_id, size, id_size);
device_id_check(mod->name, device_id, size, id_size, symval);
/* Leave last one: it's the terminator. */
size -= id_size;

Expand All @@ -557,14 +575,21 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
Elf_Sym *sym, const char *symname)
{
void *symval;
char *zeros = NULL;

/* We're looking for a section relative symbol */
if (!sym->st_shndx || sym->st_shndx >= info->hdr->e_shnum)
return;

symval = (void *)info->hdr
+ info->sechdrs[sym->st_shndx].sh_offset
+ sym->st_value;
/* Handle all-NULL symbols allocated into .bss */
if (info->sechdrs[sym->st_shndx].sh_type & SHT_NOBITS) {
zeros = calloc(1, sym->st_size);
symval = zeros;
} else {
symval = (void *)info->hdr
+ info->sechdrs[sym->st_shndx].sh_offset
+ sym->st_value;
}

if (sym_is(symname, "__mod_pci_device_table"))
do_table(symval, sym->st_size,
Expand Down Expand Up @@ -637,6 +662,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
do_table(symval, sym->st_size,
sizeof(struct ssb_device_id), "ssb",
do_ssb_entry, mod);
free(zeros);
}

/* Now add out buffered information to the generated C source */
Expand Down

0 comments on commit e004982

Please sign in to comment.