linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] perf script: perf script tests fails with segfault
@ 2025-03-20  9:15 Aditya Bodkhe
  2025-03-21  6:04 ` Namhyung Kim
  0 siblings, 1 reply; 4+ messages in thread
From: Aditya Bodkhe @ 2025-03-20  9:15 UTC (permalink / raw)
  To: linux-perf-users; +Cc: Disha Goel, Aditya Bodkhe

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=yes, Size: 2507 bytes --]

perf script: pert script tests fails with segmentation fault as below:

1. Run perf test -vvv 'perf script tests'

	 92: perf script tests:
	--- start ---
	test child forked, pid 103769
	DB test
	[ perf record: Woken up 1 times to write data ]
	[ perf record: Captured and wrote 0.012 MB /tmp/perf-test-script.7rbftEpOzX/perf.data (9 samples) ]
	/usr/libexec/perf-core/tests/shell/script.sh: line 35: 103780 Segmentation fault      (core dumped) perf script -i "${perfdatafile}" -s "${db_test}"
	--- Cleaning up ---
	---- end(-1) ----
 	92: perf script tests                                               : FAILED!

Backtrace pointed to :
	#0  0x0000000010247dd0 in maps.machine ()
	#1  0x00000000101d178c in db_export.sample ()
	#2  0x00000000103412c8 in python_process_event ()
	#3  0x000000001004eb28 in process_sample_event ()
	#4  0x000000001024fcd0 in machines.deliver_event ()
	#5  0x000000001025005c in perf_session.deliver_event ()
	#6  0x00000000102568b0 in __ordered_events__flush.part.0 ()
	#7  0x0000000010251618 in perf_session.process_events ()
	#8  0x0000000010053620 in cmd_script ()
	#9  0x00000000100b5a28 in run_builtin ()
	#10 0x00000000100b5f94 in handle_internal_command ()
	#11 0x0000000010011114 in main ()

Further investigation reveals that this occurs in the `perf script tests`,
because it uses `db_test.py` script. This script sets `perf_db_export_mode = True`.

With `perf_db_export_mode` enabled, if a sample originates from a hypervisor,
perf doesn't set maps for “[H]” sample in the code. Consequently, `al->maps` remains NULL
when `maps__machine(al->maps)` is called from `db_export__sample`.

To prevent this NULL pointer dereference, add a check for `al->maps == NULL`
before calling `maps__machine()`. If `al->maps` is NULL, return `-1` to avoid
the segmentation fault.

Reported-by: Disha Goel <Disha.Goel@ibm.com>
Signed-off-by: Aditya Bodkhe <aditya.b1@linux.ibm.com>
---
 tools/perf/util/db-export.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index 50f916374d87..f355878a8c82 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -365,6 +365,11 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
        if (err)
                return err;

+       if (!al->maps) {
+          err = -1;
+          goto out_put;
+       }
+
        machine = maps__machine(al->maps);
        err = db_export__machine(dbe, machine);
        if (err)
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] perf script: perf script tests fails with segfault
  2025-03-20  9:15 [PATCH] perf script: perf script tests fails with segfault Aditya Bodkhe
@ 2025-03-21  6:04 ` Namhyung Kim
  2025-03-21  7:58   ` Adrian Hunter
  0 siblings, 1 reply; 4+ messages in thread
From: Namhyung Kim @ 2025-03-21  6:04 UTC (permalink / raw)
  To: Aditya Bodkhe; +Cc: linux-perf-users, Disha Goel, Aditya Bodkhe, Adrian Hunter

CC-ing Adrian,

On Thu, Mar 20, 2025 at 02:45:51PM +0530, Aditya Bodkhe wrote:
> perf script: pert script tests fails with segmentation fault as below:
> 
> 1. Run perf test -vvv 'perf script tests'
> 
> 	 92: perf script tests:
> 	--- start ---
> 	test child forked, pid 103769
> 	DB test
> 	[ perf record: Woken up 1 times to write data ]
> 	[ perf record: Captured and wrote 0.012 MB /tmp/perf-test-script.7rbftEpOzX/perf.data (9 samples) ]
> 	/usr/libexec/perf-core/tests/shell/script.sh: line 35: 103780 Segmentation fault      (core dumped) perf script -i "${perfdatafile}" -s "${db_test}"
> 	--- Cleaning up ---
> 	---- end(-1) ----
>  	92: perf script tests                                               : FAILED!
> 
> Backtrace pointed to :
> 	#0  0x0000000010247dd0 in maps.machine ()
> 	#1  0x00000000101d178c in db_export.sample ()
> 	#2  0x00000000103412c8 in python_process_event ()
> 	#3  0x000000001004eb28 in process_sample_event ()
> 	#4  0x000000001024fcd0 in machines.deliver_event ()
> 	#5  0x000000001025005c in perf_session.deliver_event ()
> 	#6  0x00000000102568b0 in __ordered_events__flush.part.0 ()
> 	#7  0x0000000010251618 in perf_session.process_events ()
> 	#8  0x0000000010053620 in cmd_script ()
> 	#9  0x00000000100b5a28 in run_builtin ()
> 	#10 0x00000000100b5f94 in handle_internal_command ()
> 	#11 0x0000000010011114 in main ()
> 
> Further investigation reveals that this occurs in the `perf script tests`,
> because it uses `db_test.py` script. This script sets `perf_db_export_mode = True`.
> 
> With `perf_db_export_mode` enabled, if a sample originates from a hypervisor,
> perf doesn't set maps for “[H]” sample in the code. Consequently, `al->maps` remains NULL
> when `maps__machine(al->maps)` is called from `db_export__sample`.
> 
> To prevent this NULL pointer dereference, add a check for `al->maps == NULL`
> before calling `maps__machine()`. If `al->maps` is NULL, return `-1` to avoid
> the segmentation fault.
> 
> Reported-by: Disha Goel <Disha.Goel@ibm.com>
> Signed-off-by: Aditya Bodkhe <aditya.b1@linux.ibm.com>
> ---
>  tools/perf/util/db-export.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
> index 50f916374d87..f355878a8c82 100644
> --- a/tools/perf/util/db-export.c
> +++ b/tools/perf/util/db-export.c
> @@ -365,6 +365,11 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
>         if (err)
>                 return err;
> 
> +       if (!al->maps) {
> +          err = -1;
> +          goto out_put;
> +       }

Maybe better to check it before db_export__evsel().  Also it seems it
should not goto out_put as it doesn't get the main_thread yet.

Thanks,
Namhyung

> +
>         machine = maps__machine(al->maps);
>         err = db_export__machine(dbe, machine);
>         if (err)
> -- 
> 2.43.0
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] perf script: perf script tests fails with segfault
  2025-03-21  6:04 ` Namhyung Kim
