ARM: tizen_tm1_defconfig: Enable missing features related with CGROUPS
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / kernel / swap / us_manager / pf / pf_group.c
1 /*
2  *  SWAP uprobe manager
3  *  modules/us_manager/pf/pf_group.c
4  *
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.
9  *
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.
14  *
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.
18  *
19  * Copyright (C) Samsung Electronics, 2013
20  *
21  * 2013  Vyacheslav Cherkashin: SWAP us_manager implement
22  *
23  */
24
25
26 #include <linux/module.h>
27 #include <linux/slab.h>
28 #include <linux/list.h>
29 #include <linux/namei.h>
30 #include <linux/mman.h>
31 #include <linux/spinlock.h>
32 #include "pf_group.h"
33 #include "proc_filters.h"
34 #include "../sspt/sspt_filter.h"
35 #include "../us_manager_common.h"
36 #include <us_manager/img/img_proc.h>
37 #include <us_manager/img/img_file.h>
38 #include <us_manager/img/img_ip.h>
39 #include <us_manager/sspt/sspt_proc.h>
40 #include <us_manager/helper.h>
41
42 struct pf_group {
43         struct list_head list;
44         struct img_proc *i_proc;
45         struct proc_filter filter;
46         struct pfg_msg_cb *msg_cb;
47         atomic_t usage;
48
49         spinlock_t pl_lock;     /* for proc_list */
50         struct list_head proc_list;
51 };
52
53 struct pl_struct {
54         struct list_head list;
55         struct sspt_proc *proc;
56 };
57
58 static LIST_HEAD(pfg_list);
59 static DEFINE_RWLOCK(pfg_list_lock);
60
61 /* struct pl_struct */
62 static struct pl_struct *create_pl_struct(struct sspt_proc *proc)
63 {
64         struct pl_struct *pls = kmalloc(sizeof(*pls), GFP_ATOMIC);
65
66         if (pls) {
67                 INIT_LIST_HEAD(&pls->list);
68                 pls->proc = sspt_proc_get(proc);
69         }
70
71         return pls;
72 }
73
74 static void free_pl_struct(struct pl_struct *pls)
75 {
76         sspt_proc_put(pls->proc);
77         kfree(pls);
78 }
79 /* struct pl_struct */
80
81 static struct pf_group *pfg_create(void)
82 {
83         struct pf_group *pfg = kmalloc(sizeof(*pfg), GFP_ATOMIC);
84
85         if (pfg == NULL)
86                 return NULL;
87
88         pfg->i_proc = create_img_proc();
89         if (pfg->i_proc == NULL)
90                 goto create_pfg_fail;
91
92         INIT_LIST_HEAD(&pfg->list);
93         memset(&pfg->filter, 0, sizeof(pfg->filter));
94         spin_lock_init(&pfg->pl_lock);
95         INIT_LIST_HEAD(&pfg->proc_list);
96         pfg->msg_cb = NULL;
97         atomic_set(&pfg->usage, 1);
98
99         return pfg;
100
101 create_pfg_fail:
102
103         kfree(pfg);
104
105         return NULL;
106 }
107
108 static void pfg_free(struct pf_group *pfg)
109 {
110         struct pl_struct *pl, *n;
111
112         free_img_proc(pfg->i_proc);
113         free_pf(&pfg->filter);
114         list_for_each_entry_safe(pl, n, &pfg->proc_list, list) {
115                 sspt_proc_del_filter(pl->proc, pfg);
116                 free_pl_struct(pl);
117         }
118
119         kfree(pfg);
120 }
121
122 static int pfg_add_proc(struct pf_group *pfg, struct sspt_proc *proc)
123 {
124         struct pl_struct *pls;
125
126         pls = create_pl_struct(proc);
127         if (pls == NULL)
128                 return -ENOMEM;
129
130         spin_lock(&pfg->pl_lock);
131         list_add(&pls->list, &pfg->proc_list);
132         spin_unlock(&pfg->pl_lock);
133
134         return 0;
135 }
136
137
138 /* called with pfg_list_lock held */
139 static void pfg_add_to_list(struct pf_group *pfg)
140 {
141         list_add(&pfg->list, &pfg_list);
142 }
143
144 /* called with pfg_list_lock held */
145 static void pfg_del_from_list(struct pf_group *pfg)
146 {
147         list_del(&pfg->list);
148 }
149
150
151 static void msg_info(struct sspt_filter *f, void *data)
152 {
153         if (f->pfg_is_inst == false) {
154                 struct pfg_msg_cb *cb;
155
156                 f->pfg_is_inst = true;
157
158                 cb = pfg_msg_cb_get(f->pfg);
159                 if (cb) {
160                         struct dentry *dentry;
161
162                         dentry = (struct dentry *)f->pfg->filter.priv;
163
164                         if (cb->msg_info)
165                                 cb->msg_info(f->proc->task, dentry);
166
167                         if (cb->msg_status_info)
168                                 cb->msg_status_info(f->proc->task);
169                 }
170         }
171 }
172
173 static void first_install(struct task_struct *task, struct sspt_proc *proc)
174 {
175         sspt_proc_priv_create(proc);
176
177         down_write(&task->mm->mmap_sem);
178         sspt_proc_on_each_filter(proc, msg_info, NULL);
179         sspt_proc_install(proc);
180         up_write(&task->mm->mmap_sem);
181 }
182
183 static void subsequent_install(struct task_struct *task,
184                                struct sspt_proc *proc, unsigned long page_addr)
185 {
186         down_write(&task->mm->mmap_sem);
187         sspt_proc_install_page(proc, page_addr);
188         up_write(&task->mm->mmap_sem);
189 }
190
191 /**
192  * @brief Get dentry struct by path
193  *
194  * @param path Path to file
195  * @return Pointer on dentry struct on NULL
196  */
197 struct dentry *dentry_by_path(const char *path)
198 {
199         struct dentry *dentry;
200         struct path st_path;
201         if (kern_path(path, LOOKUP_FOLLOW, &st_path) != 0) {
202                 printk("failed to lookup dentry for path %s!\n", path);
203                 return NULL;
204         }
205
206         dentry = st_path.dentry;
207         path_put(&st_path);
208         return dentry;
209 }
210 EXPORT_SYMBOL_GPL(dentry_by_path);
211
212
213 int pfg_msg_cb_set(struct pf_group *pfg, struct pfg_msg_cb *msg_cb)
214 {
215         if (pfg->msg_cb)
216                 return -EBUSY;
217
218         pfg->msg_cb = msg_cb;
219
220         return 0;
221 }
222 EXPORT_SYMBOL_GPL(pfg_msg_cb_set);
223
224 void pfg_msg_cb_reset(struct pf_group *pfg)
225 {
226         pfg->msg_cb = NULL;
227 }
228 EXPORT_SYMBOL_GPL(pfg_msg_cb_reset);
229
230 struct pfg_msg_cb *pfg_msg_cb_get(struct pf_group *pfg)
231 {
232         return pfg->msg_cb;
233 }
234
235 /**
236  * @brief Get pf_group struct by dentry
237  *
238  * @param dentry Dentry of file
239  * @param priv Private data
240  * @return Pointer on pf_group struct
241  */
242 struct pf_group *get_pf_group_by_dentry(struct dentry *dentry, void *priv)
243 {
244         struct pf_group *pfg;
245
246         write_lock(&pfg_list_lock);
247         list_for_each_entry(pfg, &pfg_list, list) {
248                 if (check_pf_by_dentry(&pfg->filter, dentry)) {
249                         atomic_inc(&pfg->usage);
250                         goto unlock;
251                 }
252         }
253
254         pfg = pfg_create();
255         if (pfg == NULL)
256                 goto unlock;
257
258         set_pf_by_dentry(&pfg->filter, dentry, priv);
259
260         pfg_add_to_list(pfg);
261
262 unlock:
263         write_unlock(&pfg_list_lock);
264         return pfg;
265 }
266 EXPORT_SYMBOL_GPL(get_pf_group_by_dentry);
267
268 /**
269  * @brief Get pf_group struct by TGID
270  *
271  * @param tgid Thread group ID
272  * @param priv Private data
273  * @return Pointer on pf_group struct
274  */
275 struct pf_group *get_pf_group_by_tgid(pid_t tgid, void *priv)
276 {
277         struct pf_group *pfg;
278
279         write_lock(&pfg_list_lock);
280         list_for_each_entry(pfg, &pfg_list, list) {
281                 if (check_pf_by_tgid(&pfg->filter, tgid)) {
282                         atomic_inc(&pfg->usage);
283                         goto unlock;
284                 }
285         }
286
287         pfg = pfg_create();
288         if (pfg == NULL)
289                 goto unlock;
290
291         set_pf_by_tgid(&pfg->filter, tgid, priv);
292
293         pfg_add_to_list(pfg);
294
295 unlock:
296         write_unlock(&pfg_list_lock);
297         return pfg;
298 }
299 EXPORT_SYMBOL_GPL(get_pf_group_by_tgid);
300
301 /**
302  * @brief Get pf_group struct by comm
303  *
304  * @param comm Task comm
305  * @param priv Private data
306  * @return Pointer on pf_group struct
307  */
308 struct pf_group *get_pf_group_by_comm(char *comm, void *priv)
309 {
310         int ret;
311         struct pf_group *pfg;
312
313         write_lock(&pfg_list_lock);
314         list_for_each_entry(pfg, &pfg_list, list) {
315                 if (check_pf_by_comm(&pfg->filter, comm)) {
316                         atomic_inc(&pfg->usage);
317                         goto unlock;
318                 }
319         }
320
321         pfg = pfg_create();
322         if (pfg == NULL)
323                 goto unlock;
324
325         ret = set_pf_by_comm(&pfg->filter, comm, priv);
326         if (ret) {
327                 printk(KERN_ERR "ERROR: set_pf_by_comm, ret=%d\n", ret);
328                 pfg_free(pfg);
329                 pfg = NULL;
330                 goto unlock;
331         }
332
333         pfg_add_to_list(pfg);
334 unlock:
335         write_unlock(&pfg_list_lock);
336         return pfg;
337 }
338 EXPORT_SYMBOL_GPL(get_pf_group_by_comm);
339
340 /**
341  * @brief Get pf_group struct for each process
342  *
343  * @param priv Private data
344  * @return Pointer on pf_group struct
345  */
346 struct pf_group *get_pf_group_dumb(void *priv)
347 {
348         struct pf_group *pfg;
349
350         write_lock(&pfg_list_lock);
351         list_for_each_entry(pfg, &pfg_list, list) {
352                 if (check_pf_dumb(&pfg->filter)) {
353                         atomic_inc(&pfg->usage);
354                         goto unlock;
355                 }
356         }
357
358         pfg = pfg_create();
359         if (pfg == NULL)
360                 goto unlock;
361
362         set_pf_dumb(&pfg->filter, priv);
363
364         pfg_add_to_list(pfg);
365
366 unlock:
367         write_unlock(&pfg_list_lock);
368         return pfg;
369 }
370 EXPORT_SYMBOL_GPL(get_pf_group_dumb);
371
372 /**
373  * @brief Put pf_group struct
374  *
375  * @param pfg Pointer to the pf_group struct
376  * @return Void
377  */
378 void put_pf_group(struct pf_group *pfg)
379 {
380         if (atomic_dec_and_test(&pfg->usage)) {
381                 write_lock(&pfg_list_lock);
382                 pfg_del_from_list(pfg);
383                 write_unlock(&pfg_list_lock);
384
385                 pfg_free(pfg);
386         }
387 }
388 EXPORT_SYMBOL_GPL(put_pf_group);
389
390 /**
391  * @brief Register prober for pf_grpup struct
392  *
393  * @param pfg Pointer to the pf_group struct
394  * @param dentry Dentry of file
395  * @param offset Function offset
396  * @param probe_info Pointer to the related probe_info struct
397  * @return Error code
398  */
399 int pf_register_probe(struct pf_group *pfg, struct dentry *dentry,
400                       unsigned long offset, struct probe_info *probe_i)
401 {
402         return img_proc_add_ip(pfg->i_proc, dentry, offset, probe_i);
403 }
404 EXPORT_SYMBOL_GPL(pf_register_probe);
405
406 /**
407  * @brief Unregister prober from pf_grpup struct
408  *
409  * @param pfg Pointer to the pf_group struct
410  * @param dentry Dentry of file
411  * @param offset Function offset
412  * @return Error code
413  */
414 int pf_unregister_probe(struct pf_group *pfg, struct dentry *dentry,
415                         unsigned long offset)
416 {
417         return img_proc_del_ip(pfg->i_proc, dentry, offset);
418 }
419 EXPORT_SYMBOL_GPL(pf_unregister_probe);
420
421 /**
422  * @brief Check the task, to meet the filter criteria
423  *
424  * @prarm task Pointer on the task_struct struct
425  * @return
426  *       - 0 - false
427  *       - 1 - true
428  */
429 int check_task_on_filters(struct task_struct *task)
430 {
431         int ret = 0;
432         struct pf_group *pfg;
433
434         read_lock(&pfg_list_lock);
435         list_for_each_entry(pfg, &pfg_list, list) {
436                 if (check_task_f(&pfg->filter, task)) {
437                         ret = 1;
438                         goto unlock;
439                 }
440         }
441
442 unlock:
443         read_unlock(&pfg_list_lock);
444         return ret;
445 }
446
447 enum pf_inst_flag {
448         PIF_NONE,
449         PIF_FIRST,
450         PIF_SECOND,
451         PIF_ADD_PFG
452 };
453
454 static enum pf_inst_flag pfg_check_task(struct task_struct *task)
455 {
456         struct pf_group *pfg;
457         struct sspt_proc *proc = NULL;
458         enum pf_inst_flag flag = PIF_NONE;
459
460         read_lock(&pfg_list_lock);
461         list_for_each_entry(pfg, &pfg_list, list) {
462                 if (check_task_f(&pfg->filter, task) == NULL)
463                         continue;
464
465                 if (proc == NULL)
466                         proc = sspt_proc_get_by_task(task);
467
468                 if (proc) {
469                         flag = flag == PIF_NONE ? PIF_SECOND : flag;
470                 } else if (task->tgid == task->pid) {
471                         proc = sspt_proc_get_by_task_or_new(task);
472                         if (proc == NULL) {
473                                 printk(KERN_ERR "cannot create sspt_proc\n");
474                                 break;
475                         }
476                         flag = PIF_FIRST;
477                 }
478
479                 if (proc) {
480                         write_lock(&proc->filter_lock);
481                                 if (sspt_proc_is_filter_new(proc, pfg)) {
482                                         img_proc_copy_to_sspt(pfg->i_proc, proc);
483                                         sspt_proc_add_filter(proc, pfg);
484                                         pfg_add_proc(pfg, proc);
485                                         flag = flag == PIF_FIRST ? flag : PIF_ADD_PFG;
486                         }
487                         write_unlock(&proc->filter_lock);
488                 }
489         }
490         read_unlock(&pfg_list_lock);
491
492         return flag;
493 }
494
495 /**
496  * @brief Check task and install probes on demand
497  *
498  * @prarm task Pointer on the task_struct struct
499  * @return Void
500  */
501 void check_task_and_install(struct task_struct *task)
502 {
503         struct sspt_proc *proc;
504         enum pf_inst_flag flag;
505
506         flag = pfg_check_task(task);
507         switch (flag) {
508         case PIF_FIRST:
509         case PIF_ADD_PFG:
510                 proc = sspt_proc_get_by_task(task);
511                 if (proc)
512                         first_install(task, proc);
513                 break;
514
515         case PIF_NONE:
516         case PIF_SECOND:
517                 break;
518         }
519 }
520
521 /**
522  * @brief Check task and install probes on demand
523  *
524  * @prarm task Pointer on the task_struct struct
525  * @param page_addr Page fault address
526  * @return Void
527  */
528 void call_page_fault(struct task_struct *task, unsigned long page_addr)
529 {
530         struct sspt_proc *proc;
531         enum pf_inst_flag flag;
532
533         flag = pfg_check_task(task);
534         switch (flag) {
535         case PIF_FIRST:
536         case PIF_ADD_PFG:
537                 proc = sspt_proc_get_by_task(task);
538                 if (proc)
539                         first_install(task, proc);
540                 break;
541
542         case PIF_SECOND:
543                 proc = sspt_proc_get_by_task(task);
544                 if (proc)
545                         subsequent_install(task, proc, page_addr);
546                 break;
547
548         case PIF_NONE:
549                 break;
550         }
551 }
552
553 /**
554  * @brief Uninstall probes from the sspt_proc struct
555  *
556  * @prarm proc Pointer on the sspt_proc struct
557  * @return Void
558  */
559
560 /* called with sspt_proc_write_lock() */
561 void uninstall_proc(struct sspt_proc *proc)
562 {
563         struct task_struct *task = proc->task;
564
565         sspt_proc_uninstall(proc, task, US_UNREGS_PROBE);
566         sspt_proc_cleanup(proc);
567 }
568
569 /**
570  * @brief Remove probes from the task on demand
571  *
572  * @prarm task Pointer on the task_struct struct
573  * @return Void
574  */
575 void call_mm_release(struct task_struct *task)
576 {
577         struct sspt_proc *proc;
578
579         sspt_proc_write_lock();
580         proc = sspt_proc_get_by_task_no_lock(task);
581         if (proc)
582                 list_del(&proc->list);
583         sspt_proc_write_unlock();
584
585         if (proc)
586                 uninstall_proc(proc);
587 }
588
589 /**
590  * @brief Legacy code, it is need remove
591  *
592  * @param addr Page address
593  * @return Void
594  */
595 void uninstall_page(unsigned long addr)
596 {
597
598 }
599
600 /**
601  * @brief Install probes on running processes
602  *
603  * @return Void
604  */
605 void install_all(void)
606 {
607         /* TODO: to be implemented */
608 }
609
610 /**
611  * @brief Uninstall probes from all processes
612  *
613  * @return Void
614  */
615 void uninstall_all(void)
616 {
617         struct list_head *proc_list = sspt_proc_list();
618
619         sspt_proc_write_lock();
620         while (!list_empty(proc_list)) {
621                 struct sspt_proc *proc;
622                 proc = list_first_entry(proc_list, struct sspt_proc, list);
623
624                 list_del(&proc->list);
625
626                 sspt_proc_write_unlock();
627                 uninstall_proc(proc);
628                 sspt_proc_write_lock();
629         }
630         sspt_proc_write_unlock();
631 }
632
633 static void __do_get_proc(struct sspt_proc *proc, void *data)
634 {
635         get_task_struct(proc->task);
636         proc->__task = proc->task;
637         proc->__mm = get_task_mm(proc->task);
638 }
639
640 static void __do_put_proc(struct sspt_proc *proc, void *data)
641 {
642         if (proc->__mm) {
643                 mmput(proc->__mm);
644                 proc->__mm = NULL;
645         }
646
647         if (proc->__task) {
648                 put_task_struct(proc->__task);
649                 proc->__task = NULL;
650         }
651 }
652
653 void get_all_procs(void)
654 {
655         sspt_proc_read_lock();
656         on_each_proc_no_lock(__do_get_proc, NULL);
657         sspt_proc_read_unlock();
658 }
659
660 void put_all_procs(void)
661 {
662         sspt_proc_read_lock();
663         on_each_proc_no_lock(__do_put_proc, NULL);
664         sspt_proc_read_unlock();
665 }
666
667 /**
668  * @brief For debug
669  *
670  * @param pfg Pointer to the pf_group struct
671  * @return Void
672  */
673
674 /* debug */
675 void pfg_print(struct pf_group *pfg)
676 {
677         img_proc_print(pfg->i_proc);
678 }
679 EXPORT_SYMBOL_GPL(pfg_print);
680 /* debug */