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 |
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.
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.
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 --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
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(-)