Commit 38a81da2205f94e8a2a834b51a6b99c91fc7c2e8
Committed by
Ingo Molnar
1 parent
2ebd4ffb6d
perf events: Clean up pid passing
The kernel perf event creation path shouldn't use find_task_by_vpid() because a vpid exists in a specific namespace. find_task_by_vpid() uses current's pid namespace which isn't always the correct namespace to use for the vpid in all the places perf_event_create_kernel_counter() (and thus find_get_context()) is called. The goal is to clean up pid namespace handling and prevent bugs like: https://bugzilla.kernel.org/show_bug.cgi?id=17281 Instead of using pids switch find_get_context() to use task struct pointers directly. The syscall is responsible for resolving the pid to a task struct. This moves the pid namespace resolution into the syscall much like every other syscall that takes pid parameters. Signed-off-by: Matt Helsley <matthltc@us.ibm.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Robin Green <greenrd@greenrd.org> Cc: Prasad <prasad@linux.vnet.ibm.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Will Deacon <will.deacon@arm.com> Cc: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> LKML-Reference: <a134e5e392ab0204961fd1a62c84a222bf5874a9.1284407763.git.matthltc@us.ibm.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Showing 5 changed files with 15 additions and 17 deletions Side-by-side Diff
arch/arm/oprofile/common.c
include/linux/perf_event.h
... | ... | @@ -902,7 +902,7 @@ |
902 | 902 | extern struct perf_event * |
903 | 903 | perf_event_create_kernel_counter(struct perf_event_attr *attr, |
904 | 904 | int cpu, |
905 | - pid_t pid, | |
905 | + struct task_struct *task, | |
906 | 906 | perf_overflow_handler_t callback); |
907 | 907 | extern u64 perf_event_read_value(struct perf_event *event, |
908 | 908 | u64 *enabled, u64 *running); |
kernel/hw_breakpoint.c
... | ... | @@ -433,8 +433,7 @@ |
433 | 433 | perf_overflow_handler_t triggered, |
434 | 434 | struct task_struct *tsk) |
435 | 435 | { |
436 | - return perf_event_create_kernel_counter(attr, -1, task_pid_vnr(tsk), | |
437 | - triggered); | |
436 | + return perf_event_create_kernel_counter(attr, -1, tsk, triggered); | |
438 | 437 | } |
439 | 438 | EXPORT_SYMBOL_GPL(register_user_hw_breakpoint); |
440 | 439 | |
... | ... | @@ -516,7 +515,7 @@ |
516 | 515 | get_online_cpus(); |
517 | 516 | for_each_online_cpu(cpu) { |
518 | 517 | pevent = per_cpu_ptr(cpu_events, cpu); |
519 | - bp = perf_event_create_kernel_counter(attr, cpu, -1, triggered); | |
518 | + bp = perf_event_create_kernel_counter(attr, cpu, NULL, triggered); | |
520 | 519 | |
521 | 520 | *pevent = bp; |
522 | 521 |
kernel/perf_event.c
... | ... | @@ -2053,15 +2053,14 @@ |
2053 | 2053 | } |
2054 | 2054 | |
2055 | 2055 | static struct perf_event_context * |
2056 | -find_get_context(struct pmu *pmu, pid_t pid, int cpu) | |
2056 | +find_get_context(struct pmu *pmu, struct task_struct *task, int cpu) | |
2057 | 2057 | { |
2058 | 2058 | struct perf_event_context *ctx; |
2059 | 2059 | struct perf_cpu_context *cpuctx; |
2060 | - struct task_struct *task; | |
2061 | 2060 | unsigned long flags; |
2062 | 2061 | int ctxn, err; |
2063 | 2062 | |
2064 | - if (pid == -1 && cpu != -1) { | |
2063 | + if (!task && cpu != -1) { | |
2065 | 2064 | /* Must be root to operate on a CPU event: */ |
2066 | 2065 | if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN)) |
2067 | 2066 | return ERR_PTR(-EACCES); |
... | ... | @@ -2084,10 +2083,6 @@ |
2084 | 2083 | return ctx; |
2085 | 2084 | } |
2086 | 2085 | |
2087 | - task = find_lively_task_by_vpid(pid); | |
2088 | - if (IS_ERR(task)) | |
2089 | - return (void*)task; | |
2090 | - | |
2091 | 2086 | err = -EINVAL; |
2092 | 2087 | ctxn = pmu->task_ctx_nr; |
2093 | 2088 | if (ctxn < 0) |
... | ... | @@ -5527,6 +5522,7 @@ |
5527 | 5522 | struct perf_event_context *ctx; |
5528 | 5523 | struct file *event_file = NULL; |
5529 | 5524 | struct file *group_file = NULL; |
5525 | + struct task_struct *task = NULL; | |
5530 | 5526 | struct pmu *pmu; |
5531 | 5527 | int event_fd; |
5532 | 5528 | int fput_needed = 0; |
5533 | 5529 | |
... | ... | @@ -5581,10 +5577,13 @@ |
5581 | 5577 | if ((pmu->task_ctx_nr == perf_sw_context) && group_leader) |
5582 | 5578 | pmu = group_leader->pmu; |
5583 | 5579 | |
5580 | + if (pid != -1) | |
5581 | + task = find_lively_task_by_vpid(pid); | |
5582 | + | |
5584 | 5583 | /* |
5585 | 5584 | * Get the target context (task or percpu): |
5586 | 5585 | */ |
5587 | - ctx = find_get_context(pmu, pid, cpu); | |
5586 | + ctx = find_get_context(pmu, task, cpu); | |
5588 | 5587 | if (IS_ERR(ctx)) { |
5589 | 5588 | err = PTR_ERR(ctx); |
5590 | 5589 | goto err_group_fd; |
5591 | 5590 | |
... | ... | @@ -5666,11 +5665,11 @@ |
5666 | 5665 | * |
5667 | 5666 | * @attr: attributes of the counter to create |
5668 | 5667 | * @cpu: cpu in which the counter is bound |
5669 | - * @pid: task to profile | |
5668 | + * @task: task to profile (NULL for percpu) | |
5670 | 5669 | */ |
5671 | 5670 | struct perf_event * |
5672 | 5671 | perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, |
5673 | - pid_t pid, | |
5672 | + struct task_struct *task, | |
5674 | 5673 | perf_overflow_handler_t overflow_handler) |
5675 | 5674 | { |
5676 | 5675 | struct perf_event_context *ctx; |
... | ... | @@ -5687,7 +5686,7 @@ |
5687 | 5686 | goto err; |
5688 | 5687 | } |
5689 | 5688 | |
5690 | - ctx = find_get_context(event->pmu, pid, cpu); | |
5689 | + ctx = find_get_context(event->pmu, task, cpu); | |
5691 | 5690 | if (IS_ERR(ctx)) { |
5692 | 5691 | err = PTR_ERR(ctx); |
5693 | 5692 | goto err_free; |
kernel/watchdog.c
... | ... | @@ -358,7 +358,7 @@ |
358 | 358 | /* Try to register using hardware perf events */ |
359 | 359 | wd_attr = &wd_hw_attr; |
360 | 360 | wd_attr->sample_period = hw_nmi_get_sample_period(); |
361 | - event = perf_event_create_kernel_counter(wd_attr, cpu, -1, watchdog_overflow_callback); | |
361 | + event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback); | |
362 | 362 | if (!IS_ERR(event)) { |
363 | 363 | printk(KERN_INFO "NMI watchdog enabled, takes one hw-pmu counter.\n"); |
364 | 364 | goto out_save; |