* [PATCH] perf bpf: Remove undefined behavior from bpf_perf_object__next
@ 2022-07-26 22:09 Ian Rogers
2022-07-27 14:16 ` Arnaldo Carvalho de Melo
0 siblings, 1 reply; 2+ messages in thread
From: Ian Rogers @ 2022-07-26 22:09 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
Nathan Chancellor, Nick Desaulniers, Tom Rix, Andrii Nakryiko,
Christy Lee, Alexei Starovoitov, Miaoqian Lin, Ian Rogers,
linux-perf-users, linux-kernel, bpf, llvm
Cc: Stephane Eranian
bpf_perf_object__next folded the last element in the list test with the
empty list test. However, this meant that offsets were computed against
null and that a struct list_head was compared against a struct
bpf_perf_object. Working around this with clang's undefined behavior
sanitizer required -fno-sanitize=null and -fno-sanitize=object-size.
Remove the undefined behavior by using the regular Linux list APIs and
handling the starting case separately from the end testing case. Looking
at uses like bpf_perf_object__for_each, as the constant NULL or non-NULL
argument can be constant propagated the code is no less efficient.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/bpf-loader.c | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index f8ad581ea247..cdd6463a5b68 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -63,20 +63,16 @@ static struct hashmap *bpf_map_hash;
static struct bpf_perf_object *
bpf_perf_object__next(struct bpf_perf_object *prev)
{
- struct bpf_perf_object *next;
-
- if (!prev)
- next = list_first_entry(&bpf_objects_list,
- struct bpf_perf_object,
- list);
- else
- next = list_next_entry(prev, list);
+ if (!prev) {
+ if (list_empty(&bpf_objects_list))
+ return NULL;
- /* Empty list is noticed here so don't need checking on entry. */
- if (&next->list == &bpf_objects_list)
+ return list_first_entry(&bpf_objects_list, struct bpf_perf_object, list);
+ }
+ if (list_is_last(&prev->list, &bpf_objects_list))
return NULL;
- return next;
+ return list_next_entry(prev, list);
}
#define bpf_perf_object__for_each(perf_obj, tmp) \
--
2.37.1.359.gd136c6c3e2-goog
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] perf bpf: Remove undefined behavior from bpf_perf_object__next
2022-07-26 22:09 [PATCH] perf bpf: Remove undefined behavior from bpf_perf_object__next Ian Rogers
@ 2022-07-27 14:16 ` Arnaldo Carvalho de Melo
0 siblings, 0 replies; 2+ messages in thread
From: Arnaldo Carvalho de Melo @ 2022-07-27 14:16 UTC (permalink / raw)
To: Ian Rogers
Cc: Peter Zijlstra, Ingo Molnar, Mark Rutland, Alexander Shishkin,
Jiri Olsa, Namhyung Kim, Nathan Chancellor, Nick Desaulniers,
Tom Rix, Andrii Nakryiko, Christy Lee, Alexei Starovoitov,
Miaoqian Lin, linux-perf-users, linux-kernel, bpf, llvm,
Stephane Eranian
Em Tue, Jul 26, 2022 at 03:09:21PM -0700, Ian Rogers escreveu:
> bpf_perf_object__next folded the last element in the list test with the
> empty list test. However, this meant that offsets were computed against
> null and that a struct list_head was compared against a struct
> bpf_perf_object. Working around this with clang's undefined behavior
> sanitizer required -fno-sanitize=null and -fno-sanitize=object-size.
> in
> Remove the undefined behav(ior by using the regular Linux list APIs and
> handling the starting case separately from the end testing case. Looking
> at uses like bpf_perf_object__for_each, as the constant NULL or non-NULL
> argument can be constant propagated the code is no less efficient.
Nicely spotted!
In some places people solve this with list_first_entry_or_null(), like
in cs_etm__queue_aux_records().
Applied.
- Arnado
> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
> tools/perf/util/bpf-loader.c | 18 +++++++-----------
> 1 file changed, 7 insertions(+), 11 deletions(-)
>
> diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
> indelx f8ad581ea247..cdd6463a5b68 100644
> --- a/tools/perf/util/bpf-loader.c
> +++ b/tools/perf/util/bpf-loader.c
> @@ -63,20 +63,16 @@ static struct hashmap *bpf_map_hash;
> static struct bpf_perf_object *
> bpf_perf_object__next(struct bpf_perf_object *prev)
> {
> - struct bpf_perf_object *next;
> -
> - if (!prev)
> - next = list_first_entry(&bpf_objects_list,
> - struct bpf_perf_object,
> - list);
> - else
> - next = list_next_entry(prev, list);
> + if (!prev) {
> + if (list_empty(&bpf_objects_list))
> + return NULL;
>
> - /* Empty list is noticed here so don't need checking on entry. */
> - if (&next->list == &bpf_objects_list)
> + return list_first_entry(&bpf_objects_list, struct bpf_perf_object, list);
> + }
> + if (list_is_last(&prev->list, &bpf_objects_list))
> return NULL;
>
> - return next;
> + return list_next_entry(prev, list);
> }
>
> #define bpf_perf_object__for_each(perf_obj, tmp) \
> --
> 2.37.1.359.gd136c6c3e2-goog
--
- Arnaldo
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-07-27 14:17 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-07-26 22:09 [PATCH] perf bpf: Remove undefined behavior from bpf_perf_object__next Ian Rogers
2022-07-27 14:16 ` Arnaldo Carvalho de Melo
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).