1 #include <linux/kernel.h>
2 #include <linux/module.h>
3 #include <linux/sched.h>
4 #include <linux/stop_machine.h>
5 #include <linux/slab.h>
6 #include <kprobe/swap_kprobes.h>
7 #include <ksyms/ksyms.h>
10 /* lower bits are used as flags */
11 #define TD_MAGIC_MASK 0xfffffff0
12 #define TD_FLAGS_MASK (~TD_MAGIC_MASK)
14 #define __DEFINE_TD_MAGIC(m) ((m) & TD_MAGIC_MASK)
16 #define TD_MAGIC __DEFINE_TD_MAGIC(0xbebebebe)
17 #define TD_OFFSET 1 /* skip STACK_END_MAGIC */
18 #define TD_PREFIX "[TASK_DATA] "
23 } __attribute__((packed));
25 #define get_magic(td) ((td)->magic & TD_MAGIC_MASK)
26 #define get_flags(td) ((td)->magic & TD_FLAGS_MASK)
28 static inline struct task_data *__td(struct task_struct *task)
30 return (struct task_data *)(end_of_stack(task) + TD_OFFSET);
33 static inline bool __td_check(struct task_data *td)
35 return (get_magic(td) == TD_MAGIC);
38 static inline void __td_init(struct task_data *td, void *data,
41 td->magic = TD_MAGIC | (flags & TD_FLAGS_MASK);
45 static inline void __td_free(struct task_data *td)
47 unsigned long flags = get_flags(td);
48 bool ok = __td_check(td);
50 /* freeing the data if consistency check fails is dangerous:
51 * better leave it as a memory leak instead */
53 if ((flags & SWAP_TD_FREE) && td->data)
60 WARN(!ok, TD_PREFIX "td(%p) check failed: %08lx", td, get_magic(td));
63 void *swap_task_data_get(struct task_struct *task, int *ok)
65 struct task_data *td = __td(task);
72 EXPORT_SYMBOL_GPL(swap_task_data_get);
74 void swap_task_data_set(struct task_struct *task, void *data,
77 struct task_data *td = __td(task);
79 __td_init(td, data, flags);
81 EXPORT_SYMBOL_GPL(swap_task_data_set);
83 static int copy_process_ret_handler(struct kretprobe_instance *ri,
86 struct task_struct *task;
88 task = (struct task_struct *)regs_return_value(regs);
90 swap_task_data_clean(task);
95 static int do_exit_handler(struct kprobe *p, struct pt_regs *regs)
97 struct task_data *td = __td(current);
104 static struct kretprobe copy_process_rp = {
105 .handler = copy_process_ret_handler
108 static struct kprobe do_exit_probe = {
109 .pre_handler = do_exit_handler
112 static int __task_data_init(void *data)
114 struct task_struct *g, *t;
118 addr = swap_ksyms_substr("copy_process");
120 printk(TD_PREFIX "Cannot find address for copy_process\n");
123 copy_process_rp.kp.addr = (kprobe_opcode_t *)addr;
124 ret = swap_register_kretprobe(©_process_rp);
128 addr = swap_ksyms_substr("do_exit");
130 printk(TD_PREFIX "Cannot find address for do_exit\n");
133 do_exit_probe.addr = (kprobe_opcode_t *)addr;
134 ret = swap_register_kprobe(&do_exit_probe);
136 goto unreg_copy_process;
138 do_each_thread(g, t) {
139 swap_task_data_clean(t);
140 } while_each_thread(g, t);
145 swap_unregister_kretprobe(©_process_rp);
148 printk(TD_PREFIX "0x%lx: probe registration failed\n", addr);
153 static int __task_data_exit(void *data)
155 struct task_struct *g, *t;
156 struct task_data *td;
158 swap_unregister_kprobe(&do_exit_probe);
159 swap_unregister_kretprobe(©_process_rp);
161 do_each_thread(g, t) {
164 } while_each_thread(g, t);
169 static int __init task_data_init(void)
173 /* stop_machine: cannot get tasklist_lock from module */
174 ret = stop_machine(__task_data_init, NULL, NULL);
176 printk(TD_PREFIX "task data initialization failed: %d\n", ret);
181 static void __exit task_data_exit(void)
185 /* stop_machine: the same here */
186 ret = stop_machine(__task_data_exit, ©_process_rp, NULL);
188 printk(TD_PREFIX "task data cleanup failed: %d\n", ret);
189 /* something went wrong: at least make sure we unregister
190 * all the installed probes */
191 swap_unregister_kprobe(&do_exit_probe);
192 swap_unregister_kretprobe(©_process_rp);
196 module_init(task_data_init);
197 module_exit(task_data_exit);
199 MODULE_LICENSE("GPL");
200 MODULE_DESCRIPTION("SWAP Task Data Module");