[FIX] buffer put in case of erroneous args packing (entry/exit)
[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                 goto put_buf;
762         }
763
764         buf_end = args + ret;
765
766         set_len_msg(buf, buf_end);
767
768         ret = write_to_buffer(buf);
769
770 put_buf:
771         put_current_buf();
772
773         return ret;
774 }
775 EXPORT_SYMBOL_GPL(entry_event);
776
777
778
779
780
781 /* ============================================================================
782  * =                                 EXIT                                     =
783  * ============================================================================
784  */
785
786 struct msg_func_exit {
787         u32 pid;
788         u32 tid;
789         u64 pc_addr;
790         u64 caller_pc_addr;
791         u32 cpu_num;
792         char ret_val[0];
793 } __attribute__((packed));
794
795 static int pack_msg_ret_val(char *buf, int len, char ret_type,
796                               struct pt_regs *regs)
797 {
798         const char *buf_old = buf;
799         u32 *tmp_u32;
800         u64 *tmp_u64;
801
802         *buf = ret_type;
803         ++buf;
804
805         switch (ret_type) {
806         case 'b': /* 1 byte(bool) */
807                 if (len < 1)
808                         return -ENOMEM;
809                 *buf = (char)!!get_regs_ret_val(regs);
810                 ++buf;
811                 break;
812         case 'c': /* 1 byte(char) */
813                 if (len < 1)
814                         return -ENOMEM;
815                 *buf = (char)get_regs_ret_val(regs);
816                 ++buf;
817                 break;
818         case 'd': /* 4 byte(int) */
819                 if (len < 4)
820                         return -ENOMEM;
821                 tmp_u32 = (u32 *)buf;
822                 *tmp_u32 = get_regs_ret_val(regs);
823                 buf += 4;
824                 break;
825         case 'x': /* 8 byte(long) */
826         case 'p': /* 8 byte(pointer) */
827                 if (len < 8)
828                         return -ENOMEM;
829                 tmp_u64 = (u64 *)buf;
830                 *tmp_u64 = (u64)get_regs_ret_val(regs);
831                 buf += 8;
832                 break;
833         case 's': /* string end with '\0' */
834         {
835                 enum { max_str_len = 512 };
836                 const char __user *user_s;
837                 int len_s, ret;
838
839                 user_s = (const char __user *)get_regs_ret_val(regs);
840                 len_s = strnlen_user(user_s, max_str_len);
841                 if (len < len_s)
842                         return -ENOMEM;
843
844                 ret = strncpy_from_user(buf, user_s, len_s);
845                 if (ret < 0)
846                         return -EFAULT;
847
848                 buf[ret] = '\0';
849                 buf += ret + 1;
850         }
851                 break;
852         case 'n':
853         case 'v':
854                 break;
855         case 'f': /* 4 byte(float) */
856                 if (len < 4)
857                         return -ENOMEM;
858                 tmp_u32 = (u32 *)buf;
859                 *tmp_u32 = swap_get_urp_float(regs);
860                 buf += 4;
861                 break;
862         case 'w': /* 8 byte(double) */
863                 if (len < 8)
864                         return -ENOMEM;
865                 tmp_u64 = (u64 *)buf;
866                 *tmp_u64 = swap_get_urp_double(regs);
867                 buf += 8;
868                 break;
869         default:
870                 return -EINVAL;
871         }
872
873         return buf - buf_old;
874 }
875
876
877 static int pack_msg_func_exit(char *buf, int len, char ret_type,
878                               struct pt_regs *regs, unsigned long func_addr,
879                               unsigned long ret_addr)
880 {
881         struct msg_func_exit *mfe = (struct msg_func_exit *)buf;
882         struct task_struct *task = current;
883         int ret;
884
885         mfe->pid = task->tgid;
886         mfe->tid = task->pid;
887         mfe->cpu_num = smp_processor_id();
888         mfe->pc_addr = func_addr;
889         mfe->caller_pc_addr = ret_addr;
890
891         ret = pack_msg_ret_val(mfe->ret_val, len, ret_type, regs);
892         if (ret < 0) {
893                 printk("ERROR: packing MSG_FUNCTION_EXIT (ret=%d)\n", ret);
894                 return ret;
895         }
896
897         return sizeof(*mfe) + ret;
898 }
899
900 int exit_event(char ret_type, struct pt_regs *regs, unsigned long func_addr,
901                unsigned long ret_addr)
902 {
903         char *buf, *payload, *buf_end;
904         int ret;
905
906         if (!check_event(current))
907                 return 0;
908
909         buf = get_current_buf();
910         payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_EXIT);
911         /* FIXME: len=1024 */
912         ret = pack_msg_func_exit(payload, 1024, ret_type, regs,
913                                  func_addr, ret_addr);
914         if (ret < 0)
915                 goto put_buf;
916
917         buf_end = payload + ret;
918         set_len_msg(buf, buf_end);
919
920         ret = write_to_buffer(buf);
921
922 put_buf:
923         put_current_buf();
924
925         return ret;
926 }
927 EXPORT_SYMBOL_GPL(exit_event);
928
929
930
931
932
933 /* ============================================================================
934  * =                            CONTEXT SWITCH                                =
935  * ============================================================================
936  */
937
938 struct msg_context_switch {
939         u64 pc_addr;
940         u32 pid;
941         u32 tid;
942         u32 cpu_num;
943 } __attribute__((packed));
944
945 static char *pack_msg_context_switch(char *payload, struct pt_regs *regs)
946 {
947         struct msg_context_switch *mcs = (struct msg_context_switch *)payload;
948         struct task_struct *task = current;
949
950         mcs->pc_addr = 0;
951         mcs->pid = task->tgid;
952         mcs->tid = task->pid;
953         mcs->cpu_num = smp_processor_id();
954
955         return payload + sizeof(*mcs);
956 }
957
958 static int context_switch(struct pt_regs *regs, enum MSG_ID id)
959 {
960         char *buf, *payload, *buf_end;
961         int ret;
962
963         buf = get_current_buf();
964         payload = pack_basic_msg_fmt(buf, id);
965         buf_end = pack_msg_context_switch(payload, regs);
966         set_len_msg(buf, buf_end);
967
968         ret = write_to_buffer(buf);
969         put_current_buf();
970
971         return ret;
972 }
973
974 int switch_entry(struct pt_regs *regs)
975 {
976         if (!check_event(current))
977                 return 0;
978
979         return context_switch(regs, MSG_CONTEXT_SWITCH_ENTRY);
980 }
981 EXPORT_SYMBOL_GPL(switch_entry);
982
983 int switch_exit(struct pt_regs *regs)
984 {
985         if (!check_event(current))
986                 return 0;
987
988         return context_switch(regs, MSG_CONTEXT_SWITCH_EXIT);
989 }
990 EXPORT_SYMBOL_GPL(switch_exit);
991
992
993
994
995 /* ============================================================================
996  * =                                 ERROR                                    =
997  * ============================================================================
998  */
999
1000 struct msg_err {
1001         char msg[0];
1002 } __attribute__((packed));
1003
1004 static char *pack_msg_err(char *payload, const char *fmt, va_list args)
1005 {
1006         struct msg_err *me = (struct msg_err *)payload;
1007         int ret;
1008
1009         ret = vsprintf(me->msg, fmt, args);
1010         if (ret < 0)
1011                 return payload;
1012
1013         return payload + sizeof(*me) + ret + 1;
1014 }
1015
1016 int error_msg(const char *fmt, ...)
1017 {
1018         char *buf, *payload, *buf_end;
1019         va_list args;
1020         int ret;
1021
1022         buf = get_current_buf();
1023         payload = pack_basic_msg_fmt(buf, MSG_ERROR);
1024
1025         va_start(args, fmt);
1026         buf_end = pack_msg_err(payload, fmt, args);
1027         va_end(args);
1028
1029         set_len_msg(buf, buf_end);
1030
1031         ret = write_to_buffer(buf);
1032         put_current_buf();
1033
1034         return ret;
1035 }
1036 EXPORT_SYMBOL_GPL(error_msg);
1037
1038
1039
1040
1041
1042 /* ============================================================================
1043  * =                         MESSAGES FROM USER SPACE                         =
1044  * ============================================================================
1045  */
1046
1047 int raw_msg(char *buf, size_t len)
1048 {
1049         struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf;
1050
1051         if (sizeof(*bmf) > len)
1052                 return -EINVAL;
1053
1054         if (bmf->len + sizeof(*bmf) != len)
1055                 return -EINVAL;
1056
1057         set_seq_num(bmf);
1058         write_to_buffer(buf);
1059
1060         return len;
1061 }
1062
1063
1064
1065 /* ============================================================================
1066  * =                              CUSTOM EVENT                                =
1067  * ============================================================================
1068  */
1069
1070 static int pack_custom_event(char *buf, int len, const char *fmt, va_list args)
1071 {
1072         enum { max_str_len = 512 };
1073         const char *p;
1074         char *buf_orig = buf;
1075
1076         for (p = fmt; *p != '\0'; p++) {
1077                 char ch = *p;
1078
1079                 if (len < 1)
1080                         return -ENOMEM;
1081
1082                 *buf = tolower(ch);
1083                 buf += 1;
1084                 len -= 1;
1085
1086                 switch (ch) {
1087                 case 'b': /* 1 byte(bool) */
1088                         if (len < 1)
1089                                 return -ENOMEM;
1090                         *buf = !!(char)va_arg(args, int);
1091                         buf += 1;
1092                         len -= 1;
1093                         break;
1094                 case 'c': /* 1 byte(char) */
1095                         if (len < 1)
1096                                 return -ENOMEM;
1097                         *buf = (char)va_arg(args, int);
1098                         buf += 1;
1099                         len -= 1;
1100                         break;
1101                 case 'f': /* 4 byte(float) */
1102                 case 'd': /* 4 byte(int) */
1103                         if (len < 4)
1104                                 return -ENOMEM;
1105                         *(u32 *)buf = va_arg(args, u32);
1106                         buf += 4;
1107                         len -= 4;
1108                         break;
1109                 case 'x': /* 8 byte(long) */
1110                 case 'w': /* 8 byte(double) */
1111                         if (len < 8)
1112                                 return -ENOMEM;
1113                         *(u64 *)buf = va_arg(args, u64);
1114                         buf += 8;
1115                         len -= 8;
1116                         break;
1117                 case 'p': /* 8 byte(pointer) */
1118                         if (len < 8)
1119                                 return -ENOMEM;
1120                         *(u64 *)buf = va_arg(args, unsigned long);
1121                         buf += 8;
1122                         len -= 8;
1123                         break;
1124                 case 's': /* userspace string with '\0' terminating byte */
1125                 {
1126                         const char __user *str;
1127                         int len_s, n;
1128
1129                         str = va_arg(args, const char __user *);
1130                         /* strnlen_user includes '\0' in its return value */
1131                         len_s = strnlen_user(str, max_str_len);
1132                         if (len < len_s)
1133                                 return -ENOMEM;
1134                         /* strncpy_from_user returns the length of the copied
1135                          * string (without '\0') */
1136                         n = strncpy_from_user(buf, str, len_s - 1);
1137                         if (n < 0)
1138                                 return n;
1139                         buf[n] = '\0';
1140
1141                         buf += n + 1;
1142                         len -= n + 1;
1143                         break;
1144                 }
1145                 case 'S': /* kernelspace string with '\0' terminating byte */
1146                 {
1147                         const char *str;
1148                         int len_s;
1149
1150                         str = va_arg(args, const char *);
1151                         len_s = strnlen(str, max_str_len);
1152                         if (len < len_s + 1) /* + '\0' */
1153                                 return -ENOMEM;
1154                         strncpy(buf, str, len_s);
1155                         buf[len_s] = '\0';
1156
1157                         buf += len_s + 1;
1158                         len -= len_s + 1;
1159                         break;
1160                 }
1161                 case 'a': /* userspace byte array (len + ptr) */
1162                 {
1163                         const void __user *ptr;
1164                         u32 len_p, n;
1165
1166                         len_p = va_arg(args, u32);
1167                         if (len < sizeof(len_p) + len_p)
1168                                 return -ENOMEM;
1169                         *(u32 *)buf = len_p;
1170                         buf += sizeof(len_p);
1171                         len -= sizeof(len_p);
1172
1173                         ptr = va_arg(args, const void __user *);
1174                         n = copy_from_user(buf, ptr, len_p);
1175                         if (n < len_p)
1176                                 return -EFAULT;
1177                         buf += len_p;
1178                         len -= len_p;
1179                         break;
1180                 }
1181                 case 'A': /* kernelspace byte array (len + ptr) */
1182                 {
1183                         const void *ptr;
1184                         u32 len_p;
1185
1186                         /* array size */
1187                         len_p = va_arg(args, u32);
1188                         if (len < sizeof(len_p) + len_p)
1189                                 return -ENOMEM;
1190                         *(u32 *)buf = len_p;
1191                         buf += sizeof(len_p);
1192                         len -= sizeof(len_p);
1193
1194                         /* byte array */
1195                         ptr = va_arg(args, const void *);
1196                         memcpy(buf, ptr, len_p);
1197                         buf += len_p;
1198                         len -= len_p;
1199                         break;
1200                 }
1201                 default:
1202                         return -EINVAL;
1203                 }
1204         }
1205
1206         return buf - buf_orig;
1207 }
1208
1209 enum { max_custom_event_size = 2048 };
1210
1211 int custom_entry_event(unsigned long func_addr, struct pt_regs *regs,
1212                        int type, int sub_type, const char *fmt, ...)
1213 {
1214         char *buf, *payload, *args, *buf_end;
1215         va_list vargs;
1216         int ret;
1217
1218         buf = get_current_buf();
1219         payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_ENTRY);
1220         args = pack_msg_func_entry(payload, fmt, func_addr,
1221                                    regs, type, sub_type);
1222
1223         va_start(vargs, fmt);
1224         ret = pack_custom_event(args, max_custom_event_size, fmt, vargs);
1225         va_end(vargs);
1226
1227         if (ret < 0)
1228                 goto put_buf;
1229
1230         buf_end = args + ret;
1231         set_len_msg(buf, buf_end);
1232         ret = write_to_buffer(buf);
1233
1234 put_buf:
1235         put_current_buf();
1236
1237         return ret;
1238 }
1239 EXPORT_SYMBOL_GPL(custom_entry_event);
1240
1241 /* TODO currently this function is a simple wrapper. it will be refactored when
1242  * protocol changes are applied */
1243 int custom_exit_event(unsigned long func_addr, unsigned long ret_addr,
1244                       struct pt_regs *regs, const char *fmt, ...)
1245 {
1246         char *buf, *payload, *buf_end;
1247         int ret;
1248
1249         buf = get_current_buf();
1250         payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_EXIT);
1251         ret = pack_msg_func_exit(payload, max_custom_event_size,
1252                                  fmt[0], regs, func_addr, ret_addr);
1253         if (ret < 0)
1254                 goto put_buf;
1255
1256         buf_end = payload + ret;
1257         set_len_msg(buf, buf_end);
1258
1259         ret = write_to_buffer(buf);
1260
1261 put_buf:
1262         put_current_buf();
1263
1264         return ret;
1265 }
1266 EXPORT_SYMBOL_GPL(custom_exit_event);
1267
1268 static int __init swap_writer_module_init(void)
1269 {
1270         int ret;
1271
1272         ret = event_filter_init();
1273         if (ret)
1274                 return ret;
1275
1276         ret = init_debugfs_writer();
1277         if (ret)
1278                 event_filter_exit();
1279
1280         return ret;
1281 }
1282
1283 static void __exit swap_writer_module_exit(void)
1284 {
1285         exit_debugfs_writer();
1286         event_filter_exit();
1287 }
1288
1289 module_init(swap_writer_module_init);
1290 module_exit(swap_writer_module_exit);
1291
1292 MODULE_LICENSE("GPL");
1293 MODULE_DESCRIPTION("SWAP Writer module");
1294 MODULE_AUTHOR("Cherkashin V., Aksenov A.S.");