diff options
author | Tejun Heo <tj@kernel.org> | 2010-01-04 19:17:33 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2010-01-04 19:17:33 -0500 |
commit | 32032df6c2f6c9c6b2ada2ce42322231824f70c2 (patch) | |
tree | b1ce838a37044bb38dfc128e2116ca35630e629a /kernel/module.c | |
parent | 22b737f4c75197372d64afc6ed1bccd58c00e549 (diff) | |
parent | c5974b835a909ff15c3b7e6cf6789b5eb919f419 (diff) |
Merge branch 'master' into percpu
Conflicts:
arch/powerpc/platforms/pseries/hvCall.S
include/linux/percpu.h
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 46 |
1 files changed, 33 insertions, 13 deletions
diff --git a/kernel/module.c b/kernel/module.c index 64787cddeb5e..e96b8ed1cb6a 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. */ | ||
884 | static 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 | |||
883 | static int check_version(Elf_Shdr *sechdrs, | 894 | static 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; |
@@ -1037,7 +1051,8 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect, | |||
1037 | 1051 | ||
1038 | /* Count loaded sections and allocate structures */ | 1052 | /* Count loaded sections and allocate structures */ |
1039 | for (i = 0; i < nsect; i++) | 1053 | for (i = 0; i < nsect; i++) |
1040 | if (sechdrs[i].sh_flags & SHF_ALLOC) | 1054 | if (sechdrs[i].sh_flags & SHF_ALLOC |
1055 | && sechdrs[i].sh_size) | ||
1041 | nloaded++; | 1056 | nloaded++; |
1042 | size[0] = ALIGN(sizeof(*sect_attrs) | 1057 | size[0] = ALIGN(sizeof(*sect_attrs) |
1043 | + nloaded * sizeof(sect_attrs->attrs[0]), | 1058 | + nloaded * sizeof(sect_attrs->attrs[0]), |
@@ -1057,6 +1072,8 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect, | |||
1057 | for (i = 0; i < nsect; i++) { | 1072 | for (i = 0; i < nsect; i++) { |
1058 | if (! (sechdrs[i].sh_flags & SHF_ALLOC)) | 1073 | if (! (sechdrs[i].sh_flags & SHF_ALLOC)) |
1059 | continue; | 1074 | continue; |
1075 | if (!sechdrs[i].sh_size) | ||
1076 | continue; | ||
1060 | sattr->address = sechdrs[i].sh_addr; | 1077 | sattr->address = sechdrs[i].sh_addr; |
1061 | sattr->name = kstrdup(secstrings + sechdrs[i].sh_name, | 1078 | sattr->name = kstrdup(secstrings + sechdrs[i].sh_name, |
1062 | GFP_KERNEL); | 1079 | GFP_KERNEL); |
@@ -1893,9 +1910,7 @@ static void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr, | |||
1893 | unsigned int i; | 1910 | unsigned int i; |
1894 | 1911 | ||
1895 | /* only scan the sections containing data */ | 1912 | /* only scan the sections containing data */ |
1896 | kmemleak_scan_area(mod->module_core, (unsigned long)mod - | 1913 | kmemleak_scan_area(mod, sizeof(struct module), GFP_KERNEL); |
1897 | (unsigned long)mod->module_core, | ||
1898 | sizeof(struct module), GFP_KERNEL); | ||
1899 | 1914 | ||
1900 | for (i = 1; i < hdr->e_shnum; i++) { | 1915 | for (i = 1; i < hdr->e_shnum; i++) { |
1901 | if (!(sechdrs[i].sh_flags & SHF_ALLOC)) | 1916 | if (!(sechdrs[i].sh_flags & SHF_ALLOC)) |
@@ -1904,8 +1919,7 @@ static void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr, | |||
1904 | && strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) != 0) | 1919 | && strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) != 0) |
1905 | continue; | 1920 | continue; |
1906 | 1921 | ||
1907 | kmemleak_scan_area(mod->module_core, sechdrs[i].sh_addr - | 1922 | kmemleak_scan_area((void *)sechdrs[i].sh_addr, |
1908 | (unsigned long)mod->module_core, | ||
1909 | sechdrs[i].sh_size, GFP_KERNEL); | 1923 | sechdrs[i].sh_size, GFP_KERNEL); |
1910 | } | 1924 | } |
1911 | } | 1925 | } |
@@ -2233,6 +2247,12 @@ static noinline struct module *load_module(void __user *umod, | |||
2233 | "_ftrace_events", | 2247 | "_ftrace_events", |
2234 | sizeof(*mod->trace_events), | 2248 | sizeof(*mod->trace_events), |
2235 | &mod->num_trace_events); | 2249 | &mod->num_trace_events); |
2250 | /* | ||
2251 | * This section contains pointers to allocated objects in the trace | ||
2252 | * code and not scanning it leads to false positives. | ||
2253 | */ | ||
2254 | kmemleak_scan_area(mod->trace_events, sizeof(*mod->trace_events) * | ||
2255 | mod->num_trace_events, GFP_KERNEL); | ||
2236 | #endif | 2256 | #endif |
2237 | #ifdef CONFIG_FTRACE_MCOUNT_RECORD | 2257 | #ifdef CONFIG_FTRACE_MCOUNT_RECORD |
2238 | /* sechdrs[0].sh_size is always zero */ | 2258 | /* sechdrs[0].sh_size is always zero */ |