From 5cb4ed053f33848da6781c25d550e6490320a327 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 22 Jun 2019 17:33:07 +0200 Subject: [PATCH] 4.14-stable patches added patches: objtool-support-per-function-rodata-sections.patch tracing-silence-gcc-9-array-bounds-warning.patch --- ...support-per-function-rodata-sections.patch | 189 ++++++++++++++++++ queue-4.14/series | 2 + ...g-silence-gcc-9-array-bounds-warning.patch | 103 ++++++++++ 3 files changed, 294 insertions(+) create mode 100644 queue-4.14/objtool-support-per-function-rodata-sections.patch create mode 100644 queue-4.14/tracing-silence-gcc-9-array-bounds-warning.patch diff --git a/queue-4.14/objtool-support-per-function-rodata-sections.patch b/queue-4.14/objtool-support-per-function-rodata-sections.patch new file mode 100644 index 00000000000..6ab52410907 --- /dev/null +++ b/queue-4.14/objtool-support-per-function-rodata-sections.patch @@ -0,0 +1,189 @@ +From 4a60aa05a0634241ce17f957bf9fb5ac1eed6576 Mon Sep 17 00:00:00 2001 +From: Allan Xavier +Date: Fri, 7 Sep 2018 08:12:01 -0500 +Subject: objtool: Support per-function rodata sections + +From: Allan Xavier + +commit 4a60aa05a0634241ce17f957bf9fb5ac1eed6576 upstream. + +Add support for processing switch jump tables in objects with multiple +.rodata sections, such as those created by '-ffunction-sections' and +'-fdata-sections'. Currently, objtool always looks in .rodata for jump +table information, which results in many "sibling call from callable +instruction with modified stack frame" warnings with objects compiled +using those flags. + +The fix is comprised of three parts: + +1. Flagging all .rodata sections when importing ELF information for + easier checking later. + +2. Keeping a reference to the section each relocation is from in order + to get the list_head for the other relocations in that section. + +3. Finding jump tables by following relocations to .rodata sections, + rather than always referencing a single global .rodata section. + +The patch has been tested without data sections enabled and no +differences in the resulting orc unwind information were seen. + +Note that as objtool adds terminators to end of each .text section the +unwind information generated between a function+data sections build and +a normal build aren't directly comparable. Manual inspection suggests +that objtool is now generating the correct information, or at least +making more of an effort to do so than it did previously. + +Signed-off-by: Allan Xavier +Signed-off-by: Josh Poimboeuf +Signed-off-by: Thomas Gleixner +Link: https://lkml.kernel.org/r/099bdc375195c490dda04db777ee0b95d566ded1.1536325914.git.jpoimboe@redhat.com +Signed-off-by: Greg Kroah-Hartman + +--- + tools/objtool/check.c | 38 ++++++++++++++++++++++++++++++++------ + tools/objtool/check.h | 4 ++-- + tools/objtool/elf.c | 1 + + tools/objtool/elf.h | 3 ++- + 4 files changed, 37 insertions(+), 9 deletions(-) + +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -814,7 +814,7 @@ static int add_switch_table(struct objto + struct symbol *pfunc = insn->func->pfunc; + unsigned int prev_offset = 0; + +- list_for_each_entry_from(rela, &file->rodata->rela->rela_list, list) { ++ list_for_each_entry_from(rela, &table->rela_sec->rela_list, list) { + if (rela == next_table) + break; + +@@ -904,6 +904,7 @@ static struct rela *find_switch_table(st + { + struct rela *text_rela, *rodata_rela; + struct instruction *orig_insn = insn; ++ struct section *rodata_sec; + unsigned long table_offset; + + /* +@@ -931,10 +932,13 @@ static struct rela *find_switch_table(st + /* look for a relocation which references .rodata */ + text_rela = find_rela_by_dest_range(insn->sec, insn->offset, + insn->len); +- if (!text_rela || text_rela->sym != file->rodata->sym) ++ if (!text_rela || text_rela->sym->type != STT_SECTION || ++ !text_rela->sym->sec->rodata) + continue; + + table_offset = text_rela->addend; ++ rodata_sec = text_rela->sym->sec; ++ + if (text_rela->type == R_X86_64_PC32) + table_offset += 4; + +@@ -942,10 +946,10 @@ static struct rela *find_switch_table(st + * Make sure the .rodata address isn't associated with a + * symbol. gcc jump tables are anonymous data. + */ +- if (find_symbol_containing(file->rodata, table_offset)) ++ if (find_symbol_containing(rodata_sec, table_offset)) + continue; + +- rodata_rela = find_rela_by_dest(file->rodata, table_offset); ++ rodata_rela = find_rela_by_dest(rodata_sec, table_offset); + if (rodata_rela) { + /* + * Use of RIP-relative switch jumps is quite rare, and +@@ -1030,7 +1034,7 @@ static int add_switch_table_alts(struct + struct symbol *func; + int ret; + +- if (!file->rodata || !file->rodata->rela) ++ if (!file->rodata) + return 0; + + for_each_sec(file, sec) { +@@ -1175,10 +1179,33 @@ static int read_retpoline_hints(struct o + return 0; + } + ++static void mark_rodata(struct objtool_file *file) ++{ ++ struct section *sec; ++ bool found = false; ++ ++ /* ++ * This searches for the .rodata section or multiple .rodata.func_name ++ * sections if -fdata-sections is being used. The .str.1.1 and .str.1.8 ++ * rodata sections are ignored as they don't contain jump tables. ++ */ ++ for_each_sec(file, sec) { ++ if (!strncmp(sec->name, ".rodata", 7) && ++ !strstr(sec->name, ".str1.")) { ++ sec->rodata = true; ++ found = true; ++ } ++ } ++ ++ file->rodata = found; ++} ++ + static int decode_sections(struct objtool_file *file) + { + int ret; + ++ mark_rodata(file); ++ + ret = decode_instructions(file); + if (ret) + return ret; +@@ -2150,7 +2177,6 @@ int check(const char *_objname, bool orc + INIT_LIST_HEAD(&file.insn_list); + hash_init(file.insn_hash); + file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard"); +- file.rodata = find_section_by_name(file.elf, ".rodata"); + file.c_file = find_section_by_name(file.elf, ".comment"); + file.ignore_unreachables = no_unreachable; + file.hints = false; +--- a/tools/objtool/check.h ++++ b/tools/objtool/check.h +@@ -60,8 +60,8 @@ struct objtool_file { + struct elf *elf; + struct list_head insn_list; + DECLARE_HASHTABLE(insn_hash, 16); +- struct section *rodata, *whitelist; +- bool ignore_unreachables, c_file, hints; ++ struct section *whitelist; ++ bool ignore_unreachables, c_file, hints, rodata; + }; + + int check(const char *objname, bool orc); +--- a/tools/objtool/elf.c ++++ b/tools/objtool/elf.c +@@ -390,6 +390,7 @@ static int read_relas(struct elf *elf) + rela->offset = rela->rela.r_offset; + symndx = GELF_R_SYM(rela->rela.r_info); + rela->sym = find_symbol_by_index(elf, symndx); ++ rela->rela_sec = sec; + if (!rela->sym) { + WARN("can't find rela entry symbol %d for %s", + symndx, sec->name); +--- a/tools/objtool/elf.h ++++ b/tools/objtool/elf.h +@@ -48,7 +48,7 @@ struct section { + char *name; + int idx; + unsigned int len; +- bool changed, text; ++ bool changed, text, rodata; + }; + + struct symbol { +@@ -68,6 +68,7 @@ struct rela { + struct list_head list; + struct hlist_node hash; + GElf_Rela rela; ++ struct section *rela_sec; + struct symbol *sym; + unsigned int type; + unsigned long offset; diff --git a/queue-4.14/series b/queue-4.14/series index e69de29bb2d..b39ee0d2d31 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -0,0 +1,2 @@ +tracing-silence-gcc-9-array-bounds-warning.patch +objtool-support-per-function-rodata-sections.patch diff --git a/queue-4.14/tracing-silence-gcc-9-array-bounds-warning.patch b/queue-4.14/tracing-silence-gcc-9-array-bounds-warning.patch new file mode 100644 index 00000000000..4c708bd103e --- /dev/null +++ b/queue-4.14/tracing-silence-gcc-9-array-bounds-warning.patch @@ -0,0 +1,103 @@ +From 0c97bf863efce63d6ab7971dad811601e6171d2f Mon Sep 17 00:00:00 2001 +From: Miguel Ojeda +Date: Thu, 23 May 2019 14:45:35 +0200 +Subject: tracing: Silence GCC 9 array bounds warning + +From: Miguel Ojeda + +commit 0c97bf863efce63d6ab7971dad811601e6171d2f upstream. + +Starting with GCC 9, -Warray-bounds detects cases when memset is called +starting on a member of a struct but the size to be cleared ends up +writing over further members. + +Such a call happens in the trace code to clear, at once, all members +after and including `seq` on struct trace_iterator: + + In function 'memset', + inlined from 'ftrace_dump' at kernel/trace/trace.c:8914:3: + ./include/linux/string.h:344:9: warning: '__builtin_memset' offset + [8505, 8560] from the object at 'iter' is out of the bounds of + referenced subobject 'seq' with type 'struct trace_seq' at offset + 4368 [-Warray-bounds] + 344 | return __builtin_memset(p, c, size); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In order to avoid GCC complaining about it, we compute the address +ourselves by adding the offsetof distance instead of referring +directly to the member. + +Since there are two places doing this clear (trace.c and trace_kdb.c), +take the chance to move the workaround into a single place in +the internal header. + +Link: http://lkml.kernel.org/r/20190523124535.GA12931@gmail.com + +Signed-off-by: Miguel Ojeda +[ Removed unnecessary parenthesis around "iter" ] +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/trace/trace.c | 6 +----- + kernel/trace/trace.h | 18 ++++++++++++++++++ + kernel/trace/trace_kdb.c | 6 +----- + 3 files changed, 20 insertions(+), 10 deletions(-) + +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -8249,12 +8249,8 @@ void ftrace_dump(enum ftrace_dump_mode o + + cnt++; + +- /* reset all but tr, trace, and overruns */ +- memset(&iter.seq, 0, +- sizeof(struct trace_iterator) - +- offsetof(struct trace_iterator, seq)); ++ trace_iterator_reset(&iter); + iter.iter_flags |= TRACE_FILE_LAT_FMT; +- iter.pos = -1; + + if (trace_find_next_entry_inc(&iter) != NULL) { + int ret; +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -1871,4 +1871,22 @@ static inline int tracing_alloc_snapshot + + extern struct trace_iterator *tracepoint_print_iter; + ++/* ++ * Reset the state of the trace_iterator so that it can read consumed data. ++ * Normally, the trace_iterator is used for reading the data when it is not ++ * consumed, and must retain state. ++ */ ++static __always_inline void trace_iterator_reset(struct trace_iterator *iter) ++{ ++ const size_t offset = offsetof(struct trace_iterator, seq); ++ ++ /* ++ * Keep gcc from complaining about overwriting more than just one ++ * member in the structure. ++ */ ++ memset((char *)iter + offset, 0, sizeof(struct trace_iterator) - offset); ++ ++ iter->pos = -1; ++} ++ + #endif /* _LINUX_KERNEL_TRACE_H */ +--- a/kernel/trace/trace_kdb.c ++++ b/kernel/trace/trace_kdb.c +@@ -41,12 +41,8 @@ static void ftrace_dump_buf(int skip_lin + + kdb_printf("Dumping ftrace buffer:\n"); + +- /* reset all but tr, trace, and overruns */ +- memset(&iter.seq, 0, +- sizeof(struct trace_iterator) - +- offsetof(struct trace_iterator, seq)); ++ trace_iterator_reset(&iter); + iter.iter_flags |= TRACE_FILE_LAT_FMT; +- iter.pos = -1; + + if (cpu_file == RING_BUFFER_ALL_CPUS) { + for_each_tracing_cpu(cpu) { -- 2.47.2