2 * Dynamic Binary Instrumentation Module based on KProbes
3 * modules/driver/sspt/sspt_proc.c
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 * Copyright (C) Samsung Electronics, 2013
21 * 2013 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
26 #include "sspt_proc.h"
27 #include "sspt_page.h"
28 #include "sspt_feature.h"
29 #include "sspt_filter.h"
30 #include "../pf/proc_filters.h"
31 #include <linux/module.h>
32 #include <linux/slab.h>
33 #include <linux/list.h>
34 #include <us_manager/us_slot_manager.h>
36 static LIST_HEAD(proc_probes_list);
37 static DEFINE_RWLOCK(sspt_proc_rwlock);
40 struct list_head *sspt_proc_list()
42 return &proc_probes_list;
46 * @brief Global read lock for sspt_proc
50 void sspt_proc_read_lock(void)
52 read_lock(&sspt_proc_rwlock);
56 * @brief Global read unlock for sspt_proc
60 void sspt_proc_read_unlock(void)
62 read_unlock(&sspt_proc_rwlock);
66 * @brief Global write lock for sspt_proc
70 void sspt_proc_write_lock(void)
72 write_lock(&sspt_proc_rwlock);
76 * @brief Global write unlock for sspt_proc
80 void sspt_proc_write_unlock(void)
82 write_unlock(&sspt_proc_rwlock);
87 * @brief Create sspt_proc struct
89 * @param task Pointer to the task_struct struct
90 * @param priv Private data
91 * @return Pointer to the created sspt_proc struct
93 struct sspt_proc *sspt_proc_create(struct task_struct *task)
95 struct sspt_proc *proc = kzalloc(sizeof(*proc), GFP_ATOMIC);
98 proc->feature = sspt_create_feature();
99 if (proc->feature == NULL) {
104 INIT_LIST_HEAD(&proc->list);
105 proc->tgid = task->tgid;
106 proc->task = task->group_leader;
107 proc->sm = create_sm_us(task);
108 INIT_LIST_HEAD(&proc->file_list);
109 rwlock_init(&proc->filter_lock);
110 INIT_LIST_HEAD(&proc->filter_list);
111 atomic_set(&proc->usage, 1);
113 get_task_struct(proc->task);
116 list_add(&proc->list, &proc_probes_list);
123 * @brief Remove sspt_proc struct
125 * @param proc remove object
129 /* called with sspt_proc_write_lock() */
130 void sspt_proc_cleanup(struct sspt_proc *proc)
132 struct sspt_file *file, *n;
134 sspt_proc_del_all_filters(proc);
136 list_for_each_entry_safe(file, n, &proc->file_list, list) {
137 list_del(&file->list);
138 sspt_file_free(file);
141 sspt_destroy_feature(proc->feature);
143 free_sm_us(proc->sm);
147 struct sspt_proc *sspt_proc_get(struct sspt_proc *proc)
149 atomic_inc(&proc->usage);
154 void sspt_proc_put(struct sspt_proc *proc)
156 if (atomic_dec_and_test(&proc->usage)) {
162 put_task_struct(proc->__task);
166 put_task_struct(proc->task);
171 struct sspt_proc *sspt_proc_get_by_task(struct task_struct *task)
173 struct sspt_proc *proc;
175 sspt_proc_read_lock();
176 proc = sspt_proc_get_by_task_no_lock(task);
177 sspt_proc_read_unlock();
181 EXPORT_SYMBOL_GPL(sspt_proc_get_by_task);
184 * @brief Get sspt_proc by task
186 * @param task Pointer on the task_struct struct
187 * @return Pointer on the sspt_proc struct
189 struct sspt_proc *sspt_proc_get_by_task_no_lock(struct task_struct *task)
191 struct sspt_proc *proc, *tmp;
193 list_for_each_entry_safe(proc, tmp, &proc_probes_list, list) {
194 if (proc->tgid == task->tgid)
200 EXPORT_SYMBOL_GPL(sspt_proc_get_by_task_no_lock);
203 * @brief Call func() on each proc (no lock)
205 * @param func Callback
206 * @param data Data for callback
209 void on_each_proc_no_lock(void (*func)(struct sspt_proc *, void *), void *data)
211 struct sspt_proc *proc, *tmp;
213 list_for_each_entry_safe(proc, tmp, &proc_probes_list, list) {
219 * @brief Call func() on each proc
221 * @param func Callback
222 * @param data Data for callback
225 void on_each_proc(void (*func)(struct sspt_proc *, void *), void *data)
227 sspt_proc_read_lock();
228 on_each_proc_no_lock(func, data);
229 sspt_proc_read_unlock();
231 EXPORT_SYMBOL_GPL(on_each_proc);
234 * @brief Get sspt_proc by task or create sspt_proc
236 * @param task Pointer on the task_struct struct
237 * @param priv Private data
238 * @return Pointer on the sspt_proc struct
240 struct sspt_proc *sspt_proc_get_by_task_or_new(struct task_struct *task)
242 struct sspt_proc *proc;
244 sspt_proc_write_lock();
245 proc = sspt_proc_get_by_task_no_lock(task);
247 proc = sspt_proc_create(task);
248 sspt_proc_write_unlock();
254 * @brief Free all sspt_proc
256 * @return Pointer on the sspt_proc struct
258 void sspt_proc_free_all(void)
260 struct sspt_proc *proc, *n;
262 list_for_each_entry_safe(proc, n, &proc_probes_list, list) {
263 list_del(&proc->list);
264 sspt_proc_cleanup(proc);
268 static void sspt_proc_add_file(struct sspt_proc *proc, struct sspt_file *file)
270 list_add(&file->list, &proc->file_list);
275 * @brief Get sspt_file from sspt_proc by dentry or new
277 * @param proc Pointer on the sspt_proc struct
278 * @param dentry Dentry of file
279 * @return Pointer on the sspt_file struct
281 struct sspt_file *sspt_proc_find_file_or_new(struct sspt_proc *proc,
282 struct dentry *dentry)
284 struct sspt_file *file;
286 file = sspt_proc_find_file(proc, dentry);
288 file = sspt_file_create(dentry, 10);
290 sspt_proc_add_file(proc, file);
297 * @brief Get sspt_file from sspt_proc by dentry
299 * @param proc Pointer on the sspt_proc struct
300 * @param dentry Dentry of file
301 * @return Pointer on the sspt_file struct
303 struct sspt_file *sspt_proc_find_file(struct sspt_proc *proc,
304 struct dentry *dentry)
306 struct sspt_file *file;
308 list_for_each_entry(file, &proc->file_list, list) {
309 if (dentry == file->dentry)
317 * @brief Install probes on the page to monitored process
319 * @param proc Pointer on the sspt_proc struct
320 * @param page_addr Page address
323 void sspt_proc_install_page(struct sspt_proc *proc, unsigned long page_addr)
325 struct mm_struct *mm = proc->task->mm;
326 struct vm_area_struct *vma;
328 vma = find_vma_intersection(mm, page_addr, page_addr + 1);
329 if (vma && check_vma(vma)) {
330 struct dentry *dentry = vma->vm_file->f_dentry;
331 struct sspt_file *file = sspt_proc_find_file(proc, dentry);
333 struct sspt_page *page;
335 sspt_file_set_mapping(file, vma);
337 page = sspt_find_page_mapped(file, page_addr);
339 sspt_register_page(page, file);
345 * @brief Install probes to monitored process
347 * @param proc Pointer on the sspt_proc struct
350 void sspt_proc_install(struct sspt_proc *proc)
352 struct vm_area_struct *vma;
353 struct mm_struct *mm = proc->task->mm;
355 proc->first_install = 1;
357 for (vma = mm->mmap; vma; vma = vma->vm_next) {
358 if (check_vma(vma)) {
359 struct dentry *dentry = vma->vm_file->f_dentry;
360 struct sspt_file *file =
361 sspt_proc_find_file(proc, dentry);
363 sspt_file_set_mapping(file, vma);
364 sspt_file_install(file);
371 * @brief Uninstall probes to monitored process
373 * @param proc Pointer on the sspt_proc struct
374 * @param task Pointer on the task_struct struct
375 * @param flag Action for probes
378 int sspt_proc_uninstall(struct sspt_proc *proc,
379 struct task_struct *task,
383 struct sspt_file *file;
385 list_for_each_entry_rcu(file, &proc->file_list, list) {
386 err = sspt_file_uninstall(file, task, flag);
388 printk(KERN_INFO "ERROR sspt_proc_uninstall: err=%d\n",
397 static int intersection(unsigned long start_a, unsigned long end_a,
398 unsigned long start_b, unsigned long end_b)
400 return start_a < start_b ?
406 * @brief Get sspt_file list by region (remove sspt_file from sspt_proc list)
408 * @param proc Pointer on the sspt_proc struct
409 * @param head[out] Pointer on the head list
410 * @param start Region start
411 * @param len Region length
414 int sspt_proc_get_files_by_region(struct sspt_proc *proc,
415 struct list_head *head,
416 unsigned long start, size_t len)
419 struct sspt_file *file, *n;
420 unsigned long end = start + len;
422 list_for_each_entry_safe(file, n, &proc->file_list, list) {
423 if (intersection(file->vm_start, file->vm_end, start, end)) {
425 list_move(&file->list, head);
433 * @brief Insert sspt_file to sspt_proc list
435 * @param proc Pointer on the sspt_proc struct
436 * @param head Pointer on the head list
439 void sspt_proc_insert_files(struct sspt_proc *proc, struct list_head *head)
441 list_splice(head, &proc->file_list);
445 * @brief Add sspt_filter to sspt_proc list
447 * @param proc Pointer to sspt_proc struct
448 * @param pfg Pointer to pf_group struct
451 void sspt_proc_add_filter(struct sspt_proc *proc, struct pf_group *pfg)
453 struct sspt_filter *f;
455 f = sspt_filter_create(proc, pfg);
457 list_add(&f->list, &proc->filter_list);
461 * @brief Remove sspt_filter from sspt_proc list
463 * @param proc Pointer to sspt_proc struct
464 * @param pfg Pointer to pf_group struct
467 void sspt_proc_del_filter(struct sspt_proc *proc, struct pf_group *pfg)
469 struct sspt_filter *fl, *tmp;
471 write_lock(&proc->filter_lock);
472 list_for_each_entry_safe(fl, tmp, &proc->filter_list, list) {
473 if (fl->pfg == pfg) {
475 sspt_filter_free(fl);
478 write_unlock(&proc->filter_lock);
482 * @brief Remove all sspt_filters from sspt_proc list
484 * @param proc Pointer to sspt_proc struct
487 void sspt_proc_del_all_filters(struct sspt_proc *proc)
489 struct sspt_filter *fl, *tmp;
491 write_lock(&proc->filter_lock);
492 list_for_each_entry_safe(fl, tmp, &proc->filter_list, list) {
494 sspt_filter_free(fl);
496 write_unlock(&proc->filter_lock);
500 * @brief Check if sspt_filter is already in sspt_proc list
502 * @param proc Pointer to sspt_proc struct
503 * @param pfg Pointer to pf_group struct
506 bool sspt_proc_is_filter_new(struct sspt_proc *proc, struct pf_group *pfg)
508 struct sspt_filter *fl;
510 list_for_each_entry(fl, &proc->filter_list, list)
517 void sspt_proc_on_each_filter(struct sspt_proc *proc,
518 void (*func)(struct sspt_filter *, void *),
521 struct sspt_filter *fl;
523 list_for_each_entry(fl, &proc->filter_list, list)
527 void sspt_proc_on_each_ip(struct sspt_proc *proc,
528 void (*func)(struct us_ip *, void *), void *data)
530 struct sspt_file *file;
532 list_for_each_entry(file, &proc->file_list, list)
533 sspt_file_on_each_ip(file, func, data);
536 static void is_send_event(struct sspt_filter *f, void *data)
538 bool *is_send = (bool *)data;
540 if (!*is_send && f->pfg_is_inst)
541 *is_send = !!pfg_msg_cb_get(f->pfg);
544 bool sspt_proc_is_send_event(struct sspt_proc *proc)
546 bool is_send = false;
548 /* FIXME: add read lock (deadlock in sampler) */
549 sspt_proc_on_each_filter(proc, is_send_event, (void *)&is_send);
555 static struct sspt_proc_cb *proc_cb;
557 int sspt_proc_cb_set(struct sspt_proc_cb *cb)
566 EXPORT_SYMBOL_GPL(sspt_proc_cb_set);
568 void sspt_proc_priv_create(struct sspt_proc *proc)
570 if (proc_cb && proc_cb->priv_create)
571 proc->private_data = proc_cb->priv_create(proc);
574 void sspt_proc_priv_destroy(struct sspt_proc *proc)
576 if (proc->first_install && proc_cb && proc_cb->priv_destroy)
577 proc_cb->priv_destroy(proc, proc->private_data);