tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / kernel / swap / parser / usm_msg.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/fs.h>
24 #include <linux/stat.h>
25 #include <linux/sched.h>
26 #include <linux/dcache.h>
27 #include <linux/fdtable.h>
28 #include <writer/swap_msg.h>
29 #include <us_manager/sspt/sspt.h>       /* ... check_vma() */
30
31
32 #define USM_PREFIX      KERN_INFO "[USM] "
33
34
35 static struct files_struct *(*swap_get_files_struct)(struct task_struct *);
36 static void (*swap_put_files_struct)(struct files_struct *fs);
37
38 int usm_msg_once(void)
39 {
40         const char *sym;
41
42         sym = "get_files_struct";
43         swap_get_files_struct = (void *)swap_ksyms(sym);
44         if (swap_get_files_struct == NULL)
45                 goto not_found;
46
47         sym = "put_files_struct";
48         swap_put_files_struct = (void *)swap_ksyms(sym);
49         if (swap_put_files_struct == NULL)
50                 goto not_found;
51
52         return 0;
53
54 not_found:
55         printk("ERROR: symbol '%s' not found\n", sym);
56         return -ESRCH;
57 }
58
59
60
61
62
63 struct kmem_info {
64         const char *name;
65         unsigned long start;
66         unsigned long end;
67 };
68
69 static void kmem_info_fill(struct kmem_info *info, struct mm_struct *mm)
70 {
71 #if defined(CONFIG_ARM)
72         info->name = "[vectors]";
73         info->start = CONFIG_VECTORS_BASE;
74         info->end = CONFIG_VECTORS_BASE + PAGE_SIZE;
75 #elif defined(CONFIG_X86_32)
76         unsigned long vdso;
77         struct vm_area_struct *vma_vdso;
78
79         vdso = (unsigned long)mm->context.vdso;
80         vma_vdso = find_vma_intersection(mm, vdso, vdso + 1);
81         if (vma_vdso) {
82                 info->name = "[vdso]";
83                 info->start = vma_vdso->vm_start;
84                 info->end = vma_vdso->vm_end;
85         } else {
86                 printk(USM_PREFIX "Cannot get VDSO mapping\n");
87
88                 info->name = NULL;
89                 info->start = 0;
90                 info->end = 0;
91         }
92 #endif /* CONFIG_arch */
93 }
94
95
96 static int pack_path(void *data, size_t size, struct file *file)
97 {
98         enum { TMP_BUF_LEN = 512 };
99         char tmp_buf[TMP_BUF_LEN];
100         const char NA[] = "N/A";
101         const char *filename;
102         size_t len = sizeof(NA);
103
104         if (file == NULL) {
105                 filename = NA;
106                 goto cp2buf;
107         }
108
109         path_get(&file->f_path);
110         filename = d_path(&file->f_path, tmp_buf, TMP_BUF_LEN);
111         path_put(&file->f_path);
112
113         if (IS_ERR_OR_NULL(filename)) {
114                 filename = NA;
115                 goto cp2buf;
116         }
117
118         len = strlen(filename) + 1;
119
120 cp2buf:
121         if (size < len)
122                 return -ENOMEM;
123
124         memcpy(data, filename, len);
125         return len;
126 }
127
128
129
130
131
132 /* ============================================================================
133  * =                             MSG_PROCESS_INFO                             =
134  * ============================================================================
135  */
136 struct proc_info_top {
137         u32 pid;
138         char comm[0];
139 } __packed;
140
141 struct proc_info_bottom {
142         u32 ppid;
143         u64 start_time;
144         u64 low_addr;
145         u64 high_addr;
146         char bin_path[0];
147 } __packed;
148
149 struct lib_obj {
150         u64 low_addr;
151         u64 high_addr;
152         char lib_path[0];
153 } __packed;
154
155 static int pack_lib_obj(void *data, size_t size, struct vm_area_struct *vma)
156 {
157         int ret;
158         struct lib_obj *obj = (struct lib_obj *)data;
159
160         if (size < sizeof(*obj))
161                 return -ENOMEM;
162
163         obj->low_addr = vma->vm_start;
164         obj->high_addr = vma->vm_end;
165         size -= sizeof(*obj);
166
167         ret = pack_path(obj->lib_path, size, vma->vm_file);
168         if (ret < 0)
169                 return ret;
170
171         return ret + sizeof(*obj);
172 }
173
174 static int pack_shared_kmem(void *data, size_t size, struct mm_struct *mm)
175 {
176         struct lib_obj *obj = (struct lib_obj *)data;
177         struct kmem_info info;
178         size_t name_len, obj_size;
179
180         if (size < sizeof(*obj))
181                 return -ENOMEM;
182
183         kmem_info_fill(&info, mm);
184
185         if (info.name == NULL)
186                 return 0;
187
188         obj->low_addr = (u64)info.start;
189         obj->high_addr = (u64)info.end;
190
191         name_len = strlen(info.name) + 1;
192         obj_size = sizeof(*obj) + name_len;
193         if (size < obj_size)
194                 return -ENOMEM;
195
196         memcpy(obj->lib_path, info.name, name_len);
197
198         return obj_size;
199 }
200
201 static int pack_libs(void *data, size_t size, struct mm_struct *mm)
202 {
203         int ret;
204         struct vm_area_struct *vma;
205         u32 *lib_cnt = (u32 *)data;
206         const size_t old_size = size;
207
208         if (size < sizeof(*lib_cnt))
209                 return -ENOMEM;
210
211         /* packing libraries count */
212         *lib_cnt = 0;
213         data += sizeof(*lib_cnt);
214         size -= sizeof(*lib_cnt);
215
216         /* packing libraries */
217         for (vma = mm->mmap; vma; vma = vma->vm_next) {
218                 if (check_vma(vma)) {
219                         ret = pack_lib_obj(data, size, vma);
220                         if (ret < 0)
221                                 return ret;
222
223                         data += ret;
224                         size -= ret;
225                         ++(*lib_cnt);
226                 }
227         }
228
229         /* packing shared kernel memory */
230         ret = pack_shared_kmem(data, size, mm);
231         if (ret < 0)
232                 return ret;
233
234         *lib_cnt += !!ret;
235         size -= ret;
236
237         return old_size - size;
238 }
239
240 static struct vm_area_struct *find_vma_exe_by_dentry(struct mm_struct *mm,
241                                                      struct dentry *dentry)
242 {
243         struct vm_area_struct *vma;
244
245         for (vma = mm->mmap; vma; vma = vma->vm_next) {
246                 if (vma->vm_file && (vma->vm_flags & VM_EXEC) &&
247                    (vma->vm_file->f_dentry == dentry))
248                         goto out;
249         }
250
251         vma = NULL;
252 out:
253
254         return vma;
255 }
256
257 static int pack_proc_info_top(void *data, size_t size,
258                               struct task_struct *task)
259 {
260         struct proc_info_top *pit = (struct proc_info_top *)data;
261
262         if (size < sizeof(*pit) + sizeof(task->comm))
263                 return -ENOMEM;
264
265         pit->pid = task->tgid;
266         get_task_comm(pit->comm, task);
267
268         return sizeof(*pit) + strlen(pit->comm) + 1;
269 }
270
271 static int pack_proc_info_bottom(void *data, size_t size,
272                                  struct task_struct *task,
273                                  struct dentry *dentry)
274 {
275         struct proc_info_bottom *pib = (struct proc_info_bottom *)data;
276         struct vm_area_struct *vma = find_vma_exe_by_dentry(task->mm, dentry);
277         struct timespec boot_time;
278         struct timespec start_time;
279         int ret;
280
281         if (size < sizeof(*pib))
282                 return -ENOMEM;
283
284         getboottime(&boot_time);
285         start_time = timespec_add(boot_time, task->real_start_time);
286
287         pib->ppid = task->real_parent->tgid;
288         pib->start_time = swap_msg_spec2time(&start_time);
289
290         if (vma) {
291                 pib->low_addr = vma->vm_start;
292                 pib->high_addr = vma->vm_end;
293                 ret = pack_path(pib->bin_path, size, vma->vm_file);
294         } else {
295                 pib->low_addr = 0;
296                 pib->high_addr = 0;
297                 ret = pack_path(pib->bin_path, size, NULL);
298         }
299
300         if (ret < 0)
301                 return ret;
302
303         return sizeof(*pib) + ret;
304 }
305
306 static int pack_proc_info(void *data, size_t size, struct task_struct *task,
307                             struct dentry *dentry)
308 {
309         int ret;
310         const size_t old_size = size;
311
312         ret = pack_proc_info_top(data, size, task);
313         if (ret < 0)
314                 return ret;
315
316         data += ret;
317         size -= ret;
318
319         ret = pack_proc_info_bottom(data, size, task, dentry);
320         if (ret < 0)
321                 return ret;
322
323         data += ret;
324         size -= ret;
325
326         ret = pack_libs(data, size, task->mm);
327         if (ret < 0)
328                 return ret;
329
330         return old_size - size + ret;
331 }
332
333 /* Called with down\up\_read(&task->mm->mmap_sem). */
334 void usm_msg_info(struct task_struct *task, struct dentry *dentry)
335 {
336         int ret;
337         struct swap_msg *m;
338         void *p;
339         size_t size;
340
341         m = swap_msg_get(MSG_PROC_INFO);
342         p = swap_msg_payload(m);
343         size = swap_msg_size(m);
344
345         ret = pack_proc_info(p, size, task, dentry);
346         if (ret < 0) {
347                 printk(USM_PREFIX "ERROR: message process info packing, "
348                        "ret=%d\n", ret);
349                 goto put_msg;
350         }
351
352         swap_msg_flush(m, ret);
353
354 put_msg:
355         swap_msg_put(m);
356 }
357
358
359
360
361
362 /* ============================================================================
363  * =                              MSG_TERMINATE                               =
364  * ============================================================================
365  */
366 struct proc_terminate {
367         u32 pid;
368 } __packed;
369
370 void usm_msg_term(struct task_struct *task)
371 {
372         struct swap_msg *m;
373         struct proc_terminate *term;
374
375         m = swap_msg_get(MSG_TERMINATE);
376
377         term = swap_msg_payload(m);
378         term->pid = task->pid;
379
380         swap_msg_flush(m, sizeof(*term));
381         swap_msg_put(m);
382 }
383
384
385
386
387
388 /* ============================================================================
389  * =                              MSG_PROCESS_MAP                             =
390  * ============================================================================
391  */
392 struct proc_map {
393         u32 pid;
394         u64 low_addr;
395         u64 high_addr;
396         char bin_path[0];
397 } __packed;
398
399 static int pack_proc_map(void *data, size_t size, struct vm_area_struct *vma)
400 {
401         struct proc_map *map = (struct proc_map *)data;
402         int ret;
403
404         map->pid = current->tgid;
405         map->low_addr = vma->vm_start;
406         map->high_addr = vma->vm_end;
407
408         ret = pack_path(map->bin_path, size - sizeof(*map), vma->vm_file);
409         if (ret < 0)
410                 return ret;
411
412         return ret + sizeof(*map);
413 }
414
415 void usm_msg_map(struct vm_area_struct *vma)
416 {
417         int ret;
418         struct swap_msg *m;
419         void *p;
420         size_t size;
421
422         m = swap_msg_get(MSG_PROC_MAP);
423         p = swap_msg_payload(m);
424         size = swap_msg_size(m);
425
426         ret = pack_proc_map(p, size, vma);
427         if (ret < 0) {
428                 printk(USM_PREFIX "ERROR: message process mapping packing, "
429                        "ret=%d\n", ret);
430                 goto put_msg;
431         }
432
433         swap_msg_flush(m, ret);
434
435 put_msg:
436         swap_msg_put(m);
437 }
438
439
440
441
442
443 /* ============================================================================
444  * =                             MSG_PROCESS_UNMAP                            =
445  * ============================================================================
446  */
447 struct proc_unmap {
448         u32 pid;
449         u64 low_addr;
450         u64 high_addr;
451 } __packed;
452
453 void usm_msg_unmap(unsigned long start, unsigned long end)
454 {
455         struct swap_msg *m;
456         struct proc_unmap *unmap;
457
458         m = swap_msg_get(MSG_PROC_UNMAP);
459
460         unmap = swap_msg_payload(m);
461         unmap->pid = current->tgid;
462         unmap->low_addr = (u64)start;
463         unmap->high_addr = (u64)end;
464
465         swap_msg_flush(m, sizeof(*unmap));
466         swap_msg_put(m);
467 }
468
469
470
471
472
473 /* ============================================================================
474  * =                             MSG_PROCESS_COMM                             =
475  * ============================================================================
476  */
477 struct proc_comm {
478         u32 pid;
479         char comm[0];
480 } __packed;
481
482 void usm_msg_comm(struct task_struct *task)
483 {
484         struct swap_msg *m;
485         struct proc_comm *c;
486
487         m = swap_msg_get(MSG_PROC_COMM);
488
489         c = swap_msg_payload(m);
490         c->pid = task->tgid;
491         get_task_comm(c->comm, task);
492
493         swap_msg_flush(m, sizeof(*c) + strlen(c->comm) + 1);
494         swap_msg_put(m);
495 }
496
497
498
499
500
501 /* ============================================================================
502  * =                          MSG_PROCESS_STATUS_INFO                         =
503  * ============================================================================
504  */
505 struct ofile {
506         u32 fd;
507         u64 size;
508         char path[0];
509 } __packed;
510
511 static int pack_ofile(void *data, size_t size, int fd, struct file *file,
512                       loff_t fsize)
513 {
514         int ret;
515         struct ofile *ofile;
516
517         if (size < sizeof(*ofile))
518                 return -ENOMEM;
519
520         ofile = (struct ofile *)data;
521         ofile->fd = (u32)fd;
522         ofile->size = (u64)fsize;
523
524         ret = pack_path(ofile->path, size - sizeof(*ofile), file);
525         if (ret < 0)
526                 return ret;
527
528         return sizeof(*ofile) + ret;
529 }
530
531 static int pack_status_info(void *data, size_t size, struct task_struct *task)
532 {
533         int ret, fd;
534         u32 *file_cnt;
535         struct files_struct *files;
536         const size_t old_size = size;
537
538         files = swap_get_files_struct(task);
539         if (files == NULL)
540                 return -EIO;
541
542         /* pack pid */
543         *((u32 *)data) = (u32)task->tgid;
544         data += 4;
545         size -= 4;
546
547         /* pack file count */
548         file_cnt = (u32 *)data;
549         *file_cnt = 0;
550         data += 4;
551         size -= 4;
552
553         /* pack file list */
554         rcu_read_lock();
555         for (fd = 0; fd < files_fdtable(files)->max_fds; ++fd) {
556                 struct file *file;
557                 struct inode *inode;
558                 loff_t fsize;
559
560                 file = fcheck_files(files, fd);
561                 if (file == NULL)
562                         continue;
563
564                 inode = file->f_path.dentry->d_inode;
565                 /* check inode and if it is a regular file */
566                 if (inode == NULL || !S_ISREG(inode->i_mode))
567                         continue;
568
569                 fsize = inode->i_size;
570                 rcu_read_unlock();
571
572                 ret = pack_ofile(data, size, fd, file, fsize);
573                 if (ret < 0)
574                         goto put_fstruct;
575
576                 data += ret;
577                 size -= ret;
578                 ++(*file_cnt);
579
580                 rcu_read_lock();
581         }
582         rcu_read_unlock();
583         ret = old_size - size;
584
585 put_fstruct:
586         swap_put_files_struct(files);
587         return ret;
588 }
589
590 void usm_msg_status_info(struct task_struct *task)
591 {
592         int ret;
593         void *data;
594         size_t size;
595         struct swap_msg *m;
596
597         m = swap_msg_get(MSG_PROCESS_STATUS_INFO);
598
599         data = swap_msg_payload(m);
600         size = swap_msg_size(m);
601         ret = pack_status_info(data, size, task);
602         if (ret < 0) {
603                 printk(USM_PREFIX "ERROR: MSG_PROCESS_STATUS_INFO "
604                        "packing, ret=%d\n", ret);
605                 goto put_msg;
606         }
607
608         swap_msg_flush(m, ret);
609
610 put_msg:
611         swap_msg_put(m);
612 }