diff options
-rw-r--r-- | include/linux/kprobes.h | 2 | ||||
-rw-r--r-- | kernel/kprobes.c | 20 |
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 | ||
269 | struct kprobe_insn_cache { | 269 | struct 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[] = { | |||
112 | struct kprobe_insn_page { | 112 | struct 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 | ||
136 | static void *alloc_insn_page(void) | ||
137 | { | ||
138 | return module_alloc(PAGE_SIZE); | ||
139 | } | ||
140 | |||
141 | static void free_insn_page(void *page) | ||
142 | { | ||
143 | module_free(NULL, page); | ||
144 | } | ||
145 | |||
135 | struct kprobe_insn_cache kprobe_insn_slots = { | 146 | struct 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; |
197 | out: | 211 | out: |
@@ -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 */ |
275 | struct kprobe_insn_cache kprobe_optinsn_slots = { | 289 | struct 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, |