[PATCH 1/2] perf ioctl: Add check for the sample_period value

Subsystems: performance events subsystem, the rest

STALE2595d

12 messages, 5 authors, 2019-06-18 · open the first message on its own page

[PATCH 1/2] perf ioctl: Add check for the sample_period value

From: Ravi Bangoria <hidden>
Date: 2019-05-11 02:42:40

Add a check for sample_period value sent from userspace. Negative
value does not make sense. And in powerpc arch code this could cause
a recursive PMI leading to a hang (reported when running perf-fuzzer).

Signed-off-by: Ravi Bangoria <redacted>
---
 kernel/events/core.c | 3 +++
 1 file changed, 3 insertions(+)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index abbd4b3b96c2..e44c90378940 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5005,6 +5005,9 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
 	if (perf_event_check_period(event, value))
 		return -EINVAL;
 
+	if (!event->attr.freq && (value & (1ULL << 63)))
+		return -EINVAL;
+
 	event_function_call(event, __perf_event_period, &value);
 
 	return 0;
-- 
2.20.1

[PATCH 2/2] powerpc/perf: Fix mmcra corruption by bhrb_filter

From: Ravi Bangoria <hidden>
Date: 2019-05-11 02:42:48

Consider a scenario where user creates two events:

  1st event:
    attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
    attr.branch_sample_type = PERF_SAMPLE_BRANCH_ANY;
    fd = perf_event_open(attr, 0, 1, -1, 0);

  This sets cpuhw->bhrb_filter to 0 and returns valid fd.

  2nd event:
    attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
    attr.branch_sample_type = PERF_SAMPLE_BRANCH_CALL;
    fd = perf_event_open(attr, 0, 1, -1, 0);

  It overrides cpuhw->bhrb_filter to -1 and returns with error.

Now if power_pmu_enable() gets called by any path other than
power_pmu_add(), ppmu->config_bhrb(-1) will set mmcra to -1.

Signed-off-by: Ravi Bangoria <redacted>
---
 arch/powerpc/perf/core-book3s.c | 6 ++++--
 arch/powerpc/perf/power8-pmu.c  | 3 +++
 arch/powerpc/perf/power9-pmu.c  | 3 +++
 3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index b0723002a396..8eb5dc5df62b 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -1846,6 +1846,7 @@ static int power_pmu_event_init(struct perf_event *event)
 	int n;
 	int err;
 	struct cpu_hw_events *cpuhw;
+	u64 bhrb_filter;
 
 	if (!ppmu)
 		return -ENOENT;
