aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/kprobes.h2
-rw-r--r--kernel/kprobes.c20
2 files changed, 20 insertions, 2 deletions
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 077f65321b5e..925eaf28fca9 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -268,6 +268,8 @@ extern void kprobes_inc_nmissed_count(struct kprobe *p);
268 268
269struct kprobe_insn_cache { 269struct kprobe_insn_cache {
270 struct mutex mutex; 270 struct mutex mutex;
271 void *(*alloc)(void); /* allocate insn page */
272 void (*free)(void *); /* free insn page */
271 struct list_head pages; /* list of kprobe_insn_page */ 273 struct list_head pages; /* list of kprobe_insn_page */
272 size_t insn_size; /* size of instruction slot */ 274 size_t insn_size; /* size of instruction slot */
273 int nr_garbage; 275 int nr_garbage;
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 9e4912dc5559..a0d367a49122 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -112,6 +112,7 @@ static struct kprobe_blackpoint kprobe_blacklist[] = {
112struct kprobe_insn_page { 112struct kprobe_insn_page {
113 struct list_head list; 113 struct list_head list;
114 kprobe_opcode_t *insns; /* Page of instruction slots */ 114 kprobe_opcode_t *insns; /* Page of instruction slots */
115 struct kprobe_insn_cache *cache;
115 int nused; 116 int nused;
116 int ngarbage; 117 int ngarbage;
117 char slot_used[]; 118 char slot_used[];
@@ -132,8 +133,20 @@ enum kprobe_slot_state {
132 SLOT_USED = 2, 133 SLOT_USED = 2,
133}; 134};
134 135
136static void *alloc_insn_page(void)
137{
138 return module_alloc(PAGE_SIZE);
139}
140
141static void free_insn_page(void *page)
142{
143 module_free(NULL, page);
144}
145
135struct kprobe_insn_cache kprobe_insn_slots = { 146struct kprobe_insn_cache kprobe_insn_slots = {
136 .mutex = __MUTEX_INITIALIZER(kprobe_insn_slots.mutex), 147 .mutex = __MUTEX_INITIALIZER(kprobe_insn_slots.mutex),
148 .alloc = alloc_insn_page,
149 .free = free_insn_page,
137 .pages = LIST_HEAD_INIT(kprobe_insn_slots.pages), 150 .pages = LIST_HEAD_INIT(kprobe_insn_slots.pages),
138 .insn_size = MAX_INSN_SIZE, 151 .insn_size = MAX_INSN_SIZE,
139 .nr_garbage = 0, 152 .nr_garbage = 0,
@@ -182,7 +195,7 @@ kprobe_opcode_t __kprobes *__get_insn_slot(struct kprobe_insn_cache *c)
182 * kernel image and loaded module images reside. This is required 195 * kernel image and loaded module images reside. This is required
183 * so x86_64 can correctly handle the %rip-relative fixups. 196 * so x86_64 can correctly handle the %rip-relative fixups.
184 */ 197 */
185 kip->insns = module_alloc(PAGE_SIZE); 198 kip->insns = c->alloc();
186 if (!kip->insns) { 199 if (!kip->insns) {
187 kfree(kip); 200 kfree(kip);
188 goto out; 201 goto out;
@@ -192,6 +205,7 @@ kprobe_opcode_t __kprobes *__get_insn_slot(struct kprobe_insn_cache *c)
192 kip->slot_used[0] = SLOT_USED; 205 kip->slot_used[0] = SLOT_USED;
193 kip->nused = 1; 206 kip->nused = 1;
194 kip->ngarbage = 0; 207 kip->ngarbage = 0;
208 kip->cache = c;
195 list_add(&kip->list, &c->pages); 209 list_add(&kip->list, &c->pages);
196 slot = kip->insns; 210 slot = kip->insns;
197out: 211out:
@@ -213,7 +227,7 @@ static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx)
213 */ 227 */
214 if (!list_is_singular(&kip->list)) { 228 if (!list_is_singular(&kip->list)) {
215 list_del(&kip->list); 229 list_del(&kip->list);
216 module_free(NULL, kip->insns); 230 kip->cache->free(kip->insns);
217 kfree(kip); 231 kfree(kip);
218 } 232 }
219 return 1; 233 return 1;
@@ -274,6 +288,8 @@ out:
274/* For optimized_kprobe buffer */ 288/* For optimized_kprobe buffer */
275struct kprobe_insn_cache kprobe_optinsn_slots = { 289struct kprobe_insn_cache kprobe_optinsn_slots = {
276 .mutex = __MUTEX_INITIALIZER(kprobe_optinsn_slots.mutex), 290 .mutex = __MUTEX_INITIALIZER(kprobe_optinsn_slots.mutex),
291 .alloc = alloc_insn_page,
292 .free = free_insn_page,
277 .pages = LIST_HEAD_INIT(kprobe_optinsn_slots.pages), 293 .pages = LIST_HEAD_INIT(kprobe_optinsn_slots.pages),
278 /* .insn_size is initialized later */ 294 /* .insn_size is initialized later */
279 .nr_garbage = 0, 295 .nr_garbage = 0,