Skip to content

Commit 2e498d0

Browse files
melverPeter Zijlstra
authored andcommitted
perf: Add support for event removal on exec
Adds bit perf_event_attr::remove_on_exec, to support removing an event from a task on exec. This option supports the case where an event is supposed to be process-wide only, and should not propagate beyond exec, to limit monitoring to the original process image only. Suggested-by: Peter Zijlstra <[email protected]> Signed-off-by: Marco Elver <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 2b26f0a commit 2e498d0

File tree

2 files changed

+64
-9
lines changed

2 files changed

+64
-9
lines changed

include/uapi/linux/perf_event.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,8 @@ struct perf_event_attr {
390390
text_poke : 1, /* include text poke events */
391391
build_id : 1, /* use build id in mmap2 events */
392392
inherit_thread : 1, /* children only inherit if cloned with CLONE_THREAD */
393-
__reserved_1 : 28;
393+
remove_on_exec : 1, /* event is removed from task on exec */
394+
__reserved_1 : 27;
394395

395396
union {
396397
__u32 wakeup_events; /* wakeup every n events */

kernel/events/core.c

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4248,6 +4248,57 @@ static void perf_event_enable_on_exec(int ctxn)
42484248
put_ctx(clone_ctx);
42494249
}
42504250

4251+
static void perf_remove_from_owner(struct perf_event *event);
4252+
static void perf_event_exit_event(struct perf_event *event,
4253+
struct perf_event_context *ctx);
4254+
4255+
/*
4256+
* Removes all events from the current task that have been marked
4257+
* remove-on-exec, and feeds their values back to parent events.
4258+
*/
4259+
static void perf_event_remove_on_exec(int ctxn)
4260+
{
4261+
struct perf_event_context *ctx, *clone_ctx = NULL;
4262+
struct perf_event *event, *next;
4263+
LIST_HEAD(free_list);
4264+
unsigned long flags;
4265+
bool modified = false;
4266+
4267+
ctx = perf_pin_task_context(current, ctxn);
4268+
if (!ctx)
4269+
return;
4270+
4271+
mutex_lock(&ctx->mutex);
4272+
4273+
if (WARN_ON_ONCE(ctx->task != current))
4274+
goto unlock;
4275+
4276+
list_for_each_entry_safe(event, next, &ctx->event_list, event_entry) {
4277+
if (!event->attr.remove_on_exec)
4278+
continue;
4279+
4280+
if (!is_kernel_event(event))
4281+
perf_remove_from_owner(event);
4282+
4283+
modified = true;
4284+
4285+
perf_event_exit_event(event, ctx);
4286+
}
4287+
4288+
raw_spin_lock_irqsave(&ctx->lock, flags);
4289+
if (modified)
4290+
clone_ctx = unclone_ctx(ctx);
4291+
--ctx->pin_count;
4292+
raw_spin_unlock_irqrestore(&ctx->lock, flags);
4293+
4294+
unlock:
4295+
mutex_unlock(&ctx->mutex);
4296+
4297+
put_ctx(ctx);
4298+
if (clone_ctx)
4299+
put_ctx(clone_ctx);
4300+
}
4301+
42514302
struct perf_read_data {
42524303
struct perf_event *event;
42534304
bool group;
@@ -7560,18 +7611,18 @@ void perf_event_exec(void)
75607611
struct perf_event_context *ctx;
75617612
int ctxn;
75627613

7563-
rcu_read_lock();
75647614
for_each_task_context_nr(ctxn) {
7565-
ctx = current->perf_event_ctxp[ctxn];
7566-
if (!ctx)
7567-
continue;
7568-
75697615
perf_event_enable_on_exec(ctxn);
7616+
perf_event_remove_on_exec(ctxn);
75707617

7571-
perf_iterate_ctx(ctx, perf_event_addr_filters_exec, NULL,
7572-
true);
7618+
rcu_read_lock();
7619+
ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
7620+
if (ctx) {
7621+
perf_iterate_ctx(ctx, perf_event_addr_filters_exec,
7622+
NULL, true);
7623+
}
7624+
rcu_read_unlock();
75737625
}
7574-
rcu_read_unlock();
75757626
}
75767627

75777628
struct remote_output {
@@ -11656,6 +11707,9 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr,
1165611707
if (!attr->inherit && attr->inherit_thread)
1165711708
return -EINVAL;
1165811709

11710+
if (attr->remove_on_exec && attr->enable_on_exec)
11711+
return -EINVAL;
11712+
1165911713
out:
1166011714
return ret;
1166111715

0 commit comments

Comments
 (0)