From: Rusty Russell <rusty@rustcorp.com.au>
Subject: module: fix overlapping entries in symtab case.

The prior patch didn't handle the (theoretical?) case where strings in
the strtab are partially shared by two symtab entries.  This detects
that correctly, and does an exhaustive search for that case.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 kernel/module.c |   29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2221,7 +2221,7 @@ static void layout_symtab(struct module 
 
 static void add_kallsyms(struct module *mod, const struct load_info *info)
 {
-	unsigned int i, j, stridx = 1, ndst;
+	unsigned int i, ndst;
 	const Elf_Sym *src;
 	Elf_Sym *dst;
 	char *s;
@@ -2242,23 +2242,26 @@ static void add_kallsyms(struct module *
 	*dst = *src;
 	*s++ = 0;
 	for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) {
+		const char *name;
 		if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum))
 			continue;
 		dst[ndst] = *src;
+
+		name = &mod->strtab[src->st_name];
 		if (unlikely(!test_bit(src->st_name, info->strmap))) {
-			dst[ndst].st_name = 0;
-			for (j = 1; j < ndst; j++)
-				if (!strcmp(&mod->strtab[src->st_name],
-					    &mod->core_strtab[dst[j].st_name]))
-					dst[ndst].st_name = dst[j].st_name;
+			char *dup;
+
+			for (dup = mod->core_strtab; strcmp(dup, name); dup++)
+				BUG_ON(dup > s);
+
+			dst[ndst].st_name = dup - mod->core_strtab;
 		} else {
-			dst[ndst].st_name = stridx;
-			j = src->st_name;
-			clear_bit(j, info->strmap);
-			do {
-				*s = mod->strtab[j++];
-				stridx++;
-			} while (*s++);
+			unsigned len = strlen(name) + 1;
+
+			dst[ndst].st_name = s - mod->core_strtab;
+			memcpy(s, name, len);
+			s += len;
+			bitmap_clear(info->strmap, src->st_name, len);
 		}
 		++ndst;
 	}
