Skip to content

Commit b338817

Browse files
mhiramatingomolnar
authored andcommitted
kprobes: Free kretprobe_instance with RCU callback
Free kretprobe_instance with RCU callback instead of directly freeing the object in the kretprobe handler context. This will make kretprobe run safer in NMI context. Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/159870616685.1229682.11978742048709542226.stgit@devnote2
1 parent e03b4a0 commit b338817

2 files changed

Lines changed: 10 additions & 21 deletions

File tree

include/linux/kprobes.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,10 @@ struct kretprobe {
156156
};
157157

158158
struct kretprobe_instance {
159-
struct hlist_node hlist;
159+
union {
160+
struct hlist_node hlist;
161+
struct rcu_head rcu;
162+
};
160163
struct kretprobe *rp;
161164
kprobe_opcode_t *ret_addr;
162165
struct task_struct *task;
@@ -395,7 +398,6 @@ int register_kretprobes(struct kretprobe **rps, int num);
395398
void unregister_kretprobes(struct kretprobe **rps, int num);
396399

397400
void kprobe_flush_task(struct task_struct *tk);
398-
void recycle_rp_inst(struct kretprobe_instance *ri, struct hlist_head *head);
399401

400402
int disable_kprobe(struct kprobe *kp);
401403
int enable_kprobe(struct kprobe *kp);

kernel/kprobes.c

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,8 +1223,7 @@ void kprobes_inc_nmissed_count(struct kprobe *p)
12231223
}
12241224
NOKPROBE_SYMBOL(kprobes_inc_nmissed_count);
12251225

1226-
void recycle_rp_inst(struct kretprobe_instance *ri,
1227-
struct hlist_head *head)
1226+
static void recycle_rp_inst(struct kretprobe_instance *ri)
12281227
{
12291228
struct kretprobe *rp = ri->rp;
12301229

@@ -1236,8 +1235,7 @@ void recycle_rp_inst(struct kretprobe_instance *ri,
12361235
hlist_add_head(&ri->hlist, &rp->free_instances);
12371236
raw_spin_unlock(&rp->lock);
12381237
} else
1239-
/* Unregistering */
1240-
hlist_add_head(&ri->hlist, head);
1238+
kfree_rcu(ri, rcu);
12411239
}
12421240
NOKPROBE_SYMBOL(recycle_rp_inst);
12431241

@@ -1313,7 +1311,7 @@ void kprobe_busy_end(void)
13131311
void kprobe_flush_task(struct task_struct *tk)
13141312
{
13151313
struct kretprobe_instance *ri;
1316-
struct hlist_head *head, empty_rp;
1314+
struct hlist_head *head;
13171315
struct hlist_node *tmp;
13181316
unsigned long hash, flags = 0;
13191317

@@ -1323,19 +1321,14 @@ void kprobe_flush_task(struct task_struct *tk)
13231321

13241322
kprobe_busy_begin();
13251323

1326-
INIT_HLIST_HEAD(&empty_rp);
13271324
hash = hash_ptr(tk, KPROBE_HASH_BITS);
13281325
head = &kretprobe_inst_table[hash];
13291326
kretprobe_table_lock(hash, &flags);
13301327
hlist_for_each_entry_safe(ri, tmp, head, hlist) {
13311328
if (ri->task == tk)
1332-
recycle_rp_inst(ri, &empty_rp);
1329+
recycle_rp_inst(ri);
13331330
}
13341331
kretprobe_table_unlock(hash, &flags);
1335-
hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
1336-
hlist_del(&ri->hlist);
1337-
kfree(ri);
1338-
}
13391332

13401333
kprobe_busy_end();
13411334
}
@@ -1936,13 +1929,12 @@ unsigned long __kretprobe_trampoline_handler(struct pt_regs *regs,
19361929
void *frame_pointer)
19371930
{
19381931
struct kretprobe_instance *ri = NULL, *last = NULL;
1939-
struct hlist_head *head, empty_rp;
1932+
struct hlist_head *head;
19401933
struct hlist_node *tmp;
19411934
unsigned long flags;
19421935
kprobe_opcode_t *correct_ret_addr = NULL;
19431936
bool skipped = false;
19441937

1945-
INIT_HLIST_HEAD(&empty_rp);
19461938
kretprobe_hash_lock(current, &head, &flags);
19471939

19481940
/*
@@ -2011,19 +2003,14 @@ unsigned long __kretprobe_trampoline_handler(struct pt_regs *regs,
20112003
__this_cpu_write(current_kprobe, prev);
20122004
}
20132005

2014-
recycle_rp_inst(ri, &empty_rp);
2006+
recycle_rp_inst(ri);
20152007

20162008
if (ri == last)
20172009
break;
20182010
}
20192011

20202012
kretprobe_hash_unlock(current, &flags);
20212013

2022-
hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
2023-
hlist_del(&ri->hlist);
2024-
kfree(ri);
2025-
}
2026-
20272014
return (unsigned long)correct_ret_addr;
20282015
}
20292016
NOKPROBE_SYMBOL(__kretprobe_trampoline_handler)

0 commit comments

Comments
 (0)