
From: Petr Vandrovec <vandrove@vc.cvut.cz>

Weak symbol may be unavailable in kernel, but if it is available, its
signature should be same as was at the build time.  If we do not attach
signatures to weak symbols, kernel is tainted when such module is loaded.

vmmon: no version for "sys_ioctl" found: kernel tainted.

I also believe that it is safer to add & check signatures here - module
wants either sys_ioctl with right signature, or no sys_ioctl at all, not
sys_ioctl with different signature (which signals that there is some
misbuild occuring).

Signed-off-by: Petr Vandrovec <vandrove@vc.cvut.cz>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (forwarded)
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/scripts/mod/modpost.c |   14 +++++++++-----
 1 files changed, 9 insertions(+), 5 deletions(-)

diff -puN scripts/mod/modpost.c~weak-symbols-in-modules-and-versioned-symbols scripts/mod/modpost.c
--- 25/scripts/mod/modpost.c~weak-symbols-in-modules-and-versioned-symbols	2004-10-21 14:55:15.344469392 -0700
+++ 25-akpm/scripts/mod/modpost.c	2004-10-21 14:55:15.347468936 -0700
@@ -104,6 +104,7 @@ struct symbol {
 	struct module *module;
 	unsigned int crc;
 	int crc_valid;
+	unsigned int weak:1;
 	char name[0];
 };
 
@@ -126,12 +127,13 @@ static inline unsigned int tdb_hash(cons
  * the list of unresolved symbols per module */
 
 struct symbol *
-alloc_symbol(const char *name, struct symbol *next)
+alloc_symbol(const char *name, unsigned int weak, struct symbol *next)
 {
 	struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1));
 
 	memset(s, 0, sizeof(*s));
 	strcpy(s->name, name);
+	s->weak = weak;
 	s->next = next;
 	return s;
 }
@@ -145,7 +147,7 @@ new_symbol(const char *name, struct modu
 	struct symbol *new;
 
 	hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
-	new = symbolhash[hash] = alloc_symbol(name, symbolhash[hash]);
+	new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]);
 	new->module = module;
 	if (crc) {
 		new->crc = *crc;
@@ -349,7 +351,8 @@ handle_modversions(struct module *mod, s
 		break;
 	case SHN_UNDEF:
 		/* undefined symbol */
-		if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL)
+		if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL &&
+		    ELF_ST_BIND(sym->st_info) != STB_WEAK)
 			break;
 		/* ignore global offset table */
 		if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0)
@@ -370,6 +373,7 @@ handle_modversions(struct module *mod, s
 			   strlen(MODULE_SYMBOL_PREFIX)) == 0)
 			mod->unres = alloc_symbol(symname +
 						  strlen(MODULE_SYMBOL_PREFIX),
+						  ELF_ST_BIND(sym->st_info) == STB_WEAK,
 						  mod->unres);
 		break;
 	default:
@@ -476,7 +480,7 @@ read_symbols(char *modname)
 	 * the automatic versioning doesn't pick it up, but it's really
 	 * important anyhow */
 	if (modversions)
-		mod->unres = alloc_symbol("struct_module", mod->unres);
+		mod->unres = alloc_symbol("struct_module", 0, mod->unres);
 }
 
 #define SZ 500
@@ -548,7 +552,7 @@ add_versions(struct buffer *b, struct mo
 	for (s = mod->unres; s; s = s->next) {
 		exp = find_symbol(s->name);
 		if (!exp || exp->module == mod) {
-			if (have_vmlinux)
+			if (have_vmlinux && !s->weak)
 				fprintf(stderr, "*** Warning: \"%s\" [%s.ko] "
 				"undefined!\n",	s->name, mod->name);
 			continue;
_
