mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
Revert "perf: Fix event leak upon exec and file release"
This reverts commit ed2c202dac which is
commit 3a5465418f5fd970e86a86c7f4075be262682840 upstream.
It breaks the Android kernel abi and can be brought back in the future
in an abi-safe way if it is really needed.
Bug: 161946584
Change-Id: I29cfc492dd3ef6c7a9ebc2aa28d238f392a48ce6
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -767,7 +767,6 @@ struct perf_event {
|
|||||||
struct irq_work pending_irq;
|
struct irq_work pending_irq;
|
||||||
struct callback_head pending_task;
|
struct callback_head pending_task;
|
||||||
unsigned int pending_work;
|
unsigned int pending_work;
|
||||||
struct rcuwait pending_work_wait;
|
|
||||||
|
|
||||||
atomic_t event_limit;
|
atomic_t event_limit;
|
||||||
|
|
||||||
|
|||||||
@@ -2320,6 +2320,7 @@ event_sched_out(struct perf_event *event,
|
|||||||
if (state != PERF_EVENT_STATE_OFF &&
|
if (state != PERF_EVENT_STATE_OFF &&
|
||||||
!event->pending_work &&
|
!event->pending_work &&
|
||||||
!task_work_add(current, &event->pending_task, TWA_RESUME)) {
|
!task_work_add(current, &event->pending_task, TWA_RESUME)) {
|
||||||
|
WARN_ON_ONCE(!atomic_long_inc_not_zero(&event->refcount));
|
||||||
event->pending_work = 1;
|
event->pending_work = 1;
|
||||||
} else {
|
} else {
|
||||||
local_dec(&event->ctx->nr_pending);
|
local_dec(&event->ctx->nr_pending);
|
||||||
@@ -5004,35 +5005,9 @@ static bool exclusive_event_installable(struct perf_event *event,
|
|||||||
static void perf_addr_filters_splice(struct perf_event *event,
|
static void perf_addr_filters_splice(struct perf_event *event,
|
||||||
struct list_head *head);
|
struct list_head *head);
|
||||||
|
|
||||||
static void perf_pending_task_sync(struct perf_event *event)
|
|
||||||
{
|
|
||||||
struct callback_head *head = &event->pending_task;
|
|
||||||
|
|
||||||
if (!event->pending_work)
|
|
||||||
return;
|
|
||||||
/*
|
|
||||||
* If the task is queued to the current task's queue, we
|
|
||||||
* obviously can't wait for it to complete. Simply cancel it.
|
|
||||||
*/
|
|
||||||
if (task_work_cancel(current, head)) {
|
|
||||||
event->pending_work = 0;
|
|
||||||
local_dec(&event->ctx->nr_pending);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* All accesses related to the event are within the same
|
|
||||||
* non-preemptible section in perf_pending_task(). The RCU
|
|
||||||
* grace period before the event is freed will make sure all
|
|
||||||
* those accesses are complete by then.
|
|
||||||
*/
|
|
||||||
rcuwait_wait_event(&event->pending_work_wait, !event->pending_work, TASK_UNINTERRUPTIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _free_event(struct perf_event *event)
|
static void _free_event(struct perf_event *event)
|
||||||
{
|
{
|
||||||
irq_work_sync(&event->pending_irq);
|
irq_work_sync(&event->pending_irq);
|
||||||
perf_pending_task_sync(event);
|
|
||||||
|
|
||||||
unaccount_event(event);
|
unaccount_event(event);
|
||||||
|
|
||||||
@@ -6662,28 +6637,24 @@ static void perf_pending_task(struct callback_head *head)
|
|||||||
struct perf_event *event = container_of(head, struct perf_event, pending_task);
|
struct perf_event *event = container_of(head, struct perf_event, pending_task);
|
||||||
int rctx;
|
int rctx;
|
||||||
|
|
||||||
/*
|
|
||||||
* All accesses to the event must belong to the same implicit RCU read-side
|
|
||||||
* critical section as the ->pending_work reset. See comment in
|
|
||||||
* perf_pending_task_sync().
|
|
||||||
*/
|
|
||||||
preempt_disable_notrace();
|
|
||||||
/*
|
/*
|
||||||
* If we 'fail' here, that's OK, it means recursion is already disabled
|
* If we 'fail' here, that's OK, it means recursion is already disabled
|
||||||
* and we won't recurse 'further'.
|
* and we won't recurse 'further'.
|
||||||
*/
|
*/
|
||||||
|
preempt_disable_notrace();
|
||||||
rctx = perf_swevent_get_recursion_context();
|
rctx = perf_swevent_get_recursion_context();
|
||||||
|
|
||||||
if (event->pending_work) {
|
if (event->pending_work) {
|
||||||
event->pending_work = 0;
|
event->pending_work = 0;
|
||||||
perf_sigtrap(event);
|
perf_sigtrap(event);
|
||||||
local_dec(&event->ctx->nr_pending);
|
local_dec(&event->ctx->nr_pending);
|
||||||
rcuwait_wake_up(&event->pending_work_wait);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rctx >= 0)
|
if (rctx >= 0)
|
||||||
perf_swevent_put_recursion_context(rctx);
|
perf_swevent_put_recursion_context(rctx);
|
||||||
preempt_enable_notrace();
|
preempt_enable_notrace();
|
||||||
|
|
||||||
|
put_event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_GUEST_PERF_EVENTS
|
#ifdef CONFIG_GUEST_PERF_EVENTS
|
||||||
@@ -11792,7 +11763,6 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
|
|||||||
init_waitqueue_head(&event->waitq);
|
init_waitqueue_head(&event->waitq);
|
||||||
init_irq_work(&event->pending_irq, perf_pending_irq);
|
init_irq_work(&event->pending_irq, perf_pending_irq);
|
||||||
init_task_work(&event->pending_task, perf_pending_task);
|
init_task_work(&event->pending_task, perf_pending_task);
|
||||||
rcuwait_init(&event->pending_work_wait);
|
|
||||||
|
|
||||||
mutex_init(&event->mmap_mutex);
|
mutex_init(&event->mmap_mutex);
|
||||||
raw_spin_lock_init(&event->addr_filters.lock);
|
raw_spin_lock_init(&event->addr_filters.lock);
|
||||||
|
|||||||
Reference in New Issue
Block a user