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 <kprobe/swap_ktd.h>
35 #include <us_manager/us_slot_manager.h>
37 static LIST_HEAD(proc_probes_list);
38 static DEFINE_RWLOCK(sspt_proc_rwlock);
41 struct list_head *sspt_proc_list()
43 return &proc_probes_list;
47 * @brief Global read lock for sspt_proc
51 void sspt_proc_read_lock(void)
53 read_lock(&sspt_proc_rwlock);
57 * @brief Global read unlock for sspt_proc
61 void sspt_proc_read_unlock(void)
63 read_unlock(&sspt_proc_rwlock);
67 * @brief Global write lock for sspt_proc
71 void sspt_proc_write_lock(void)
73 write_lock(&sspt_proc_rwlock);
77 * @brief Global write unlock for sspt_proc
81 void sspt_proc_write_unlock(void)
83 write_unlock(&sspt_proc_rwlock);
87 static void ktd_init(struct task_struct *task, void *data)
89 struct sspt_proc **pproc = (struct sspt_proc **)data;
94 static void ktd_exit(struct task_struct *task, void *data)
96 struct sspt_proc **pproc = (struct sspt_proc **)data;
101 struct ktask_data ktd = {
104 .size = sizeof(struct sspt_proc *),
107 static struct sspt_proc **pproc_by_task(struct task_struct *task)
109 return (struct sspt_proc **)swap_ktd(&ktd, task);
112 int sspt_proc_init(void)
114 return swap_ktd_reg(&ktd);
117 void sspt_proc_uninit(void)
119 swap_ktd_unreg(&ktd);
122 void sspt_change_leader(struct task_struct *prev, struct task_struct *next)
124 struct sspt_proc **prev_pproc;
126 prev_pproc = pproc_by_task(prev);
128 struct sspt_proc **next_pproc;
130 next_pproc = pproc_by_task(next);
131 get_task_struct(next);
133 /* Change the keeper sspt_proc */
135 *next_pproc = *prev_pproc;
138 /* Set new the task leader to sspt_proc */
139 (*next_pproc)->leader = next;
141 put_task_struct(prev);
145 void sspt_reset_proc(struct task_struct *task)
147 struct sspt_proc **pproc;
149 pproc = pproc_by_task(task->group_leader);
157 static struct sspt_proc *sspt_proc_create(struct task_struct *leader)
159 struct sspt_proc *proc = kzalloc(sizeof(*proc), GFP_KERNEL);
162 proc->feature = sspt_create_feature();
163 if (proc->feature == NULL) {
168 INIT_LIST_HEAD(&proc->list);
169 proc->tgid = leader->tgid;
170 proc->leader = leader;
171 /* FIXME: change the task leader */
172 proc->sm = create_sm_us(leader);
173 INIT_LIST_HEAD(&proc->file_head);
174 mutex_init(&proc->filters.mtx);
175 INIT_LIST_HEAD(&proc->filters.head);
176 atomic_set(&proc->usage, 1);
178 get_task_struct(proc->leader);
180 proc->suspect.after_exec = 1;
181 proc->suspect.after_fork = 0;
188 * @brief Remove sspt_proc struct
190 * @param proc remove object
194 /* called with sspt_proc_write_lock() */
195 void sspt_proc_cleanup(struct sspt_proc *proc)
197 struct sspt_file *file, *n;
199 sspt_proc_del_all_filters(proc);
201 list_for_each_entry_safe(file, n, &proc->file_head, list) {
202 list_del(&file->list);
203 sspt_file_free(file);
206 sspt_destroy_feature(proc->feature);
208 free_sm_us(proc->sm);
212 struct sspt_proc *sspt_proc_get(struct sspt_proc *proc)
214 atomic_inc(&proc->usage);
219 void sspt_proc_put(struct sspt_proc *proc)
221 if (atomic_dec_and_test(&proc->usage)) {
227 put_task_struct(proc->__task);
231 put_task_struct(proc->leader);
236 struct sspt_proc *sspt_proc_by_task(struct task_struct *task)
238 return *pproc_by_task(task->group_leader);
240 EXPORT_SYMBOL_GPL(sspt_proc_by_task);
243 * @brief Call func() on each proc (no lock)
245 * @param func Callback
246 * @param data Data for callback
249 void on_each_proc_no_lock(void (*func)(struct sspt_proc *, void *), void *data)
251 struct sspt_proc *proc, *tmp;
253 list_for_each_entry_safe(proc, tmp, &proc_probes_list, list) {
259 * @brief Call func() on each proc
261 * @param func Callback
262 * @param data Data for callback
265 void on_each_proc(void (*func)(struct sspt_proc *, void *), void *data)
267 sspt_proc_read_lock();
268 on_each_proc_no_lock(func, data);
269 sspt_proc_read_unlock();
271 EXPORT_SYMBOL_GPL(on_each_proc);
274 * @brief Get sspt_proc by task or create sspt_proc
276 * @param task Pointer on the task_struct struct
277 * @param priv Private data
278 * @return Pointer on the sspt_proc struct
280 struct sspt_proc *sspt_proc_get_by_task_or_new(struct task_struct *task)
282 static DEFINE_MUTEX(local_mutex);
283 struct sspt_proc **pproc;
284 struct task_struct *leader = task->group_leader;
286 pproc = pproc_by_task(leader);
290 /* This lock for synchronizing to create sspt_proc */
291 mutex_lock(&local_mutex);
292 pproc = pproc_by_task(leader);
293 if (*pproc == NULL) {
294 *pproc = sspt_proc_create(leader);
296 sspt_proc_write_lock();
297 list_add(&(*pproc)->list, &proc_probes_list);
298 sspt_proc_write_unlock();
301 mutex_unlock(&local_mutex);
308 * @brief Free all sspt_proc
310 * @return Pointer on the sspt_proc struct
312 void sspt_proc_free_all(void)
314 struct sspt_proc *proc, *n;
316 list_for_each_entry_safe(proc, n, &proc_probes_list, list) {
317 list_del(&proc->list);
318 sspt_proc_cleanup(proc);
322 static void sspt_proc_add_file(struct sspt_proc *proc, struct sspt_file *file)
324 list_add(&file->list, &proc->file_head);
329 * @brief Get sspt_file from sspt_proc by dentry or new
331 * @param proc Pointer on the sspt_proc struct
332 * @param dentry Dentry of file
333 * @return Pointer on the sspt_file struct
335 struct sspt_file *sspt_proc_find_file_or_new(struct sspt_proc *proc,
336 struct dentry *dentry)
338 struct sspt_file *file;
340 file = sspt_proc_find_file(proc, dentry);
342 file = sspt_file_create(dentry, 10);
344 sspt_proc_add_file(proc, file);
351 * @brief Get sspt_file from sspt_proc by dentry
353 * @param proc Pointer on the sspt_proc struct
354 * @param dentry Dentry of file
355 * @return Pointer on the sspt_file struct
357 struct sspt_file *sspt_proc_find_file(struct sspt_proc *proc,
358 struct dentry *dentry)
360 struct sspt_file *file;
362 list_for_each_entry(file, &proc->file_head, list) {
363 if (dentry == file->dentry)
371 * @brief Install probes on the page to monitored process
373 * @param proc Pointer on the sspt_proc struct
374 * @param page_addr Page address
377 void sspt_proc_install_page(struct sspt_proc *proc, unsigned long page_addr)
379 struct mm_struct *mm = proc->leader->mm;
380 struct vm_area_struct *vma;
382 vma = find_vma_intersection(mm, page_addr, page_addr + 1);
383 if (vma && check_vma(vma)) {
384 struct dentry *dentry = vma->vm_file->f_dentry;
385 struct sspt_file *file = sspt_proc_find_file(proc, dentry);
387 struct sspt_page *page;
389 sspt_file_set_mapping(file, vma);
391 page = sspt_find_page_mapped(file, page_addr);
393 sspt_register_page(page, file);
399 * @brief Install probes to monitored process
401 * @param proc Pointer on the sspt_proc struct
404 void sspt_proc_install(struct sspt_proc *proc)
406 struct vm_area_struct *vma;
407 struct mm_struct *mm = proc->leader->mm;
409 proc->first_install = 1;
411 for (vma = mm->mmap; vma; vma = vma->vm_next) {
412 if (check_vma(vma)) {
413 struct dentry *dentry = vma->vm_file->f_dentry;
414 struct sspt_file *file =
415 sspt_proc_find_file(proc, dentry);
417 sspt_file_set_mapping(file, vma);
418 sspt_file_install(file);
425 * @brief Uninstall probes to monitored process
427 * @param proc Pointer on the sspt_proc struct
428 * @param task Pointer on the task_struct struct
429 * @param flag Action for probes
432 int sspt_proc_uninstall(struct sspt_proc *proc,
433 struct task_struct *task,
437 struct sspt_file *file;
439 list_for_each_entry_rcu(file, &proc->file_head, list) {
440 err = sspt_file_uninstall(file, task, flag);
442 printk(KERN_INFO "ERROR sspt_proc_uninstall: err=%d\n",
451 static int intersection(unsigned long start_a, unsigned long end_a,
452 unsigned long start_b, unsigned long end_b)
454 return start_a < start_b ?
460 * @brief Get sspt_file list by region (remove sspt_file from sspt_proc list)
462 * @param proc Pointer on the sspt_proc struct
463 * @param head[out] Pointer on the head list
464 * @param start Region start
465 * @param len Region length
468 int sspt_proc_get_files_by_region(struct sspt_proc *proc,
469 struct list_head *head,
470 unsigned long start, size_t len)
473 struct sspt_file *file, *n;
474 unsigned long end = start + len;
476 list_for_each_entry_safe(file, n, &proc->file_head, list) {
477 if (intersection(file->vm_start, file->vm_end, start, end)) {
479 list_move(&file->list, head);
487 * @brief Insert sspt_file to sspt_proc list
489 * @param proc Pointer on the sspt_proc struct
490 * @param head Pointer on the head list
493 void sspt_proc_insert_files(struct sspt_proc *proc, struct list_head *head)
495 list_splice(head, &proc->file_head);
499 * @brief Add sspt_filter to sspt_proc list
501 * @param proc Pointer to sspt_proc struct
502 * @param pfg Pointer to pf_group struct
505 void sspt_proc_add_filter(struct sspt_proc *proc, struct pf_group *pfg)
507 struct sspt_filter *f;
509 f = sspt_filter_create(proc, pfg);
511 list_add(&f->list, &proc->filters.head);
515 * @brief Remove sspt_filter from sspt_proc list
517 * @param proc Pointer to sspt_proc struct
518 * @param pfg Pointer to pf_group struct
521 void sspt_proc_del_filter(struct sspt_proc *proc, struct pf_group *pfg)
523 struct sspt_filter *fl, *tmp;
525 mutex_lock(&proc->filters.mtx);
526 list_for_each_entry_safe(fl, tmp, &proc->filters.head, list) {
527 if (fl->pfg == pfg) {
529 sspt_filter_free(fl);
532 mutex_unlock(&proc->filters.mtx);
536 * @brief Remove all sspt_filters from sspt_proc list
538 * @param proc Pointer to sspt_proc struct
541 void sspt_proc_del_all_filters(struct sspt_proc *proc)
543 struct sspt_filter *fl, *tmp;
545 mutex_lock(&proc->filters.mtx);
546 list_for_each_entry_safe(fl, tmp, &proc->filters.head, list) {
548 sspt_filter_free(fl);
550 mutex_unlock(&proc->filters.mtx);
554 * @brief Check if sspt_filter is already in sspt_proc list
556 * @param proc Pointer to sspt_proc struct
557 * @param pfg Pointer to pf_group struct
560 bool sspt_proc_is_filter_new(struct sspt_proc *proc, struct pf_group *pfg)
562 struct sspt_filter *fl;
564 list_for_each_entry(fl, &proc->filters.head, list)
571 void sspt_proc_on_each_filter(struct sspt_proc *proc,
572 void (*func)(struct sspt_filter *, void *),
575 struct sspt_filter *fl;
577 list_for_each_entry(fl, &proc->filters.head, list)
581 void sspt_proc_on_each_ip(struct sspt_proc *proc,
582 void (*func)(struct sspt_ip *, void *), void *data)
584 struct sspt_file *file;
586 list_for_each_entry(file, &proc->file_head, list)
587 sspt_file_on_each_ip(file, func, data);
590 static void is_send_event(struct sspt_filter *f, void *data)
592 bool *is_send = (bool *)data;
594 if (!*is_send && f->pfg_is_inst)
595 *is_send = !!pfg_msg_cb_get(f->pfg);
598 bool sspt_proc_is_send_event(struct sspt_proc *proc)
600 bool is_send = false;
602 /* FIXME: add read lock (deadlock in sampler) */
603 sspt_proc_on_each_filter(proc, is_send_event, (void *)&is_send);
609 static struct sspt_proc_cb *proc_cb;
611 int sspt_proc_cb_set(struct sspt_proc_cb *cb)
620 EXPORT_SYMBOL_GPL(sspt_proc_cb_set);
622 void sspt_proc_priv_create(struct sspt_proc *proc)
624 if (proc_cb && proc_cb->priv_create)
625 proc->private_data = proc_cb->priv_create(proc);
628 void sspt_proc_priv_destroy(struct sspt_proc *proc)
630 if (proc->first_install && proc_cb && proc_cb->priv_destroy)
631 proc_cb->priv_destroy(proc, proc->private_data);