a87cddfb6640c24387f62feb53f652819f62fc0a
[kernel/swap-modules.git] / writer / swap_writer_module.c
1 /*
2  *  SWAP Writer
3  *  modules/writer/swap_writer_module.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  Alexander Aksenov <a.aksenov@samsung.com>, Vyacheslav Cherkashin: 
22  *                  SWAP Writer module implement
23  *
24  */
25
26 #include <linux/types.h>
27 #include <linux/ctype.h>
28 #include <linux/errno.h>
29 #include <linux/sched.h>
30 #include <linux/dcache.h>
31 #include <linux/mm.h>
32 #include <linux/mm_types.h>
33 #include <linux/fs.h>
34 #include <linux/err.h>
35 #include <linux/module.h>
36 #include <linux/slab.h>
37 #include <asm/uaccess.h>
38 #include <kprobe/arch/asm/swap_kprobes.h>
39 #include <uprobe/arch/asm/swap_uprobes.h>
40
41 #include <buffer/swap_buffer_module.h>
42 #include <buffer/swap_buffer_errors.h>
43
44 #include "swap_writer_module.h"
45 #include "swap_writer_errors.h"
46 #include "kernel_operations.h"
47 #include "debugfs_writer.h"
48 #include "event_filter.h"
49
50
51 enum MSG_ID {
52         MSG_PROC_INFO                   = 0x0001,
53         MSG_TERMINATE                   = 0x0002,
54         MSG_ERROR                       = 0x0003,
55         MSG_SAMPLE                      = 0x0004,
56         MSG_FUNCTION_ENTRY              = 0x0008,
57         MSG_FUNCTION_EXIT               = 0x0009,
58         MSG_CONTEXT_SWITCH_ENTRY        = 0x0010,
59         MSG_CONTEXT_SWITCH_EXIT         = 0x0011,
60         MSG_PROC_MAP                    = 0x0012,
61         MSG_PROC_UNMAP                  = 0x0013,
62         MSG_PROC_COMM                   = 0x0014
63 };
64
65 static char *cpu_buf[NR_CPUS];
66 static u32 seq_num = 0;
67 static unsigned int discarded = 0;
68
69 int init_msg(size_t buf_size)
70 {
71         int i;
72
73         for (i = 0; i < NR_CPUS; ++i)
74                 cpu_buf[i] = kmalloc(buf_size, GFP_KERNEL);
75
76         return E_SW_SUCCESS;
77 }
78 EXPORT_SYMBOL_GPL(init_msg);
79
80 void uninit_msg(void)
81 {
82         int i;
83
84         for (i = 0; i < NR_CPUS; ++i)
85                 kfree(cpu_buf[i]);
86 }
87 EXPORT_SYMBOL_GPL(uninit_msg);
88
89 void reset_discarded(void)
90 {
91         discarded = 0;
92 }
93 EXPORT_SYMBOL_GPL(reset_discarded);
94
95 void reset_seq_num(void)
96 {
97         seq_num = 0;
98 }
99 EXPORT_SYMBOL_GPL(reset_seq_num);
100
101 unsigned int get_discarded_count(void)
102 {
103         return discarded;
104 }
105 EXPORT_SYMBOL_GPL(get_discarded_count);
106
107 static inline char *get_current_buf(void)
108 {
109         return cpu_buf[get_cpu()];
110 }
111
112 static inline void put_current_buf(void)
113 {
114         put_cpu();
115 }
116
117 static inline u64 timespec2time(struct timespec *ts)
118 {
119         return ((u64)ts->tv_nsec) << 32 | ts->tv_sec;
120 }
121
122 /* ============================================================================
123  * =                         BASIC MESSAGE FORMAT                             =
124  * ============================================================================
125  */
126
127 struct basic_msg_fmt {
128         u32 msg_id;
129         u32 seq_number;
130         u64 time;
131         u32 len;
132         char payload[0];
133 } __attribute__((packed));
134
135 #if 0 /* debug */
136 static void print_hex(char *ptr, int len)
137 {
138         int i;
139
140         printk("print_hex:\n");
141         for (i = 0; i < len; ++i) {
142                 printk("[%x]  [%3d]=%2x\n", &ptr[i], i, ptr[i]);
143         }
144 }
145 #endif
146
147 static int write_to_buffer(void *data)
148 {
149         int result;
150         struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)data;
151
152         result = swap_buffer_write(bmf, bmf->len + sizeof(*bmf));
153         if (result < 0) {
154                 discarded++;
155         }
156
157         return result;
158 }
159
160 static void set_len_msg(char *buf, char *end)
161 {
162         struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf;
163         bmf->len = end - buf - sizeof(*bmf);
164 }
165
166 static inline void set_seq_num(struct basic_msg_fmt *bmf)
167 {
168         bmf->seq_number = seq_num;
169         seq_num++;
170 }
171
172 static inline void set_time(struct basic_msg_fmt *bmf)
173 {
174         struct timespec ts;
175
176         getnstimeofday(&ts);
177         bmf->time = timespec2time(&ts);
178 }
179
180 static char* pack_basic_msg_fmt(char *buf, enum MSG_ID id)
181 {
182         struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf;
183
184         set_time(bmf);
185         set_seq_num(bmf);
186         bmf->msg_id = id;
187
188         return bmf->payload;
189 }
190
191
192
193
194
195 /* ============================================================================
196  * =                             PROCESS INFO                                 =
197  * ============================================================================
198  */
199
200 struct proc_info_top {
201         u32 pid;
202         char comm[0];
203 } __attribute__((packed));
204
205 struct proc_info_bottom {
206         u32 ppid;
207         u32 start_sec;
208         u32 start_nsec;
209         u64 low_addr;
210         u64 high_addr;
211         char bin_path[0];
212 } __attribute__((packed));
213
214 struct proc_info_part {
215         u32 lib_cnt;
216         char libs[0];
217 } __attribute__((packed));
218
219 struct lib_obj {
220         u64 low_addr;
221         u64 high_addr;
222         char lib_path[0];
223 } __attribute__((packed));
224
225 static char *pack_path(char *buf, struct file *file)
226 {
227         enum { TMP_BUF_LEN = 512 };
228         char tmp_buf[TMP_BUF_LEN];
229         char NA[] = "N/A";
230         char *filename;
231         size_t len;
232
233         if (file == NULL)
234                 return strcpy(buf, NA) + sizeof(NA);
235
236         filename = d_path(&file->f_path, tmp_buf, TMP_BUF_LEN);
237         if (IS_ERR_OR_NULL(filename))
238                 return strcpy(buf, NA) + sizeof(NA);
239
240         len = strlen(filename) + 1;
241         memcpy(buf, filename, len);
242
243         return buf + len;
244 }
245
246 static char *pack_lib_obj(char *lib_obj, struct vm_area_struct *vma)
247 {
248         struct lib_obj *lo = (struct lib_obj *)lib_obj;
249
250         lo->low_addr = vma->vm_start;
251         lo->high_addr = vma->vm_end;
252
253         return pack_path(lo->lib_path, vma->vm_file);
254 }
255
256 /* FIXME: check_vma()*/
257 static int check_vma(struct vm_area_struct *vma)
258 {
259         return vma->vm_file &&
260                !(vma->vm_pgoff != 0 ||
261                  !(vma->vm_flags & VM_EXEC) ||
262                  !(vma->vm_flags & (VM_READ | VM_MAYREAD)));
263 }
264
265 static struct vm_area_struct *find_vma_exe_by_dentry(struct mm_struct *mm, struct dentry *dentry)
266 {
267         struct vm_area_struct *vma;
268
269         for (vma = mm->mmap; vma; vma = vma->vm_next) {
270                 if (vma->vm_file && (vma->vm_flags & VM_EXEC) &&
271                    (vma->vm_file->f_dentry == dentry))
272                         goto out;
273         }
274
275         vma = NULL;
276 out:
277
278         return vma;
279 }
280
281 static char *pack_shared_kmem(char *lib_obj, struct mm_struct *mm,
282                               u32 *lib_cnt_p)
283 {
284         struct lib_obj *so = (struct lib_obj *)lib_obj;
285         char *so_obj;
286         unsigned long start = 0, end = 0;
287
288         const char *kmem_name = get_shared_kmem(mm, &start, &end);
289         size_t name_len;
290
291         if (kmem_name == NULL)
292                 return lib_obj;
293
294         name_len = strlen(kmem_name) + 1;
295         so->low_addr = (u64)start;
296         so->high_addr = (u64)end;
297         memcpy(so->lib_path, kmem_name, name_len);
298         (*lib_cnt_p)++;
299         so_obj = so->lib_path + name_len;
300
301         return so_obj;
302 }
303
304 static char *pack_libs(char *lib_obj, struct mm_struct *mm, u32 *lib_cnt_p)
305 {
306         struct vm_area_struct *vma;
307
308         for (vma = mm->mmap; vma; vma = vma->vm_next) {
309                 if (check_vma(vma)) {
310                         lib_obj = pack_lib_obj(lib_obj, vma);
311                         ++(*lib_cnt_p);
312                 }
313         }
314
315         return lib_obj;
316 }
317
318 static char *pack_proc_info_part(char *end_path, struct mm_struct *mm)
319 {
320         struct proc_info_part *pip;
321         char *lib_obj;
322         u32 *lib_cnt_p;
323
324         pip = (struct proc_info_part *)end_path;
325         pip->lib_cnt = 0;
326         lib_obj = pip->libs;
327         lib_cnt_p = &pip->lib_cnt;
328
329         lib_obj = pack_libs(lib_obj, mm, lib_cnt_p);
330         lib_obj = pack_shared_kmem(lib_obj, mm, lib_cnt_p);
331
332         return lib_obj;
333 }
334
335 static char *pack_comm(char *buf, struct task_struct *task)
336 {
337         get_task_comm(buf, task);
338
339         return buf + strlen(buf) + 1;
340 }
341
342 static char *pack_proc_info_top(char *data, struct task_struct *task)
343 {
344         struct proc_info_top *pit = (struct proc_info_top *)data;
345
346         pit->pid = task->tgid;
347
348         return pack_comm(pit->comm, task);
349 }
350
351 static char *pack_proc_info_bottom(char *data, struct task_struct *task,
352                                    struct dentry *dentry)
353 {
354         struct proc_info_bottom *pib = (struct proc_info_bottom *)data;
355         struct vm_area_struct *vma = find_vma_exe_by_dentry(task->mm, dentry);
356         struct timespec boot_time;
357         struct timespec start_time;
358         char *end_path = NULL;
359
360         getboottime(&boot_time);
361         start_time = timespec_add(boot_time, task->real_start_time);
362
363         pib->ppid = task->real_parent->tgid;
364         pib->start_sec = (u32)start_time.tv_sec;
365         pib->start_nsec = (u32)start_time.tv_nsec;
366
367         if (vma) {
368                 pib->low_addr = vma->vm_start;
369                 pib->high_addr = vma->vm_end;
370                 end_path = pack_path(pib->bin_path, vma->vm_file);
371         } else {
372                 pib->low_addr = 0;
373                 pib->high_addr = 0;
374                 end_path = pack_path(pib->bin_path, NULL);
375         }
376         return pack_proc_info_part(end_path, task->mm);
377 }
378
379 static char *pack_proc_info(char *payload, struct task_struct *task,
380                             struct dentry *dentry)
381 {
382         payload = pack_proc_info_top(payload, task);
383         return pack_proc_info_bottom(payload, task, dentry);
384 }
385
386 /* called with down\up\_read(&task->mm->mmap_sem) */
387 int proc_info_msg(struct task_struct *task, struct dentry *dentry)
388 {
389         char *buf, *payload, *buf_end;
390         int ret;
391
392         buf = get_current_buf();
393         payload = pack_basic_msg_fmt(buf, MSG_PROC_INFO);
394         buf_end = pack_proc_info(payload, task, dentry);
395
396         set_len_msg(buf, buf_end);
397
398         ret = write_to_buffer(buf);
399         put_current_buf();
400
401         return ret;
402 }
403 EXPORT_SYMBOL_GPL(proc_info_msg);
404
405
406
407
408
409 /* ============================================================================
410  * =                           PROCESS TERMINATE                              =
411  * ============================================================================
412  */
413
414 struct proc_terminate {
415         u32 pid;
416 } __attribute__((packed));
417
418 static char *pack_proc_terminate(char *payload, struct task_struct *task)
419 {
420         struct proc_terminate *pt = (struct proc_terminate *)payload;
421
422         pt->pid = task->pid;
423         return payload + sizeof(*pt);
424 }
425
426 void terminate_msg(struct task_struct *task)
427 {
428         char *buf, *payload, *buf_end;
429
430         buf = get_current_buf();
431         payload = pack_basic_msg_fmt(buf, MSG_TERMINATE);
432         buf_end = pack_proc_terminate(payload, task);
433
434         set_len_msg(buf, buf_end);
435
436         write_to_buffer(buf);
437         put_current_buf();
438 }
439 EXPORT_SYMBOL_GPL(terminate_msg);
440
441
442
443
444
445 /* ============================================================================
446  * =                             PROCESS MAP                                  =
447  * ============================================================================
448  */
449 struct proc_map {
450         u32 pid;
451         u64 low_addr;
452         u64 high_addr;
453         char bin_path[0];
454 } __attribute__((packed));
455
456 static char *pack_proc_map(char *payload, struct vm_area_struct *vma)
457 {
458         struct proc_map *pm = (struct proc_map *)payload;
459
460         pm->pid = current->tgid;
461         pm->low_addr = vma->vm_start;
462         pm->high_addr = vma->vm_end;
463
464         return pack_path(pm->bin_path, vma->vm_file);
465 }
466
467 void pcoc_map_msg(struct vm_area_struct *vma)
468 {
469         char *buf, *payload, *buf_end;
470
471         buf = get_current_buf();
472         payload = pack_basic_msg_fmt(buf, MSG_PROC_MAP);
473         buf_end = pack_proc_map(payload, vma);
474
475         set_len_msg(buf, buf_end);
476
477         write_to_buffer(buf);
478         put_current_buf();
479 }
480 EXPORT_SYMBOL_GPL(pcoc_map_msg);
481
482
483
484
485
486 /* ============================================================================
487  * =                            PROCESS UNMAP                                 =
488  * ============================================================================
489  */
490 struct proc_unmap {
491         u32 pid;
492         u64 low_addr;
493         u64 high_addr;
494 } __attribute__((packed));
495
496 static char *pack_proc_unmap(char *payload, unsigned long start,
497                              unsigned long end)
498 {
499         struct proc_unmap *pum = (struct proc_unmap *)payload;
500
501         pum->pid = current->tgid;
502         pum->low_addr = start;
503         pum->high_addr = end;
504
505         return payload + sizeof(*pum);
506 }
507
508 void proc_unmap_msg(unsigned long start, unsigned long end)
509 {
510         char *buf, *payload, *buf_end;
511
512         buf = get_current_buf();
513         payload = pack_basic_msg_fmt(buf, MSG_PROC_UNMAP);
514         buf_end = pack_proc_unmap(payload, start, end);
515
516         set_len_msg(buf, buf_end);
517
518         write_to_buffer(buf);
519         put_current_buf();
520 }
521 EXPORT_SYMBOL_GPL(proc_unmap_msg);
522
523
524
525
526
527 /* ============================================================================
528  * =                              PROCESS COMM                                =
529  * ============================================================================
530  */
531 struct proc_comm {
532         u32 pid;
533         char comm[0];
534 } __attribute__((packed));
535
536 static char *pack_proc_comm(char *data, struct task_struct *task)
537 {
538         struct proc_comm *pcomm= (struct proc_comm *)data;
539
540         pcomm->pid = task->tgid;
541
542         return pack_comm(pcomm->comm, task);
543 }
544
545 void proc_comm_msg(struct task_struct *task)
546 {
547         char *buf, *payload, *buf_end;
548
549         buf = get_current_buf();
550         payload = pack_basic_msg_fmt(buf, MSG_PROC_COMM);
551         buf_end = pack_proc_comm(payload, task);
552
553         set_len_msg(buf, buf_end);
554
555         write_to_buffer(buf);
556         put_current_buf();
557 }
558 EXPORT_SYMBOL_GPL(proc_comm_msg);
559
560
561
562
563
564 /* ============================================================================
565  * =                                 SAMPLE                                   =
566  * ============================================================================
567  */
568
569 struct sample {
570         u32 pid;
571         u64 pc_addr;
572         u32 tid;
573         u32 cpu_num;
574 } __attribute__((packed));
575
576 static char *pack_sample(char *payload, struct pt_regs *regs)
577 {
578         struct sample *s = (struct sample *)payload;
579         struct task_struct *task = current;
580
581         s->pid = task->tgid;
582         s->pc_addr = get_regs_ip(regs);
583         s->tid = task->pid;
584         s->cpu_num = smp_processor_id();
585
586         return payload + sizeof(*s);
587 }
588
589 int sample_msg(struct pt_regs *regs)
590 {
591         char *buf, *payload, *buf_end;
592         int ret;
593
594         if (!check_event(current))
595                 return 0;
596
597         buf = get_current_buf();
598         payload = pack_basic_msg_fmt(buf, MSG_SAMPLE);
599         buf_end = pack_sample(payload, regs);
600
601         set_len_msg(buf, buf_end);
602
603         ret = write_to_buffer(buf);
604         put_current_buf();
605
606         return ret;
607 }
608 EXPORT_SYMBOL_GPL(sample_msg);
609
610
611
612
613 /* ============================================================================
614  * =                                 ENTRY                                    =
615  * ============================================================================
616  */
617
618 struct msg_func_entry {
619         u64 pc_addr;
620         u64 caller_pc_addr;
621         u16 probe_type;
622         u16 probe_sub_type;
623         u32 pid;
624         u32 tid;
625         u32 cpu_num;
626         u32 cnt_args;
627         char args[0];
628 } __attribute__((packed));
629
630 static char *pack_msg_func_entry(char *payload, const char *fmt,
631                                  unsigned long func_addr, struct pt_regs *regs,
632                                  enum PROBE_TYPE pt, int sub_type)
633 {
634         struct msg_func_entry *mfe = (struct msg_func_entry *)payload;
635         struct task_struct *task = current;
636
637         mfe->pid = task->tgid;
638         mfe->tid = task->pid;
639         mfe->cpu_num = smp_processor_id();
640         mfe->pc_addr = func_addr;
641         mfe->caller_pc_addr = get_regs_ret_func(regs);
642         mfe->probe_type = pt;
643         mfe->probe_sub_type = sub_type;
644         mfe->cnt_args = strlen(fmt);
645
646         return payload + sizeof(*mfe);
647 }
648
649 static unsigned long get_arg(struct pt_regs *regs, unsigned long n)
650 {
651         return user_mode(regs) ?
652                         swap_get_uarg(regs, n) :        /* US argument */
653                         swap_get_sarg(regs, n);         /* sys_call argument */
654 }
655
656 static int pack_args(char *buf, int len, const char *fmt, struct pt_regs *regs)
657 {
658         char *buf_old = buf;
659         u32 *tmp_u32;
660         u64 *tmp_u64;
661         int i,          /* the index of the argument */
662             fmt_i,      /* format index */
663             fmt_len;    /* the number of parameters, in format */
664
665         fmt_len = strlen(fmt);
666
667         for (i = 0, fmt_i = 0; fmt_i < fmt_len; ++i, ++fmt_i) {
668                 if (len < 2)
669                         return -ENOMEM;
670
671                 *buf = fmt[fmt_i];
672                 buf += 1;
673                 len -= 1;
674
675                 switch (fmt[fmt_i]) {
676                 case 'b': /* 1 byte(bool) */
677                         *buf = (char)!!get_arg(regs, i);
678                         buf += 1;
679                         len -= 1;
680                         break;
681                 case 'c': /* 1 byte(char) */
682                         *buf = (char)get_arg(regs, i);
683                         buf += 1;
684                         len -= 1;
685                         break;
686                 case 'f': /* 4 byte(float) */
687                 case 'd': /* 4 byte(int) */
688                         if (len < 4)
689                                 return -ENOMEM;
690                         tmp_u32 = (u32 *)buf;
691                         *tmp_u32 = (u32)get_arg(regs, i);
692                         buf += 4;
693                         len -= 4;
694                         break;
695                 case 'x': /* 8 byte(long) */
696                 case 'p': /* 8 byte(pointer) */
697                         if (len < 8)
698                                 return -ENOMEM;
699                         tmp_u64 = (u64 *)buf;
700                         *tmp_u64 = (u64)get_arg(regs, i);
701                         buf += 8;
702                         len -= 8;
703                         break;
704                 case 'w': /* 8 byte(double) */
705                         if (len < 8)
706                                 return -ENOMEM;
707                         tmp_u64 = (u64 *)buf;
708                         *tmp_u64 = get_arg(regs, i);
709                         ++i;
710                         *tmp_u64 |= (u64)get_arg(regs, i) << 32;
711                         buf += 8;
712                         len -= 8;
713                         break;
714                 case 's': /* string end with '\0' */
715                 {
716                         enum { max_str_len = 512 };
717                         const char __user *user_s;
718                         int len_s, ret;
719
720                         user_s = (const char __user *)get_arg(regs, i);
721                         len_s = strnlen_user(user_s, max_str_len);
722                         if (len < len_s)
723                                 return -ENOMEM;
724
725                         ret = strncpy_from_user(buf, user_s, len_s);
726                         if (ret < 0)
727                                 return -EFAULT;
728
729                         buf[ret] = '\0';
730
731                         buf += ret + 1;
732                         len -= ret + 1;
733                 }
734                         break;
735                 default:
736                         return -EINVAL;
737                 }
738         }
739
740         return buf - buf_old;
741 }
742
743 int entry_event(const char *fmt, unsigned long func_addr, struct pt_regs *regs,
744                 enum PROBE_TYPE pt, int sub_type)
745 {
746         char *buf, *payload, *args, *buf_end;
747         int ret;
748
749         if (pt == PT_KS && !check_event(current))
750                 return 0;
751
752         buf = get_current_buf();
753         payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_ENTRY);
754         args = pack_msg_func_entry(payload, fmt, func_addr,
755                                    regs, pt, sub_type);
756
757         /* FIXME: len = 1024 */
758         ret = pack_args(args, 1024, fmt, regs);
759         if (ret < 0) {
760                 printk("ERROR: !!!!!\n");
761                 return ret;
762         }
763
764         buf_end = args + ret;
765
766         set_len_msg(buf, buf_end);
767
768         ret = write_to_buffer(buf);
769         put_current_buf();
770
771         return ret;
772 }
773 EXPORT_SYMBOL_GPL(entry_event);
774
775
776
777
778
779 /* ============================================================================
780  * =                                 EXIT                                     =
781  * ============================================================================
782  */
783
784 struct msg_func_exit {
785         u32 pid;
786         u32 tid;
787         u64 pc_addr;
788         u64 caller_pc_addr;
789         u32 cpu_num;
790         char ret_val[0];
791 } __attribute__((packed));
792
793 static int pack_msg_ret_val(char *buf, int len, char ret_type,
794                               struct pt_regs *regs)
795 {
796         const char *buf_old = buf;
797         u32 *tmp_u32;
798         u64 *tmp_u64;
799
800         *buf = ret_type;
801         ++buf;
802
803         switch (ret_type) {
804         case 'b': /* 1 byte(bool) */
805                 if (len < 1)
806                         return -ENOMEM;
807                 *buf = (char)!!get_regs_ret_val(regs);
808                 ++buf;
809                 break;
810         case 'c': /* 1 byte(char) */
811                 if (len < 1)
812                         return -ENOMEM;
813                 *buf = (char)get_regs_ret_val(regs);
814                 ++buf;
815                 break;
816         case 'd': /* 4 byte(int) */
817                 if (len < 4)
818                         return -ENOMEM;
819                 tmp_u32 = (u32 *)buf;
820                 *tmp_u32 = get_regs_ret_val(regs);
821                 buf += 4;
822                 break;
823         case 'x': /* 8 byte(long) */
824         case 'p': /* 8 byte(pointer) */
825                 if (len < 8)
826                         return -ENOMEM;
827                 tmp_u64 = (u64 *)buf;
828                 *tmp_u64 = (u64)get_regs_ret_val(regs);
829                 buf += 8;
830                 break;
831         case 's': /* string end with '\0' */
832         {
833                 enum { max_str_len = 512 };
834                 const char __user *user_s;
835                 int len_s, ret;
836
837                 user_s = (const char __user *)get_regs_ret_val(regs);
838                 len_s = strnlen_user(user_s, max_str_len);
839                 if (len < len_s)
840                         return -ENOMEM;
841
842                 ret = strncpy_from_user(buf, user_s, len_s);
843                 if (ret < 0)
844                         return -EFAULT;
845
846                 buf[ret] = '\0';
847                 buf += ret + 1;
848         }
849                 break;
850         case 'n':
851         case 'v':
852                 break;
853         case 'f': /* 4 byte(float) */
854                 if (len < 4)
855                         return -ENOMEM;
856                 tmp_u32 = (u32 *)buf;
857                 *tmp_u32 = swap_get_urp_float(regs);
858                 buf += 4;
859                 break;
860         case 'w': /* 8 byte(double) */
861                 if (len < 8)
862                         return -ENOMEM;
863                 tmp_u64 = (u64 *)buf;
864                 *tmp_u64 = swap_get_urp_double(regs);
865                 buf += 8;
866                 break;
867         default:
868                 return -EINVAL;
869         }
870
871         return buf - buf_old;
872 }
873
874
875 static int pack_msg_func_exit(char *buf, int len, char ret_type,
876                               struct pt_regs *regs, unsigned long func_addr,
877                               unsigned long ret_addr)
878 {
879         struct msg_func_exit *mfe = (struct msg_func_exit *)buf;
880         struct task_struct *task = current;
881         int ret;
882
883         mfe->pid = task->tgid;
884         mfe->tid = task->pid;
885         mfe->cpu_num = smp_processor_id();
886         mfe->pc_addr = func_addr;
887         mfe->caller_pc_addr = ret_addr;
888
889         ret = pack_msg_ret_val(mfe->ret_val, len, ret_type, regs);
890         if (ret < 0) {
891                 printk("ERROR: packing MSG_FUNCTION_EXIT (ret=%d)\n", ret);
892                 return ret;
893         }
894
895         return sizeof(*mfe) + ret;
896 }
897
898 int exit_event(char ret_type, struct pt_regs *regs, unsigned long func_addr,
899                unsigned long ret_addr)
900 {
901         char *buf, *payload, *buf_end;
902         int ret;
903
904         if (!check_event(current))
905                 return 0;
906
907         buf = get_current_buf();
908         payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_EXIT);
909         /* FIXME: len=1024 */
910         ret = pack_msg_func_exit(payload, 1024, ret_type, regs,
911                                  func_addr, ret_addr);
912         if (ret < 0)
913                 return ret;
914
915         buf_end = payload + ret;
916         set_len_msg(buf, buf_end);
917
918         ret = write_to_buffer(buf);
919         put_current_buf();
920
921         return ret;
922 }
923 EXPORT_SYMBOL_GPL(exit_event);
924
925
926
927
928
929 /* ============================================================================
930  * =                            CONTEXT SWITCH                                =
931  * ============================================================================
932  */
933
934 struct msg_context_switch {
935         u64 pc_addr;
936         u32 pid;
937         u32 tid;
938         u32 cpu_num;
939 } __attribute__((packed));
940
941 static char *pack_msg_context_switch(char *payload, struct pt_regs *regs)
942 {
943         struct msg_context_switch *mcs = (struct msg_context_switch *)payload;
944         struct task_struct *task = current;
945
946         mcs->pc_addr = 0;
947         mcs->pid = task->tgid;
948         mcs->tid = task->pid;
949         mcs->cpu_num = smp_processor_id();
950
951         return payload + sizeof(*mcs);
952 }
953
954 static int context_switch(struct pt_regs *regs, enum MSG_ID id)
955 {
956         char *buf, *payload, *buf_end;
957         int ret;
958
959         buf = get_current_buf();
960         payload = pack_basic_msg_fmt(buf, id);
961         buf_end = pack_msg_context_switch(payload, regs);
962         set_len_msg(buf, buf_end);
963
964         ret = write_to_buffer(buf);
965         put_current_buf();
966
967         return ret;
968 }
969
970 int switch_entry(struct pt_regs *regs)
971 {
972         if (!check_event(current))
973                 return 0;
974
975         return context_switch(regs, MSG_CONTEXT_SWITCH_ENTRY);
976 }
977 EXPORT_SYMBOL_GPL(switch_entry);
978
979 int switch_exit(struct pt_regs *regs)
980 {
981         if (!check_event(current))
982                 return 0;
983
984         return context_switch(regs, MSG_CONTEXT_SWITCH_EXIT);
985 }
986 EXPORT_SYMBOL_GPL(switch_exit);
987
988
989
990
991 /* ============================================================================
992  * =                                 ERROR                                    =
993  * ============================================================================
994  */
995
996 struct msg_err {
997         char msg[0];
998 } __attribute__((packed));
999
1000 static char *pack_msg_err(char *payload, const char *fmt, va_list args)
1001 {
1002         struct msg_err *me = (struct msg_err *)payload;
1003         int ret;
1004
1005         ret = vsprintf(me->msg, fmt, args);
1006         if (ret < 0)
1007                 return payload;
1008
1009         return payload + sizeof(*me) + ret + 1;
1010 }
1011
1012 int error_msg(const char *fmt, ...)
1013 {
1014         char *buf, *payload, *buf_end;
1015         va_list args;
1016         int ret;
1017
1018         buf = get_current_buf();
1019         payload = pack_basic_msg_fmt(buf, MSG_ERROR);
1020
1021         va_start(args, fmt);
1022         buf_end = pack_msg_err(payload, fmt, args);
1023         va_end(args);
1024
1025         set_len_msg(buf, buf_end);
1026
1027         ret = write_to_buffer(buf);
1028         put_current_buf();
1029
1030         return ret;
1031 }
1032 EXPORT_SYMBOL_GPL(error_msg);
1033
1034
1035
1036
1037
1038 /* ============================================================================
1039  * =                         MESSAGES FROM USER SPACE                         =
1040  * ============================================================================
1041  */
1042
1043 int raw_msg(char *buf, size_t len)
1044 {
1045         struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf;
1046
1047         if (sizeof(*bmf) > len)
1048                 return -EINVAL;
1049
1050         if (bmf->len + sizeof(*bmf) != len)
1051                 return -EINVAL;
1052
1053         set_seq_num(bmf);
1054         write_to_buffer(buf);
1055
1056         return len;
1057 }
1058
1059
1060
1061 /* ============================================================================
1062  * =                              CUSTOM EVENT                                =
1063  * ============================================================================
1064  */
1065
1066 static int pack_custom_event(char *buf, int len, const char *fmt, va_list args)
1067 {
1068         enum { max_str_len = 512 };
1069         const char *p;
1070         char *buf_orig = buf;
1071
1072         for (p = fmt; *p != '\0'; p++) {
1073                 char ch = *p;
1074
1075                 if (len < 1)
1076                         return -ENOMEM;
1077
1078                 *buf = tolower(ch);
1079                 buf += 1;
1080                 len -= 1;
1081
1082                 switch (ch) {
1083                 case 'b': /* 1 byte(bool) */
1084                         if (len < 1)
1085                                 return -ENOMEM;
1086                         *buf = !!(char)va_arg(args, int);
1087                         buf += 1;
1088                         len -= 1;
1089                         break;
1090                 case 'c': /* 1 byte(char) */
1091                         if (len < 1)
1092                                 return -ENOMEM;
1093                         *buf = (char)va_arg(args, int);
1094                         buf += 1;
1095                         len -= 1;
1096                         break;
1097                 case 'f': /* 4 byte(float) */
1098                 case 'd': /* 4 byte(int) */
1099                         if (len < 4)
1100                                 return -ENOMEM;
1101                         *(u32 *)buf = va_arg(args, u32);
1102                         buf += 4;
1103                         len -= 4;
1104                         break;
1105                 case 'x': /* 8 byte(long) */
1106                 case 'w': /* 8 byte(double) */
1107                         if (len < 8)
1108                                 return -ENOMEM;
1109                         *(u64 *)buf = va_arg(args, u64);
1110                         buf += 8;
1111                         len -= 8;
1112                         break;
1113                 case 'p': /* 8 byte(pointer) */
1114                         if (len < 8)
1115                                 return -ENOMEM;
1116                         *(u64 *)buf = va_arg(args, unsigned long);
1117                         buf += 8;
1118                         len -= 8;
1119                         break;
1120                 case 's': /* userspace string with '\0' terminating byte */
1121                 {
1122                         const char __user *str;
1123                         int len_s, n;
1124
1125                         str = va_arg(args, const char __user *);
1126                         /* strnlen_user includes '\0' in its return value */
1127                         len_s = strnlen_user(str, max_str_len);
1128                         if (len < len_s)
1129                                 return -ENOMEM;
1130                         /* strncpy_from_user returns the length of the copied
1131                          * string (without '\0') */
1132                         n = strncpy_from_user(buf, str, len_s - 1);
1133                         if (n < 0)
1134                                 return n;
1135                         buf[n] = '\0';
1136
1137                         buf += n + 1;
1138                         len -= n + 1;
1139                         break;
1140                 }
1141                 case 'S': /* kernelspace string with '\0' terminating byte */
1142                 {
1143                         const char *str;
1144                         int len_s;
1145
1146                         str = va_arg(args, const char *);
1147                         len_s = strnlen(str, max_str_len);
1148                         if (len < len_s + 1) /* + '\0' */
1149                                 return -ENOMEM;
1150                         strncpy(buf, str, len_s);
1151                         buf[len_s] = '\0';
1152
1153                         buf += len_s + 1;
1154                         len -= len_s + 1;
1155                         break;
1156                 }
1157                 case 'a': /* userspace byte array (len + ptr) */
1158                 {
1159                         const void __user *ptr;
1160                         u32 len_p, n;
1161
1162                         len_p = va_arg(args, u32);
1163                         if (len < sizeof(len_p) + len_p)
1164                                 return -ENOMEM;
1165                         *(u32 *)buf = len_p;
1166                         buf += sizeof(len_p);
1167                         len -= sizeof(len_p);
1168
1169                         ptr = va_arg(args, const void __user *);
1170                         n = copy_from_user(buf, ptr, len_p);
1171                         if (n < len_p)
1172                                 return -EFAULT;
1173                         buf += len_p;
1174                         len -= len_p;
1175                         break;
1176                 }
1177                 case 'A': /* kernelspace byte array (len + ptr) */
1178                 {
1179                         const void *ptr;
1180                         u32 len_p;
1181
1182                         /* array size */
1183                         len_p = va_arg(args, u32);
1184                         if (len < sizeof(len_p) + len_p)
1185                                 return -ENOMEM;
1186                         *(u32 *)buf = len_p;
1187                         buf += sizeof(len_p);
1188                         len -= sizeof(len_p);
1189
1190                         /* byte array */
1191                         ptr = va_arg(args, const void *);
1192                         memcpy(buf, ptr, len_p);
1193                         buf += len_p;
1194                         len -= len_p;
1195                         break;
1196                 }
1197                 default:
1198                         return -EINVAL;
1199                 }
1200         }
1201
1202         return buf - buf_orig;
1203 }
1204
1205 enum { max_custom_event_size = 2048 };
1206
1207 int custom_entry_event(unsigned long func_addr, struct pt_regs *regs,
1208                        int type, int sub_type, const char *fmt, ...)
1209 {
1210         char *buf, *payload, *args, *buf_end;
1211         va_list vargs;
1212         int ret;
1213
1214         buf = get_current_buf();
1215         payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_ENTRY);
1216         args = pack_msg_func_entry(payload, fmt, func_addr,
1217                                    regs, type, sub_type);
1218
1219         va_start(vargs, fmt);
1220         ret = pack_custom_event(args, max_custom_event_size, fmt, vargs);
1221         va_end(vargs);
1222
1223         if (ret < 0)
1224                 goto put_buf;
1225
1226         buf_end = args + ret;
1227         set_len_msg(buf, buf_end);
1228         ret = write_to_buffer(buf);
1229
1230 put_buf:
1231         put_current_buf();
1232
1233         return ret;
1234 }
1235 EXPORT_SYMBOL_GPL(custom_entry_event);
1236
1237 /* TODO currently this function is a simple wrapper. it will be refactored when
1238  * protocol changes are applied */
1239 int custom_exit_event(unsigned long func_addr, unsigned long ret_addr,
1240                       struct pt_regs *regs, const char *fmt, ...)
1241 {
1242         char *buf, *payload, *buf_end;
1243         int ret;
1244
1245         buf = get_current_buf();
1246         payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_EXIT);
1247         ret = pack_msg_func_exit(payload, max_custom_event_size,
1248                                  fmt[0], regs, func_addr, ret_addr);
1249         if (ret < 0)
1250                 goto put_buf;
1251
1252         buf_end = payload + ret;
1253         set_len_msg(buf, buf_end);
1254
1255         ret = write_to_buffer(buf);
1256
1257 put_buf:
1258         put_current_buf();
1259
1260         return ret;
1261 }
1262 EXPORT_SYMBOL_GPL(custom_exit_event);
1263
1264 static int __init swap_writer_module_init(void)
1265 {
1266         int ret;
1267
1268         ret = event_filter_init();
1269         if (ret)
1270                 return ret;
1271
1272         ret = init_debugfs_writer();
1273         if (ret)
1274                 event_filter_exit();
1275
1276         return ret;
1277 }
1278
1279 static void __exit swap_writer_module_exit(void)
1280 {
1281         exit_debugfs_writer();
1282         event_filter_exit();
1283 }
1284
1285 module_init(swap_writer_module_init);
1286 module_exit(swap_writer_module_exit);
1287
1288 MODULE_LICENSE("GPL");
1289 MODULE_DESCRIPTION("SWAP Writer module");
1290 MODULE_AUTHOR("Cherkashin V., Aksenov A.S.");