Re: [PATCH] modpost: detect unterminated device id lists



Hi Kees,


On 9/13/07, Kees Cook <kees@xxxxxxxxxx> wrote:

This patch against 2.6.23-rc6 will cause modpost to fail if any device
id lists are incorrectly terminated, after reporting the offender.

Signed-off-by: Kees Cook <kees@xxxxxxxxxx>

Nice! :-)

BTW a very similar idea (but for a different problem) was discussed in:
http://lkml.org/lkml/2007/8/23/48

I tried doing something about that, but gave up in between. For the
device_id tables, a lot of infrastructure/code already exists in modpost,
but no such luck for kobjects :-( Still, if you can do something about
that, as he mentioned, I bet Greg would gladly accept such a patch :-)


--- linux-2.6.23-rc6~/scripts/mod/file2alias.c 2007-09-11 23:17:49.000000000 -0700
+++ linux-2.6.23-rc6/scripts/mod/file2alias.c 2007-09-12 17:41:30.000000000 -0700
@@ -55,10 +55,13 @@ 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)

If you pass the Elf_Sym *sym all the way from handle_moddevtable() (which
means you can get rid of the sym->st_size argument in the call chain), then
it would be possible to print out the *symbol name* too here ...


{
+ int i;

uint8_t *p;


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"
@@ -66,6 +69,18 @@ static void device_id_size_check(const c
"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) ) {

... and:

for (p = symval+size-id_size; p < symval+size; p++) {
if (*p) {

is probably clearer ?


+ fprintf(stderr,"%s: struct %s_device_id is %lu bytes. The last of
%lu is:\n", modname, device_id, id_size, size / id_size);

As I just said, printing out just the modname and device_id "type" sounds
insufficient here. Note that they were sufficient before your patch, because
previously, this function only checked if the device_id *type* itself was
incorrectly defined. But here we're talking about a specific errant *symbol*.


+ for (i = 0; i < id_size; i++ ) {
+ fprintf(stderr,"0x%02x ", *(uint8_t*)(symval+size-id_size+i) );
+ }

Again, "for (p = symval+size-id_size; p < symval+size; p++) {"
and then "fprintf(..., *p);" would be cleaner.


+ fprintf(stderr,"\n");
+ fatal("%s: struct %s_device_id is not terminated "
+ "with a NULL entry!\n", modname, device_id);

Subtle nit, but it's not really a "NULL" entry. It's an "empty object" entry,
not a "NULL" pointer ... how about replacing "a NULL" with "an empty" ?


+ }
+ }
}

/* USB is special because the bcdDevice can be matched against a numeric range */
@@ -168,7 +183,7 @@ static void do_usb_table(void *symval, u
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;
@@ -505,7 +520,7 @@ static void do_table(void *symval, unsig
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;

@@ -527,14 +542,22 @@ void handle_moddevtable(struct module *m
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;
+ }

Hmm, I don't quite grok this case. Care to explain?


+ 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,
@@ -599,6 +622,8 @@ void handle_moddevtable(struct module *m
do_table(symval, sym->st_size,
sizeof(struct parisc_device_id), "parisc",
do_parisc_entry, mod);
+
+ if (zeros) free(zeros);
}

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


Satyam
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



Relevant Pages

  • Re: [PATCH 001/002] scripts/mod/modpost.c: New option -E to load extra symbols
    ... When building kernel modules that depend on other modules not in the main ... This situation occurs when modpost processes the new module's symbols. ... This patch works together with the second patch. ... kernel_read = optarg; ...
    (Linux-Kernel)
  • [PATCH 001/002] scripts/mod/modpost.c: New option -E to load extra symbols
    ... This patch adds a new command line option -E to modpost, ... When building kernel modules that depend on other modules not in the main ... The patch adds a new command line option -E to modpost which expects a symbol ...
    (Linux-Kernel)
  • Re: [PATCH 0/4] __cpuinitconst and __devinitconst
    ... The modpost bits turned out to take longer than expected so ... So I reworked those bits and the patch has been sent out for review. ... and omitting the 'const' (as it's really an apparently ... It can always be an incremental patch as my concpet does not prevent ...
    (Linux-Kernel)
  • kbuild:
    ... confident that keeping the checks in modpost is good. ... In a follow-up mail I will post the result of a run with this patch. ... Section mismatch is identified as references to .init* ...
    (Linux-Kernel)
  • Re: [patch 2.6.20-rc4-git] remove modpost false warnings on ARM
    ... This patch stops "modpost" from issuing erroneous modpost warnings on ARM ... The erroneous warnings appear to be issued because "modpost" whitelists ...
    (Linux-Kernel)