diff --git a/tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c b/tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c index bc036a348079..3bc9e28a9b8a 100644 --- a/tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c +++ b/tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c @@ -429,6 +429,8 @@ static bool pid_filter__has(struct pids_filtered *pids, pid_t pid) return bpf_map_lookup_elem(pids, &pid) != NULL; } +u64 ZERO = 0; + /* * Determine what type of argument and how many bytes to read from user space, using the * value in the beauty_map. This is the relation of parameter type and its corresponding @@ -440,9 +442,10 @@ static bool pid_filter__has(struct pids_filtered *pids, pid_t pid) */ static inline int augment_arg(struct syscall_enter_args *args, int i, unsigned int *beauty_map, - struct augmented_arg *payload_offset) + struct beauty_payload_enter *payload, u64 offset) { int index, value_size = sizeof(struct augmented_arg) - offsetof(struct augmented_arg, value); + struct augmented_arg *payload_offset; s64 aug_size, size; bool augmented; void *arg; @@ -455,6 +458,12 @@ static inline int augment_arg(struct syscall_enter_args *args, int i, if (size == 0 || arg == NULL) return 0; + /* bounds check for the verifier */ + if (offset > sizeof(payload->aug_args) - sizeof(payload->aug_args[0])) + return -1; + barrier_var(offset); + payload_offset = (struct augmented_arg *)((void *)&payload->aug_args + offset); + if (size == 1) { /* string */ aug_size = bpf_probe_read_user_str(payload_offset->value, value_size, arg); /* minimum of 0 to pass the verifier */ @@ -498,11 +507,10 @@ static inline int augment_arg(struct syscall_enter_args *args, int i, static int augment_sys_enter(void *ctx, struct syscall_enter_args *args) { bool do_output = false; - int zero = 0, written; + int i, zero = 0, written; u64 output = 0; /* has to be u64, otherwise it won't pass the verifier */ unsigned int nr, *beauty_map; struct beauty_payload_enter *payload; - void *payload_offset; /* fall back to do predefined tail call */ if (args == NULL) @@ -514,7 +522,6 @@ static int augment_sys_enter(void *ctx, struct syscall_enter_args *args) /* set up payload for output */ payload = bpf_map_lookup_elem(&beauty_payload_enter_map, &zero); - payload_offset = (void *)&payload->aug_args; if (beauty_map == NULL || payload == NULL) return 1; @@ -522,14 +529,30 @@ static int augment_sys_enter(void *ctx, struct syscall_enter_args *args) /* copy the sys_enter header, which has the syscall_nr */ __builtin_memcpy(&payload->args, args, sizeof(struct syscall_enter_args)); - for (int i = 0; i < 6; i++) { - written = augment_arg(args, i, beauty_map, (struct augmented_arg *)payload_offset); - if (written < 0) - return 1; - if (written > 0) { - output += written; - payload_offset += written; - do_output = true; + if (bpf_ksym_exists(bpf_iter_num_new)) { + bpf_for(i, 0, 6) { + written = augment_arg(args, i, beauty_map, payload, output); + if (written < 0) + return 1; + if (written > 0) { + output += written; + /* + * guide the verifier to forget range of `output`, which + * helps to prove convergence of the loop + */ + output += ZERO; + do_output = true; + } + } + } else { + for (i = 0; i < 6; i++) { + written = augment_arg(args, i, beauty_map, payload, output); + if (written < 0) + return 1; + if (written > 0) { + output += written; + do_output = true; + } } }