diff mbox series

drivers/perf: arm_spe: Use perf_allow_kernel() for permissions

Message ID 20240807105441.2156738-1-james.clark@linaro.org (mailing list archive)
State New, archived
Headers show
Series drivers/perf: arm_spe: Use perf_allow_kernel() for permissions | expand

Commit Message

James Clark Aug. 7, 2024, 10:54 a.m. UTC
For other PMUs, PERF_SAMPLE_PHYS_ADDR requires perf_allow_kernel()
rather than just perfmon_capable(). Because PMSCR_EL1_PA is another form
of physical address, make it consistent and use perf_allow_kernel() for
SPE as well. PMSCR_EL1_PCT and PMSCR_EL1_CX also get the same change.

This improves consistency and indirectly fixes the following error
message which is misleading because perf_event_paranoid is not taken
into account by perfmon_capable():

  $ perf record -e arm_spe/pa_enable/

  Error:
  Access to performance monitoring and observability operations is
  limited. Consider adjusting /proc/sys/kernel/perf_event_paranoid
  setting ...

Suggested-by: Al Grant <al.grant@arm.com>
Signed-off-by: James Clark <james.clark@linaro.org>
---
 drivers/perf/arm_spe_pmu.c | 9 ++++-----
 kernel/events/core.c       | 1 +
 security/security.c        | 1 +
 3 files changed, 6 insertions(+), 5 deletions(-)

Comments

Peter Zijlstra Aug. 7, 2024, 11:15 a.m. UTC | #1
On Wed, Aug 07, 2024 at 11:54:41AM +0100, James Clark wrote:
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index aa3450bdc227..4a69583e329a 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -417,6 +417,7 @@ static struct kmem_cache *perf_event_cache;
>   *   2 - disallow kernel profiling for unpriv
>   */
>  int sysctl_perf_event_paranoid __read_mostly = 2;
> +EXPORT_SYMBOL_GPL(sysctl_perf_event_paranoid);

I'm never a fan of exporting variables. Perhaps create a helper function
that returns the value and use that where required?

That avoids modules getting the idea it would be okay to change this
valie themselves.
James Clark Aug. 7, 2024, 11:20 a.m. UTC | #2
On 07/08/2024 12:15 pm, Peter Zijlstra wrote:
> On Wed, Aug 07, 2024 at 11:54:41AM +0100, James Clark wrote:
>> diff --git a/kernel/events/core.c b/kernel/events/core.c
>> index aa3450bdc227..4a69583e329a 100644
>> --- a/kernel/events/core.c
>> +++ b/kernel/events/core.c
>> @@ -417,6 +417,7 @@ static struct kmem_cache *perf_event_cache;
>>    *   2 - disallow kernel profiling for unpriv
>>    */
>>   int sysctl_perf_event_paranoid __read_mostly = 2;
>> +EXPORT_SYMBOL_GPL(sysctl_perf_event_paranoid);
> 
> I'm never a fan of exporting variables. Perhaps create a helper function
> that returns the value and use that where required?
> 
> That avoids modules getting the idea it would be okay to change this
> valie themselves.

I could also remove the inline from perf_allow_kernel() and export that 
instead. I don't think it really needs to be inlined but I gave it the 
benefit of the doubt because it was added that way.
Peter Zijlstra Aug. 7, 2024, noon UTC | #3
On Wed, Aug 07, 2024 at 12:20:13PM +0100, James Clark wrote:
> 
> 
> On 07/08/2024 12:15 pm, Peter Zijlstra wrote:
> > On Wed, Aug 07, 2024 at 11:54:41AM +0100, James Clark wrote:
> > > diff --git a/kernel/events/core.c b/kernel/events/core.c
> > > index aa3450bdc227..4a69583e329a 100644
> > > --- a/kernel/events/core.c
> > > +++ b/kernel/events/core.c
> > > @@ -417,6 +417,7 @@ static struct kmem_cache *perf_event_cache;
> > >    *   2 - disallow kernel profiling for unpriv
> > >    */
> > >   int sysctl_perf_event_paranoid __read_mostly = 2;
> > > +EXPORT_SYMBOL_GPL(sysctl_perf_event_paranoid);
> > 
> > I'm never a fan of exporting variables. Perhaps create a helper function
> > that returns the value and use that where required?
> > 
> > That avoids modules getting the idea it would be okay to change this
> > valie themselves.
> 
> I could also remove the inline from perf_allow_kernel() and export that
> instead. I don't think it really needs to be inlined but I gave it the
> benefit of the doubt because it was added that way.

Yes, that works, none of that is a fast path anyway.
diff mbox series

Patch

diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c
index 9100d82bfabc..3569050f9cf3 100644
--- a/drivers/perf/arm_spe_pmu.c
+++ b/drivers/perf/arm_spe_pmu.c
@@ -41,7 +41,7 @@ 
 
 /*
  * Cache if the event is allowed to trace Context information.
- * This allows us to perform the check, i.e, perfmon_capable(),
+ * This allows us to perform the check, i.e, perf_allow_kernel(),
  * in the context of the event owner, once, during the event_init().
  */
 #define SPE_PMU_HW_FLAGS_CX			0x00001
@@ -50,7 +50,7 @@  static_assert((PERF_EVENT_FLAG_ARCH & SPE_PMU_HW_FLAGS_CX) == SPE_PMU_HW_FLAGS_C
 
 static void set_spe_event_has_cx(struct perf_event *event)
 {
-	if (IS_ENABLED(CONFIG_PID_IN_CONTEXTIDR) && perfmon_capable())
+	if (IS_ENABLED(CONFIG_PID_IN_CONTEXTIDR) && !perf_allow_kernel(&event->attr))
 		event->hw.flags |= SPE_PMU_HW_FLAGS_CX;
 }
 
@@ -745,9 +745,8 @@  static int arm_spe_pmu_event_init(struct perf_event *event)
 
 	set_spe_event_has_cx(event);
 	reg = arm_spe_event_to_pmscr(event);
-	if (!perfmon_capable() &&
-	    (reg & (PMSCR_EL1_PA | PMSCR_EL1_PCT)))
-		return -EACCES;
+	if (reg & (PMSCR_EL1_PA | PMSCR_EL1_PCT))
+		return perf_allow_kernel(&event->attr);
 
 	return 0;
 }
diff --git a/kernel/events/core.c b/kernel/events/core.c
index aa3450bdc227..4a69583e329a 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -417,6 +417,7 @@  static struct kmem_cache *perf_event_cache;
  *   2 - disallow kernel profiling for unpriv
  */
 int sysctl_perf_event_paranoid __read_mostly = 2;
+EXPORT_SYMBOL_GPL(sysctl_perf_event_paranoid);
 
 /* Minimum for 512 kiB + 1 user control page */
 int sysctl_perf_event_mlock __read_mostly = 512 + (PAGE_SIZE / 1024); /* 'free' kiB per user */
diff --git a/security/security.c b/security/security.c
index 8cee5b6c6e6d..70cc9206e902 100644
--- a/security/security.c
+++ b/security/security.c
@@ -5610,6 +5610,7 @@  int security_perf_event_open(struct perf_event_attr *attr, int type)
 {
 	return call_int_hook(perf_event_open, attr, type);
 }
+EXPORT_SYMBOL_GPL(security_perf_event_open);
 
 /**
  * security_perf_event_alloc() - Allocate a perf event LSM blob