@ 2025-03-21  7:58   ` Adrian Hunter
  2025-04-17  8:05     ` Aditya Bodkhe
  0 siblings, 1 reply; 4+ messages in thread
From: Adrian Hunter @ 2025-03-21  7:58 UTC (permalink / raw)
  To: Namhyung Kim, Aditya Bodkhe; +Cc: linux-perf-users, Disha Goel, Aditya Bodkhe

On 21/03/25 08:04, Namhyung Kim wrote:
> CC-ing Adrian,

Thanks!

> 
> On Thu, Mar 20, 2025 at 02:45:51PM +0530, Aditya Bodkhe wrote:
>> perf script: pert script tests fails with segmentation fault as below:
>>
>> 1. Run perf test -vvv 'perf script tests'
>>
>> 	 92: perf script tests:
>> 	--- start ---
>> 	test child forked, pid 103769
>> 	DB test
>> 	[ perf record: Woken up 1 times to write data ]
>> 	[ perf record: Captured and wrote 0.012 MB /tmp/perf-test-script.7rbftEpOzX/perf.data (9 samples) ]
>> 	/usr/libexec/perf-core/tests/shell/script.sh: line 35: 103780 Segmentation fault      (core dumped) perf script -i "${perfdatafile}" -s "${db_test}"
>> 	--- Cleaning up ---
>> 	---- end(-1) ----
>>  	92: perf script tests                                               : FAILED!
>>
>> Backtrace pointed to :
>> 	#0  0x0000000010247dd0 in maps.machine ()
>> 	#1  0x00000000101d178c in db_export.sample ()
>> 	#2  0x00000000103412c8 in python_process_event ()
>> 	#3  0x000000001004eb28 in process_sample_event ()
>> 	#4  0x000000001024fcd0 in machines.deliver_event ()
>> 	#5  0x000000001025005c in perf_session.deliver_event ()
>> 	#6  0x00000000102568b0 in __ordered_events__flush.part.0 ()
>> 	#7  0x0000000010251618 in perf_session.process_events ()
>> 	#8  0x0000000010053620 in cmd_script ()
>> 	#9  0x00000000100b5a28 in run_builtin ()
>> 	#10 0x00000000100b5f94 in handle_internal_command ()
>> 	#11 0x0000000010011114 in main ()
>>
>> Further investigation reveals that this occurs in the `perf script tests`,
>> because it uses `db_test.py` script. This script sets `perf_db_export_mode = True`.
>>
>> With `perf_db_export_mode` enabled, if a sample originates from a hypervisor,
>> perf doesn't set maps for “[H]” sample in the code. Consequently, `al->maps` remains NULL
>> when `maps__machine(al->maps)` is called from `db_export__sample`.
>>
>> To prevent this NULL pointer dereference, add a check for `al->maps == NULL`
>> before calling `maps__machine()`. If `al->maps` is NULL, return `-1` to avoid
>> the segmentation fault.
>>
>> Reported-by: Disha Goel <Disha.Goel@ibm.com>
>> Signed-off-by: Aditya Bodkhe <aditya.b1@linux.ibm.com>
>> ---
>>  tools/perf/util/db-export.c | 3 +++
>>  1 file changed, 3 insertions(+)
>>
>> diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
>> index 50f916374d87..f355878a8c82 100644
>> --- a/tools/perf/util/db-export.c
>> +++ b/tools/perf/util/db-export.c
>> @@ -365,6 +365,11 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
>>         if (err)
>>                 return err;
>>
>> +       if (!al->maps) {
>> +          err = -1;
>> +          goto out_put;
>> +       }
> 
> Maybe better to check it before db_export__evsel().  Also it seems it
> should not goto out_put as it doesn't get the main_thread yet.