@@ -1951,13 +1952,14 @@ static int power_pmu_event_init(struct perf_event *event)
 	err = power_check_constraints(cpuhw, events, cflags, n + 1);
 
 	if (has_branch_stack(event)) {
-		cpuhw->bhrb_filter = ppmu->bhrb_filter_map(
+		bhrb_filter = ppmu->bhrb_filter_map(
 					event->attr.branch_sample_type);
 
-		if (cpuhw->bhrb_filter == -1) {
+		if (bhrb_filter == -1) {
 			put_cpu_var(cpu_hw_events);
 			return -EOPNOTSUPP;
 		}
+		cpuhw->bhrb_filter = bhrb_filter;
 	}
 
 	put_cpu_var(cpu_hw_events);
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index d12a2db26353..d10feef93b6b 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -29,6 +29,7 @@ enum {
 #define	POWER8_MMCRA_IFM1		0x0000000040000000UL
 #define	POWER8_MMCRA_IFM2		0x0000000080000000UL
 #define	POWER8_MMCRA_IFM3		0x00000000C0000000UL
+#define	POWER8_MMCRA_BHRB_MASK		0x00000000C0000000UL
 
 /*
  * Raw event encoding for PowerISA v2.07 (Power8):
@@ -243,6 +244,8 @@ static u64 power8_bhrb_filter_map(u64 branch_sample_type)
 
 static void power8_config_bhrb(u64 pmu_bhrb_filter)
 {
+	pmu_bhrb_filter &= POWER8_MMCRA_BHRB_MASK;
+
 	/* Enable BHRB filter in PMU */
 	mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
 }
diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c
index 030544e35959..f3987915cadc 100644
--- a/arch/powerpc/perf/power9-pmu.c
+++ b/arch/powerpc/perf/power9-pmu.c
@@ -92,6 +92,7 @@ enum {
 #define POWER9_MMCRA_IFM1		0x0000000040000000UL
 #define POWER9_MMCRA_IFM2		0x0000000080000000UL
 #define POWER9_MMCRA_IFM3		0x00000000C0000000UL
+#define POWER9_MMCRA_BHRB_MASK		0x00000000C0000000UL
 
 /* Nasty Power9 specific hack */
 #define PVR_POWER9_CUMULUS		0x00002000
@@ -300,6 +301,8 @@ static u64 power9_bhrb_filter_map(u64 branch_sample_type)
 
 static void power9_config_bhrb(u64 pmu_bhrb_filter)
 {
+	pmu_bhrb_filter &= POWER9_MMCRA_BHRB_MASK;
+
 	/* Enable BHRB filter in PMU */
 	mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
 }
-- 
2.20.1

Re: [PATCH 2/2] powerpc/perf: Fix mmcra corruption by bhrb_filter

From: Ravi Bangoria <hidden>
Date: 2019-05-11 02:47:32


On 5/11/19 8:12 AM, Ravi Bangoria wrote:
Consider a scenario where user creates two events:

  1st event:
    attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
    attr.branch_sample_type = PERF_SAMPLE_BRANCH_ANY;
    fd = perf_event_open(attr, 0, 1, -1, 0);

  This sets cpuhw->bhrb_filter to 0 and returns valid fd.

  2nd event:
    attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
    attr.branch_sample_type = PERF_SAMPLE_BRANCH_CALL;
    fd = perf_event_open(attr, 0, 1, -1, 0);

  It overrides cpuhw->bhrb_filter to -1 and returns with error.

Now if power_pmu_enable() gets called by any path other than
power_pmu_add(), ppmu->config_bhrb(-1) will set mmcra to -1.

Signed-off-by: Ravi Bangoria <redacted>
Fixes: 3925f46bb590 ("powerpc/perf: Enable branch stack sampling framework")

Re: [PATCH 2/2] powerpc/perf: Fix mmcra corruption by bhrb_filter

From: Madhavan Srinivasan <hidden>
Date: 2019-05-22 05:01:46

On 11/05/19 8:12 AM, Ravi Bangoria wrote:
Consider a scenario where user creates two events:

   1st event:
     attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
     attr.branch_sample_type = PERF_SAMPLE_BRANCH_ANY;
     fd = perf_event_open(attr, 0, 1, -1, 0);

   This sets cpuhw->bhrb_filter to 0 and returns valid fd.

   2nd event:
     attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
     attr.branch_sample_type = PERF_SAMPLE_BRANCH_CALL;
     fd = perf_event_open(attr, 0, 1, -1, 0);

   It overrides cpuhw->bhrb_filter to -1 and returns with error.

Now if power_pmu_enable() gets called by any path other than
power_pmu_add(), ppmu->config_bhrb(-1) will set mmcra to -1.
Reviewed-by: Madhavan Srinivasan <redacted>

quoted hunk
Signed-off-by: Ravi Bangoria <redacted>
---
  arch/powerpc/perf/core-book3s.c | 6 ++++--
  arch/powerpc/perf/power8-pmu.c  | 3 +++
  arch/powerpc/perf/power9-pmu.c  | 3 +++
  3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index b0723002a396..8eb5dc5df62b 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -1846,6 +1846,7 @@ static int power_pmu_event_init(struct perf_event *event)
  	int n;
  	int err;
  	struct cpu_hw_events *cpuhw;
+	u64 bhrb_filter;

  	if (!ppmu)
  		return -ENOENT;
@@ -1951,13 +1952,14 @@ static int power_pmu_event_init(struct perf_event *event)
  	err = power_check_constraints(cpuhw, events, cflags, n + 1);

  	if (has_branch_stack(event)) {
-		cpuhw->bhrb_filter = ppmu->bhrb_filter_map(
+		bhrb_filter = ppmu->bhrb_filter_map(
  					event->attr.branch_sample_type);

-		if (cpuhw->bhrb_filter == -1) {
+		if (bhrb_filter == -1) {
  			put_cpu_var(cpu_hw_events);
  			return -EOPNOTSUPP;
  		}
+		cpuhw->bhrb_filter = bhrb_filter;
  	}

  	put_cpu_var(cpu_hw_events);
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index d12a2db26353..d10feef93b6b 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -29,6 +29,7 @@ enum {
  #define	POWER8_MMCRA_IFM1		0x0000000040000000UL
  #define	POWER8_MMCRA_IFM2		0x0000000080000000UL
  #define	POWER8_MMCRA_IFM3		0x00000000C0000000UL
+#define	POWER8_MMCRA_BHRB_MASK		0x00000000C0000000UL

  /*
   * Raw event encoding for PowerISA v2.07 (Power8):
@@ -243,6 +244,8 @@ static u64 power8_bhrb_filter_map(u64 branch_sample_type)

  static void power8_config_bhrb(u64 pmu_bhrb_filter)
  {
+	pmu_bhrb_filter &= POWER8_MMCRA_BHRB_MASK;
+
  	/* Enable BHRB filter in PMU */
  	mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
  }
diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c
index 030544e35959..f3987915cadc 100644
--- a/arch/powerpc/perf/power9-pmu.c
+++ b/arch/powerpc/perf/power9-pmu.c
@@ -92,6 +92,7 @@ enum {
  #define POWER9_MMCRA_IFM1		0x0000000040000000UL
  #define POWER9_MMCRA_IFM2		0x0000000080000000UL
  #define POWER9_MMCRA_IFM3		0x00000000C0000000UL
+#define POWER9_MMCRA_BHRB_MASK		0x00000000C0000000UL

  /* Nasty Power9 specific hack */
  #define PVR_POWER9_CUMULUS		0x00002000
@@ -300,6 +301,8 @@ static u64 power9_bhrb_filter_map(u64 branch_sample_type)

  static void power9_config_bhrb(u64 pmu_bhrb_filter)
  {
+	pmu_bhrb_filter &= POWER9_MMCRA_BHRB_MASK;
+
  	/* Enable BHRB filter in PMU */
  	mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
  }

Re: [PATCH 2/2] powerpc/perf: Fix mmcra corruption by bhrb_filter

From: Michael Ellerman <hidden>
Date: 2019-05-25 00:54:51

On Sat, 2019-05-11 at 02:42:17 UTC, Ravi Bangoria wrote:
Consider a scenario where user creates two events:

  1st event:
    attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
    attr.branch_sample_type = PERF_SAMPLE_BRANCH_ANY;
    fd = perf_event_open(attr, 0, 1, -1, 0);

  This sets cpuhw->bhrb_filter to 0 and returns valid fd.

  2nd event:
    attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
    attr.branch_sample_type = PERF_SAMPLE_BRANCH_CALL;
    fd = perf_event_open(attr, 0, 1, -1, 0);

  It overrides cpuhw->bhrb_filter to -1 and returns with error.

Now if power_pmu_enable() gets called by any path other than
power_pmu_add(), ppmu->config_bhrb(-1) will set mmcra to -1.

Signed-off-by: Ravi Bangoria <redacted>
Reviewed-by: Madhavan Srinivasan <redacted>
Applied to powerpc fixes, thanks.

https://git.kernel.org/powerpc/c/3202e35ec1c8fc19cea24253ff83edf7

cheers

Re: [PATCH 1/2] perf ioctl: Add check for the sample_period value

From: Peter Zijlstra <peterz@infradead.org>
Date: 2019-05-13 07:42:37

On Sat, May 11, 2019 at 08:12:16AM +0530, Ravi Bangoria wrote:
quoted hunk
Add a check for sample_period value sent from userspace. Negative
value does not make sense. And in powerpc arch code this could cause
a recursive PMI leading to a hang (reported when running perf-fuzzer).

Signed-off-by: Ravi Bangoria <redacted>
---
 kernel/events/core.c | 3 +++
 1 file changed, 3 insertions(+)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index abbd4b3b96c2..e44c90378940 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5005,6 +5005,9 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
 	if (perf_event_check_period(event, value))
 		return -EINVAL;
 
+	if (!event->attr.freq && (value & (1ULL << 63)))
+		return -EINVAL;
Well, perf_event_attr::sample_period is __u64. Would not be the site
using it as signed be the one in error?

Re: [PATCH 1/2] perf ioctl: Add check for the sample_period value

From: Peter Zijlstra <peterz@infradead.org>
Date: 2019-05-13 08:56:45

On Mon, May 13, 2019 at 09:42:13AM +0200, Peter Zijlstra wrote:
On Sat, May 11, 2019 at 08:12:16AM +0530, Ravi Bangoria wrote:
quoted
Add a check for sample_period value sent from userspace. Negative
value does not make sense. And in powerpc arch code this could cause
a recursive PMI leading to a hang (reported when running perf-fuzzer).

Signed-off-by: Ravi Bangoria <redacted>
---
 kernel/events/core.c | 3 +++
 1 file changed, 3 insertions(+)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index abbd4b3b96c2..e44c90378940 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5005,6 +5005,9 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
 	if (perf_event_check_period(event, value))
 		return -EINVAL;
 
+	if (!event->attr.freq && (value & (1ULL << 63)))
+		return -EINVAL;
Well, perf_event_attr::sample_period is __u64. Would not be the site
using it as signed be the one in error?
You forgot to mention commit: 0819b2e30ccb9, so I guess this just makes
it consistent and is fine.

Re: [PATCH 1/2] perf ioctl: Add check for the sample_period value

From: Ravi Bangoria <hidden>
Date: 2019-05-13 10:07:16


On 5/13/19 2:26 PM, Peter Zijlstra wrote:
On Mon, May 13, 2019 at 09:42:13AM +0200, Peter Zijlstra wrote:
quoted
On Sat, May 11, 2019 at 08:12:16AM +0530, Ravi Bangoria wrote:
quoted
Add a check for sample_period value sent from userspace. Negative
value does not make sense. And in powerpc arch code this could cause
a recursive PMI leading to a hang (reported when running perf-fuzzer).

Signed-off-by: Ravi Bangoria <redacted>
---
 kernel/events/core.c | 3 +++
 1 file changed, 3 insertions(+)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index abbd4b3b96c2..e44c90378940 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5005,6 +5005,9 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
 	if (perf_event_check_period(event, value))
 		return -EINVAL;
 
+	if (!event->attr.freq && (value & (1ULL << 63)))
+		return -EINVAL;
Well, perf_event_attr::sample_period is __u64. Would not be the site
using it as signed be the one in error?
You forgot to mention commit: 0819b2e30ccb9, so I guess this just makes
it consistent and is fine.
Yeah, I was about to reply :)

Re: [PATCH 1/2] perf ioctl: Add check for the sample_period value

From: Michael Ellerman <mpe@ellerman.id.au>
Date: 2019-05-28 09:50:42

Ravi Bangoria [off-list ref] writes:
On 5/13/19 2:26 PM, Peter Zijlstra wrote:
quoted
On Mon, May 13, 2019 at 09:42:13AM +0200, Peter Zijlstra wrote:
quoted
On Sat, May 11, 2019 at 08:12:16AM +0530, Ravi Bangoria wrote:
quoted
Add a check for sample_period value sent from userspace. Negative
value does not make sense. And in powerpc arch code this could cause
a recursive PMI leading to a hang (reported when running perf-fuzzer).

Signed-off-by: Ravi Bangoria <redacted>
---
 kernel/events/core.c | 3 +++
 1 file changed, 3 insertions(+)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index abbd4b3b96c2..e44c90378940 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5005,6 +5005,9 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
 	if (perf_event_check_period(event, value))
 		return -EINVAL;
 
+	if (!event->attr.freq && (value & (1ULL << 63)))
+		return -EINVAL;
Well, perf_event_attr::sample_period is __u64. Would not be the site
using it as signed be the one in error?
You forgot to mention commit: 0819b2e30ccb9, so I guess this just makes
it consistent and is fine.
Yeah, I was about to reply :)
I've taken patch 2. You should probably do a v2 of patch 1 with an
updated change log that explains things fully?

cheers

[PATCH v2] perf ioctl: Add check for the sample_period value

From: Ravi Bangoria <hidden>
Date: 2019-06-04 04:30:19

perf_event_open() limits the sample_period to 63 bits. See
commit 0819b2e30ccb ("perf: Limit perf_event_attr::sample_period
to 63 bits"). Make ioctl() consistent with it.

Also on powerpc, negative sample_period could cause a recursive
PMIs leading to a hang (reported when running perf-fuzzer).

Signed-off-by: Ravi Bangoria <redacted>
---
 kernel/events/core.c | 3 +++
 1 file changed, 3 insertions(+)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index abbd4b3b96c2..e44c90378940 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5005,6 +5005,9 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
 	if (perf_event_check_period(event, value))
 		return -EINVAL;
 
+	if (!event->attr.freq && (value & (1ULL << 63)))
+		return -EINVAL;
+
 	event_function_call(event, __perf_event_period, &value);
 
 	return 0;
-- 
2.20.1

Re: [PATCH v2] perf ioctl: Add check for the sample_period value

From: Ravi Bangoria <hidden>
Date: 2019-06-17 08:38:44

Peter / mpe,

Is the v2 looks good? If so, can anyone of you please pick this up.

On 6/4/19 9:59 AM, Ravi Bangoria wrote:
quoted hunk
perf_event_open() limits the sample_period to 63 bits. See
commit 0819b2e30ccb ("perf: Limit perf_event_attr::sample_period
to 63 bits"). Make ioctl() consistent with it.

Also on powerpc, negative sample_period could cause a recursive
PMIs leading to a hang (reported when running perf-fuzzer).

Signed-off-by: Ravi Bangoria <redacted>
---
 kernel/events/core.c | 3 +++
 1 file changed, 3 insertions(+)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index abbd4b3b96c2..e44c90378940 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5005,6 +5005,9 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
 	if (perf_event_check_period(event, value))
 		return -EINVAL;
 
+	if (!event->attr.freq && (value & (1ULL << 63)))
+		return -EINVAL;
+
 	event_function_call(event, __perf_event_period, &value);
 
 	return 0;

Re: [PATCH v2] perf ioctl: Add check for the sample_period value

From: Michael Ellerman <mpe@ellerman.id.au>
Date: 2019-06-18 12:28:26

Ravi Bangoria [off-list ref] writes:
Peter / mpe,

Is the v2 looks good? If so, can anyone of you please pick this up.
I usually wouldn't take it, it's generic perf code. Unless
peter/ingo/acme tell me otherwise.

It's sort of a bug fix for 0819b2e30ccb, should it have a fixes and/or
stable tag?

  Fixes: 0819b2e30ccb ("perf: Limit perf_event_attr::sample_period to 63 bits")
  Cc: stable@vger.kernel.org # v3.15+

cheers
On 6/4/19 9:59 AM, Ravi Bangoria wrote:
quoted
perf_event_open() limits the sample_period to 63 bits. See
commit 0819b2e30ccb ("perf: Limit perf_event_attr::sample_period
to 63 bits"). Make ioctl() consistent with it.

Also on powerpc, negative sample_period could cause a recursive
PMIs leading to a hang (reported when running perf-fuzzer).

Signed-off-by: Ravi Bangoria <redacted>
---
 kernel/events/core.c | 3 +++
 1 file changed, 3 insertions(+)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index abbd4b3b96c2..e44c90378940 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5005,6 +5005,9 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
 	if (perf_event_check_period(event, value))
 		return -EINVAL;
 
+	if (!event->attr.freq && (value & (1ULL << 63)))
+		return -EINVAL;
+
 	event_function_call(event, __perf_event_period, &value);
 
 	return 0;
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help