summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Ojeda <miguel.ojeda.sandonis@gmail.com>2019-05-23 14:45:35 +0200
committerSeung-Woo Kim <sw0312.kim@samsung.com>2019-12-24 13:12:28 +0900
commit279f52b4aed95d21025d457dfad973321d3dd860 (patch)
tree1b760212b2f060e6896d4249e09c259ee070a899
parent97dc085fa5d2cd509e18d3846d6b55eb92594b15 (diff)
downloadlinux-3.18-exynos7270-279f52b4aed95d21025d457dfad973321d3dd860.tar.gz
linux-3.18-exynos7270-279f52b4aed95d21025d457dfad973321d3dd860.tar.bz2
linux-3.18-exynos7270-279f52b4aed95d21025d457dfad973321d3dd860.zip
tracing: Silence GCC 9 array bounds warning
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 <miguel.ojeda.sandonis@gmail.com> [ Removed unnecessary parenthesis around "iter" ] Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> [sw0312.kim: backport stable linux-4.4.y commit f7247666a71 for gcc 9 build] Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com> Change-Id: I23f6f6304e67469acbd12d815fcb4882599f1829
-rw-r--r--kernel/trace/trace.c6
-rw-r--r--kernel/trace/trace.h18
-rw-r--r--kernel/trace/trace_kdb.c6
3 files changed, 20 insertions, 10 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 637f572b643..22b5c07de4f 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -6829,12 +6829,8 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
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;
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 4cf22fa591d..712260abf96 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -1312,4 +1312,22 @@ int perf_ftrace_event_register(struct ftrace_event_call *call,
#define perf_ftrace_event_register NULL
#endif
+/*
+ * 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 */
diff --git a/kernel/trace/trace_kdb.c b/kernel/trace/trace_kdb.c
index bd90e1b0608..d01fe44a1fb 100644
--- a/kernel/trace/trace_kdb.c
+++ b/kernel/trace/trace_kdb.c
@@ -36,12 +36,8 @@ static void ftrace_dump_buf(int skip_lines, long cpu_file)
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) {