There has to be a machine to have found a thread.  I'd suggest
getting the machine from the thread, like this:

diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index 50f916374d87..7ea6fd474c4c 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -181,7 +181,7 @@ static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
 	if (al->map) {
 		struct dso *dso = map__dso(al->map);
 
-		err = db_export__dso(dbe, dso, maps__machine(al->maps));
+		err = db_export__dso(dbe, dso, maps__machine(thread__maps(al->thread)));
 		if (err)
 			return err;
 		*dso_db_id = dso__db_id(dso);
@@ -358,14 +358,18 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
 	};
 	struct thread *main_thread;
 	struct comm *comm = NULL;
-	struct machine *machine;
+	struct machine *machine = NULL;
 	int err;
 
+	if (thread__maps(thread))
+		machine = maps__machine(thread__maps(thread));
+	if (!machine)
+		return -1;
+
 	err = db_export__evsel(dbe, evsel);
 	if (err)
 		return err;
 
-	machine = maps__machine(al->maps);
 	err = db_export__machine(dbe, machine);
 	if (err)
 		return err;
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 520729e78965..00f2c6c5114d 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -1306,7 +1306,7 @@ static void python_export_sample_table(struct db_export *dbe,
 
 	tuple_set_d64(t, 0, es->db_id);
 	tuple_set_d64(t, 1, es->evsel->db_id);
-	tuple_set_d64(t, 2, maps__machine(es->al->maps)->db_id);
+	tuple_set_d64(t, 2, maps__machine(thread__maps(es->al->thread))->db_id);
 	tuple_set_d64(t, 3, thread__db_id(es->al->thread));
 	tuple_set_d64(t, 4, es->comm_db_id);
 	tuple_set_d64(t, 5, es->dso_db_id);




^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] perf script: perf script tests fails with segfault
  2025-03-21  7:58   ` Adrian Hunter
@ 2025-04-17  8:05     ` Aditya Bodkhe
  0 siblings, 0 replies; 4+ messages in thread
