mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 10:09:10 +02:00
perf sched: Replace BUG_ON and add NULL checks in replay event helpers
get_new_event() has three issues:
1. The zalloc() result is dereferenced without a NULL check, crashing
on allocation failure.
2. BUG_ON(!task->atoms) kills the process when realloc() fails.
Since perf.data is untrusted input, this should be a graceful error.
3. The realloc pattern assigns directly to task->atoms, losing the old
pointer on failure. task->nr_events is also incremented before the
realloc, leaving corrupted state on failure.
Fix get_new_event() to:
- Check the zalloc() result before dereferencing
- Use a temporary for realloc() to avoid losing the old pointer
- Increment nr_events only after successful realloc
- Return NULL instead of calling BUG_ON on failure
Also fix add_sched_event_wakeup() where zalloc() for wait_sem is
passed to sem_init() without a NULL check.
Update all callers (add_sched_event_run, add_sched_event_wakeup,
add_sched_event_sleep) to handle NULL returns by returning early.
The replay may produce incomplete output on OOM but will not crash.
Fixes: ec156764d4 ("perf sched: Import schedbench.c")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
a99d6394cd
commit
75eafe4a3a
|
|
@ -365,14 +365,25 @@ get_new_event(struct task_desc *task, u64 timestamp)
|
|||
struct sched_atom *event = zalloc(sizeof(*event));
|
||||
unsigned long idx = task->nr_events;
|
||||
size_t size;
|
||||
struct sched_atom **atoms_p;
|
||||
|
||||
if (event == NULL) {
|
||||
pr_err("ERROR: sched: failed to allocate event\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event->timestamp = timestamp;
|
||||
event->nr = idx;
|
||||
|
||||
size = sizeof(struct sched_atom *) * (task->nr_events + 1);
|
||||
atoms_p = realloc(task->atoms, size);
|
||||
if (!atoms_p) {
|
||||
pr_err("ERROR: sched: failed to grow atoms array\n");
|
||||
free(event);
|
||||
return NULL;
|
||||
}
|
||||
task->atoms = atoms_p;
|
||||
task->nr_events++;
|
||||
size = sizeof(struct sched_atom *) * task->nr_events;
|
||||
task->atoms = realloc(task->atoms, size);
|
||||
BUG_ON(!task->atoms);
|
||||
|
||||
task->atoms[idx] = event;
|
||||
|
||||
|
|
@ -403,6 +414,8 @@ static void add_sched_event_run(struct perf_sched *sched, struct task_desc *task
|
|||
}
|
||||
|
||||
event = get_new_event(task, timestamp);
|
||||
if (event == NULL)
|
||||
return;
|
||||
|
||||
event->type = SCHED_EVENT_RUN;
|
||||
event->duration = duration;
|
||||
|
|
@ -416,6 +429,8 @@ static void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *t
|
|||
struct sched_atom *event, *wakee_event;
|
||||
|
||||
event = get_new_event(task, timestamp);
|
||||
if (event == NULL)
|
||||
return;
|
||||
event->type = SCHED_EVENT_WAKEUP;
|
||||
event->wakee = wakee;
|
||||
|
||||
|
|
@ -430,6 +445,10 @@ static void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *t
|
|||
}
|
||||
|
||||
wakee_event->wait_sem = zalloc(sizeof(*wakee_event->wait_sem));
|
||||
if (!wakee_event->wait_sem) {
|
||||
pr_err("ERROR: sched: failed to allocate semaphore\n");
|
||||
return;
|
||||
}
|
||||
sem_init(wakee_event->wait_sem, 0, 0);
|
||||
event->wait_sem = wakee_event->wait_sem;
|
||||
|
||||
|
|
@ -441,6 +460,9 @@ static void add_sched_event_sleep(struct perf_sched *sched, struct task_desc *ta
|
|||
{
|
||||
struct sched_atom *event = get_new_event(task, timestamp);
|
||||
|
||||
if (event == NULL)
|
||||
return;
|
||||
|
||||
event->type = SCHED_EVENT_SLEEP;
|
||||
|
||||
sched->nr_sleep_events++;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user