2 #include <linux/slab.h>
3 #include <linux/mutex.h>
4 #include <linux/limits.h>
6 #include <us_manager/sspt/ip.h>
10 #include "preload_control.h"
11 #include "preload_probe.h"
12 #include "preload_module.h"
15 #define DEFAULT_SLOTS_COUNT 5
16 #define DEFAULT_SLOTS_STEP 2
19 struct dentry *dentry;
23 static struct bin_desc *target_binaries = NULL;
24 static unsigned int target_binaries_cnt = 0;
25 static unsigned int target_binaries_slots = 0;
27 static DEFINE_MUTEX(__target_binaries_mutex);
30 static inline void __target_binaries_lock(void)
32 mutex_lock(&__target_binaries_mutex);
35 static inline void __target_binaries_unlock(void)
37 mutex_unlock(&__target_binaries_mutex);
40 static inline struct task_struct *__get_task_struct(void)
45 static int __alloc_target_binaries_no_lock(unsigned int cnt)
47 target_binaries = kmalloc(sizeof(*target_binaries) * cnt, GFP_KERNEL);
48 if (target_binaries == NULL)
51 target_binaries_slots = cnt;
56 static int __alloc_target_binaries(unsigned int cnt)
60 __target_binaries_lock();
61 ret = __alloc_target_binaries_no_lock(cnt);
62 __target_binaries_unlock();
67 static void __free_target_binaries(void)
71 __target_binaries_lock();
73 for (i = 0; i < target_binaries_cnt; i++) {
74 put_dentry(target_binaries[i].dentry);
75 kfree(target_binaries[i].filename);
78 kfree(target_binaries);
79 target_binaries_cnt = 0;
80 target_binaries_slots = 0;
82 __target_binaries_unlock();
85 static int __grow_target_binaries(void)
87 struct bin_desc *tmp = target_binaries;
90 __target_binaries_lock();
92 ret = __alloc_target_binaries_no_lock(target_binaries_slots + DEFAULT_SLOTS_STEP);
96 target_binaries_slots += DEFAULT_SLOTS_STEP;
98 for (i = 0; i < target_binaries_cnt; i++) {
99 target_binaries[i].dentry = tmp[i].dentry;
100 target_binaries[i].filename = tmp[i].filename;
103 __target_binaries_unlock();
110 static bool __check_dentry_already_exist(struct dentry *dentry)
115 __target_binaries_lock();
117 for (i = 0; i < target_binaries_cnt; i++) {
118 if (target_binaries[i].dentry == dentry) {
120 goto check_dentry_unlock;
125 __target_binaries_unlock();
130 static int __add_target_binary(struct dentry *dentry, char *filename)
135 if (__check_dentry_already_exist(dentry)) {
136 printk(PRELOAD_PREFIX "Binary already exist\n");
141 if (target_binaries_slots == target_binaries_cnt) {
142 ret = __grow_target_binaries();
147 /* Filename should be < PATH_MAX */
148 len = strnlen(filename, PATH_MAX);
152 __target_binaries_lock();
154 target_binaries[target_binaries_cnt].dentry = dentry;
155 target_binaries[target_binaries_cnt].filename = kmalloc(len + 1, GFP_KERNEL);
156 memcpy(target_binaries[target_binaries_cnt].filename, filename, len + 1);
157 ++target_binaries_cnt;
159 __target_binaries_unlock();
164 static char *__get_binary_name(struct bin_desc *bin)
166 return bin->filename;
169 static struct dentry *__get_caller_dentry(struct task_struct *task,
170 unsigned long caller)
172 struct vm_area_struct *vma = NULL;
174 if (unlikely(task->mm == NULL))
175 goto get_caller_dentry_fail;
177 vma = find_vma_intersection(task->mm, caller, caller + 1);
178 if (unlikely(vma == NULL || vma->vm_file == NULL))
179 goto get_caller_dentry_fail;
181 return vma->vm_file->f_dentry;
183 get_caller_dentry_fail:
188 static bool __check_if_instrumented(struct task_struct *task,
189 struct dentry *dentry)
193 for (i = 0; i < target_binaries_cnt; i++)
194 if (target_binaries[i].dentry == dentry)
200 static bool __is_instrumented(void *caller)
202 struct task_struct *task = __get_task_struct();
203 struct dentry *caller_dentry = __get_caller_dentry(task,
204 (unsigned long) caller);
206 if (caller_dentry == NULL)
209 return __check_if_instrumented(task, caller_dentry);
213 /* Called only form handlers. If we're there, then it is instrumented. */
214 enum preload_call_type preload_control_call_type_always_inst(void *caller)
216 if (__is_instrumented(caller))
217 return INTERNAL_CALL;
219 return EXTERNAL_CALL;
223 enum preload_call_type preload_control_call_type(struct us_ip *ip, void *caller)
225 if (__is_instrumented(caller))
226 return INTERNAL_CALL;
228 if (ip->info->pl_i.flags & SWAP_PRELOAD_ALWAYS_RUN)
229 return EXTERNAL_CALL;
231 return NOT_INSTRUMENTED;
234 int preload_control_add_instrumented_binary(char *filename)
236 struct dentry *dentry = get_dentry(filename);
242 res = __add_target_binary(dentry, filename);
246 return res > 0 ? 0 : res;
249 int preload_control_clean_instrumented_bins(void)
251 __free_target_binaries();
252 return __alloc_target_binaries(DEFAULT_SLOTS_COUNT);
255 unsigned int preload_control_get_bin_names(char ***filenames_p)
258 unsigned int ret = 0;
260 if (target_binaries_cnt == 0)
263 __target_binaries_lock();
265 *filenames_p = kmalloc(sizeof(**filenames_p) * target_binaries_cnt,
267 if (*filenames_p == NULL)
268 goto get_binaries_names_out;
270 for (i = 0; i < target_binaries_cnt; i++)
271 (*filenames_p)[i] = __get_binary_name(&target_binaries[i]);
273 ret = target_binaries_cnt;
275 get_binaries_names_out:
276 __target_binaries_unlock();
281 void preload_control_release_bin_names(char ***filenames_p)
286 int preload_control_init(void)
288 return __alloc_target_binaries(DEFAULT_SLOTS_COUNT);
291 void preload_control_exit(void)
293 __free_target_binaries();
296 #undef DEFAULT_SLOTS_STEP
297 #undef DEFAULT_SLOTS_COUNT