From: Aditya Bodkhe @ 2025-04-17  8:05 UTC (permalink / raw)
  To: Adrian Hunter, Namhyung Kim; +Cc: linux-perf-users, Disha Goel, Aditya Bodkhe

Hi Adrian,

The approach you suggested works well in general, but we encountered a 
case where al->thread was NULL, which led to a segmentation fault. To 
prevent this, we need to ensure that al->thread is properly set before 
it's used in this line:

@@ -181,7 +181,7 @@ static int db_ids_from_al(struct db_export *dbe, 
struct addr_location *al,
      if (al->map) {
          struct dso *dso = map__dso(al->map);

-        err = db_export__dso(dbe, dso, maps__machine(al->maps));
+        err = db_export__dso(dbe, dso, 
maps__machine(thread__maps(al->thread)));

So, the following additional change is required to set al->thread:

--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -256,6 +256,7 @@ static struct call_path 
*call_path_from_sample(struct db_export *dbe,
                 al.map = map__get(node->ms.map);
                 al.maps = maps__get(thread__maps(thread));
                 al.addr = node->ip;
+               al.thread = thread__get(thread);

                 if (al.map && !al.sym)
                         al.sym = dso__find_symbol(map__dso(al.map), 
al.addr);

I will send a V2 with these changes
Sent again for replying to all

Thanks
Aditya

On 21/03/25 1:28 pm, Adrian Hunter wrote:
> On 21/03/25 08:04, Namhyung Kim wrote:
>> CC-ing Adrian,
> Thanks!
>
>> On Thu, Mar 20, 2025 at 02:45:51PM +0530, Aditya Bodkhe wrote:
>>> perf script: pert script tests fails with segmentation fault as below:
>>>
>>> 1. Run perf test -vvv 'perf script tests'
>>>
>>> 	 92: perf script tests:
>>> 	--- start ---
>>> 	test child forked, pid 103769
>>> 	DB test
>>> 	[ perf record: Woken up 1 times to write data ]
>>> 	[ perf record: Captured and wrote 0.012 MB /tmp/perf-test-script.7rbftEpOzX/perf.data (9 samples) ]
>>> 	/usr/libexec/perf-core/tests/shell/script.sh: line 35: 103780 Segmentation fault      (core dumped) perf script -i "${perfdatafile}" -s "${db_test}"
>>> 	--- Cleaning up ---
>>> 	---- end(-1) ----
>>>   	92: perf script tests                                               : FAILED!
>>>
>>> Backtrace pointed to :
>>> 	#0  0x0000000010247dd0 in maps.machine ()
>>> 	#1  0x00000000101d178c in db_export.sample ()
>>> 	#2  0x00000000103412c8 in python_process_event ()
>>> 	#3  0x000000001004eb28 in process_sample_event ()
>>> 	#4  0x000000001024fcd0 in machines.deliver_event ()
>>> 	#5  0x000000001025005c in perf_session.deliver_event ()
>>> 	#6  0x00000000102568b0 in __ordered_events__flush.part.0 ()
>>> 	#7  0x0000000010251618 in perf_session.process_events ()
>>> 	#8  0x0000000010053620 in cmd_script ()
>>> 	#9  0x00000000100b5a28 in run_builtin ()
>>> 	#10 0x00000000100b5f94 in handle_internal_command ()
>>> 	#11 0x0000000010011114 in main ()
>>>
>>> Further investigation reveals that this occurs in the `perf script tests`,
>>> because it uses `db_test.py` script. This script sets `perf_db_export_mode = True`.
>>>
>>> With `perf_db_export_mode` enabled, if a sample originates from a hypervisor,
>>> perf doesn't set maps for “[H]” sample in the code. Consequently, `al->maps` remains NULL
>>> when `maps__machine(al->maps)` is called from `db_export__sample`.
>>>
>>> To prevent this NULL pointer dereference, add a check for `al->maps == NULL`
>>> before calling `maps__machine()`. If `al->maps` is NULL, return `-1` to avoid
>>> the segmentation fault.
>>>
>>> Reported-by: Disha Goel <Disha.Goel@ibm.com>
>>> Signed-off-by: Aditya Bodkhe <aditya.b1@linux.ibm.com>
>>> ---
>>>   tools/perf/util/db-export.c | 3 +++
>>>   1 file changed, 3 insertions(+)
>>>
>>> diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
>>> index 50f916374d87..f355878a8c82 100644
>>> --- a/tools/perf/util/db-export.c
>>> +++ b/tools/perf/util/db-export.c
>>> @@ -365,6 +365,11 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
>>>          if (err)
>>>                  return err;
>>>
>>> +       if (!al->maps) {
>>> +          err = -1;
>>> +          goto out_put;
>>> +       }
>> Maybe better to check it before db_export__evsel().  Also it seems it
>> should not goto out_put as it doesn't get the main_thread yet.
> There has to be a machine to have found a thread.  I'd suggest
> getting the machine from the thread, like this:
>
> diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
> index 50f916374d87..7ea6fd474c4c 100644
> --- a/tools/perf/util/db-export.c
> +++ b/tools/perf/util/db-export.c
> @@ -181,7 +181,7 @@ static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
>   	if (al->map) {
>   		struct dso *dso = map__dso(al->map);
>   
> -		err = db_export__dso(dbe, dso, maps__machine(al->maps));
> +		err = db_export__dso(dbe, dso, maps__machine(thread__maps(al->thread)));
>   		if (err)
>   			return err;
>   		*dso_db_id = dso__db_id(dso);
> @@ -358,14 +358,18 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
>   	};
>   	struct thread *main_thread;
>   	struct comm *comm = NULL;
> -	struct machine *machine;
> +	struct machine *machine = NULL;
>   	int err;
>   
> +	if (thread__maps(thread))
> +		machine = maps__machine(thread__maps(thread));
> +	if (!machine)
> +		return -1;
> +
>   	err = db_export__evsel(dbe, evsel);
>   	if (err)
>   		return err;
>   
> -	machine = maps__machine(al->maps);
>   	err = db_export__machine(dbe, machine);
>   	if (err)
>   		return err;
> diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
> index 520729e78965..00f2c6c5114d 100644
> --- a/tools/perf/util/scripting-engines/trace-event-python.c
> +++ b/tools/perf/util/scripting-engines/trace-event-python.c
> @@ -1306,7 +1306,7 @@ static void python_export_sample_table(struct db_export *dbe,
>   
>   	tuple_set_d64(t, 0, es->db_id);
>   	tuple_set_d64(t, 1, es->evsel->db_id);
> -	tuple_set_d64(t, 2, maps__machine(es->al->maps)->db_id);
> +	tuple_set_d64(t, 2, maps__machine(thread__maps(es->al->thread))->db_id);
>   	tuple_set_d64(t, 3, thread__db_id(es->al->thread));
>   	tuple_set_d64(t, 4, es->comm_db_id);
>   	tuple_set_d64(t, 5, es->dso_db_id);
>
>
>
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-04-17  8:05 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-20  9:15 [PATCH] perf script: perf script tests fails with segfault Aditya Bodkhe
2025-03-21  6:04 ` Namhyung Kim
2025-03-21  7:58   ` Adrian Hunter
2025-04-17  8:05     ` Aditya Bodkhe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).