perf_event_open() Stack Backtrace Vulnerability
perf_event_open() offers to collect various pieces of information when an event occurs, including a user stack backtrace (PERF_SAMPLE_CALLCHAIN). To collect a user stack backtrace, the kernel grabs the userland register state (if the event occured in kernelspace: the userland register state that was recorded on syscall entry), then walks the stackframes by following framepointers. On ARM, the step from one stackframe to the next one is implemented in arch/arm/kernel/perf_callchain.c as follows: The access_ok() check is intended to prevent a malicious userland process from abusing the perf_event_open() API to leak kernelspace data. However, access_ok() does not actually check anything in set_fs(KERNEL_DS) sections, and performance events can occur in pretty much any context. Therefore, by causing a performance event to fire while e.g. the splice() syscall is running under KERNEL_DS, an attacker can circumvent this protection. After circumventing the protection, the attacker can set up a stackframe whith a controlled return address, and the kernel will happily follow it.