Skip to content

Commit e004982

Browse files
keesSam Ravnborg
authored andcommitted
kbuild: make modpost detect unterminated device id lists
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 <[email protected]> Cc: Greg KH <[email protected]> Cc: Alexey Dobriyan <[email protected]> Cc: Jeff Garzik <[email protected]> Cc: Ben Collins <[email protected]> Cc: Michael Wu <[email protected]> Cc: Rusty Russell <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Sam Ravnborg <[email protected]>
1 parent 295ac05 commit e004982

File tree

1 file changed

+33
-7
lines changed

1 file changed

+33
-7
lines changed

scripts/mod/file2alias.c

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,35 @@ do { \
5555
* Check that sizeof(device_id type) are consistent with size of section
5656
* in .o file. If in-consistent then userspace and kernel does not agree
5757
* on actual size which is a bug.
58+
* Also verify that the final entry in the table is all zeros.
5859
**/
59-
static void device_id_size_check(const char *modname, const char *device_id,
60-
unsigned long size, unsigned long id_size)
60+
static void device_id_check(const char *modname, const char *device_id,
61+
unsigned long size, unsigned long id_size,
62+
void *symval)
6163
{
64+
int i;
65+
6266
if (size % id_size || size < id_size) {
6367
fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
6468
"of the size of section __mod_%s_device_table=%lu.\n"
6569
"Fix definition of struct %s_device_id "
6670
"in mod_devicetable.h\n",
6771
modname, device_id, id_size, device_id, size, device_id);
6872
}
73+
/* Verify last one is a terminator */
74+
for (i = 0; i < id_size; i++ ) {
75+
if (*(uint8_t*)(symval+size-id_size+i)) {
76+
fprintf(stderr,"%s: struct %s_device_id is %lu bytes. "
77+
"The last of %lu is:\n",
78+
modname, device_id, id_size, size / id_size);
79+
for (i = 0; i < id_size; i++ )
80+
fprintf(stderr,"0x%02x ",
81+
*(uint8_t*)(symval+size-id_size+i) );
82+
fprintf(stderr,"\n");
83+
fatal("%s: struct %s_device_id is not terminated "
84+
"with a NULL entry!\n", modname, device_id);
85+
}
86+
}
6987
}
7088

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

171-
device_id_size_check(mod->name, "usb", size, id_size);
189+
device_id_check(mod->name, "usb", size, id_size, symval);
172190

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

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

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

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

565-
symval = (void *)info->hdr
566-
+ info->sechdrs[sym->st_shndx].sh_offset
567-
+ sym->st_value;
584+
/* Handle all-NULL symbols allocated into .bss */
585+
if (info->sechdrs[sym->st_shndx].sh_type & SHT_NOBITS) {
586+
zeros = calloc(1, sym->st_size);
587+
symval = zeros;
588+
} else {
589+
symval = (void *)info->hdr
590+
+ info->sechdrs[sym->st_shndx].sh_offset
591+
+ sym->st_value;
592+
}
568593

569594
if (sym_is(symname, "__mod_pci_device_table"))
570595
do_table(symval, sym->st_size,
@@ -637,6 +662,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
637662
do_table(symval, sym->st_size,
638663
sizeof(struct ssb_device_id), "ssb",
639664
do_ssb_entry, mod);
665+
free(zeros);
640666
}
641667

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

0 commit comments

Comments
 (0)