tracing: Fix double free when function profile init failed
PATCH 1/3 tracing: Fix double free when function profile init failed
From: Namhyung Kim <[email protected]>
On the failure path, stat->start and stat->pages will refer same page. So it'll attempt to free the same page again and get kernel panic.
--- kernel/trace/ftrace.c | 1 - 1 file changed, 1 deletion(-)
kernel/trace/ftrace.c +0 -1
@@ -694,7 +694,6 @@ int ftrace_profile_pages_init(struct ftrace_profile_stat *stat)free_page (tmp); } -free_page ((unsigned long )stat->pages); stat->pages =NULL ; stat->start =NULL ;
Signature · 1 line
1.7.11.7
PATCH 2/3 tracing: Fix off-by-one on allocating stat->pages
From: Namhyung Kim <[email protected]>
The first page was allocated separately, so no need to start from 0.
--- kernel/trace/ftrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/trace/ftrace.c +1 -1
@@ -676,7 +676,7 @@ int ftrace_profile_pages_init(struct ftrace_profile_stat *stat) pages =DIV_ROUND_UP (functions,PROFILES_PER_PAGE ); -for (i =0 ; i < pages; i++) { +for (i =1 ; i < pages; i++) { pg->next = (void *)get_zeroed_page (GFP_KERNEL );if (!pg->next) goto out_free;
Signature · 1 line
1.7.11.7
PATCH 3/3 ftrace: Constify ftrace_profile_bits
In reply to Namhyung KimFrom: Namhyung Kim <[email protected]>
It seems that function profiler's hash size is fixed at 1024. Make the ftrace_profile_bits const and update hash size macro.
--- kernel/trace/ftrace.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-)
kernel/trace/ftrace.c +4 -9
@@ -486,7 +486,6 @@ struct ftrace_profile_stat {#define PROFILES_PER_PAGE \ (PROFILE_RECORDS_SIZE / sizeof(struct ftrace_profile)) -static int ftrace_profile_bits__read_mostly ;static int ftrace_profile_enabled__read_mostly ;/* ftrace_profile_lock - synchronize the enable and disable of the profiler */
@@ -494,7 +493,10 @@ static DEFINE_MUTEX(ftrace_profile_lock); static DEFINE_PER_CPU(struct ftrace_profile_stat, ftrace_profile_stats); -#define FTRACE_PROFILE_HASH_SIZE 1024/* must be power of 2 */ +#define FTRACE_PROFILE_HASH_BITS 10 +#define FTRACE_PROFILE_HASH_SIZE (1 << FTRACE_PROFILE_HASH_BITS) + +static const int ftrace_profile_bits =FTRACE_PROFILE_HASH_BITS ;static void *function_stat_next (void *v,int idx)
@@ -724,13 +726,6 @@ static int ftrace_profile_init_cpu(int cpu)if (!stat->hash)return -ENOMEM ; -if (!ftrace_profile_bits) { - size--; - -for (; size; size >>=1 ) - ftrace_profile_bits++; - } -/* Preallocate the function profiling pages */ if (ftrace_profile_pages_init (stat) <0 ) {kfree (stat->hash);
Signature · 1 line
1.7.11.7
Steven Rostedt
maintainerRe: [PATCH 3/3] ftrace: Constify ftrace_profile_bits
Quoted 5 lines · Namhyung Kim
From: Namhyung Kim <[email protected]>
It seems that function profiler's hash size is fixed at 1024. Make the
ftrace_profile_bitsconst and update hash size macro.
Thanks for the fixes. As patch 1/3 fixes a real bug (one that can cause a panic), I've labeled it as stable and will push it for 3.9.
Patch 2/3 just saves memory. I'll mark it stable, but it can wait to go into 3.10.
This patch is more of a clean up, and will only go into 3.10.
Thanks!
-- Steve
Steven Rostedt
maintainerRe: [PATCH 3/3] ftrace: Constify ftrace_profile_bits
In reply to Namhyung KimQuoted 23 lines · Namhyung Kim
From: Namhyung Kim <[email protected]>
It seems that function profiler's hash size is fixed at 1024. Make the
ftrace_profile_bitsconst and update hash size macro.Signed-off-by Namhyung Kim <[email protected]>--- kernel/trace/ftrace.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-)kernel/trace/ftrace.c +0
-1@@ -486,7 +486,6 @@ struct ftrace_profile_stat {#define PROFILES_PER_PAGE \ (PROFILE_RECORDS_SIZE / sizeof(struct ftrace_profile)) -static int ftrace_profile_bits__read_mostly ;static int ftrace_profile_enabled__read_mostly ;/* ftrace_profile_lock - synchronize the enable and disable of the profiler */
kernel/trace/ftrace.c static DEFINE_MUTEX(ftrace_profile_lock); · line 499
Quoted 8 lines
kernel/trace/ftrace.c +4
-1@@ -494,7 +493,10 @@ static DEFINE_MUTEX(ftrace_profile_lock); static DEFINE_PER_CPU(struct ftrace_profile_stat, ftrace_profile_stats); -#define FTRACE_PROFILE_HASH_SIZE 1024/* must be power of 2 */ +#define FTRACE_PROFILE_HASH_BITS 10 +#define FTRACE_PROFILE_HASH_SIZE (1 << FTRACE_PROFILE_HASH_BITS) + +static const int ftrace_profile_bits =FTRACE_PROFILE_HASH_BITS ;
Actually, can you resubmit this, and remove ftrace_profile_bits totally, and just use FTRACE_PROFILE_HASH_BITS directly?
Thanks,
-- Steve
Quoted 17 lines
kernel/trace/ftrace.c +0
-7static void *function_stat_next (void *v,int idx)@@ -724,13 +726,6 @@ static int ftrace_profile_init_cpu(int cpu)if (!stat->hash)return -ENOMEM ; -if (!ftrace_profile_bits) { - size--; - -for (; size; size >>=1 ) - ftrace_profile_bits++; - } -/* Preallocate the function profiling pages */ if (ftrace_profile_pages_init (stat) <0 ) {kfree (stat->hash);
PATCH v2 3/3 ftrace: Get rid of ftrace_profile_bits
From: Namhyung Kim <[email protected]>
It seems that function profiler's hash size is fixed at 1024. Add and use FTRACE_PROFILE_HASH_BITS instead and update hash size macro.
--- kernel/trace/ftrace.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-)
kernel/trace/ftrace.c +4 -11
@@ -486,7 +486,6 @@ struct ftrace_profile_stat {#define PROFILES_PER_PAGE \ (PROFILE_RECORDS_SIZE / sizeof(struct ftrace_profile)) -static int ftrace_profile_bits__read_mostly ;static int ftrace_profile_enabled__read_mostly ;/* ftrace_profile_lock - synchronize the enable and disable of the profiler */
@@ -494,7 +493,8 @@ static DEFINE_MUTEX(ftrace_profile_lock); static DEFINE_PER_CPU(struct ftrace_profile_stat, ftrace_profile_stats); -#define FTRACE_PROFILE_HASH_SIZE 1024/* must be power of 2 */ +#define FTRACE_PROFILE_HASH_BITS 10 +#define FTRACE_PROFILE_HASH_SIZE (1 << FTRACE_PROFILE_HASH_BITS)static void *function_stat_next (void *v,int idx)
@@ -724,13 +724,6 @@ static int ftrace_profile_init_cpu(int cpu)if (!stat->hash)return -ENOMEM ; -if (!ftrace_profile_bits) { - size--; - -for (; size; size >>=1 ) - ftrace_profile_bits++; - } -/* Preallocate the function profiling pages */ if (ftrace_profile_pages_init (stat) <0 ) {kfree (stat->hash);
@@ -764,7 +757,7 @@ ftrace_find_profiled_func(struct ftrace_profile_stat *stat, unsigned long ip)struct hlist_node *n;unsigned long key; - key =hash_long (ip, ftrace_profile_bits); + key =hash_long (ip,FTRACE_PROFILE_HASH_BITS ); hhd = &stat->hash[key];if (hlist_empty (hhd))
@@ -783,7 +776,7 @@ static void ftrace_add_profile(struct ftrace_profile_stat *stat, {unsigned long key; - key =hash_long (rec->ip, ftrace_profile_bits); + key =hash_long (rec->ip,FTRACE_PROFILE_HASH_BITS );hlist_add_head_rcu (&rec->node, &stat->hash[key]); }
Signature · 1 line
1.7.11.7
Steven Rostedt
maintainerRe: [PATCH v2 3/3] ftrace: Get rid of ftrace_profile_bits
Quoted 4 lines · Namhyung Kim
From: Namhyung Kim <[email protected]>
It seems that function profiler's hash size is fixed at 1024. Add and use
FTRACE_PROFILE_HASH_BITSinstead and update hash size macro.
Thanks! I'll queue it in my 3.10 branch.
-- Steve
Quoted 3 lines
Signed-off-by Namhyung Kim <[email protected]>---