perf trace: Mark which syscall arguments go from user space to kernel space

We need to know where to collect it in the BPF augmenters, if in the
sys_enter hook or in the sys_exit hook.

Start with the SCA_FILENAME one, that is just from user to kernel space.

The alternative, better, but takes a bit more time than I have now, is
to use the __user information that is already in the syscall args and
encoded in BTF via a tag, do it later.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Howard Chu <howardchu95@gmail.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>
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent c90a88d3
...@@ -102,6 +102,12 @@ ...@@ -102,6 +102,12 @@
/* /*
* strtoul: Go from a string to a value, i.e. for msr: MSR_FS_BASE to 0xc0000100 * strtoul: Go from a string to a value, i.e. for msr: MSR_FS_BASE to 0xc0000100
*
* We have to explicitely mark the direction of the flow of data, if from the
* kernel to user space or the other way around, since the BPF collector we
* have so far copies only from user to kernel space, mark the arguments that
* go that direction, so that we don´t end up collecting the previous contents
* for syscall args that goes from kernel to user space.
*/ */
struct syscall_arg_fmt { struct syscall_arg_fmt {
size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg); size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
...@@ -110,6 +116,7 @@ struct syscall_arg_fmt { ...@@ -110,6 +116,7 @@ struct syscall_arg_fmt {
void *parm; void *parm;
const char *name; const char *name;
u16 nr_entries; // for arrays u16 nr_entries; // for arrays
bool from_user;
bool show_zero; bool show_zero;
#ifdef HAVE_LIBBPF_SUPPORT #ifdef HAVE_LIBBPF_SUPPORT
const struct btf_type *type; const struct btf_type *type;
...@@ -851,6 +858,11 @@ static size_t syscall_arg__scnprintf_filename(char *bf, size_t size, ...@@ -851,6 +858,11 @@ static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
#define SCA_FILENAME syscall_arg__scnprintf_filename #define SCA_FILENAME syscall_arg__scnprintf_filename
// 'argname' is just documentational at this point, to remove the previous comment with that info
#define SCA_FILENAME_FROM_USER(argname) \
{ .scnprintf = SCA_FILENAME, \
.from_user = true, }
static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size, static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
struct syscall_arg *arg) struct syscall_arg *arg)
{ {
...@@ -1091,11 +1103,11 @@ static const struct syscall_fmt syscall_fmts[] = { ...@@ -1091,11 +1103,11 @@ static const struct syscall_fmt syscall_fmts[] = {
.arg = { [1] = { .scnprintf = SCA_EFD_FLAGS, /* flags */ }, }, }, .arg = { [1] = { .scnprintf = SCA_EFD_FLAGS, /* flags */ }, }, },
{ .name = "faccessat", { .name = "faccessat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dirfd */ }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* dirfd */ },
[1] = { .scnprintf = SCA_FILENAME, /* pathname */ }, [1] = SCA_FILENAME_FROM_USER(pathname),
[2] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, }, [2] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, },
{ .name = "faccessat2", { .name = "faccessat2",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dirfd */ }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* dirfd */ },
[1] = { .scnprintf = SCA_FILENAME, /* pathname */ }, [1] = SCA_FILENAME_FROM_USER(pathname),
[2] = { .scnprintf = SCA_ACCMODE, /* mode */ }, [2] = { .scnprintf = SCA_ACCMODE, /* mode */ },
[3] = { .scnprintf = SCA_FACCESSAT2_FLAGS, /* flags */ }, }, }, [3] = { .scnprintf = SCA_FACCESSAT2_FLAGS, /* flags */ }, }, },
{ .name = "fchmodat", { .name = "fchmodat",
...@@ -1117,7 +1129,7 @@ static const struct syscall_fmt syscall_fmts[] = { ...@@ -1117,7 +1129,7 @@ static const struct syscall_fmt syscall_fmts[] = {
[2] = { .scnprintf = SCA_FSMOUNT_ATTR_FLAGS, /* attr_flags */ }, }, }, [2] = { .scnprintf = SCA_FSMOUNT_ATTR_FLAGS, /* attr_flags */ }, }, },
{ .name = "fspick", { .name = "fspick",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ },
[1] = { .scnprintf = SCA_FILENAME, /* path */ }, [1] = SCA_FILENAME_FROM_USER(path),
[2] = { .scnprintf = SCA_FSPICK_FLAGS, /* flags */ }, }, }, [2] = { .scnprintf = SCA_FSPICK_FLAGS, /* flags */ }, }, },
{ .name = "fstat", .alias = "newfstat", }, { .name = "fstat", .alias = "newfstat", },
{ .name = "futex", { .name = "futex",
...@@ -1181,20 +1193,20 @@ static const struct syscall_fmt syscall_fmts[] = { ...@@ -1181,20 +1193,20 @@ static const struct syscall_fmt syscall_fmts[] = {
.parm = &strarray__mmap_flags, }, .parm = &strarray__mmap_flags, },
[5] = { .scnprintf = SCA_HEX, /* offset */ }, }, }, [5] = { .scnprintf = SCA_HEX, /* offset */ }, }, },
{ .name = "mount", { .name = "mount",
.arg = { [0] = { .scnprintf = SCA_FILENAME, /* dev_name */ }, .arg = { [0] = SCA_FILENAME_FROM_USER(devname),
[3] = { .scnprintf = SCA_MOUNT_FLAGS, /* flags */ [3] = { .scnprintf = SCA_MOUNT_FLAGS, /* flags */
.mask_val = SCAMV_MOUNT_FLAGS, /* flags */ }, }, }, .mask_val = SCAMV_MOUNT_FLAGS, /* flags */ }, }, },
{ .name = "move_mount", { .name = "move_mount",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* from_dfd */ }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* from_dfd */ },
[1] = { .scnprintf = SCA_FILENAME, /* from_pathname */ }, [1] = SCA_FILENAME_FROM_USER(pathname),
[2] = { .scnprintf = SCA_FDAT, /* to_dfd */ }, [2] = { .scnprintf = SCA_FDAT, /* to_dfd */ },
[3] = { .scnprintf = SCA_FILENAME, /* to_pathname */ }, [3] = SCA_FILENAME_FROM_USER(pathname),
[4] = { .scnprintf = SCA_MOVE_MOUNT_FLAGS, /* flags */ }, }, }, [4] = { .scnprintf = SCA_MOVE_MOUNT_FLAGS, /* flags */ }, }, },
{ .name = "mprotect", { .name = "mprotect",
.arg = { [0] = { .scnprintf = SCA_HEX, /* start */ }, .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
[2] = { .scnprintf = SCA_MMAP_PROT, .show_zero = true, /* prot */ }, }, }, [2] = { .scnprintf = SCA_MMAP_PROT, .show_zero = true, /* prot */ }, }, },
{ .name = "mq_unlink", { .name = "mq_unlink",
.arg = { [0] = { .scnprintf = SCA_FILENAME, /* u_name */ }, }, }, .arg = { [0] = SCA_FILENAME_FROM_USER(u_name), }, },
{ .name = "mremap", .hexret = true, { .name = "mremap", .hexret = true,
.arg = { [3] = { .scnprintf = SCA_MREMAP_FLAGS, /* flags */ }, }, }, .arg = { [3] = { .scnprintf = SCA_MREMAP_FLAGS, /* flags */ }, }, },
{ .name = "name_to_handle_at", { .name = "name_to_handle_at",
...@@ -1203,7 +1215,7 @@ static const struct syscall_fmt syscall_fmts[] = { ...@@ -1203,7 +1215,7 @@ static const struct syscall_fmt syscall_fmts[] = {
.arg = { [0] = { .scnprintf = SCA_TIMESPEC, /* req */ }, }, }, .arg = { [0] = { .scnprintf = SCA_TIMESPEC, /* req */ }, }, },
{ .name = "newfstatat", .alias = "fstatat", { .name = "newfstatat", .alias = "fstatat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dirfd */ }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* dirfd */ },
[1] = { .scnprintf = SCA_FILENAME, /* pathname */ }, [1] = SCA_FILENAME_FROM_USER(pathname),
[3] = { .scnprintf = SCA_FS_AT_FLAGS, /* flags */ }, }, }, [3] = { .scnprintf = SCA_FS_AT_FLAGS, /* flags */ }, }, },
{ .name = "open", { .name = "open",
.arg = { [1] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, }, .arg = { [1] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
...@@ -1299,9 +1311,9 @@ static const struct syscall_fmt syscall_fmts[] = { ...@@ -1299,9 +1311,9 @@ static const struct syscall_fmt syscall_fmts[] = {
[2] = { .scnprintf = SCA_FS_AT_FLAGS, /* flags */ } , [2] = { .scnprintf = SCA_FS_AT_FLAGS, /* flags */ } ,
[3] = { .scnprintf = SCA_STATX_MASK, /* mask */ }, }, }, [3] = { .scnprintf = SCA_STATX_MASK, /* mask */ }, }, },
{ .name = "swapoff", { .name = "swapoff",
.arg = { [0] = { .scnprintf = SCA_FILENAME, /* specialfile */ }, }, }, .arg = { [0] = SCA_FILENAME_FROM_USER(specialfile), }, },
{ .name = "swapon", { .name = "swapon",
.arg = { [0] = { .scnprintf = SCA_FILENAME, /* specialfile */ }, }, }, .arg = { [0] = SCA_FILENAME_FROM_USER(specialfile), }, },
{ .name = "symlinkat", { .name = "symlinkat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
{ .name = "sync_file_range", { .name = "sync_file_range",
...@@ -1311,11 +1323,11 @@ static const struct syscall_fmt syscall_fmts[] = { ...@@ -1311,11 +1323,11 @@ static const struct syscall_fmt syscall_fmts[] = {
{ .name = "tkill", { .name = "tkill",
.arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, }, .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
{ .name = "umount2", .alias = "umount", { .name = "umount2", .alias = "umount",
.arg = { [0] = { .scnprintf = SCA_FILENAME, /* name */ }, }, }, .arg = { [0] = SCA_FILENAME_FROM_USER(name), }, },
{ .name = "uname", .alias = "newuname", }, { .name = "uname", .alias = "newuname", },
{ .name = "unlinkat", { .name = "unlinkat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ },
[1] = { .scnprintf = SCA_FILENAME, /* pathname */ }, [1] = SCA_FILENAME_FROM_USER(pathname),
[2] = { .scnprintf = SCA_FS_AT_FLAGS, /* flags */ }, }, }, [2] = { .scnprintf = SCA_FS_AT_FLAGS, /* flags */ }, }, },
{ .name = "utimensat", { .name = "utimensat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dirfd */ }, }, }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* dirfd */ }, }, },
...@@ -1903,9 +1915,10 @@ syscall_arg_fmt__init_array(struct syscall_arg_fmt *arg, struct tep_format_field ...@@ -1903,9 +1915,10 @@ syscall_arg_fmt__init_array(struct syscall_arg_fmt *arg, struct tep_format_field
if (strcmp(field->type, "const char *") == 0 && if (strcmp(field->type, "const char *") == 0 &&
((len >= 4 && strcmp(field->name + len - 4, "name") == 0) || ((len >= 4 && strcmp(field->name + len - 4, "name") == 0) ||
strstr(field->name, "path") != NULL)) strstr(field->name, "path") != NULL)) {
arg->scnprintf = SCA_FILENAME; arg->scnprintf = SCA_FILENAME;
else if ((field->flags & TEP_FIELD_IS_POINTER) || strstr(field->name, "addr")) arg->from_user = true;
} else if ((field->flags & TEP_FIELD_IS_POINTER) || strstr(field->name, "addr"))
arg->scnprintf = SCA_PTR; arg->scnprintf = SCA_PTR;
else if (strcmp(field->type, "pid_t") == 0) else if (strcmp(field->type, "pid_t") == 0)
arg->scnprintf = SCA_PID; arg->scnprintf = SCA_PID;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment