diff options
author | Masahiro Yamada <yamada.masahiro@socionext.com> | 2019-09-09 06:53:17 -0400 |
---|---|---|
committer | Masahiro Yamada <yamada.masahiro@socionext.com> | 2019-09-13 22:40:13 -0400 |
commit | 69a94abb82eed2789d52b58665ddf4b454d9adb9 (patch) | |
tree | 44726fe41be6d99ecadfbedeae87722f317ad77a | |
parent | a0469f989fe1d051820cda7ead496f1a7371f3d8 (diff) |
export.h, genksyms: do not make genksyms calculate CRC of trimmed symbols
Arnd Bergmann reported false-positive modpost warnings detected by his
randconfig testing of linux-next.
Actually, this happens under the combination of CONFIG_MODVERSIONS
and CONFIG_TRIM_UNUSED_KSYMS since commit 15bfc2348d54 ("modpost:
check for static EXPORT_SYMBOL* functions").
For example, arch/arm/config/multi_v7_defconfig + CONFIG_MODVERSIONS
+ CONFIG_TRIM_UNUSED_KSYMS produces the following false-positives:
WARNING: "__lshrdi3" [vmlinux] is a static (unknown)
WARNING: "__ashrdi3" [vmlinux] is a static (unknown)
WARNING: "__aeabi_lasr" [vmlinux] is a static (unknown)
WARNING: "__aeabi_llsr" [vmlinux] is a static (unknown)
WARNING: "ftrace_set_clr_event" [vmlinux] is a static (unknown)
WARNING: "__muldi3" [vmlinux] is a static (unknown)
WARNING: "__aeabi_ulcmp" [vmlinux] is a static (unknown)
WARNING: "__ucmpdi2" [vmlinux] is a static (unknown)
WARNING: "__aeabi_lmul" [vmlinux] is a static (unknown)
WARNING: "__bswapsi2" [vmlinux] is a static (unknown)
WARNING: "__bswapdi2" [vmlinux] is a static (unknown)
WARNING: "__ashldi3" [vmlinux] is a static (unknown)
WARNING: "__aeabi_llsl" [vmlinux] is a static (unknown)
The root cause of the problem is not in the modpost, but in the
implementation of CONFIG_TRIM_UNUSED_KSYMS.
If there is at least one untrimmed symbol in the file, genksyms is
invoked to calculate CRC of *all* the exported symbols in that file
even if some of them have been trimmed due to no caller existing.
As a result, .tmp_*.ver files contain CRC of trimmed symbols, thus
unneeded, orphan __crc* symbols are added to objects. It had been
harmless until recently.
With commit 15bfc2348d54 ("modpost: check for static EXPORT_SYMBOL*
functions"), it is now harmful because the bogus __crc* symbols make
modpost call sym_update_crc() to add the symbols to the hash table,
but there is no one that clears the ->is_static member.
I gave Fixes to the first commit that uncovered the issue, but the
potential problem has long existed since commit f235541699bc
("export.h: allow for per-symbol configurable EXPORT_SYMBOL()").
Fixes: 15bfc2348d54 ("modpost: check for static EXPORT_SYMBOL* functions")
Reported-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Tested-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | include/linux/export.h | 42 | ||||
-rw-r--r-- | scripts/genksyms/keywords.c | 6 |
2 files changed, 17 insertions, 31 deletions
diff --git a/include/linux/export.h b/include/linux/export.h index cdd98a0d918c..7d8c112a8b61 100644 --- a/include/linux/export.h +++ b/include/linux/export.h | |||
@@ -18,9 +18,6 @@ extern struct module __this_module; | |||
18 | #define THIS_MODULE ((struct module *)0) | 18 | #define THIS_MODULE ((struct module *)0) |
19 | #endif | 19 | #endif |
20 | 20 | ||
21 | #ifdef CONFIG_MODULES | ||
22 | |||
23 | #if !defined(__GENKSYMS__) | ||
24 | #ifdef CONFIG_MODVERSIONS | 21 | #ifdef CONFIG_MODVERSIONS |
25 | /* Mark the CRC weak since genksyms apparently decides not to | 22 | /* Mark the CRC weak since genksyms apparently decides not to |
26 | * generate a checksums for some symbols */ | 23 | * generate a checksums for some symbols */ |
@@ -74,6 +71,12 @@ struct kernel_symbol { | |||
74 | }; | 71 | }; |
75 | #endif | 72 | #endif |
76 | 73 | ||
74 | #ifdef __GENKSYMS__ | ||
75 | |||
76 | #define ___EXPORT_SYMBOL(sym, sec) __GENKSYMS_EXPORT_SYMBOL(sym) | ||
77 | |||
78 | #else | ||
79 | |||
77 | /* For every exported symbol, place a struct in the __ksymtab section */ | 80 | /* For every exported symbol, place a struct in the __ksymtab section */ |
78 | #define ___EXPORT_SYMBOL(sym, sec) \ | 81 | #define ___EXPORT_SYMBOL(sym, sec) \ |
79 | extern typeof(sym) sym; \ | 82 | extern typeof(sym) sym; \ |
@@ -83,7 +86,9 @@ struct kernel_symbol { | |||
83 | = #sym; \ | 86 | = #sym; \ |
84 | __KSYMTAB_ENTRY(sym, sec) | 87 | __KSYMTAB_ENTRY(sym, sec) |
85 | 88 | ||
86 | #if defined(__DISABLE_EXPORTS) | 89 | #endif |
90 | |||
91 | #if !defined(CONFIG_MODULES) || defined(__DISABLE_EXPORTS) | ||
87 | 92 | ||
88 | /* | 93 | /* |
89 | * Allow symbol exports to be disabled completely so that C code may | 94 | * Allow symbol exports to be disabled completely so that C code may |
@@ -117,37 +122,22 @@ struct kernel_symbol { | |||
117 | #define __cond_export_sym_0(sym, sec) /* nothing */ | 122 | #define __cond_export_sym_0(sym, sec) /* nothing */ |
118 | 123 | ||
119 | #else | 124 | #else |
120 | #define __EXPORT_SYMBOL ___EXPORT_SYMBOL | ||
121 | #endif | ||
122 | 125 | ||
123 | #define EXPORT_SYMBOL(sym) \ | 126 | #define __EXPORT_SYMBOL(sym, sec) ___EXPORT_SYMBOL(sym, sec) |
124 | __EXPORT_SYMBOL(sym, "") | ||
125 | 127 | ||
126 | #define EXPORT_SYMBOL_GPL(sym) \ | 128 | #endif /* CONFIG_MODULES */ |
127 | __EXPORT_SYMBOL(sym, "_gpl") | ||
128 | |||
129 | #define EXPORT_SYMBOL_GPL_FUTURE(sym) \ | ||
130 | __EXPORT_SYMBOL(sym, "_gpl_future") | ||
131 | 129 | ||
130 | #define EXPORT_SYMBOL(sym) __EXPORT_SYMBOL(sym, "") | ||
131 | #define EXPORT_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_gpl") | ||
132 | #define EXPORT_SYMBOL_GPL_FUTURE(sym) __EXPORT_SYMBOL(sym, "_gpl_future") | ||
132 | #ifdef CONFIG_UNUSED_SYMBOLS | 133 | #ifdef CONFIG_UNUSED_SYMBOLS |
133 | #define EXPORT_UNUSED_SYMBOL(sym) __EXPORT_SYMBOL(sym, "_unused") | 134 | #define EXPORT_UNUSED_SYMBOL(sym) __EXPORT_SYMBOL(sym, "_unused") |
134 | #define EXPORT_UNUSED_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_unused_gpl") | 135 | #define EXPORT_UNUSED_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_unused_gpl") |
135 | #else | 136 | #else |
136 | #define EXPORT_UNUSED_SYMBOL(sym) | 137 | #define EXPORT_UNUSED_SYMBOL(sym) |
137 | #define EXPORT_UNUSED_SYMBOL_GPL(sym) | 138 | #define EXPORT_UNUSED_SYMBOL_GPL(sym) |
138 | #endif | 139 | #endif |
139 | 140 | ||
140 | #endif /* __GENKSYMS__ */ | ||
141 | |||
142 | #else /* !CONFIG_MODULES... */ | ||
143 | |||
144 | #define EXPORT_SYMBOL(sym) | ||
145 | #define EXPORT_SYMBOL_GPL(sym) | ||
146 | #define EXPORT_SYMBOL_GPL_FUTURE(sym) | ||
147 | #define EXPORT_UNUSED_SYMBOL(sym) | ||
148 | #define EXPORT_UNUSED_SYMBOL_GPL(sym) | ||
149 | |||
150 | #endif /* CONFIG_MODULES */ | ||
151 | #endif /* !__ASSEMBLY__ */ | 141 | #endif /* !__ASSEMBLY__ */ |
152 | 142 | ||
153 | #endif /* _LINUX_EXPORT_H */ | 143 | #endif /* _LINUX_EXPORT_H */ |
diff --git a/scripts/genksyms/keywords.c b/scripts/genksyms/keywords.c index c586d32dd2c3..7a85c4e21175 100644 --- a/scripts/genksyms/keywords.c +++ b/scripts/genksyms/keywords.c | |||
@@ -3,11 +3,7 @@ static struct resword { | |||
3 | const char *name; | 3 | const char *name; |
4 | int token; | 4 | int token; |
5 | } keywords[] = { | 5 | } keywords[] = { |
6 | { "EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW }, | 6 | { "__GENKSYMS_EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW }, |
7 | { "EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW }, | ||
8 | { "EXPORT_SYMBOL_GPL_FUTURE", EXPORT_SYMBOL_KEYW }, | ||
9 | { "EXPORT_UNUSED_SYMBOL", EXPORT_SYMBOL_KEYW }, | ||
10 | { "EXPORT_UNUSED_SYMBOL_GPL", EXPORT_SYMBOL_KEYW }, | ||
11 | { "__asm", ASM_KEYW }, | 7 | { "__asm", ASM_KEYW }, |
12 | { "__asm__", ASM_KEYW }, | 8 | { "__asm__", ASM_KEYW }, |
13 | { "__attribute", ATTRIBUTE_KEYW }, | 9 | { "__attribute", ATTRIBUTE_KEYW }, |