History

[PATCH] kprobes: fix single-step out of line - take2

Now that PPC64 has no-execute support, here is a second try to fix the single step out of line during kprobe execution. Kprobes on x86_64 already solved this problem by allocating an executable page and using it as the scratch area for stepping out of line. Reuse that.

Ananth N Mavinakayanahalli committed 21 years ago

Commit 9ec4b1f1 parent d3b8a1a6 files · +128 −117Browse files

Showing the changes to kernel (1 of 6 files). Show all

Unified · Split

kernel/kprobes.c+101−0
@@ -36,6 +36,7 @@ · 35 unmodified lines
3636 #include <linux/hash.h>
3737 #include <linux/init.h>
3838 #include <linux/module.h>
39+#include <linux/moduleloader.h>
3940 #include <asm/cacheflush.h>
4041 #include <asm/errno.h>
4142 #include <asm/kdebug.h>
@@ -50,6 +51,106 @@ unsigned int kprobe_cpu = NR_CPUS; · 8 unmodified lines
5051 static DEFINE_SPINLOCK(kprobe_lock);
5152 static struct kprobe *curr_kprobe;
5253
54+/*
55+ * kprobe->ainsn.insn points to the copy of the instruction to be
56+ * single-stepped. x86_64, POWER4 and above have no-exec support and
57+ * stepping on the instruction on a vmalloced/kmalloced/data page
58+ * is a recipe for disaster
59+ */
60+#define INSNS_PER_PAGE (PAGE_SIZE/(MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
61+
62+struct kprobe_insn_page {
63+ struct hlist_node hlist;
64+ kprobe_opcode_t *insns; /* Page of instruction slots */
65+ char slot_used[INSNS_PER_PAGE];
66+ int nused;
67+};
68+
69+static struct hlist_head kprobe_insn_pages;
70+
71+/**
72+ * get_insn_slot() - Find a slot on an executable page for an instruction.
73+ * We allocate an executable page if there's no room on existing ones.
74+ */
75+kprobe_opcode_t *get_insn_slot(void)
76+{
77+ struct kprobe_insn_page *kip;
78+ struct hlist_node *pos;
79+
80+ hlist_for_each(pos, &kprobe_insn_pages) {
81+ kip = hlist_entry(pos, struct kprobe_insn_page, hlist);
82+ if (kip->nused < INSNS_PER_PAGE) {
83+ int i;
84+ for (i = 0; i < INSNS_PER_PAGE; i++) {
85+ if (!kip->slot_used[i]) {
86+ kip->slot_used[i] = 1;
87+ kip->nused++;
88+ return kip->insns + (i * MAX_INSN_SIZE);
89+ }
90+ }
91+ /* Surprise! No unused slots. Fix kip->nused. */
92+ kip->nused = INSNS_PER_PAGE;
93+ }
94+ }
95+
96+ /* All out of space. Need to allocate a new page. Use slot 0.*/
97+ kip = kmalloc(sizeof(struct kprobe_insn_page), GFP_KERNEL);
98+ if (!kip) {
99+ return NULL;
100+ }
101+
102+ /*
103+ * Use module_alloc so this page is within +/- 2GB of where the
104+ * kernel image and loaded module images reside. This is required
105+ * so x86_64 can correctly handle the %rip-relative fixups.
106+ */
107+ kip->insns = module_alloc(PAGE_SIZE);
108+ if (!kip->insns) {
109+ kfree(kip);
110+ return NULL;
111+ }
112+ INIT_HLIST_NODE(&kip->hlist);
113+ hlist_add_head(&kip->hlist, &kprobe_insn_pages);
114+ memset(kip->slot_used, 0, INSNS_PER_PAGE);
115+ kip->slot_used[0] = 1;
116+ kip->nused = 1;
117+ return kip->insns;
118+}
119+
120+void free_insn_slot(kprobe_opcode_t *slot)
121+{
122+ struct kprobe_insn_page *kip;
123+ struct hlist_node *pos;
124+
125+ hlist_for_each(pos, &kprobe_insn_pages) {
126+ kip = hlist_entry(pos, struct kprobe_insn_page, hlist);
127+ if (kip->insns <= slot &&
128+ slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) {
129+ int i = (slot - kip->insns) / MAX_INSN_SIZE;
130+ kip->slot_used[i] = 0;
131+ kip->nused--;
132+ if (kip->nused == 0) {
133+ /*
134+ * Page is no longer in use. Free it unless
135+ * it's the last one. We keep the last one
136+ * so as not to have to set it up again the
137+ * next time somebody inserts a probe.
138+ */
139+ hlist_del(&kip->hlist);
140+ if (hlist_empty(&kprobe_insn_pages)) {
141+ INIT_HLIST_NODE(&kip->hlist);
142+ hlist_add_head(&kip->hlist,
143+ &kprobe_insn_pages);
144+ } else {
145+ module_free(NULL, kip->insns);
146+ kfree(kip);
147+ }
148+ }
149+ return;
150+ }
151+ }
152+}
153+
53154 /* Locks kprobe: irqs must be disabled */
54155 void lock_kprobes(void)
55156 {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t