Move module init and cleanup into separate functions.
[ksplice.git] / kmodsrc / primary.c
blob8f78e16c287bb1e37ff992cecebe11545e4edae9
1 /* Copyright (C) 2008 Jeffrey Brian Arnold <jbarnold@mit.edu>
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License, version 2.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
14 * 02110-1301, USA.
17 #include "modcommon.h"
18 #include "primary.h"
19 #include <linux/kthread.h>
20 #include <linux/proc_fs.h>
21 #include <linux/sched.h>
22 #include <linux/stop_machine.h>
23 #include <linux/time.h>
24 #include <asm/uaccess.h>
26 #ifndef task_thread_info
27 #define task_thread_info(task) (task)->thread_info
28 #endif /* task_thread_info */
30 /* Probably wrong. */
31 #ifdef __ASM_X86_PROCESSOR_H
32 #define KSPLICE_EIP(x) ((x)->thread.ip)
33 #define KSPLICE_ESP(x) ((x)->thread.sp)
34 #elif BITS_PER_LONG == 32
35 #define KSPLICE_EIP(x) ((x)->thread.eip)
36 #define KSPLICE_ESP(x) ((x)->thread.esp)
37 #elif BITS_PER_LONG == 64
38 #define KSPLICE_EIP(x) (KSTK_EIP(x))
39 #define KSPLICE_ESP(x) ((x)->thread.rsp)
40 #endif /* __ASM_X86_PROCESSOR_H */
42 /* defined by modcommon.c */
43 extern int safe, debug;
45 /* defined by ksplice-create */
46 extern struct ksplice_reloc ksplice_init_relocs, ksplice_relocs;
47 extern struct ksplice_patch ksplice_patches;
48 extern struct ksplice_size ksplice_sizes;
50 LIST_HEAD(reloc_addrmaps);
51 LIST_HEAD(reloc_namevals);
52 LIST_HEAD(safety_records);
54 struct module_pack KSPLICE_UNIQ(pack) = {
55 .name = "ksplice_" STR(KSPLICE_ID),
56 .map_printk = MAP_PRINTK,
57 .primary_relocs = &ksplice_relocs,
58 .primary_sizes = &ksplice_sizes,
59 .patches = &ksplice_patches,
60 .reloc_addrmaps = &reloc_addrmaps,
61 .reloc_namevals = &reloc_namevals,
62 .safety_records = &safety_records,
63 .activate_primary = &activate_primary,
65 EXPORT_SYMBOL_GPL(KSPLICE_UNIQ(pack));
67 int init_module(void)
69 struct module_pack *pack = &KSPLICE_UNIQ(pack);
70 if (process_ksplice_relocs(pack, &ksplice_init_relocs) != 0)
71 return -1;
72 safe = 1;
74 return 0;
77 void cleanup_module(void)
79 cleanup_ksplice_module(&KSPLICE_UNIQ(pack));
82 void cleanup_ksplice_module(struct module_pack *pack)
84 remove_proc_entry(pack->name, &proc_root);
87 int activate_primary(struct module_pack *pack)
89 int i;
90 struct proc_dir_entry *proc_entry;
92 pack->helper = 0;
94 if (process_ksplice_relocs(pack, pack->primary_relocs) != 0)
95 return -1;
97 if (resolve_patch_symbols(pack) != 0)
98 return -1;
100 proc_entry = create_proc_entry(pack->name, 0644, NULL);
101 if (proc_entry == NULL) {
102 remove_proc_entry(pack->name, &proc_root);
103 print_abort("primary module: could not create proc entry");
104 return -1;
107 proc_entry->read_proc = procfile_read;
108 proc_entry->write_proc = procfile_write;
109 proc_entry->data = pack;
110 proc_entry->owner = THIS_MODULE;
111 proc_entry->mode = S_IFREG | S_IRUSR | S_IWUSR;
112 proc_entry->uid = 0;
113 proc_entry->gid = 0;
114 proc_entry->size = 0;
116 for (i = 0; pack->state != KSPLICE_APPLIED && i < 5; i++) {
117 bust_spinlocks(1);
118 stop_machine_run(__apply_patches, pack, NR_CPUS);
119 bust_spinlocks(0);
120 set_current_state(TASK_INTERRUPTIBLE);
121 schedule_timeout(msecs_to_jiffies(1000));
123 if (pack->state != KSPLICE_APPLIED) {
124 remove_proc_entry(pack->name, &proc_root);
125 print_abort("stack check: to-be-replaced code is busy");
126 return -1;
129 printk("ksplice: Update %s applied successfully\n", pack->name);
130 return 0;
133 int resolve_patch_symbols(struct module_pack *pack)
135 struct ksplice_patch *p;
136 LIST_HEAD(vals);
138 for (p = pack->patches; p->oldstr; p++) {
139 p->saved = kmalloc(5, GFP_KERNEL);
141 if (p->oldaddr != 0)
142 add_candidate_val(&vals, p->oldaddr);
144 compute_address(pack, p->oldstr, &vals);
145 if (!singular(&vals)) {
146 release_vals(&vals);
147 failed_to_find(p->oldstr);
148 return -1;
150 p->oldaddr =
151 list_entry(vals.next, struct candidate_val, list)->val;
152 release_vals(&vals);
155 return 0;
158 int procfile_read(char *buffer, char **buffer_location,
159 off_t offset, int buffer_length, int *eof, void *data)
161 return 0;
164 int procfile_write(struct file *file, const char *buffer, unsigned long count,
165 void *data)
167 int i;
168 struct module_pack *pack = data;
169 printk("ksplice: Preparing to reverse %s\n", pack->name);
171 for (i = 0; pack->state == KSPLICE_APPLIED && i < 5; i++) {
172 bust_spinlocks(1);
173 stop_machine_run(__reverse_patches, pack, NR_CPUS);
174 bust_spinlocks(0);
175 set_current_state(TASK_INTERRUPTIBLE);
176 schedule_timeout(msecs_to_jiffies(1000));
178 if (pack->state == KSPLICE_APPLIED)
179 print_abort("stack check: to-be-reversed code is busy");
181 return count;
184 int __apply_patches(void *packptr)
186 struct module_pack *pack = packptr;
187 struct ksplice_patch *p;
188 struct list_head *pos;
189 struct safety_record *rec;
191 list_for_each(pos, pack->safety_records) {
192 rec = list_entry(pos, struct safety_record, list);
193 for (p = pack->patches; p->oldstr; p++) {
194 if (p->oldaddr == rec->addr) {
195 rec->care = 1;
200 if (check_each_task(pack) != 0)
201 return 0;
203 if (!try_module_get(THIS_MODULE))
204 return 0;
206 pack->state = KSPLICE_APPLIED;
208 for (p = pack->patches; p->oldstr; p++) {
209 memcpy((void *)p->saved, (void *)p->oldaddr, 5);
210 *((u8 *) p->oldaddr) = 0xE9;
211 *((u32 *) (p->oldaddr + 1)) = p->repladdr - (p->oldaddr + 5);
213 return 0;
216 int __reverse_patches(void *packptr)
218 struct module_pack *pack = packptr;
219 struct ksplice_patch *p;
221 if (pack->state != KSPLICE_APPLIED)
222 return 0;
224 if (check_each_task(pack) != 0)
225 return 0;
227 clear_list(pack->safety_records, struct safety_record, list);
228 pack->state = KSPLICE_REVERSED;
229 module_put(THIS_MODULE);
231 p = pack->patches;
232 for (; p->oldstr; p++) {
233 memcpy((void *)p->oldaddr, (void *)p->saved, 5);
234 kfree(p->saved);
235 *((u8 *) p->repladdr) = 0xE9;
236 *((u32 *) (p->repladdr + 1)) = p->oldaddr - (p->repladdr + 5);
239 printk("ksplice: Update %s reversed successfully\n", pack->name);
240 return 0;
243 int check_each_task(struct module_pack *pack)
245 struct task_struct *g, *p;
246 int status = 0;
247 read_lock(&tasklist_lock);
248 do_each_thread(g, p) {
249 /* do_each_thread is a double loop! */
250 if (check_task(pack, p) != 0) {
251 if (debug == 1) {
252 debug = 2;
253 check_task(pack, p);
254 debug = 1;
256 status = -1;
259 while_each_thread(g, p);
260 read_unlock(&tasklist_lock);
261 return status;
264 int check_task(struct module_pack *pack, struct task_struct *t)
266 int status;
267 long addr = KSPLICE_EIP(t);
268 int conflict = check_address_for_conflict(pack, addr);
269 if (debug >= 2) {
270 printk("ksplice: stack check: pid %d (%s) eip %08lx",
271 t->pid, t->comm, KSPLICE_EIP(t));
272 if (conflict)
273 printk(" [<-- CONFLICT]: ");
274 else
275 printk(": ");
277 if (t == current) {
278 status =
279 check_stack(pack, task_thread_info(t),
280 (long *)__builtin_frame_address(0));
281 } else if (!task_curr(t)) {
282 status =
283 check_stack(pack, task_thread_info(t),
284 (long *)KSPLICE_ESP(t));
285 } else if (strcmp(t->comm, "kstopmachine") == 0) {
286 if (debug >= 2)
287 printk("\n");
288 return 0;
289 } else {
290 if (debug >= 2)
291 printk("unexpected running task!\n");
292 return -1;
295 if (conflict)
296 status = -1;
297 return status;
300 /* Modified version of Linux's print_context_stack */
301 int check_stack(struct module_pack *pack, struct thread_info *tinfo,
302 long *stack)
304 int conflict, status = 0;
305 long addr;
307 while (valid_stack_ptr(tinfo, stack)) {
308 addr = *stack++;
309 if (__kernel_text_address(addr)) {
310 conflict = check_address_for_conflict(pack, addr);
311 if (conflict)
312 status = -1;
313 if (debug >= 2) {
314 printk("%08lx ", addr);
315 if (conflict)
316 printk("[<-- CONFLICT] ");
320 if (debug >= 2)
321 printk("\n");
323 return status;
326 int check_address_for_conflict(struct module_pack *pack, long addr)
328 struct ksplice_size *s = pack->primary_sizes;
329 struct list_head *pos;
330 struct safety_record *rec;
332 list_for_each(pos, pack->safety_records) {
333 rec = list_entry(pos, struct safety_record, list);
334 if (rec->care == 1 && addr > rec->addr
335 && addr <= (rec->addr + rec->size)) {
336 return -1;
339 for (; s->name != NULL; s++) {
340 if (addr > s->thismod_addr
341 && addr <= (s->thismod_addr + s->size)) {
342 return -1;
346 return 0;
349 /* Modified version of Linux's valid_stack_ptr */
350 int valid_stack_ptr(struct thread_info *tinfo, void *p)
352 return p > (void *)tinfo
353 && p <= (void *)tinfo + THREAD_SIZE - sizeof(long);