[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20240613133711.2867745-6-zhengyejian1@huawei.com>
Date: Thu, 13 Jun 2024 21:37:10 +0800
From: Zheng Yejian <zhengyejian1@...wei.com>
To: <rostedt@...dmis.org>, <mhiramat@...nel.org>, <mark.rutland@....com>,
<mpe@...erman.id.au>, <npiggin@...il.com>, <christophe.leroy@...roup.eu>,
<naveen.n.rao@...ux.ibm.com>, <tglx@...utronix.de>, <mingo@...hat.com>,
<bp@...en8.de>, <dave.hansen@...ux.intel.com>, <x86@...nel.org>,
<hpa@...or.com>, <mcgrof@...nel.org>, <mathieu.desnoyers@...icios.com>,
<masahiroy@...nel.org>, <nathan@...nel.org>, <nicolas@...sle.eu>,
<kees@...nel.org>, <james.clark@....com>, <kent.overstreet@...ux.dev>,
<yhs@...com>, <jpoimboe@...nel.org>, <peterz@...radead.org>
CC: <zhengyejian1@...wei.com>, <linux-kernel@...r.kernel.org>,
<linux-trace-kernel@...r.kernel.org>, <linuxppc-dev@...ts.ozlabs.org>,
<linux-modules@...r.kernel.org>, <linux-kbuild@...r.kernel.org>,
<bpf@...r.kernel.org>
Subject: [PATCH 5/6] ftrace: Fix possible out-of-bound issue in ftrace_process_locs()
In ftrace_process_locs(), a series pages are prepared and linked in
start_pg, then fentry records are skipped or added, then unused pages
are freed.
However, assume that all records are skipped, currently the start_pg
will still be in list of ftrace_pages_start but without any record.
Then in ftrace_free_mem() index record by (pg->index - 1) will be out
of bound.
To fix this issue, properly handle with unused start_pg and add
WARN_ON_ONCE() where the records need to be indexed.
Fixes: 26efd79c4624 ("ftrace: Fix possible warning on checking all pages used in ftrace_process_locs()")
Signed-off-by: Zheng Yejian <zhengyejian1@...wei.com>
---
kernel/trace/ftrace.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 0e8628e4d296..c46c35ac9b42 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -6575,10 +6575,22 @@ static int ftrace_process_locs(struct module *mod,
rec->ip = addr;
}
- if (pg->next) {
+ if (pg->index == 0) {
+ /* No record is added on the current page, so it's unused */
+ pg_unuse = pg;
+ } else if (pg->next) {
+ /* Current page has records, so it's next page is unused */
pg_unuse = pg->next;
pg->next = NULL;
}
+ /*
+ * Even the start_pg hasn't been used, that means, no record has
+ * been added, so restore state of ftrace_pages and just go out.
+ */
+ if (pg_unuse == start_pg) {
+ ftrace_pages->next = NULL;
+ goto out;
+ }
/* Assign the last page to ftrace_pages */
ftrace_pages = pg;
@@ -6794,6 +6806,8 @@ void ftrace_release_mod(struct module *mod)
*/
last_pg = &ftrace_pages_start;
for (pg = ftrace_pages_start; pg; pg = *last_pg) {
+ /* The page should have at lease one record */
+ WARN_ON_ONCE(!pg->index);
rec = &pg->records[0];
if (within_module(rec->ip, mod)) {
/*
@@ -7176,6 +7190,8 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
mod_map = allocate_ftrace_mod_map(mod, start, end);
for (pg = ftrace_pages_start; pg; last_pg = &pg->next, pg = *last_pg) {
+ /* The page should have at lease one record */
+ WARN_ON_ONCE(!pg->index);
if (end < pg->records[0].ip ||
start >= (pg->records[pg->index - 1].ip + MCOUNT_INSN_SIZE))
continue;
--
2.25.1
Powered by blists - more mailing lists