aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-22 12:49:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-22 12:49:24 -0400
commit15ce2658ddbd3db20dfba3622f3d224f01837fdc (patch)
treec1a62e6d2c0b5942cbb8624e8db9be06e28e04b0
parentf3ca10dde49043fbbb055854278b26954b549b36 (diff)
parent4a3893d069b788f3570c19c12d9e986e8e15870f (diff)
Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux
Pull module updates from Rusty Russell: "Quentin opened a can of worms by adding extable entry checking to modpost, but most architectures seem fixed now. Thanks to all involved. Last minute rebase because I noticed a "[PATCH]" had snuck into a commit message somehow" * tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux: modpost: don't emit section mismatch warnings for compiler optimizations modpost: expand pattern matching to support substring matches modpost: do not try to match the SHT_NUL section. modpost: fix extable entry size calculation. modpost: fix inverted logic in is_extable_fault_address(). modpost: handle -ffunction-sections modpost: Whitelist .text.fixup and .exception.text params: handle quotes properly for values not of form foo="bar". modpost: document the use of struct section_check. modpost: handle relocations mismatch in __ex_table. scripts: add check_extable.sh script. modpost: mismatch_handler: retrieve tosym information only when needed. modpost: factorize symbol pretty print in get_pretty_name(). modpost: add handler function pointer to sectioncheck. modpost: add .sched.text and .kprobes.text to the TEXT_SECTIONS list. modpost: add strict white-listing when referencing sections. module: do not print allocation-fail warning on bogus user buffer size kernel/module.c: fix typos in message about unused symbols
-rw-r--r--kernel/module.c9
-rw-r--r--kernel/params.c4
-rwxr-xr-xscripts/check_extable.sh146
-rw-r--r--scripts/mod/modpost.c341
4 files changed, 440 insertions, 60 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 650b038ae520..42a1d2afb217 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -387,9 +387,9 @@ static bool check_symbol(const struct symsearch *syms,
387 pr_warn("Symbol %s is marked as UNUSED, however this module is " 387 pr_warn("Symbol %s is marked as UNUSED, however this module is "
388 "using it.\n", fsa->name); 388 "using it.\n", fsa->name);
389 pr_warn("This symbol will go away in the future.\n"); 389 pr_warn("This symbol will go away in the future.\n");
390 pr_warn("Please evalute if this is the right api to use and if " 390 pr_warn("Please evaluate if this is the right api to use and "
391 "it really is, submit a report the linux kernel " 391 "if it really is, submit a report to the linux kernel "
392 "mailinglist together with submitting your code for " 392 "mailing list together with submitting your code for "
393 "inclusion.\n"); 393 "inclusion.\n");
394 } 394 }
395#endif 395#endif
@@ -2511,7 +2511,8 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
2511 return err; 2511 return err;
2512 2512
2513 /* Suck in entire file: we'll want most of it. */ 2513 /* Suck in entire file: we'll want most of it. */
2514 info->hdr = vmalloc(info->len); 2514 info->hdr = __vmalloc(info->len,
2515 GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN, PAGE_KERNEL);
2515 if (!info->hdr) 2516 if (!info->hdr)
2516 return -ENOMEM; 2517 return -ENOMEM;
2517 2518
diff --git a/kernel/params.c b/kernel/params.c
index 728e05b167de..a22d6a759b1a 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -173,9 +173,9 @@ static char *next_arg(char *args, char **param, char **val)
173 if (args[i-1] == '"') 173 if (args[i-1] == '"')
174 args[i-1] = '\0'; 174 args[i-1] = '\0';
175 } 175 }
176 if (quoted && args[i-1] == '"')
177 args[i-1] = '\0';
178 } 176 }
177 if (quoted && args[i-1] == '"')
178 args[i-1] = '\0';
179 179
180 if (args[i]) { 180 if (args[i]) {
181 args[i] = '\0'; 181 args[i] = '\0';
diff --git a/scripts/check_extable.sh b/scripts/check_extable.sh
new file mode 100755
index 000000000000..0fb6b1c97c27
--- /dev/null
+++ b/scripts/check_extable.sh
@@ -0,0 +1,146 @@
1#! /bin/bash
2# (c) 2015, Quentin Casasnovas <quentin.casasnovas@oracle.com>
3
4obj=$1
5
6file ${obj} | grep -q ELF || (echo "${obj} is not and ELF file." 1>&2 ; exit 0)
7
8# Bail out early if there isn't an __ex_table section in this object file.
9objdump -hj __ex_table ${obj} 2> /dev/null > /dev/null
10[ $? -ne 0 ] && exit 0
11
12white_list=.text,.fixup
13
14suspicious_relocs=$(objdump -rj __ex_table ${obj} | tail -n +6 |
15 grep -v $(eval echo -e{${white_list}}) | awk '{print $3}')
16
17# No suspicious relocs in __ex_table, jobs a good'un
18[ -z "${suspicious_relocs}" ] && exit 0
19
20
21# After this point, something is seriously wrong since we just found out we
22# have some relocations in __ex_table which point to sections which aren't
23# white listed. If you're adding a new section in the Linux kernel, and
24# you're expecting this section to contain code which can fault (i.e. the
25# __ex_table relocation to your new section is expected), simply add your
26# new section to the white_list variable above. If not, you're probably
27# doing something wrong and the rest of this code is just trying to print
28# you more information about it.
29
30function find_section_offset_from_symbol()
31{
32 eval $(objdump -t ${obj} | grep ${1} | sed 's/\([0-9a-f]\+\) .\{7\} \([^ \t]\+\).*/section="\2"; section_offset="0x\1" /')
33
34 # addr2line takes addresses in hexadecimal...
35 section_offset=$(printf "0x%016x" $(( ${section_offset} + $2 )) )
36}
37
38function find_symbol_and_offset_from_reloc()
39{
40 # Extract symbol and offset from the objdump output
41 eval $(echo $reloc | sed 's/\([^+]\+\)+\?\(0x[0-9a-f]\+\)\?/symbol="\1"; symbol_offset="\2"/')
42
43 # When the relocation points to the begining of a symbol or section, it
44 # won't print the offset since it is zero.
45 if [ -z "${symbol_offset}" ]; then
46 symbol_offset=0x0
47 fi
48}
49
50function find_alt_replacement_target()
51{
52 # The target of the .altinstr_replacement is the relocation just before
53 # the .altinstr_replacement one.
54 eval $(objdump -rj .altinstructions ${obj} | grep -B1 "${section}+${section_offset}" | head -n1 | awk '{print $3}' |
55 sed 's/\([^+]\+\)+\(0x[0-9a-f]\+\)/alt_target_section="\1"; alt_target_offset="\2"/')
56}
57
58function handle_alt_replacement_reloc()
59{
60 # This will define alt_target_section and alt_target_section_offset
61 find_alt_replacement_target ${section} ${section_offset}
62
63 echo "Error: found a reference to .altinstr_replacement in __ex_table:"
64 addr2line -fip -j ${alt_target_section} -e ${obj} ${alt_target_offset} | awk '{print "\t" $0}'
65
66 error=true
67}
68
69function is_executable_section()
70{
71 objdump -hwj ${section} ${obj} | grep -q CODE
72 return $?
73}
74
75function handle_suspicious_generic_reloc()
76{
77 if is_executable_section ${section}; then
78 # We've got a relocation to a non white listed _executable_
79 # section, print a warning so the developper adds the section to
80 # the white list or fix his code. We try to pretty-print the file
81 # and line number where that relocation was added.
82 echo "Warning: found a reference to section \"${section}\" in __ex_table:"
83 addr2line -fip -j ${section} -e ${obj} ${section_offset} | awk '{print "\t" $0}'
84 else
85 # Something is definitively wrong here since we've got a relocation
86 # to a non-executable section, there's no way this would ever be
87 # running in the kernel.
88 echo "Error: found a reference to non-executable section \"${section}\" in __ex_table at offset ${section_offset}"
89 error=true
90 fi
91}
92
93function handle_suspicious_reloc()
94{
95 case "${section}" in
96 ".altinstr_replacement")
97 handle_alt_replacement_reloc ${section} ${section_offset}
98 ;;
99 *)
100 handle_suspicious_generic_reloc ${section} ${section_offset}
101 ;;
102 esac
103}
104
105function diagnose()
106{
107
108 for reloc in ${suspicious_relocs}; do
109 # Let's find out where the target of the relocation in __ex_table
110 # is, this will define ${symbol} and ${symbol_offset}
111 find_symbol_and_offset_from_reloc ${reloc}
112
113 # When there's a global symbol at the place of the relocation,
114 # objdump will use it instead of giving us a section+offset, so
115 # let's find out which section is this symbol in and the total
116 # offset withing that section.
117 find_section_offset_from_symbol ${symbol} ${symbol_offset}
118
119 # In this case objdump was presenting us with a reloc to a symbol
120 # rather than a section. Now that we've got the actual section,
121 # we can skip it if it's in the white_list.
122 if [ -z "$( echo $section | grep -v $(eval echo -e{${white_list}}))" ]; then
123 continue;
124 fi
125
126 # Will either print a warning if the relocation happens to be in a
127 # section we do not know but has executable bit set, or error out.
128 handle_suspicious_reloc
129 done
130}
131
132function check_debug_info() {
133 objdump -hj .debug_info ${obj} 2> /dev/null > /dev/null ||
134 echo -e "${obj} does not contain debug information, the addr2line output will be limited.\n" \
135 "Recompile ${obj} with CONFIG_DEBUG_INFO to get a more useful output."
136}
137
138check_debug_info
139
140diagnose
141
142if [ "${error}" ]; then
143 exit 1
144fi
145
146exit 0
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index d439856f8176..91ee1b2e0f9a 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -776,6 +776,7 @@ static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr)
776 * "foo" will match an exact string equal to "foo" 776 * "foo" will match an exact string equal to "foo"
777 * "*foo" will match a string that ends with "foo" 777 * "*foo" will match a string that ends with "foo"
778 * "foo*" will match a string that begins with "foo" 778 * "foo*" will match a string that begins with "foo"
779 * "*foo*" will match a string that contains "foo"
779 */ 780 */
780static int match(const char *sym, const char * const pat[]) 781static int match(const char *sym, const char * const pat[])
781{ 782{
@@ -784,8 +785,17 @@ static int match(const char *sym, const char * const pat[])
784 p = *pat++; 785 p = *pat++;
785 const char *endp = p + strlen(p) - 1; 786 const char *endp = p + strlen(p) - 1;
786 787
788 /* "*foo*" */
789 if (*p == '*' && *endp == '*') {
790 char *here, *bare = strndup(p + 1, strlen(p) - 2);
791
792 here = strstr(sym, bare);
793 free(bare);
794 if (here != NULL)
795 return 1;
796 }
787 /* "*foo" */ 797 /* "*foo" */
788 if (*p == '*') { 798 else if (*p == '*') {
789 if (strrcmp(sym, p + 1) == 0) 799 if (strrcmp(sym, p + 1) == 0)
790 return 1; 800 return 1;
791 } 801 }
@@ -873,7 +883,10 @@ static void check_section(const char *modname, struct elf_info *elf,
873#define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS 883#define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS
874 884
875#define DATA_SECTIONS ".data", ".data.rel" 885#define DATA_SECTIONS ".data", ".data.rel"
876#define TEXT_SECTIONS ".text", ".text.unlikely" 886#define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
887 ".kprobes.text"
888#define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
889 ".fixup", ".entry.text", ".exception.text", ".text.*"
877 890
878#define INIT_SECTIONS ".init.*" 891#define INIT_SECTIONS ".init.*"
879#define MEM_INIT_SECTIONS ".meminit.*" 892#define MEM_INIT_SECTIONS ".meminit.*"
@@ -881,6 +894,9 @@ static void check_section(const char *modname, struct elf_info *elf,
881#define EXIT_SECTIONS ".exit.*" 894#define EXIT_SECTIONS ".exit.*"
882#define MEM_EXIT_SECTIONS ".memexit.*" 895#define MEM_EXIT_SECTIONS ".memexit.*"
883 896
897#define ALL_TEXT_SECTIONS ALL_INIT_TEXT_SECTIONS, ALL_EXIT_TEXT_SECTIONS, \
898 TEXT_SECTIONS, OTHER_TEXT_SECTIONS
899
884/* init data sections */ 900/* init data sections */
885static const char *const init_data_sections[] = 901static const char *const init_data_sections[] =
886 { ALL_INIT_DATA_SECTIONS, NULL }; 902 { ALL_INIT_DATA_SECTIONS, NULL };
@@ -892,6 +908,9 @@ static const char *const init_sections[] = { ALL_INIT_SECTIONS, NULL };
892static const char *const init_exit_sections[] = 908static const char *const init_exit_sections[] =
893 {ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }; 909 {ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL };
894 910
911/* all text sections */
912static const char *const text_sections[] = { ALL_TEXT_SECTIONS, NULL };
913
895/* data section */ 914/* data section */
896static const char *const data_sections[] = { DATA_SECTIONS, NULL }; 915static const char *const data_sections[] = { DATA_SECTIONS, NULL };
897 916
@@ -910,6 +929,7 @@ static const char *const data_sections[] = { DATA_SECTIONS, NULL };
910static const char *const head_sections[] = { ".head.text*", NULL }; 929static const char *const head_sections[] = { ".head.text*", NULL };
911static const char *const linker_symbols[] = 930static const char *const linker_symbols[] =
912 { "__init_begin", "_sinittext", "_einittext", NULL }; 931 { "__init_begin", "_sinittext", "_einittext", NULL };
932static const char *const optim_symbols[] = { "*.constprop.*", NULL };
913 933
914enum mismatch { 934enum mismatch {
915 TEXT_TO_ANY_INIT, 935 TEXT_TO_ANY_INIT,
@@ -921,34 +941,65 @@ enum mismatch {
921 ANY_INIT_TO_ANY_EXIT, 941 ANY_INIT_TO_ANY_EXIT,
922 ANY_EXIT_TO_ANY_INIT, 942 ANY_EXIT_TO_ANY_INIT,
923 EXPORT_TO_INIT_EXIT, 943 EXPORT_TO_INIT_EXIT,
944 EXTABLE_TO_NON_TEXT,
924}; 945};
925 946
947/**
948 * Describe how to match sections on different criterias:
949 *
950 * @fromsec: Array of sections to be matched.
951 *
952 * @bad_tosec: Relocations applied to a section in @fromsec to a section in
953 * this array is forbidden (black-list). Can be empty.
954 *
955 * @good_tosec: Relocations applied to a section in @fromsec must be
956 * targetting sections in this array (white-list). Can be empty.
957 *
958 * @mismatch: Type of mismatch.
959 *
960 * @symbol_white_list: Do not match a relocation to a symbol in this list
961 * even if it is targetting a section in @bad_to_sec.
962 *
963 * @handler: Specific handler to call when a match is found. If NULL,
964 * default_mismatch_handler() will be called.
965 *
966 */
926struct sectioncheck { 967struct sectioncheck {
927 const char *fromsec[20]; 968 const char *fromsec[20];
928 const char *tosec[20]; 969 const char *bad_tosec[20];
970 const char *good_tosec[20];
929 enum mismatch mismatch; 971 enum mismatch mismatch;
930 const char *symbol_white_list[20]; 972 const char *symbol_white_list[20];
973 void (*handler)(const char *modname, struct elf_info *elf,
974 const struct sectioncheck* const mismatch,
975 Elf_Rela *r, Elf_Sym *sym, const char *fromsec);
976
931}; 977};
932 978
979static void extable_mismatch_handler(const char *modname, struct elf_info *elf,
980 const struct sectioncheck* const mismatch,
981 Elf_Rela *r, Elf_Sym *sym,
982 const char *fromsec);
983
933static const struct sectioncheck sectioncheck[] = { 984static const struct sectioncheck sectioncheck[] = {
934/* Do not reference init/exit code/data from 985/* Do not reference init/exit code/data from
935 * normal code and data 986 * normal code and data
936 */ 987 */
937{ 988{
938 .fromsec = { TEXT_SECTIONS, NULL }, 989 .fromsec = { TEXT_SECTIONS, NULL },
939 .tosec = { ALL_INIT_SECTIONS, NULL }, 990 .bad_tosec = { ALL_INIT_SECTIONS, NULL },
940 .mismatch = TEXT_TO_ANY_INIT, 991 .mismatch = TEXT_TO_ANY_INIT,
941 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 992 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
942}, 993},
943{ 994{
944 .fromsec = { DATA_SECTIONS, NULL }, 995 .fromsec = { DATA_SECTIONS, NULL },
945 .tosec = { ALL_XXXINIT_SECTIONS, NULL }, 996 .bad_tosec = { ALL_XXXINIT_SECTIONS, NULL },
946 .mismatch = DATA_TO_ANY_INIT, 997 .mismatch = DATA_TO_ANY_INIT,
947 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 998 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
948}, 999},
949{ 1000{
950 .fromsec = { DATA_SECTIONS, NULL }, 1001 .fromsec = { DATA_SECTIONS, NULL },
951 .tosec = { INIT_SECTIONS, NULL }, 1002 .bad_tosec = { INIT_SECTIONS, NULL },
952 .mismatch = DATA_TO_ANY_INIT, 1003 .mismatch = DATA_TO_ANY_INIT,
953 .symbol_white_list = { 1004 .symbol_white_list = {
954 "*_template", "*_timer", "*_sht", "*_ops", 1005 "*_template", "*_timer", "*_sht", "*_ops",
@@ -957,56 +1008,66 @@ static const struct sectioncheck sectioncheck[] = {
957}, 1008},
958{ 1009{
959 .fromsec = { TEXT_SECTIONS, NULL }, 1010 .fromsec = { TEXT_SECTIONS, NULL },
960 .tosec = { ALL_EXIT_SECTIONS, NULL }, 1011 .bad_tosec = { ALL_EXIT_SECTIONS, NULL },
961 .mismatch = TEXT_TO_ANY_EXIT, 1012 .mismatch = TEXT_TO_ANY_EXIT,
962 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 1013 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
963}, 1014},
964{ 1015{
965 .fromsec = { DATA_SECTIONS, NULL }, 1016 .fromsec = { DATA_SECTIONS, NULL },
966 .tosec = { ALL_EXIT_SECTIONS, NULL }, 1017 .bad_tosec = { ALL_EXIT_SECTIONS, NULL },
967 .mismatch = DATA_TO_ANY_EXIT, 1018 .mismatch = DATA_TO_ANY_EXIT,
968 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 1019 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
969}, 1020},
970/* Do not reference init code/data from meminit code/data */ 1021/* Do not reference init code/data from meminit code/data */
971{ 1022{
972 .fromsec = { ALL_XXXINIT_SECTIONS, NULL }, 1023 .fromsec = { ALL_XXXINIT_SECTIONS, NULL },
973 .tosec = { INIT_SECTIONS, NULL }, 1024 .bad_tosec = { INIT_SECTIONS, NULL },
974 .mismatch = XXXINIT_TO_SOME_INIT, 1025 .mismatch = XXXINIT_TO_SOME_INIT,
975 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 1026 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
976}, 1027},
977/* Do not reference exit code/data from memexit code/data */ 1028/* Do not reference exit code/data from memexit code/data */
978{ 1029{
979 .fromsec = { ALL_XXXEXIT_SECTIONS, NULL }, 1030 .fromsec = { ALL_XXXEXIT_SECTIONS, NULL },
980 .tosec = { EXIT_SECTIONS, NULL }, 1031 .bad_tosec = { EXIT_SECTIONS, NULL },
981 .mismatch = XXXEXIT_TO_SOME_EXIT, 1032 .mismatch = XXXEXIT_TO_SOME_EXIT,
982 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 1033 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
983}, 1034},
984/* Do not use exit code/data from init code */ 1035/* Do not use exit code/data from init code */
985{ 1036{
986 .fromsec = { ALL_INIT_SECTIONS, NULL }, 1037 .fromsec = { ALL_INIT_SECTIONS, NULL },
987 .tosec = { ALL_EXIT_SECTIONS, NULL }, 1038 .bad_tosec = { ALL_EXIT_SECTIONS, NULL },
988 .mismatch = ANY_INIT_TO_ANY_EXIT, 1039 .mismatch = ANY_INIT_TO_ANY_EXIT,
989 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 1040 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
990}, 1041},
991/* Do not use init code/data from exit code */ 1042/* Do not use init code/data from exit code */
992{ 1043{
993 .fromsec = { ALL_EXIT_SECTIONS, NULL }, 1044 .fromsec = { ALL_EXIT_SECTIONS, NULL },
994 .tosec = { ALL_INIT_SECTIONS, NULL }, 1045 .bad_tosec = { ALL_INIT_SECTIONS, NULL },
995 .mismatch = ANY_EXIT_TO_ANY_INIT, 1046 .mismatch = ANY_EXIT_TO_ANY_INIT,
996 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 1047 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
997}, 1048},
998{ 1049{
999 .fromsec = { ALL_PCI_INIT_SECTIONS, NULL }, 1050 .fromsec = { ALL_PCI_INIT_SECTIONS, NULL },
1000 .tosec = { INIT_SECTIONS, NULL }, 1051 .bad_tosec = { INIT_SECTIONS, NULL },
1001 .mismatch = ANY_INIT_TO_ANY_EXIT, 1052 .mismatch = ANY_INIT_TO_ANY_EXIT,
1002 .symbol_white_list = { NULL }, 1053 .symbol_white_list = { NULL },
1003}, 1054},
1004/* Do not export init/exit functions or data */ 1055/* Do not export init/exit functions or data */
1005{ 1056{
1006 .fromsec = { "__ksymtab*", NULL }, 1057 .fromsec = { "__ksymtab*", NULL },
1007 .tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL }, 1058 .bad_tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL },
1008 .mismatch = EXPORT_TO_INIT_EXIT, 1059 .mismatch = EXPORT_TO_INIT_EXIT,
1009 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 1060 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
1061},
1062{
1063 .fromsec = { "__ex_table", NULL },
1064 /* If you're adding any new black-listed sections in here, consider
1065 * adding a special 'printer' for them in scripts/check_extable.
1066 */
1067 .bad_tosec = { ".altinstr_replacement", NULL },
1068 .good_tosec = {ALL_TEXT_SECTIONS , NULL},
1069 .mismatch = EXTABLE_TO_NON_TEXT,
1070 .handler = extable_mismatch_handler,
1010} 1071}
1011}; 1072};
1012 1073
@@ -1017,10 +1078,22 @@ static const struct sectioncheck *section_mismatch(
1017 int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck); 1078 int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck);
1018 const struct sectioncheck *check = &sectioncheck[0]; 1079 const struct sectioncheck *check = &sectioncheck[0];
1019 1080
1081 /*
1082 * The target section could be the SHT_NUL section when we're
1083 * handling relocations to un-resolved symbols, trying to match it
1084 * doesn't make much sense and causes build failures on parisc and
1085 * mn10300 architectures.
1086 */
1087 if (*tosec == '\0')
1088 return NULL;
1089
1020 for (i = 0; i < elems; i++) { 1090 for (i = 0; i < elems; i++) {
1021 if (match(fromsec, check->fromsec) && 1091 if (match(fromsec, check->fromsec)) {
1022 match(tosec, check->tosec)) 1092 if (check->bad_tosec[0] && match(tosec, check->bad_tosec))
1023 return check; 1093 return check;
1094 if (check->good_tosec[0] && !match(tosec, check->good_tosec))
1095 return check;
1096 }
1024 check++; 1097 check++;
1025 } 1098 }
1026 return NULL; 1099 return NULL;
@@ -1067,6 +1140,17 @@ static const struct sectioncheck *section_mismatch(
1067 * This pattern is identified by 1140 * This pattern is identified by
1068 * refsymname = __init_begin, _sinittext, _einittext 1141 * refsymname = __init_begin, _sinittext, _einittext
1069 * 1142 *
1143 * Pattern 5:
1144 * GCC may optimize static inlines when fed constant arg(s) resulting
1145 * in functions like cpumask_empty() -- generating an associated symbol
1146 * cpumask_empty.constprop.3 that appears in the audit. If the const that
1147 * is passed in comes from __init, like say nmi_ipi_mask, we get a
1148 * meaningless section warning. May need to add isra symbols too...
1149 * This pattern is identified by
1150 * tosec = init section
1151 * fromsec = text section
1152 * refsymname = *.constprop.*
1153 *
1070 **/ 1154 **/
1071static int secref_whitelist(const struct sectioncheck *mismatch, 1155static int secref_whitelist(const struct sectioncheck *mismatch,
1072 const char *fromsec, const char *fromsym, 1156 const char *fromsec, const char *fromsym,
@@ -1099,6 +1183,12 @@ static int secref_whitelist(const struct sectioncheck *mismatch,
1099 if (match(tosym, linker_symbols)) 1183 if (match(tosym, linker_symbols))
1100 return 0; 1184 return 0;
1101 1185
1186 /* Check for pattern 5 */
1187 if (match(fromsec, text_sections) &&
1188 match(tosec, init_sections) &&
1189 match(fromsym, optim_symbols))
1190 return 0;
1191
1102 return 1; 1192 return 1;
1103} 1193}
1104 1194
@@ -1261,6 +1351,15 @@ static void print_section_list(const char * const list[20])
1261 fprintf(stderr, "\n"); 1351 fprintf(stderr, "\n");
1262} 1352}
1263 1353
1354static inline void get_pretty_name(int is_func, const char** name, const char** name_p)
1355{
1356 switch (is_func) {
1357 case 0: *name = "variable"; *name_p = ""; break;
1358 case 1: *name = "function"; *name_p = "()"; break;
1359 default: *name = "(unknown reference)"; *name_p = ""; break;
1360 }
1361}
1362
1264/* 1363/*
1265 * Print a warning about a section mismatch. 1364 * Print a warning about a section mismatch.
1266 * Try to find symbols near it so user can find it. 1365 * Try to find symbols near it so user can find it.
@@ -1280,21 +1379,13 @@ static void report_sec_mismatch(const char *modname,
1280 char *prl_from; 1379 char *prl_from;
1281 char *prl_to; 1380 char *prl_to;
1282 1381
1283 switch (from_is_func) {
1284 case 0: from = "variable"; from_p = ""; break;
1285 case 1: from = "function"; from_p = "()"; break;
1286 default: from = "(unknown reference)"; from_p = ""; break;
1287 }
1288 switch (to_is_func) {
1289 case 0: to = "variable"; to_p = ""; break;
1290 case 1: to = "function"; to_p = "()"; break;
1291 default: to = "(unknown reference)"; to_p = ""; break;
1292 }
1293
1294 sec_mismatch_count++; 1382 sec_mismatch_count++;
1295 if (!sec_mismatch_verbose) 1383 if (!sec_mismatch_verbose)
1296 return; 1384 return;
1297 1385
1386 get_pretty_name(from_is_func, &from, &from_p);
1387 get_pretty_name(to_is_func, &to, &to_p);
1388
1298 warn("%s(%s+0x%llx): Section mismatch in reference from the %s %s%s " 1389 warn("%s(%s+0x%llx): Section mismatch in reference from the %s %s%s "
1299 "to the %s %s:%s%s\n", 1390 "to the %s %s:%s%s\n",
1300 modname, fromsec, fromaddr, from, fromsym, from_p, to, tosec, 1391 modname, fromsec, fromaddr, from, fromsym, from_p, to, tosec,
@@ -1408,41 +1499,179 @@ static void report_sec_mismatch(const char *modname,
1408 tosym, prl_to, prl_to, tosym); 1499 tosym, prl_to, prl_to, tosym);
1409 free(prl_to); 1500 free(prl_to);
1410 break; 1501 break;
1502 case EXTABLE_TO_NON_TEXT:
1503 fatal("There's a special handler for this mismatch type, "
1504 "we should never get here.");
1505 break;
1411 } 1506 }
1412 fprintf(stderr, "\n"); 1507 fprintf(stderr, "\n");
1413} 1508}
1414 1509
1415static void check_section_mismatch(const char *modname, struct elf_info *elf, 1510static void default_mismatch_handler(const char *modname, struct elf_info *elf,
1416 Elf_Rela *r, Elf_Sym *sym, const char *fromsec) 1511 const struct sectioncheck* const mismatch,
1512 Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
1417{ 1513{
1418 const char *tosec; 1514 const char *tosec;
1419 const struct sectioncheck *mismatch; 1515 Elf_Sym *to;
1516 Elf_Sym *from;
1517 const char *tosym;
1518 const char *fromsym;
1519
1520 from = find_elf_symbol2(elf, r->r_offset, fromsec);
1521 fromsym = sym_name(elf, from);
1522
1523 if (!strncmp(fromsym, "reference___initcall",
1524 sizeof("reference___initcall")-1))
1525 return;
1420 1526
1421 tosec = sec_name(elf, get_secindex(elf, sym)); 1527 tosec = sec_name(elf, get_secindex(elf, sym));
1422 mismatch = section_mismatch(fromsec, tosec); 1528 to = find_elf_symbol(elf, r->r_addend, sym);
1529 tosym = sym_name(elf, to);
1530
1531 /* check whitelist - we may ignore it */
1532 if (secref_whitelist(mismatch,
1533 fromsec, fromsym, tosec, tosym)) {
1534 report_sec_mismatch(modname, mismatch,
1535 fromsec, r->r_offset, fromsym,
1536 is_function(from), tosec, tosym,
1537 is_function(to));
1538 }
1539}
1540
1541static int is_executable_section(struct elf_info* elf, unsigned int section_index)
1542{
1543 if (section_index > elf->num_sections)
1544 fatal("section_index is outside elf->num_sections!\n");
1545
1546 return ((elf->sechdrs[section_index].sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR);
1547}
1548
1549/*
1550 * We rely on a gross hack in section_rel[a]() calling find_extable_entry_size()
1551 * to know the sizeof(struct exception_table_entry) for the target architecture.
1552 */
1553static unsigned int extable_entry_size = 0;
1554static void find_extable_entry_size(const char* const sec, const Elf_Rela* r)
1555{
1556 /*
1557 * If we're currently checking the second relocation within __ex_table,
1558 * that relocation offset tells us the offsetof(struct
1559 * exception_table_entry, fixup) which is equal to sizeof(struct
1560 * exception_table_entry) divided by two. We use that to our advantage
1561 * since there's no portable way to get that size as every architecture
1562 * seems to go with different sized types. Not pretty but better than
1563 * hard-coding the size for every architecture..
1564 */
1565 if (!extable_entry_size)
1566 extable_entry_size = r->r_offset * 2;
1567}
1568
1569static inline bool is_extable_fault_address(Elf_Rela *r)
1570{
1571 /*
1572 * extable_entry_size is only discovered after we've handled the
1573 * _second_ relocation in __ex_table, so only abort when we're not
1574 * handling the first reloc and extable_entry_size is zero.
1575 */
1576 if (r->r_offset && extable_entry_size == 0)
1577 fatal("extable_entry size hasn't been discovered!\n");
1578
1579 return ((r->r_offset == 0) ||
1580 (r->r_offset % extable_entry_size == 0));
1581}
1582
1583#define is_second_extable_reloc(Start, Cur, Sec) \
1584 (((Cur) == (Start) + 1) && (strcmp("__ex_table", (Sec)) == 0))
1585
1586static void report_extable_warnings(const char* modname, struct elf_info* elf,
1587 const struct sectioncheck* const mismatch,
1588 Elf_Rela* r, Elf_Sym* sym,
1589 const char* fromsec, const char* tosec)
1590{
1591 Elf_Sym* fromsym = find_elf_symbol2(elf, r->r_offset, fromsec);
1592 const char* fromsym_name = sym_name(elf, fromsym);
1593 Elf_Sym* tosym = find_elf_symbol(elf, r->r_addend, sym);
1594 const char* tosym_name = sym_name(elf, tosym);
1595 const char* from_pretty_name;
1596 const char* from_pretty_name_p;
1597 const char* to_pretty_name;
1598 const char* to_pretty_name_p;
1599
1600 get_pretty_name(is_function(fromsym),
1601 &from_pretty_name, &from_pretty_name_p);
1602 get_pretty_name(is_function(tosym),
1603 &to_pretty_name, &to_pretty_name_p);
1604
1605 warn("%s(%s+0x%lx): Section mismatch in reference"
1606 " from the %s %s%s to the %s %s:%s%s\n",
1607 modname, fromsec, (long)r->r_offset, from_pretty_name,
1608 fromsym_name, from_pretty_name_p,
1609 to_pretty_name, tosec, tosym_name, to_pretty_name_p);
1610
1611 if (!match(tosec, mismatch->bad_tosec) &&
1612 is_executable_section(elf, get_secindex(elf, sym)))
1613 fprintf(stderr,
1614 "The relocation at %s+0x%lx references\n"
1615 "section \"%s\" which is not in the list of\n"
1616 "authorized sections. If you're adding a new section\n"
1617 "and/or if this reference is valid, add \"%s\" to the\n"
1618 "list of authorized sections to jump to on fault.\n"
1619 "This can be achieved by adding \"%s\" to \n"
1620 "OTHER_TEXT_SECTIONS in scripts/mod/modpost.c.\n",
1621 fromsec, (long)r->r_offset, tosec, tosec, tosec);
1622}
1623
1624static void extable_mismatch_handler(const char* modname, struct elf_info *elf,
1625 const struct sectioncheck* const mismatch,
1626 Elf_Rela* r, Elf_Sym* sym,
1627 const char *fromsec)
1628{
1629 const char* tosec = sec_name(elf, get_secindex(elf, sym));
1630
1631 sec_mismatch_count++;
1632
1633 if (sec_mismatch_verbose)
1634 report_extable_warnings(modname, elf, mismatch, r, sym,
1635 fromsec, tosec);
1636
1637 if (match(tosec, mismatch->bad_tosec))
1638 fatal("The relocation at %s+0x%lx references\n"
1639 "section \"%s\" which is black-listed.\n"
1640 "Something is seriously wrong and should be fixed.\n"
1641 "You might get more information about where this is\n"
1642 "coming from by using scripts/check_extable.sh %s\n",
1643 fromsec, (long)r->r_offset, tosec, modname);
1644 else if (!is_executable_section(elf, get_secindex(elf, sym))) {
1645 if (is_extable_fault_address(r))
1646 fatal("The relocation at %s+0x%lx references\n"
1647 "section \"%s\" which is not executable, IOW\n"
1648 "it is not possible for the kernel to fault\n"
1649 "at that address. Something is seriously wrong\n"
1650 "and should be fixed.\n",
1651 fromsec, (long)r->r_offset, tosec);
1652 else
1653 fatal("The relocation at %s+0x%lx references\n"
1654 "section \"%s\" which is not executable, IOW\n"
1655 "the kernel will fault if it ever tries to\n"
1656 "jump to it. Something is seriously wrong\n"
1657 "and should be fixed.\n",
1658 fromsec, (long)r->r_offset, tosec);
1659 }
1660}
1661
1662static void check_section_mismatch(const char *modname, struct elf_info *elf,
1663 Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
1664{
1665 const char *tosec = sec_name(elf, get_secindex(elf, sym));;
1666 const struct sectioncheck *mismatch = section_mismatch(fromsec, tosec);
1667
1423 if (mismatch) { 1668 if (mismatch) {
1424 Elf_Sym *to; 1669 if (mismatch->handler)
1425 Elf_Sym *from; 1670 mismatch->handler(modname, elf, mismatch,
1426 const char *tosym; 1671 r, sym, fromsec);
1427 const char *fromsym; 1672 else
1428 1673 default_mismatch_handler(modname, elf, mismatch,
1429 from = find_elf_symbol2(elf, r->r_offset, fromsec); 1674 r, sym, fromsec);
1430 fromsym = sym_name(elf, from);
1431 to = find_elf_symbol(elf, r->r_addend, sym);
1432 tosym = sym_name(elf, to);
1433
1434 if (!strncmp(fromsym, "reference___initcall",
1435 sizeof("reference___initcall")-1))
1436 return;
1437
1438 /* check whitelist - we may ignore it */
1439 if (secref_whitelist(mismatch,
1440 fromsec, fromsym, tosec, tosym)) {
1441 report_sec_mismatch(modname, mismatch,
1442 fromsec, r->r_offset, fromsym,
1443 is_function(from), tosec, tosym,
1444 is_function(to));
1445 }
1446 } 1675 }
1447} 1676}
1448 1677
@@ -1582,6 +1811,8 @@ static void section_rela(const char *modname, struct elf_info *elf,
1582 /* Skip special sections */ 1811 /* Skip special sections */
1583 if (is_shndx_special(sym->st_shndx)) 1812 if (is_shndx_special(sym->st_shndx))
1584 continue; 1813 continue;
1814 if (is_second_extable_reloc(start, rela, fromsec))
1815 find_extable_entry_size(fromsec, &r);
1585 check_section_mismatch(modname, elf, &r, sym, fromsec); 1816 check_section_mismatch(modname, elf, &r, sym, fromsec);
1586 } 1817 }
1587} 1818}
@@ -1640,6 +1871,8 @@ static void section_rel(const char *modname, struct elf_info *elf,
1640 /* Skip special sections */ 1871 /* Skip special sections */
1641 if (is_shndx_special(sym->st_shndx)) 1872 if (is_shndx_special(sym->st_shndx))
1642 continue; 1873 continue;
1874 if (is_second_extable_reloc(start, rel, fromsec))
1875 find_extable_entry_size(fromsec, &r);
1643 check_section_mismatch(modname, elf, &r, sym, fromsec); 1876 check_section_mismatch(modname, elf, &r, sym, fromsec);
1644 } 1877 }
1645} 1878}