perf trace augmented_raw_syscalls: Add more checks to pass the verifier
Add some more checks to pass the verifier in more kernels. Signed-off-by: Howard Chu <howardchu95@gmail.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alan Maguire <alan.maguire@oracle.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: https://lore.kernel.org/r/20241011021403.4089793-3-howardchu95@gmail.com [ Reduced the patch removing things that can be done later ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
ecabac70ff
commit
395d38419f
@ -288,6 +288,10 @@ int sys_enter_rename(struct syscall_enter_args *args)
|
|||||||
augmented_args->arg.size = PERF_ALIGN(oldpath_len + 1, sizeof(u64));
|
augmented_args->arg.size = PERF_ALIGN(oldpath_len + 1, sizeof(u64));
|
||||||
len += augmented_args->arg.size;
|
len += augmented_args->arg.size;
|
||||||
|
|
||||||
|
/* Every read from userspace is limited to value size */
|
||||||
|
if (augmented_args->arg.size > sizeof(augmented_args->arg.value))
|
||||||
|
return 1; /* Failure: don't filter */
|
||||||
|
|
||||||
struct augmented_arg *arg2 = (void *)&augmented_args->arg.value + augmented_args->arg.size;
|
struct augmented_arg *arg2 = (void *)&augmented_args->arg.value + augmented_args->arg.size;
|
||||||
|
|
||||||
newpath_len = augmented_arg__read_str(arg2, newpath_arg, sizeof(augmented_args->arg.value));
|
newpath_len = augmented_arg__read_str(arg2, newpath_arg, sizeof(augmented_args->arg.value));
|
||||||
@ -315,6 +319,10 @@ int sys_enter_renameat2(struct syscall_enter_args *args)
|
|||||||
augmented_args->arg.size = PERF_ALIGN(oldpath_len + 1, sizeof(u64));
|
augmented_args->arg.size = PERF_ALIGN(oldpath_len + 1, sizeof(u64));
|
||||||
len += augmented_args->arg.size;
|
len += augmented_args->arg.size;
|
||||||
|
|
||||||
|
/* Every read from userspace is limited to value size */
|
||||||
|
if (augmented_args->arg.size > sizeof(augmented_args->arg.value))
|
||||||
|
return 1; /* Failure: don't filter */
|
||||||
|
|
||||||
struct augmented_arg *arg2 = (void *)&augmented_args->arg.value + augmented_args->arg.size;
|
struct augmented_arg *arg2 = (void *)&augmented_args->arg.value + augmented_args->arg.size;
|
||||||
|
|
||||||
newpath_len = augmented_arg__read_str(arg2, newpath_arg, sizeof(augmented_args->arg.value));
|
newpath_len = augmented_arg__read_str(arg2, newpath_arg, sizeof(augmented_args->arg.value));
|
||||||
@ -423,8 +431,9 @@ static bool pid_filter__has(struct pids_filtered *pids, pid_t pid)
|
|||||||
static int augment_sys_enter(void *ctx, struct syscall_enter_args *args)
|
static int augment_sys_enter(void *ctx, struct syscall_enter_args *args)
|
||||||
{
|
{
|
||||||
bool augmented, do_output = false;
|
bool augmented, do_output = false;
|
||||||
int zero = 0, size, aug_size, index, output = 0,
|
int zero = 0, size, aug_size, index,
|
||||||
value_size = sizeof(struct augmented_arg) - offsetof(struct augmented_arg, value);
|
value_size = sizeof(struct augmented_arg) - offsetof(struct augmented_arg, value);
|
||||||
|
u64 output = 0; /* has to be u64, otherwise it won't pass the verifier */
|
||||||
unsigned int nr, *beauty_map;
|
unsigned int nr, *beauty_map;
|
||||||
struct beauty_payload_enter *payload;
|
struct beauty_payload_enter *payload;
|
||||||
void *arg, *payload_offset;
|
void *arg, *payload_offset;
|
||||||
@ -490,10 +499,17 @@ static int augment_sys_enter(void *ctx, struct syscall_enter_args *args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Augmented data size is limited to sizeof(augmented_arg->unnamed union with value field) */
|
||||||
|
if (aug_size > value_size)
|
||||||
|
aug_size = value_size;
|
||||||
|
|
||||||
/* write data to payload */
|
/* write data to payload */
|
||||||
if (augmented) {
|
if (augmented) {
|
||||||
int written = offsetof(struct augmented_arg, value) + aug_size;
|
int written = offsetof(struct augmented_arg, value) + aug_size;
|
||||||
|
|
||||||
|
if (written < 0 || written > sizeof(struct augmented_arg))
|
||||||
|
return 1;
|
||||||
|
|
||||||
((struct augmented_arg *)payload_offset)->size = aug_size;
|
((struct augmented_arg *)payload_offset)->size = aug_size;
|
||||||
output += written;
|
output += written;
|
||||||
payload_offset += written;
|
payload_offset += written;
|
||||||
@ -501,7 +517,7 @@ static int augment_sys_enter(void *ctx, struct syscall_enter_args *args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!do_output)
|
if (!do_output || (sizeof(struct syscall_enter_args) + output) > sizeof(struct beauty_payload_enter))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return augmented__beauty_output(ctx, payload, sizeof(struct syscall_enter_args) + output);
|
return augmented__beauty_output(ctx, payload, sizeof(struct syscall_enter_args) + output);
|
||||||
|
Loading…
Reference in New Issue
Block a user