[for-3.18,3/7] perf: Tighten (and fix) the grouping condition

Message ID 1493832958-12489-4-git-send-email-amit.pundir@linaro.org
State New
Headers show
Series
  • Security fixes picked from android security bulletins
Related show

Commit Message

Amit Pundir May 3, 2017, 5:35 p.m.
From: Peter Zijlstra <peterz@infradead.org>


The fix from 9fc81d87420d ("perf: Fix events installation during
moving group") was incomplete in that it failed to recognise that
creating a group with events for different CPUs is semantically
broken -- they cannot be co-scheduled.

Furthermore, it leads to real breakage where, when we create an event
for CPU Y and then migrate it to form a group on CPU X, the code gets
confused where the counter is programmed -- triggered in practice
as well by me via the perf fuzzer.

Fix this by tightening the rules for creating groups. Only allow
grouping of counters that can be co-scheduled in the same context.
This means for the same task and/or the same cpu.

Fixes: 9fc81d87420d ("perf: Fix events installation during moving group")
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/20150123125834.090683288@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>

(cherry picked from commit c3c87e770458aa004bd7ed3f29945ff436fd6511)
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>

---
 include/linux/perf_event.h |  6 ------
 kernel/events/core.c       | 15 +++++++++++++--
 2 files changed, 13 insertions(+), 8 deletions(-)

-- 
2.7.4

Comments

Linus Torvalds May 3, 2017, 5:42 p.m. | #1
On Wed, May 3, 2017 at 10:35 AM, Amit Pundir <amit.pundir@linaro.org> wrote:
>

> Signed-off-by: Ingo Molnar <mingo@kernel.org>

> (cherry picked from commit c3c87e770458aa004bd7ed3f29945ff436fd6511)

> Signed-off-by: Amit Pundir <amit.pundir@linaro.org>


When sending things to the stable tree, it's better to make that
upstream information explicit at the top, rather than hiding it like
this in the sign-off change.

IOW, just somethuing like

   "commit c3c87e770458aa004bd7ed3f29945ff436fd6511 upstream"

as the first line of the body (not the subject line) tends to be the
standard way.

I suspect Greg edits things that way anyway, but it presumably helps
if it's already in the right format.

That way i*really* stands out what commit that is upstream.

                    Linus
Amit Pundir May 3, 2017, 5:58 p.m. | #2
On 3 May 2017 at 23:12, Linus Torvalds <torvalds@linux-foundation.org> wrote:
> On Wed, May 3, 2017 at 10:35 AM, Amit Pundir <amit.pundir@linaro.org> wrote:

>>

>> Signed-off-by: Ingo Molnar <mingo@kernel.org>

>> (cherry picked from commit c3c87e770458aa004bd7ed3f29945ff436fd6511)

>> Signed-off-by: Amit Pundir <amit.pundir@linaro.org>

>

> When sending things to the stable tree, it's better to make that

> upstream information explicit at the top, rather than hiding it like

> this in the sign-off change.

>

> IOW, just somethuing like

>

>    "commit c3c87e770458aa004bd7ed3f29945ff436fd6511 upstream"

>

> as the first line of the body (not the subject line) tends to be the

> standard way.

>

> I suspect Greg edits things that way anyway, but it presumably helps

> if it's already in the right format.

>

> That way i*really* stands out what commit that is upstream.


Thanks. I'll take care of the format from next time.

Regards,
Amit Pundir

>

>                     Linus

Patch

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index df8904fea40c..482ccff29bc9 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -455,11 +455,6 @@  struct perf_event {
 #endif /* CONFIG_PERF_EVENTS */
 };
 
-enum perf_event_context_type {
-	task_context,
-	cpu_context,
-};
-
 /**
  * struct perf_event_context - event context structure
  *
@@ -467,7 +462,6 @@  enum perf_event_context_type {
  */
 struct perf_event_context {
 	struct pmu			*pmu;
-	enum perf_event_context_type	type;
 	/*
 	 * Protect the states of the events in the list,
 	 * nr_active, and the list:
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 3ebad2556698..26c40faa8ea4 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6803,7 +6803,6 @@  skip_type:
 		__perf_event_init_context(&cpuctx->ctx);
 		lockdep_set_class(&cpuctx->ctx.mutex, &cpuctx_mutex);
 		lockdep_set_class(&cpuctx->ctx.lock, &cpuctx_lock);
-		cpuctx->ctx.type = cpu_context;
 		cpuctx->ctx.pmu = pmu;
 
 		__perf_cpu_hrtimer_init(cpuctx, cpu);
@@ -7445,7 +7444,19 @@  SYSCALL_DEFINE5(perf_event_open,
 		 * task or CPU context:
 		 */
 		if (move_group) {
-			if (group_leader->ctx->type != ctx->type)
+			/*
+			 * Make sure we're both on the same task, or both
+			 * per-cpu events.
+			 */
+			if (group_leader->ctx->task != ctx->task)
+				goto err_context;
+
+			/*
+			 * Make sure we're both events for the same CPU;
+			 * grouping events for different CPUs is broken; since
+			 * you can never concurrently schedule them anyhow.
+			 */
+			if (group_leader->cpu != event->cpu)
 				goto err_context;
 		} else {
 			if (group_leader->ctx != ctx)