Skip to contentSkip to conversation

fix insidious bug with init section identification in the kernel module loader

PATCH In review James Bottomley 2 participants 3 messages Jun 12, 2003 – Jun 13, 2003

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 fix insidious bug with init section identification in the kernel module loader

This problem manifests itself nastily on parisc, where the linker seems to generate large number of elf sections, often one for each non static function, with names like

.text.<function name>

The problem is that the kernel/module.c uses the following test to identify init sections:

                           || strstr(secstrings + s->sh_name, ".init"))

Which will pass if ".init" is matched anywhere in the elf section name. Obviously, any parisc sections for functions that begin with "init" match, and are spuriously dumped into the init code.

The fix that works for me on parisc is just to check the beginning of the string for ".init". However, I can't find any document that guarantees this to be correct. On the other hand, no non-init section will begin with ".init", so the patch should be safe, just may be non optimal.

James

===== kernel/module.c 1.86 vs edited =====

kernel/module.c +5 -3
@@ -1194,7 +1194,8 @@
 			if ((s->sh_flags & masks[m][0]) != masks[m][0]
 			    || (s->sh_flags & masks[m][1])
 			    || s->sh_entsize != ~0UL
-			    || strstr(secstrings + s->sh_name, ".init"))
+			    || strncmp(secstrings + s->sh_name,
+				       ".init", 5) == 0)
 				continue;
 			s->sh_entsize = get_offset(&mod->core_size, s);
 			DEBUGP("\t%s\n", secstrings + s->sh_name);
@@ -1209,7 +1210,8 @@
 			if ((s->sh_flags & masks[m][0]) != masks[m][0]
 			    || (s->sh_flags & masks[m][1])
 			    || s->sh_entsize != ~0UL
-			    || !strstr(secstrings + s->sh_name, ".init"))
+			    || strncmp(secstrings + s->sh_name,
+				       ".init", 5) != 0)
 				continue;
 			s->sh_entsize = (get_offset(&mod->init_size, s)
 					 | INIT_OFFSET_MASK);
@@ -1413,7 +1415,7 @@
 		}
 #ifndef CONFIG_MODULE_UNLOAD
 		/* Don't load .exit sections */
-		if (strstr(secstrings+sechdrs[i].sh_name, ".exit"))
+		if (strncmp(secstrings+sechdrs[i].sh_name, ".exit", 5) == 0)
 			sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;
 #endif
 	}
#1 lore raw

In message <1055452158.2117.52.camel@mulgrave> you write:

Quoted 5 lines

This problem manifests itself nastily on parisc, where the linker seems to generate large number of elf sections, often one for each non static function, with names like

.text.<function name>

-ffunction-sections, perhaps?

Quoted 8 lines

The problem is that the kernel/module.c uses the following test to identify init sections:

                           || strstr(secstrings + s->sh_name, ".init"))

Which will pass if ".init" is matched anywhere in the elf section name. Obviously, any parisc sections for functions that begin with "init" match, and are spuriously dumped into the init code.

Yep. I agree with your fix: there are some archs which haven't changed over from ".data.init" to ".init.data", and ".data.exit" to ".exit.data", but as you point out, the worst that happens is they don't discard stuff they could.

Linus, please apply.
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

===== kernel/module.c 1.86 vs edited =====

kernel/module.c +5 -3
@@ -1194,7 +1194,8 @@
 			if ((s->sh_flags & masks[m][0]) != masks[m][0]
 			    || (s->sh_flags & masks[m][1])
 			    || s->sh_entsize != ~0UL
-			    || strstr(secstrings + s->sh_name, ".init"))
+			    || strncmp(secstrings + s->sh_name,
+				       ".init", 5) == 0)
 				continue;
 			s->sh_entsize = get_offset(&mod->core_size, s);
 			DEBUGP("\t%s\n", secstrings + s->sh_name);
@@ -1209,7 +1210,8 @@
 			if ((s->sh_flags & masks[m][0]) != masks[m][0]
 			    || (s->sh_flags & masks[m][1])
 			    || s->sh_entsize != ~0UL
-			    || !strstr(secstrings + s->sh_name, ".init"))
+			    || strncmp(secstrings + s->sh_name,
+				       ".init", 5) != 0)
 				continue;
 			s->sh_entsize = (get_offset(&mod->init_size, s)
 					 | INIT_OFFSET_MASK);
@@ -1413,7 +1415,7 @@
 		}
 #ifndef CONFIG_MODULE_UNLOAD
 		/* Don't load .exit sections */
-		if (strstr(secstrings+sechdrs[i].sh_name, ".exit"))
+		if (strncmp(secstrings+sechdrs[i].sh_name, ".exit", 5) == 0)
 			sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;
 #endif
 	}
#2 lore raw
Quoted 8 lines · Rusty Russell

In message <1055452158.2117.52.camel@mulgrave> you write:

Quoted 5 lines

This problem manifests itself nastily on parisc, where the linker seems to generate large number of elf sections, often one for each non static function, with names like

.text.<function name>

-ffunction-sections, perhaps?

Yes, we only have nineteen bit branch relocations on the parisc1.1, so we usually have to interleave trampoline stubs in between the function sections to get from one end of the kernel to the other.

I suppose as long as we never get a module bigger than 256k, we don't actually need to split modules up this way...

James