Tizen 2.4.0 rev3 SDK Public Release
[kernel/swap-modules.git] / nsp / nsp.c
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15  *
16  * Copyright (C) Samsung Electronics, 2015
17  *
18  * 2015         Vyacheslav Cherkashin <v.cherkashin@samsung.com>
19  *
20  */
21
22
23 #include <linux/module.h>
24 #include <writer/swap_msg.h>
25 #include <uprobe/swap_uaccess.h>
26 #include <us_manager/pf/pf_group.h>
27 #include <us_manager/sspt/sspt_proc.h>
28 #include <us_manager/probes/probe_info_new.h>
29 #include "nsp.h"
30 #include "nsp_msg.h"
31 #include "nsp_tdata.h"
32 #include "nsp_print.h"
33 #include "nsp_debugfs.h"
34
35
36 /* ============================================================================
37  * =                                 probes                                   =
38  * ============================================================================
39  */
40
41 /* dlopen@plt */
42 static int dlopen_eh(struct uretprobe_instance *ri, struct pt_regs *regs);
43 static int dlopen_rh(struct uretprobe_instance *ri, struct pt_regs *regs);
44 static struct probe_info_new pin_dlopen = MAKE_URPROBE(dlopen_eh, dlopen_rh, 0);
45 static struct probe_new p_dlopen = {
46         .info = &pin_dlopen
47 };
48
49 /* dlsym@plt */
50 static int dlsym_eh(struct uretprobe_instance *ri, struct pt_regs *regs);
51 static int dlsym_rh(struct uretprobe_instance *ri, struct pt_regs *regs);
52 static struct probe_info_new pin_dlsym = MAKE_URPROBE(dlsym_eh, dlsym_rh, 0);
53 static struct probe_new p_dlsym = {
54         .info = &pin_dlsym
55 };
56
57 /* main */
58 static int main_eh(struct uretprobe_instance *ri, struct pt_regs *regs);
59 static int main_rh(struct uretprobe_instance *ri, struct pt_regs *regs);
60 static struct probe_info_new pin_main = MAKE_URPROBE(main_eh, main_rh, 0);
61
62 /* appcore_efl_main */
63 static int ac_efl_main_h(struct kprobe *p, struct pt_regs *regs);
64 static struct probe_info_new pin_ac_efl_main = MAKE_UPROBE(ac_efl_main_h);
65 static struct probe_new p_ac_efl_main = {
66         .info = &pin_ac_efl_main
67 };
68
69 /* appcore_init@plt */
70 static int ac_init_rh(struct uretprobe_instance *ri, struct pt_regs *regs);
71 static struct probe_info_new pin_ac_init = MAKE_URPROBE(NULL, ac_init_rh, 0);
72 static struct probe_new p_ac_init = {
73         .info = &pin_ac_init
74 };
75
76 /* elm_run@plt */
77 static int elm_run_h(struct kprobe *p, struct pt_regs *regs);
78 static struct probe_info_new pin_elm_run = MAKE_UPROBE(elm_run_h);
79 static struct probe_new p_elm_run = {
80         .info = &pin_elm_run
81 };
82
83 /* __do_app */
84 static int do_app_eh(struct uretprobe_instance *ri, struct pt_regs *regs);
85 static int do_app_rh(struct uretprobe_instance *ri, struct pt_regs *regs);
86 static struct probe_info_new pin_do_app = MAKE_URPROBE(do_app_eh, do_app_rh, 0);
87 static struct probe_new p_do_app = {
88         .info = &pin_do_app
89 };
90
91
92
93
94
95 /* ============================================================================
96  * =                the variables are initialized by the user                 =
97  * ============================================================================
98  */
99 static const char *lpad_path;
100 static struct dentry *lpad_dentry;
101
102 static const char *libappcore_path;
103 static struct dentry *libappcore_dentry;
104
105 static void uninit_variables(void)
106 {
107         kfree(lpad_path);
108         lpad_path = NULL;
109         lpad_dentry = NULL;
110
111         kfree(libappcore_path);
112         libappcore_path = NULL;
113         libappcore_dentry = NULL;
114 }
115
116 static bool is_init(void)
117 {
118         return lpad_dentry && libappcore_dentry;
119 }
120
121 static int do_set_lpad_info(const char *path, unsigned long dlopen,
122                             unsigned long dlsym)
123 {
124         struct dentry *dentry;
125         const char *new_path;
126
127         dentry = dentry_by_path(path);
128         if (dentry == NULL) {
129                 pr_err("dentry not found (path='%s')\n", path);
130                 return -EINVAL;
131         }
132
133         new_path = kstrdup(path, GFP_KERNEL);
134         if (new_path == NULL) {
135                 pr_err("out of memory\n");
136                 return -ENOMEM;
137         }
138
139         kfree(lpad_path);
140
141         lpad_path = new_path;
142         lpad_dentry = dentry;
143         p_dlopen.offset = dlopen;
144         p_dlsym.offset = dlsym;
145
146         return 0;
147 }
148
149 static int do_set_appcore_info(struct appcore_info_data *info)
150 {
151         struct dentry *dentry;
152         const char *new_path;
153
154         dentry = dentry_by_path(info->path);
155         if (dentry == NULL) {
156                 pr_err("dentry not found (path='%s')\n", info->path);
157                 return -EINVAL;
158         }
159
160         new_path = kstrdup(info->path, GFP_KERNEL);
161         if (new_path == NULL) {
162                 pr_err("out of memory\n");
163                 return -ENOMEM;
164         }
165
166         kfree(libappcore_path);
167
168         libappcore_path = new_path;
169         libappcore_dentry = dentry;
170         p_ac_efl_main.offset = info->ac_efl_main;
171         p_ac_init.offset = info->ac_init;
172         p_elm_run.offset = info->elm_run;
173         p_do_app.offset = info->do_app;
174
175         return 0;
176 }
177
178
179
180
181
182 /* ============================================================================
183  * =                                nsp_data                                  =
184  * ============================================================================
185  */
186 struct nsp_data {
187         struct list_head list;
188
189         const char *app_path;
190         struct dentry *app_dentry;
191         struct probe_new p_main;
192
193         struct pf_group *pfg;
194 };
195
196 static LIST_HEAD(nsp_data_list);
197
198 static struct nsp_data *nsp_data_create(const char *app_path,
199                                         unsigned long main_addr)
200 {
201         struct dentry *dentry;
202         struct nsp_data *data;
203
204         dentry = dentry_by_path(app_path);
205         if (dentry == NULL)
206                 return ERR_PTR(-ENOENT);
207
208         data = kmalloc(sizeof(*data), GFP_KERNEL);
209         if (data == NULL)
210                 return ERR_PTR(-ENOMEM);
211
212         data->app_path = kstrdup(app_path, GFP_KERNEL);
213         if (data->app_path == NULL) {
214                 kfree(data);
215                 return ERR_PTR(-ENOMEM);
216         }
217
218         data->app_dentry = dentry;
219         data->p_main.info = &pin_main;
220         data->p_main.offset = main_addr;
221         data->pfg = NULL;
222
223         return data;
224 }
225
226 static void nsp_data_destroy(struct nsp_data *data)
227 {
228         kfree(data->app_path);
229         kfree(data);
230 }
231
232 static struct nsp_data *nsp_data_find(const struct dentry *dentry)
233 {
234         struct nsp_data *data;
235
236         list_for_each_entry(data, &nsp_data_list, list) {
237                 if (data->app_dentry == dentry)
238                         return data;
239         }
240
241         return NULL;
242 }
243
244 static struct nsp_data *nsp_data_find_by_path(const char *path)
245 {
246         struct nsp_data *data;
247
248         list_for_each_entry(data, &nsp_data_list, list) {
249                 if (strcmp(data->app_path, path) == 0)
250                         return data;
251         }
252
253         return NULL;
254 }
255
256 static void nsp_data_add(struct nsp_data *data)
257 {
258         list_add(&data->list, &nsp_data_list);
259 }
260
261 static void nsp_data_rm(struct nsp_data *data)
262 {
263         list_del(&data->list);
264 }
265
266 static int nsp_data_inst(struct nsp_data *data)
267 {
268         int ret;
269         struct pf_group *pfg;
270
271         pfg = get_pf_group_by_dentry(lpad_dentry, (void *)data->app_dentry);
272         if (pfg == NULL)
273                 return -ENOMEM;
274
275         ret = pin_register(&p_dlsym, pfg, lpad_dentry);
276         if (ret)
277                 goto put_g;
278
279         ret = pin_register(&p_dlopen, pfg, lpad_dentry);
280         if (ret)
281                 goto ur_dlsym;
282
283         ret = pin_register(&data->p_main, pfg, data->app_dentry);
284         if (ret)
285                 goto ur_dlopen;
286
287         ret = pin_register(&p_ac_efl_main, pfg, libappcore_dentry);
288         if (ret)
289                 goto ur_main;
290
291         ret = pin_register(&p_ac_init, pfg, libappcore_dentry);
292         if (ret)
293                 goto ur_ac_efl_main;
294
295         ret = pin_register(&p_elm_run, pfg, libappcore_dentry);
296         if (ret)
297                 goto ur_ac_init;
298
299         ret = pin_register(&p_do_app, pfg, libappcore_dentry);
300         if (ret)
301                 goto ur_elm_run;
302
303         data->pfg = pfg;
304
305         return 0;
306
307 ur_elm_run:
308         pin_unregister(&p_elm_run, pfg, libappcore_dentry);
309 ur_ac_init:
310         pin_unregister(&p_ac_init, pfg, libappcore_dentry);
311 ur_ac_efl_main:
312         pin_unregister(&p_ac_efl_main, pfg, libappcore_dentry);
313 ur_main:
314         pin_unregister(&data->p_main, pfg, data->app_dentry);
315 ur_dlopen:
316         pin_unregister(&p_dlopen, pfg, lpad_dentry);
317 ur_dlsym:
318         pin_unregister(&p_dlsym, pfg, lpad_dentry);
319 put_g:
320         put_pf_group(pfg);
321         return ret;
322 }
323
324 static void nsp_data_uninst(struct nsp_data *data)
325 {
326         struct pf_group *pfg = data->pfg;
327
328         pin_unregister(&p_do_app, pfg, libappcore_dentry);
329         pin_unregister(&p_elm_run, pfg, libappcore_dentry);
330         pin_unregister(&p_ac_init, pfg, libappcore_dentry);
331         pin_unregister(&p_ac_efl_main, pfg, libappcore_dentry);
332         pin_unregister(&data->p_main, pfg, data->app_dentry);
333         pin_unregister(&p_dlopen, pfg, lpad_dentry);
334         pin_unregister(&p_dlsym, pfg, lpad_dentry);
335         put_pf_group(pfg);
336
337         data->pfg = NULL;
338 }
339
340 static int __nsp_add(const char *app_path, unsigned long main_addr)
341 {
342         struct nsp_data *data;
343
344         if (nsp_data_find_by_path(app_path))
345                 return -EEXIST;
346
347         data = nsp_data_create(app_path, main_addr);
348         if (IS_ERR(data))
349                 return PTR_ERR(data);
350
351         nsp_data_add(data);
352
353         return 0;
354 }
355
356 static int __nsp_rm(const char *path)
357 {
358         struct dentry *dentry;
359         struct nsp_data *data;
360
361         dentry = dentry_by_path(path);
362         if (dentry == NULL)
363                 return -ENOENT;
364
365         data = nsp_data_find(dentry);
366         if (data == NULL)
367                 return -ESRCH;
368
369         nsp_data_rm(data);
370         nsp_data_destroy(data);
371
372         return 0;
373 }
374
375 static int __nsp_rm_all(void)
376 {
377         struct nsp_data *data, *n;
378
379         list_for_each_entry_safe(data, n, &nsp_data_list, list) {
380                 nsp_data_rm(data);
381                 nsp_data_destroy(data);
382         }
383
384         return 0;
385 }
386
387 static void __nsp_disabel(void)
388 {
389         struct nsp_data *data;
390
391         list_for_each_entry(data, &nsp_data_list, list) {
392                 if (data->pfg)
393                         nsp_data_uninst(data);
394         }
395 }
396
397 static int __nsp_enable(void)
398 {
399         int ret;
400         struct nsp_data *data;
401
402         list_for_each_entry(data, &nsp_data_list, list) {
403                 ret = nsp_data_inst(data);
404                 if (ret)
405                         goto fail;
406         }
407
408         return 0;
409
410 fail:
411         __nsp_disabel();
412         return ret;
413 }
414
415
416
417
418
419
420
421 /* ============================================================================
422  * =                             set parameters                               =
423  * ============================================================================
424  */
425 #define F_ARG1(m, t, a)         m(t, a)
426 #define F_ARG2(m, t, a, ...)    m(t, a), F_ARG1(m, __VA_ARGS__)
427 #define F_ARG3(m, t, a, ...)    m(t, a), F_ARG2(m, __VA_ARGS__)
428 #define F_ARG(n, m, ...)        F_ARG##n(m, __VA_ARGS__)
429
430 #define M_TYPE_AND_ARG(t, a)    t a
431 #define M_ARG(t, a)             a
432
433 #define DECLARE_SAFE_FUNC(n, func_name, do_func, ...)   \
434 int func_name(F_ARG(n, M_TYPE_AND_ARG,  __VA_ARGS__))   \
435 {                                                       \
436         int ret;                                        \
437         mutex_lock(&stat_mutex);                        \
438         if (stat == NS_ON) {                            \
439                 ret = -EBUSY;                           \
440                 goto unlock;                            \
441         }                                               \
442         ret = do_func(F_ARG(n, M_ARG,  __VA_ARGS__));   \
443 unlock:                                                 \
444         mutex_unlock(&stat_mutex);                      \
445         return ret;                                     \
446 }
447
448 #define DECLARE_SAFE_FUNC0(name, _do)           DECLARE_SAFE_FUNC(1, name, _do, void, /* */);
449 #define DECLARE_SAFE_FUNC1(name, _do, ...)      DECLARE_SAFE_FUNC(1, name, _do, __VA_ARGS__);
450 #define DECLARE_SAFE_FUNC2(name, _do, ...)      DECLARE_SAFE_FUNC(2, name, _do, __VA_ARGS__);
451 #define DECLARE_SAFE_FUNC3(name, _do, ...)      DECLARE_SAFE_FUNC(3, name, _do, __VA_ARGS__);
452
453
454 static DEFINE_MUTEX(stat_mutex);
455 static enum nsp_stat stat = NS_OFF;
456
457 DECLARE_SAFE_FUNC2(nsp_add, __nsp_add, const char *, app_path,
458                    unsigned long, main_addr);
459 DECLARE_SAFE_FUNC1(nsp_rm, __nsp_rm, const char *, app_path);
460 DECLARE_SAFE_FUNC0(nsp_rm_all, __nsp_rm_all);
461 DECLARE_SAFE_FUNC3(nsp_set_lpad_info, do_set_lpad_info,
462                    const char *, path, unsigned long, dlopen,
463                    unsigned long, dlsym);
464 DECLARE_SAFE_FUNC1(nsp_set_appcore_info, do_set_appcore_info,
465                    struct appcore_info_data *, info);
466
467
468
469
470
471 /* ============================================================================
472  * =                               set stat                                   =
473  * ============================================================================
474  */
475 static int set_stat_off(void)
476 {
477         if (stat == NS_OFF)
478                 return -EINVAL;
479
480         __nsp_disabel();
481         tdata_disable();
482
483         stat = NS_OFF;
484
485         return 0;
486 }
487
488 static int set_stat_on(void)
489 {
490         int ret;
491
492         if (is_init() == false)
493                 return -EPERM;
494
495         if (stat == NS_ON)
496                 return -EINVAL;
497
498         ret = tdata_enable();
499         if (ret)
500                 return ret;
501
502         __nsp_enable();
503
504         stat = NS_ON;
505
506         return 0;
507 }
508
509 int nsp_set_stat(enum nsp_stat st)
510 {
511         int ret = -EINVAL;
512
513         mutex_lock(&stat_mutex);
514         switch (st) {
515         case NS_OFF:
516                 ret = set_stat_off();
517                 break;
518         case NS_ON:
519                 ret = set_stat_on();
520                 break;
521         }
522         mutex_unlock(&stat_mutex);
523
524         return ret;
525 }
526
527 enum nsp_stat nsp_get_stat(void)
528 {
529         return stat;
530 }
531
532
533
534
535
536 /* ============================================================================
537  * =                                handlers                                  =
538  * ============================================================================
539  */
540 static int dlopen_eh(struct uretprobe_instance *ri, struct pt_regs *regs)
541 {
542         const char __user *user_s = (const char __user *)swap_get_uarg(regs, 0);
543         const char *path;
544         struct nsp_data *nsp_data;
545
546         path = strdup_from_user(user_s, GFP_ATOMIC);
547         if (path == NULL)
548                 return 0;
549
550         nsp_data = nsp_data_find_by_path(path);
551         if (nsp_data) {
552                 struct task_struct *task = current;
553                 struct tdata *tdata;
554
555                 tdata = tdata_get(task);
556                 if (tdata) {
557                         nsp_print("ERROR: dlopen already cal for '%s'\n", path);
558                         tdata_put(tdata);
559                         goto free_path;
560                 }
561
562                 tdata = tdata_create(task);
563                 if (tdata) {
564                         tdata->stat = NPS_OPEN_E;
565                         tdata->time = swap_msg_current_time();
566                         tdata->nsp_data = nsp_data;
567                         tdata_put(tdata);
568                 } else {
569                         nsp_print("ERROR: out of memory\n");
570                 }
571         }
572
573 free_path:
574         kfree(path);
575         return 0;
576 }
577
578 static int dlopen_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
579 {
580         struct tdata *tdata;
581
582         tdata = tdata_get(current);
583         if (tdata) {
584                 void *handle;
585
586                 handle = (void *)regs_return_value(regs);
587                 if ((tdata->stat == NPS_OPEN_E) && handle) {
588                         tdata->stat = NPS_OPEN_R;
589                         tdata->handle = handle;
590                         tdata_put(tdata);
591                 } else {
592                         tdata_destroy(tdata);
593                 }
594         }
595
596         return 0;
597 }
598
599 static int dlsym_eh(struct uretprobe_instance *ri, struct pt_regs *regs)
600 {
601         struct tdata *tdata;
602
603         tdata = tdata_get(current);
604         if (tdata) {
605                 const char __user *str = (char __user *)swap_get_uarg(regs, 1);
606                 const char *name;
607                 void *handle;
608
609                 handle = (void *)swap_get_uarg(regs, 0);
610                 if (handle == tdata->handle && tdata->stat == NPS_OPEN_R) {
611                         name = strdup_from_user(str, GFP_ATOMIC);
612                         if (name && (strcmp(name, "main") == 0))
613                                 tdata->stat = NPS_SYM_E;
614
615                         kfree(name);
616                 }
617
618                 tdata_put(tdata);
619         }
620
621         return 0;
622 }
623
624 static int dlsym_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
625 {
626         struct tdata *tdata;
627
628         tdata = tdata_get(current);
629         if (tdata) {
630                 if (tdata->stat == NPS_SYM_E)
631                         tdata->stat = NPS_SYM_R;
632                 tdata_put(tdata);
633         }
634
635         return 0;
636 }
637
638 static void stage_begin(enum nsp_proc_stat priv, enum nsp_proc_stat cur)
639 {
640         struct tdata *tdata;
641
642         tdata = tdata_get(current);
643         if (tdata) {
644                 if (tdata->stat == priv) {
645                         tdata->stat = cur;
646                         tdata->time = swap_msg_current_time();
647                 }
648
649                 tdata_put(tdata);
650         }
651 }
652
653 static void stage_end(enum nsp_proc_stat priv, enum nsp_proc_stat cur,
654                       enum nsp_msg_stage st)
655 {
656         struct tdata *tdata;
657         u64 time_start;
658         u64 time_end;
659
660         tdata = tdata_get(current);
661         if (tdata) {
662                 if (tdata->stat != priv) {
663                         tdata_put(tdata);
664                         return;
665                 }
666
667                 tdata->stat = cur;
668                 time_start = tdata->time;
669                 tdata_put(tdata);
670
671                 time_end = swap_msg_current_time();
672                 nsp_msg(st, time_start, time_end);
673         }
674 }
675
676 static int main_h(struct kprobe *p, struct pt_regs *regs)
677 {
678         struct tdata *tdata;
679         u64 time_start;
680         u64 time_end;
681
682         tdata = tdata_get(current);
683         if (tdata) {
684                 if (tdata->stat != NPS_SYM_R) {
685                         tdata_put(tdata);
686                         return 0;
687                 }
688
689                 tdata->stat = NPS_MAIN_E;
690                 time_start = tdata->time;
691                 time_end = swap_msg_current_time();
692                 tdata->time = time_end;
693
694                 tdata_put(tdata);
695
696                 nsp_msg(NMS_MAPPING, time_start, time_end);
697         }
698
699         return 0;
700 }
701
702 /* FIXME: workaround for simultaneously nsp and main() function profiling */
703 #include <retprobe/rp_msg.h>
704 #include <us_manager/us_manager.h>
705
706 static int main_eh(struct uretprobe_instance *ri, struct pt_regs *regs)
707 {
708         struct uretprobe *rp = ri->rp;
709
710         if (rp) {
711                 main_h(&rp->up.kp, regs);
712
713                 if (get_quiet() == QT_OFF) {
714                         struct us_ip *ip;
715                         unsigned long func_addr;
716
717                         ip = container_of(rp, struct us_ip, retprobe);
718                         func_addr = (unsigned long)ip->orig_addr;
719                         rp_msg_entry(regs, func_addr, "p");
720                 }
721         }
722
723         return 0;
724 }
725
726 static int main_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
727 {
728         struct uretprobe *rp = ri->rp;
729
730         if (rp && get_quiet() == QT_OFF) {
731                 struct us_ip *ip;
732                 char ret_type;
733                 unsigned long func_addr;
734                 unsigned long ret_addr;
735
736                 ip = container_of(rp, struct us_ip, retprobe);
737                 func_addr = (unsigned long)ip->orig_addr;
738                 ret_addr = (unsigned long)ri->ret_addr;
739                 ret_type = ip->info->rp_i.ret_type;
740                 rp_msg_exit(regs, func_addr, 'n', ret_addr);
741         }
742
743         return 0;
744 }
745
746 static int ac_efl_main_h(struct kprobe *p, struct pt_regs *regs)
747 {
748         stage_end(NPS_MAIN_E, NPS_AC_EFL_MAIN_E, NMS_MAIN);
749         return 0;
750 }
751
752 static int ac_init_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
753 {
754         stage_begin(NPS_AC_EFL_MAIN_E, NPS_AC_INIT_R);
755         return 0;
756 }
757
758 static int elm_run_h(struct kprobe *p, struct pt_regs *regs)
759 {
760         stage_end(NPS_AC_INIT_R, NPS_ELM_RUN_E, NMS_CREATE);
761         return 0;
762 }
763
764 static int do_app_eh(struct uretprobe_instance *ri, struct pt_regs *regs)
765 {
766         int event = swap_get_uarg(regs, 0);
767         enum { AE_RESET = 5 };  /* FIXME: hardcode */
768
769         if (event == AE_RESET)
770                 stage_begin(NPS_ELM_RUN_E, NPS_DO_APP_E);
771
772         return 0;
773 }
774
775 static int do_app_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
776 {
777         stage_end(NPS_DO_APP_E, NPS_DO_APP_R, NMS_RESET);
778         return 0;
779 }
780
781
782
783
784
785 int nsp_init(void)
786 {
787         return 0;
788 }
789
790 void nsp_exit(void)
791 {
792         if (stat == NS_ON)
793                 set_stat_off();
794
795         uninit_variables();
796 }