Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e5ac623a authored by Raghavendra Rao Ananta's avatar Raghavendra Rao Ananta
Browse files

perf: Satisfy the kernel's request to request PMU counters



The SELinux policy on Android doesn't provide the kernel-space
with CAP_SYS_ADMIN capability. The perf-core checks for this
capability before giving access to the callers to read the PMU
counters. Hence, when the kernel drivers try to gain access
to the PMU (via perf_event_create_kernel_counter()), it fails
with -EACCES.

To get past this, add another condition to check if the request
is coming from kernel-space or user-space. If kernel-space,
don't check for the capability any further and move on.

Change-Id: Ie2ddc6b619fa0d60d4752994ea0c9cedf5b96b5c
Signed-off-by: default avatarRaghavendra Rao Ananta <rananta@codeaurora.org>
parent 333b4ccb
Loading
Loading
Loading
Loading
+17 −3
Original line number Diff line number Diff line
@@ -1253,6 +1253,13 @@ int perf_event_max_stack_handler(struct ctl_table *table, int write,
#define PERF_SECURITY_KERNEL		2
#define PERF_SECURITY_TRACEPOINT	3

#define TASK_TOMBSTONE ((void *)-1L)

static bool is_kernel_event(struct perf_event *event)
{
	return READ_ONCE(event->owner) == TASK_TOMBSTONE;
}

static inline bool perf_paranoid_any(void)
{
	return sysctl_perf_event_paranoid > 2;
@@ -1271,12 +1278,19 @@ static inline int perf_allow_kernel(struct perf_event_attr *attr)
	return security_perf_event_open(attr, PERF_SECURITY_KERNEL);
}

static inline int perf_allow_cpu(struct perf_event_attr *attr)
static inline int perf_allow_cpu(struct perf_event *event)
{
	if (sysctl_perf_event_paranoid > 0 && !capable(CAP_SYS_ADMIN))
	if (sysctl_perf_event_paranoid > 0 && !is_kernel_event(event) &&
		!capable(CAP_SYS_ADMIN)) {
		return -EACCES;
	}

	return security_perf_event_open(attr, PERF_SECURITY_CPU);
	/*
	 * Bypass the system call security check if the
	 * event creation is from the kernel
	 */
	return is_kernel_event(event) ? 0 :
		security_perf_event_open(&event->attr, PERF_SECURITY_CPU);
}

static inline int perf_allow_tracepoint(struct perf_event_attr *attr)
+1 −8
Original line number Diff line number Diff line
@@ -164,13 +164,6 @@ static void perf_ctx_unlock(struct perf_cpu_context *cpuctx,
	raw_spin_unlock(&cpuctx->ctx.lock);
}

#define TASK_TOMBSTONE ((void *)-1L)

static bool is_kernel_event(struct perf_event *event)
{
	return READ_ONCE(event->owner) == TASK_TOMBSTONE;
}

/*
 * On task ctx scheduling...
 *
@@ -4234,7 +4227,7 @@ find_get_context(struct pmu *pmu, struct task_struct *task,

	if (!task) {
		/* Must be root to operate on a CPU event: */
		err = perf_allow_cpu(&event->attr);
		err = perf_allow_cpu(event);
		if (err)
			return ERR_PTR(err);