1 #include <linux/slab.h>
2 #include <linux/spinlock.h>
3 #include <linux/limits.h>
4 #include <linux/list.h>
6 #include <us_manager/sspt/sspt_ip.h>
9 #include "preload_module.h"
10 #include "preload_control.h"
11 #include "preload_probe.h"
14 struct list_head list;
15 struct dentry *dentry;
20 struct list_head list;
25 static struct list_desc target = {
26 .list = LIST_HEAD_INIT(target.list),
27 .lock = __RW_LOCK_UNLOCKED(&target.lock),
31 static struct list_desc ignored = {
32 .list = LIST_HEAD_INIT(ignored.list),
33 .lock = __RW_LOCK_UNLOCKED(&ignored.lock),
37 static inline struct task_struct *__get_task_struct(void)
42 static struct bin_desc *__alloc_binary(struct dentry *dentry, char *name,
45 struct bin_desc *p = NULL;
47 p = kzalloc(sizeof(*p), GFP_KERNEL);
51 INIT_LIST_HEAD(&p->list);
52 p->filename = kmalloc(namelen + 1, GFP_KERNEL);
55 memcpy(p->filename, name, namelen);
56 p->filename[namelen] = '\0';
65 static void __free_binary(struct bin_desc *p)
71 static void __free_binaries(struct list_desc *tl)
73 struct bin_desc *p, *n;
74 struct list_head rm_head;
76 INIT_LIST_HEAD(&rm_head);
77 write_lock(&tl->lock);
78 list_for_each_entry_safe(p, n, &tl->list, list) {
79 list_move(&p->list, &rm_head);
82 write_unlock(&tl->lock);
84 list_for_each_entry_safe(p, n, &rm_head, list) {
86 put_dentry(p->dentry);
91 static bool __check_dentry_already_exist(struct dentry *dentry,
98 list_for_each_entry(p, &tl->list, list) {
99 if (p->dentry == dentry) {
105 read_unlock(&tl->lock);
110 static int __add_binary(struct dentry *dentry, char *filename,
111 struct list_desc *tl)
116 if (__check_dentry_already_exist(dentry, tl)) {
117 printk(PRELOAD_PREFIX "Binary already exist\n");
121 /* Filename should be < PATH_MAX */
122 len = strnlen(filename, PATH_MAX);
126 p = __alloc_binary(dentry, filename, len);
130 write_lock(&tl->lock);
131 list_add_tail(&p->list, &tl->list);
133 write_unlock(&tl->lock);
138 static struct dentry *__get_caller_dentry(struct task_struct *task,
139 unsigned long caller)
141 struct vm_area_struct *vma = NULL;
143 if (unlikely(task->mm == NULL))
144 goto get_caller_dentry_fail;
146 vma = find_vma_intersection(task->mm, caller, caller + 1);
147 if (unlikely(vma == NULL || vma->vm_file == NULL))
148 goto get_caller_dentry_fail;
150 return vma->vm_file->f_path.dentry;
152 get_caller_dentry_fail:
157 static bool __check_if_instrumented(struct task_struct *task,
158 struct dentry *dentry)
160 return __check_dentry_already_exist(dentry, &target);
163 static bool __is_instrumented(void *caller)
165 struct task_struct *task = __get_task_struct();
166 struct dentry *caller_dentry = __get_caller_dentry(task,
167 (unsigned long) caller);
169 if (caller_dentry == NULL)
172 return __check_if_instrumented(task, caller_dentry);
175 static unsigned int __get_names(struct list_desc *tl, char ***filenames_p)
177 unsigned int i, ret = 0;
181 read_lock(&tl->lock);
185 a = kmalloc(sizeof(*a) * tl->cnt, GFP_KERNEL);
190 list_for_each_entry(p, &tl->list, list) {
193 a[i++] = p->filename;
199 read_unlock(&tl->lock);
204 /* Called only form handlers. If we're there, then it is instrumented. */
205 enum preload_call_type pc_call_type_always_inst(void *caller)
207 if (__is_instrumented(caller))
208 return INTERNAL_CALL;
210 return EXTERNAL_CALL;
214 enum preload_call_type pc_call_type(struct sspt_ip *ip, void *caller)
216 if (__is_instrumented(caller))
217 return INTERNAL_CALL;
219 if (ip->desc->info.pl_i.flags & SWAP_PRELOAD_ALWAYS_RUN)
220 return EXTERNAL_CALL;
222 return NOT_INSTRUMENTED;
225 int pc_add_instrumented_binary(char *filename)
227 struct dentry *dentry = get_dentry(filename);
233 res = __add_binary(dentry, filename, &target);
237 return res > 0 ? 0 : res;
240 int pc_clean_instrumented_bins(void)
242 __free_binaries(&target);
247 int pc_add_ignored_binary(char *filename)
249 struct dentry *dentry = get_dentry(filename);
255 res = __add_binary(dentry, filename, &ignored);
259 return res > 0 ? 0 : res;
262 int pc_clean_ignored_bins(void)
264 __free_binaries(&ignored);
269 unsigned int pc_get_target_names(char ***filenames_p)
271 return __get_names(&target, filenames_p);
274 void pc_release_target_names(char ***filenames_p)
279 unsigned int pc_get_ignored_names(char ***filenames_p)
281 return __get_names(&ignored, filenames_p);
284 void pc_release_ignored_names(char ***filenames_p)
289 bool pc_check_dentry_is_ignored(struct dentry *dentry)
297 read_lock(&ignored.lock);
299 list_for_each_entry(p, &ignored.list, list) {
300 if (p->dentry == dentry) {
306 read_unlock(&ignored.lock);
318 __free_binaries(&target);
319 __free_binaries(&ignored);