Skip to content

Commit a0e752b

Browse files
committed
Merge tag 'probes-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull probes updates from Masami Hiramatsu: "Kprobes cleanups. Functionality does not change. - kprobes: Cleanup the config comment Adjust #endif comments. - kprobes: Cleanup collect_one_slot() and __disable_kprobe() Make fail fast to reduce code nested level. - kprobes: Use struct_size() in __get_insn_slot() Use struct_size() to avoid special macro. - x86/kprobes: Cleanup kprobes on ftrace code Use macro instead of direct field access/magic number, and avoid redundant instruction pointer setting" * tag 'probes-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: x86/kprobes: Cleanup kprobes on ftrace code kprobes: Use struct_size() in __get_insn_slot() kprobes: Cleanup collect_one_slot() and __disable_kprobe() kprobes: Cleanup the config comment
2 parents aa44f41 + 4638d7e commit a0e752b

File tree

2 files changed

+55
-55
lines changed

2 files changed

+55
-55
lines changed

arch/x86/kernel/kprobes/ftrace.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/hardirq.h>
1010
#include <linux/preempt.h>
1111
#include <linux/ftrace.h>
12+
#include <asm/text-patching.h>
1213

1314
#include "common.h"
1415

@@ -36,23 +37,25 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
3637
if (kprobe_running()) {
3738
kprobes_inc_nmissed_count(p);
3839
} else {
39-
unsigned long orig_ip = regs->ip;
40+
unsigned long orig_ip = instruction_pointer(regs);
41+
4042
/* Kprobe handler expects regs->ip = ip + 1 as breakpoint hit */
41-
regs->ip = ip + sizeof(kprobe_opcode_t);
43+
instruction_pointer_set(regs, ip + INT3_INSN_SIZE);
4244

4345
__this_cpu_write(current_kprobe, p);
4446
kcb->kprobe_status = KPROBE_HIT_ACTIVE;
4547
if (!p->pre_handler || !p->pre_handler(p, regs)) {
46-
/*
47-
* Emulate singlestep (and also recover regs->ip)
48-
* as if there is a 5byte nop
49-
*/
50-
regs->ip = (unsigned long)p->addr + MCOUNT_INSN_SIZE;
5148
if (unlikely(p->post_handler)) {
49+
/*
50+
* Emulate singlestep (and also recover regs->ip)
51+
* as if there is a 5byte nop
52+
*/
53+
instruction_pointer_set(regs, ip + MCOUNT_INSN_SIZE);
5254
kcb->kprobe_status = KPROBE_HIT_SSDONE;
5355
p->post_handler(p, regs, 0);
5456
}
55-
regs->ip = orig_ip;
57+
/* Recover IP address */
58+
instruction_pointer_set(regs, orig_ip);
5659
}
5760
/*
5861
* If pre_handler returns !0, it changes regs->ip. We have to

kernel/kprobes.c

Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,6 @@ struct kprobe_insn_page {
9595
char slot_used[];
9696
};
9797

98-
#define KPROBE_INSN_PAGE_SIZE(slots) \
99-
(offsetof(struct kprobe_insn_page, slot_used) + \
100-
(sizeof(char) * (slots)))
101-
10298
static int slots_per_page(struct kprobe_insn_cache *c)
10399
{
104100
return PAGE_SIZE/(c->insn_size * sizeof(kprobe_opcode_t));
@@ -175,7 +171,7 @@ kprobe_opcode_t *__get_insn_slot(struct kprobe_insn_cache *c)
175171
goto retry;
176172

177173
/* All out of space. Need to allocate a new page. */
178-
kip = kmalloc(KPROBE_INSN_PAGE_SIZE(slots_per_page(c)), GFP_KERNEL);
174+
kip = kmalloc(struct_size(kip, slot_used, slots_per_page(c)), GFP_KERNEL);
179175
if (!kip)
180176
goto out;
181177

@@ -206,29 +202,29 @@ static bool collect_one_slot(struct kprobe_insn_page *kip, int idx)
206202
{
207203
kip->slot_used[idx] = SLOT_CLEAN;
208204
kip->nused--;
209-
if (kip->nused == 0) {
205+
if (kip->nused != 0)
206+
return false;
207+
208+
/*
209+
* Page is no longer in use. Free it unless
210+
* it's the last one. We keep the last one
211+
* so as not to have to set it up again the
212+
* next time somebody inserts a probe.
213+
*/
214+
if (!list_is_singular(&kip->list)) {
210215
/*
211-
* Page is no longer in use. Free it unless
212-
* it's the last one. We keep the last one
213-
* so as not to have to set it up again the
214-
* next time somebody inserts a probe.
216+
* Record perf ksymbol unregister event before removing
217+
* the page.
215218
*/
216-
if (!list_is_singular(&kip->list)) {
217-
/*
218-
* Record perf ksymbol unregister event before removing
219-
* the page.
220-
*/
221-
perf_event_ksymbol(PERF_RECORD_KSYMBOL_TYPE_OOL,
222-
(unsigned long)kip->insns, PAGE_SIZE, true,
223-
kip->cache->sym);
224-
list_del_rcu(&kip->list);
225-
synchronize_rcu();
226-
kip->cache->free(kip->insns);
227-
kfree(kip);
228-
}
229-
return true;
219+
perf_event_ksymbol(PERF_RECORD_KSYMBOL_TYPE_OOL,
220+
(unsigned long)kip->insns, PAGE_SIZE, true,
221+
kip->cache->sym);
222+
list_del_rcu(&kip->list);
223+
synchronize_rcu();
224+
kip->cache->free(kip->insns);
225+
kfree(kip);
230226
}
231-
return false;
227+
return true;
232228
}
233229

234230
static int collect_garbage_slots(struct kprobe_insn_cache *c)
@@ -353,8 +349,8 @@ struct kprobe_insn_cache kprobe_optinsn_slots = {
353349
/* .insn_size is initialized later */
354350
.nr_garbage = 0,
355351
};
356-
#endif
357-
#endif
352+
#endif /* CONFIG_OPTPROBES */
353+
#endif /* __ARCH_WANT_KPROBES_INSN_SLOT */
358354

359355
/* We have preemption disabled.. so it is safe to use __ versions */
360356
static inline void set_kprobe_instance(struct kprobe *kp)
@@ -1543,7 +1539,7 @@ static int check_ftrace_location(struct kprobe *p)
15431539
if (ftrace_location(addr) == addr) {
15441540
#ifdef CONFIG_KPROBES_ON_FTRACE
15451541
p->flags |= KPROBE_FLAG_FTRACE;
1546-
#else /* !CONFIG_KPROBES_ON_FTRACE */
1542+
#else
15471543
return -EINVAL;
15481544
#endif
15491545
}
@@ -1725,28 +1721,29 @@ static struct kprobe *__disable_kprobe(struct kprobe *p)
17251721
if (unlikely(orig_p == NULL))
17261722
return ERR_PTR(-EINVAL);
17271723

1728-
if (!kprobe_disabled(p)) {
1729-
/* Disable probe if it is a child probe */
1730-
if (p != orig_p)
1731-
p->flags |= KPROBE_FLAG_DISABLED;
1724+
if (kprobe_disabled(p))
1725+
return orig_p;
17321726

1733-
/* Try to disarm and disable this/parent probe */
1734-
if (p == orig_p || aggr_kprobe_disabled(orig_p)) {
1735-
/*
1736-
* Don't be lazy here. Even if 'kprobes_all_disarmed'
1737-
* is false, 'orig_p' might not have been armed yet.
1738-
* Note arm_all_kprobes() __tries__ to arm all kprobes
1739-
* on the best effort basis.
1740-
*/
1741-
if (!kprobes_all_disarmed && !kprobe_disabled(orig_p)) {
1742-
ret = disarm_kprobe(orig_p, true);
1743-
if (ret) {
1744-
p->flags &= ~KPROBE_FLAG_DISABLED;
1745-
return ERR_PTR(ret);
1746-
}
1727+
/* Disable probe if it is a child probe */
1728+
if (p != orig_p)
1729+
p->flags |= KPROBE_FLAG_DISABLED;
1730+
1731+
/* Try to disarm and disable this/parent probe */
1732+
if (p == orig_p || aggr_kprobe_disabled(orig_p)) {
1733+
/*
1734+
* Don't be lazy here. Even if 'kprobes_all_disarmed'
1735+
* is false, 'orig_p' might not have been armed yet.
1736+
* Note arm_all_kprobes() __tries__ to arm all kprobes
1737+
* on the best effort basis.
1738+
*/
1739+
if (!kprobes_all_disarmed && !kprobe_disabled(orig_p)) {
1740+
ret = disarm_kprobe(orig_p, true);
1741+
if (ret) {
1742+
p->flags &= ~KPROBE_FLAG_DISABLED;
1743+
return ERR_PTR(ret);
17471744
}
1748-
orig_p->flags |= KPROBE_FLAG_DISABLED;
17491745
}
1746+
orig_p->flags |= KPROBE_FLAG_DISABLED;
17501747
}
17511748

17521749
return orig_p;

0 commit comments

Comments
 (0)