From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Howard Chu <howardchu95@gmail.com>
Cc: adrian.hunter@intel.com, irogers@google.com, jolsa@kernel.org,
kan.liang@linux.intel.com, namhyung@kernel.org,
linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org,
Arnaldo Carvalho de Melo <acme@redhat.com>
Subject: Re: [PATCH v3 2/8] perf trace: Add trace__bpf_sys_enter_beauty_map() to prepare for fetching data in BPF
Date: Mon, 9 Sep 2024 17:14:02 -0300 [thread overview]
Message-ID: <Zt9XCtTHeJ-1MCCl@x1> (raw)
In-Reply-To: <Zt9Qa_znFmHADff1@x1>
On Mon, Sep 09, 2024 at 04:45:47PM -0300, Arnaldo Carvalho de Melo wrote:
> On Sun, Aug 25, 2024 at 12:33:16AM +0800, Howard Chu wrote:
> > Set up beauty_map, load it to BPF, in such format: if argument No.3 is a
> > struct of size 32 bytes (of syscall number 114) beauty_map[114][2] = 32;
> >
> > if argument No.3 is a string (of syscall number 114) beauty_map[114][2] =
> > 1;
> >
> > if argument No.3 is a buffer, its size is indicated by argument No.4 (of
> > syscall number 114) beauty_map[114][2] = -4; /* -1 ~ -6, we'll read this
> > buffer size in BPF */
> >
> > Committer notes:
> >
> > Moved syscall_arg_fmt__cache_btf_struct() from a ifdef
> > HAVE_LIBBPF_SUPPORT to closer to where it is used, that is ifdef'ed on
> > HAVE_BPF_SKEL and thus breaks the build when building with
> > BUILD_BPF_SKEL=0, as detected using 'make -C tools/perf build-test'.
>
> Here we have to have this:
My pahole hat was not working, we have this:
SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
size_t, count)
{
return ksys_write(fd, buf, count);
}
ssize_t ksys_pread64(unsigned int fd, char __user *buf, size_t count,
loff_t pos)
See that __user?
That should be available in BTF as a tag and then we can use it... For
now I'll continue adding a flag to the syscall_arg_fmt, as I have that
much time before flying to Europe, but that is an avenue we _have_ to
investigate and use that info.
It will not cover all cases, and I think we'll even have to improve BTF
in that regard with some sort of __user_maybe thing for args that get
thing from userspace according to some other argument (you was overly
clever on the heuristic to find the size of buffers, more on that at
some point, but I'm running out of time).
- Arnaldo
> diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> index ba7b1338123dc5f1..588305b26a064edf 100644
> --- a/tools/perf/builtin-trace.c
> +++ b/tools/perf/builtin-trace.c
> @@ -3572,6 +3572,10 @@ static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int key, unsigne
> for (i = 0, field = sc->args; field; ++i, field = field->next) {
> struct_offset = strstr(field->type, "struct ");
>
> + // XXX We're only collecting pointer payloads _from_ user space
> + if (!sc->arg_fmt[i].from_user)
> + continue;
> +
> if (field->flags & TEP_FIELD_IS_POINTER && struct_offset) { /* struct */
> struct_offset += 7;
>
> I added some patches before this one that add that .from_user field and
> marks the syscall args that flow from user to kernel space, we'll
> probably need to tune that a bit, but then its "better" not to collect
> old contents of buffers in syscalls that flows from kernel to userspace
> than to lose the opportunity to collect data flowing from user to kernel
> space.
>
> I.e. its better to not show something useful than to show something
> misleading/utterly bogus.
>
> - Arnaldo
>
> > Signed-off-by: Howard Chu <howardchu95@gmail.com>
> > Cc: Adrian Hunter <adrian.hunter@intel.com>
> > Cc: Ian Rogers <irogers@google.com>
> > Cc: Jiri Olsa <jolsa@kernel.org>
> > Cc: Kan Liang <kan.liang@linux.intel.com>
> > Cc: Namhyung Kim <namhyung@kernel.org>
> > Link: https://lore.kernel.org/r/20240815013626.935097-4-howardchu95@gmail.com
> > Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> > ---
> > tools/perf/builtin-trace.c | 106 +++++++++++++++++++++++++++++++++++++
> > 1 file changed, 106 insertions(+)
> >
> > diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> > index d6ca541fdc78..c26eab196623 100644
> > --- a/tools/perf/builtin-trace.c
> > +++ b/tools/perf/builtin-trace.c
> > @@ -113,6 +113,7 @@ struct syscall_arg_fmt {
> > bool show_zero;
> > #ifdef HAVE_LIBBPF_SUPPORT
> > const struct btf_type *type;
> > + int type_id; /* used in btf_dump */
> > #endif
> > };
> >
> > @@ -3446,6 +3447,23 @@ static int trace__set_ev_qualifier_tp_filter(struct trace *trace)
> > }
> >
> > #ifdef HAVE_BPF_SKEL
> > +static int syscall_arg_fmt__cache_btf_struct(struct syscall_arg_fmt *arg_fmt, struct btf *btf, char *type)
> > +{
> > + int id;
> > +
> > + if (arg_fmt->type != NULL)
> > + return -1;
> > +
> > + id = btf__find_by_name(btf, type);
> > + if (id < 0)
> > + return -1;
> > +
> > + arg_fmt->type = btf__type_by_id(btf, id);
> > + arg_fmt->type_id = id;
> > +
> > + return 0;
> > +}
> > +
> > static struct bpf_program *trace__find_bpf_program_by_title(struct trace *trace, const char *name)
> > {
> > struct bpf_program *pos, *prog = NULL;
> > @@ -3521,6 +3539,83 @@ static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int id)
> > return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
> > }
> >
> > +static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int key, unsigned int *beauty_array)
> > +{
> > + struct tep_format_field *field;
> > + struct syscall *sc = trace__syscall_info(trace, NULL, key);
> > + const struct btf_type *bt;
> > + char *struct_offset, *tmp, name[32];
> > + bool can_augment = false;
> > + int i, cnt;
> > +
> > + if (sc == NULL)
> > + return -1;
> > +
> > + trace__load_vmlinux_btf(trace);
> > + if (trace->btf == NULL)
> > + return -1;
> > +
> > + for (i = 0, field = sc->args; field; ++i, field = field->next) {
> > + struct_offset = strstr(field->type, "struct ");
> > +
> > + if (field->flags & TEP_FIELD_IS_POINTER && struct_offset) { /* struct */
> > + struct_offset += 7;
> > +
> > + /* for 'struct foo *', we only want 'foo' */
> > + for (tmp = struct_offset, cnt = 0; *tmp != ' ' && *tmp != '\0'; ++tmp, ++cnt) {
> > + }
> > +
> > + strncpy(name, struct_offset, cnt);
> > + name[cnt] = '\0';
> > +
> > + /* cache struct's btf_type and type_id */
> > + if (syscall_arg_fmt__cache_btf_struct(&sc->arg_fmt[i], trace->btf, name))
> > + continue;
> > +
> > + bt = sc->arg_fmt[i].type;
> > + beauty_array[i] = bt->size;
> > + can_augment = true;
> > + } else if (field->flags & TEP_FIELD_IS_POINTER && /* string */
> > + strcmp(field->type, "const char *") == 0 &&
> > + (strstr(field->name, "name") ||
> > + strstr(field->name, "path") ||
> > + strstr(field->name, "file") ||
> > + strstr(field->name, "root") ||
> > + strstr(field->name, "key") ||
> > + strstr(field->name, "special") ||
> > + strstr(field->name, "type") ||
> > + strstr(field->name, "description"))) {
> > + beauty_array[i] = 1;
> > + can_augment = true;
> > + } else if (field->flags & TEP_FIELD_IS_POINTER && /* buffer */
> > + strstr(field->type, "char *") &&
> > + (strstr(field->name, "buf") ||
> > + strstr(field->name, "val") ||
> > + strstr(field->name, "msg"))) {
> > + int j;
> > + struct tep_format_field *field_tmp;
> > +
> > + /* find the size of the buffer that appears in pairs with buf */
> > + for (j = 0, field_tmp = sc->args; field_tmp; ++j, field_tmp = field_tmp->next) {
> > + if (!(field_tmp->flags & TEP_FIELD_IS_POINTER) && /* only integers */
> > + (strstr(field_tmp->name, "count") ||
> > + strstr(field_tmp->name, "siz") || /* size, bufsiz */
> > + (strstr(field_tmp->name, "len") && strcmp(field_tmp->name, "filename")))) {
> > + /* filename's got 'len' in it, we don't want that */
> > + beauty_array[i] = -(j + 1);
> > + can_augment = true;
> > + break;
> > + }
> > + }
> > + }
> > + }
> > +
> > + if (can_augment)
> > + return 0;
> > +
> > + return -1;
> > +}
> > +
> > static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace, struct syscall *sc)
> > {
> > struct tep_format_field *field, *candidate_field;
> > @@ -3625,7 +3720,9 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
> > {
> > int map_enter_fd = bpf_map__fd(trace->skel->maps.syscalls_sys_enter);
> > int map_exit_fd = bpf_map__fd(trace->skel->maps.syscalls_sys_exit);
> > + int beauty_map_fd = bpf_map__fd(trace->skel->maps.beauty_map_enter);
> > int err = 0;
> > + unsigned int beauty_array[6];
> >
> > for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
> > int prog_fd, key = syscalltbl__id_at_idx(trace->sctbl, i);
> > @@ -3644,6 +3741,15 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
> > err = bpf_map_update_elem(map_exit_fd, &key, &prog_fd, BPF_ANY);
> > if (err)
> > break;
> > +
> > + /* use beauty_map to tell BPF how many bytes to collect, set beauty_map's value here */
> > + memset(beauty_array, 0, sizeof(beauty_array));
> > + err = trace__bpf_sys_enter_beauty_map(trace, key, (unsigned int *)beauty_array);
> > + if (err)
> > + continue;
> > + err = bpf_map_update_elem(beauty_map_fd, &key, beauty_array, BPF_ANY);
> > + if (err)
> > + break;
> > }
> >
> > /*
> > --
> > 2.45.2
next prev parent reply other threads:[~2024-09-09 20:14 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-24 16:33 [PATCH v3 0/8] perf trace: Enhanced augmentation for pointer arguments Howard Chu
2024-08-24 16:33 ` [PATCH v3 1/8] perf trace: Fix perf trace -p <PID> Howard Chu
2024-08-24 16:33 ` [PATCH v3 2/8] perf trace: Add trace__bpf_sys_enter_beauty_map() to prepare for fetching data in BPF Howard Chu
2024-09-09 19:45 ` Arnaldo Carvalho de Melo
2024-09-09 20:14 ` Arnaldo Carvalho de Melo [this message]
2024-09-10 4:59 ` Howard Chu
2024-08-24 16:33 ` [PATCH v3 3/8] perf trace: Pass the richer 'struct syscall_arg' pointer to trace__btf_scnprintf() Howard Chu
2024-08-24 16:33 ` [PATCH v3 4/8] perf trace: Pretty print struct data Howard Chu
2024-08-28 21:04 ` Arnaldo Carvalho de Melo
2024-08-30 0:16 ` Howard Chu
2024-09-09 14:40 ` Arnaldo Carvalho de Melo
2024-09-09 14:46 ` Arnaldo Carvalho de Melo
2024-08-24 16:33 ` [PATCH v3 5/8] perf trace: Pretty print buffer data Howard Chu
2024-09-09 16:33 ` Arnaldo Carvalho de Melo
2024-09-09 16:45 ` Arnaldo Carvalho de Melo
2024-09-09 16:50 ` Arnaldo Carvalho de Melo
2024-09-09 17:17 ` Howard Chu
2024-09-09 19:19 ` Arnaldo Carvalho de Melo
2024-09-09 17:14 ` Howard Chu
2024-08-24 16:33 ` [PATCH v3 6/8] perf trace: Collect augmented data using BPF Howard Chu
2024-09-04 19:52 ` Arnaldo Carvalho de Melo
2024-09-04 21:11 ` Howard Chu
2024-09-11 14:23 ` Arnaldo Carvalho de Melo
2024-08-24 16:33 ` [PATCH v3 7/8] perf trace: Add --force-btf for debugging Howard Chu
2024-08-24 16:33 ` [PATCH v3 8/8] perf trace: Add general tests for augmented syscalls Howard Chu
2024-09-09 22:11 ` Arnaldo Carvalho de Melo
2024-09-10 5:00 ` Howard Chu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Zt9XCtTHeJ-1MCCl@x1 \
--to=acme@kernel.org \
--cc=acme@redhat.com \
--cc=adrian.hunter@intel.com \
--cc=howardchu95@gmail.com \
--cc=irogers@google.com \
--cc=jolsa@kernel.org \
--cc=kan.liang@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=namhyung@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).