Messages in this thread | | | Date | Mon, 07 Jul 2014 20:41:57 +0400 | From | Alexander Yarygin <> | Subject | [BUG] perf stat: events inheritance can break task targets |
| |
perf stat can block pthread_create() for a multithreaded userspace process (i.e. qemu) when: - process is running with non-root privileges - perf stat is running as root with trace events in -e option - it is attached to the process's pid.
Here is a simple test scenario:
~$ cat test.c #include <stdio.h> #include <pthread.h> #include <unistd.h> #include <string.h>
#define THREADS 50
static pthread_t threads[THREADS];
void *loop() { while(1); }
int main() { for (int i = 0; i < THREADS; i++) {
int err = pthread_create(&threads[i], NULL, loop, 0);
if (!err) printf("thread created: %i\n", i); else printf("couldn't create thread %i: %s\n", i, strerror(err));
sleep(1); }
return 0; } ~$ gcc test.c -lpthread -std=c99 -o test ~$ ./test thread created: 0 thread created: 1 # now perf is running: # ~$ sudo perf stat -e "kvm:*" -p `pidof test` couldn't create thread 2: Operation not permitted couldn't create thread 3: Operation not permitted couldn't create thread 4: Operation not permitted # here is perf was stopped thread created: 5 thread created: 6 ^C
When perf is running, every invoke of pthread_create() returns -EPERM.
On the kernel side, copy_process() creates a task, scheduled it, than perf_event_init_task() (kernel/events/core.c) returns an error, and the kernel cleans task's resources.
It looks like child process doesn't have access to trace events, so perf_trace_event_perm() (kernel/trace/trace_event_perf.c) returns -EPERM:
static int perf_trace_event_perm(struct ftrace_event_call *tp_event, struct perf_event *p_event) { ... /* * ...otherwise raw tracepoint data can be a severe data leak, * only allow root to have these. */ if (perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN)) return -EPERM; ... }
If we explicitly use the --no-inherit option, payload wouldn't die.
| |