aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2009-12-15 17:28:32 -0500
committerRusty Russell <rusty@rustcorp.com.au>2009-12-15 00:58:34 -0500
commitd4703aefdbc8f9f347f6dcefcddd791294314eb7 (patch)
tree198936f4f91d6e571548f5b9aba9ee62e93134a6 /kernel
parenta8773769d1a1e08d0ca15f890515401ab3860637 (diff)
module: handle ppc64 relocating kcrctabs when CONFIG_RELOCATABLE=y
powerpc applies relocations to the kcrctab. They're absolute symbols, but it's not completely unreasonable: other archs may too, but the relocation is often 0. http://lists.ozlabs.org/pipermail/linuxppc-dev/2009-November/077972.html Inspired-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Tested-by: Neil Horman <nhorman@tuxdriver.com> Acked-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/module.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 12afc5a3ddd3..a65dc787a27b 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -880,11 +880,23 @@ static int try_to_force_load(struct module *mod, const char *reason)
880} 880}
881 881
882#ifdef CONFIG_MODVERSIONS 882#ifdef CONFIG_MODVERSIONS
883/* If the arch applies (non-zero) relocations to kernel kcrctab, unapply it. */
884static unsigned long maybe_relocated(unsigned long crc,
885 const struct module *crc_owner)
886{
887#ifdef ARCH_RELOCATES_KCRCTAB
888 if (crc_owner == NULL)
889 return crc - (unsigned long)reloc_start;
890#endif
891 return crc;
892}
893
883static int check_version(Elf_Shdr *sechdrs, 894static int check_version(Elf_Shdr *sechdrs,
884 unsigned int versindex, 895 unsigned int versindex,
885 const char *symname, 896 const char *symname,
886 struct module *mod, 897 struct module *mod,
887 const unsigned long *crc) 898 const unsigned long *crc,
899 const struct module *crc_owner)
888{ 900{
889 unsigned int i, num_versions; 901 unsigned int i, num_versions;
890 struct modversion_info *versions; 902 struct modversion_info *versions;
@@ -905,10 +917,10 @@ static int check_version(Elf_Shdr *sechdrs,
905 if (strcmp(versions[i].name, symname) != 0) 917 if (strcmp(versions[i].name, symname) != 0)
906 continue; 918 continue;
907 919
908 if (versions[i].crc == *crc) 920 if (versions[i].crc == maybe_relocated(*crc, crc_owner))
909 return 1; 921 return 1;
910 DEBUGP("Found checksum %lX vs module %lX\n", 922 DEBUGP("Found checksum %lX vs module %lX\n",
911 *crc, versions[i].crc); 923 maybe_relocated(*crc, crc_owner), versions[i].crc);
912 goto bad_version; 924 goto bad_version;
913 } 925 }
914 926
@@ -931,7 +943,8 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
931 if (!find_symbol(MODULE_SYMBOL_PREFIX "module_layout", NULL, 943 if (!find_symbol(MODULE_SYMBOL_PREFIX "module_layout", NULL,
932 &crc, true, false)) 944 &crc, true, false))
933 BUG(); 945 BUG();
934 return check_version(sechdrs, versindex, "module_layout", mod, crc); 946 return check_version(sechdrs, versindex, "module_layout", mod, crc,
947 NULL);
935} 948}
936 949
937/* First part is kernel version, which we ignore if module has crcs. */ 950/* First part is kernel version, which we ignore if module has crcs. */
@@ -949,7 +962,8 @@ static inline int check_version(Elf_Shdr *sechdrs,
949 unsigned int versindex, 962 unsigned int versindex,
950 const char *symname, 963 const char *symname,
951 struct module *mod, 964 struct module *mod,
952 const unsigned long *crc) 965 const unsigned long *crc,
966 const struct module *crc_owner)
953{ 967{
954 return 1; 968 return 1;
955} 969}
@@ -984,8 +998,8 @@ static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs,
984 /* use_module can fail due to OOM, 998 /* use_module can fail due to OOM,
985 or module initialization or unloading */ 999 or module initialization or unloading */
986 if (sym) { 1000 if (sym) {
987 if (!check_version(sechdrs, versindex, name, mod, crc) || 1001 if (!check_version(sechdrs, versindex, name, mod, crc, owner)
988 !use_module(mod, owner)) 1002 || !use_module(mod, owner))
989 sym = NULL; 1003 sym = NULL;
990 } 1004 }
991 return sym; 1005 return sym;