[IMPROVE] Kernel shared memory area addresses are pushed to host
authorAlexander Aksenov <a.aksenov@samsung.com>
Wed, 27 Nov 2013 10:30:57 +0000 (14:30 +0400)
committerGerrit Code Review <gerrit@gerrit.vlan144.tizendev.org>
Mon, 2 Dec 2013 12:39:43 +0000 (12:39 +0000)
Change-Id: I9304bdfa3ce3ad89e50020cc48f0a82679251da1
Signed-off-by: Alexander Aksenov <a.aksenov@samsung.com>
writer/Kbuild
writer/kernel_operations.h
writer/kernel_operations_arm.c [new file with mode: 0644]
writer/kernel_operations_x86.c [moved from writer/kernel_operations.c with 68% similarity]
writer/swap_writer_module.c

index e09374a..1df96c8 100644 (file)
@@ -4,6 +4,8 @@ KBUILD_EXTRA_SYMBOLS = $(src)/../buffer/Module.symvers \
 
 obj-m := swap_writer.o
 swap_writer-y := swap_writer_module.o \
-                 kernel_operations.o \
                  debugfs_writer.o \
                  event_filter.o
+
+swap_writer-$(CONFIG_ARM) += kernel_operations_arm.o
+swap_writer-$(CONFIG_X86) += kernel_operations_x86.o
index 26c2fad..8d6b718 100644 (file)
@@ -45,6 +45,8 @@
 
 /* ARCH-DEPENDED OPERATIONS */
 
+
+/* Regs manipulations */
 #if defined(CONFIG_ARM)
 
 #define get_regs_ip(regs)           regs->ARM_pc
@@ -79,4 +81,8 @@ static inline u32 get_regs_ret_func(struct pt_regs *regs)
 
 int get_args(unsigned long args[], int cnt, struct pt_regs *regs);
 
+/* Returns shared kernel memory area name if it is found, otherwise - NULL */
+const char *get_shared_kmem(struct mm_struct *mm, unsigned long *start,
+                           unsigned long *end);
+
 #endif /* __KERNEL_OPERATIONS_H__ */
diff --git a/writer/kernel_operations_arm.c b/writer/kernel_operations_arm.c
new file mode 100644 (file)
index 0000000..460a563
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ *  SWAP Writer
+ *  modules/writer/kernel_operations_arm.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Samsung Electronics, 2013
+ *
+ * 2013         Alexander Aksenov <a.aksenov@samsung.com>: SWAP Writer module kernel
+ * operaions implement
+ *
+ */
+
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <generated/autoconf.h>
+
+#include "kernel_operations.h"
+
+
+/* ======================= ARGS ========================== */
+
+int get_args(unsigned long args[], int cnt, struct pt_regs *regs)
+{
+       /* All args, except first 4, are passed on the stack */
+       enum { stack_args = 4 };
+       int i, args_in_regs;
+
+       args_in_regs = cnt < 3 ? cnt : 3;
+
+       /* Get first 4 args from registers */
+       switch (args_in_regs) {
+               case 3:
+                       args[3] = regs->ARM_r3;
+               case 2:
+                       args[2] = regs->ARM_r2;
+               case 1:
+                       args[1] = regs->ARM_r1;
+               case 0:
+                       args[0] = regs->ARM_r0;
+       }
+
+       /* Get other args from stack */
+       for (i = stack_args; i < cnt; ++i) {
+               unsigned long *args_in_sp = (unsigned long *)regs->ARM_sp +
+                                           i - stack_args;
+               if (get_user(args[i], args_in_sp))
+                       printk("failed to dereference a pointer, addr=%p\n",
+                              args_in_sp);
+       }
+
+       return 0;
+}
+
+
+/* ================== KERNEL SHARED MEM ===================== */
+
+/* CONFIG_VECTORS_BASE used to handle both MMU and non-MMU cases.
+ * According to docs (Documentation/arm/memory.txt) all vector addresses
+ * are fixed and vectors are always equal to one page, so,
+ * end = start + PAGE_SIZE
+ * */
+
+const char *get_shared_kmem(struct mm_struct *mm, unsigned long *start,
+                            unsigned long *end)
+{
+       *start = CONFIG_VECTORS_BASE;
+       *end = CONFIG_VECTORS_BASE + PAGE_SIZE;
+
+       return "[vectors]";
+}
similarity index 68%
rename from writer/kernel_operations.c
rename to writer/kernel_operations_x86.c
index d69fe74..c830af0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  SWAP Writer
- *  modules/writer/swap_writer_module.c
+ *  modules/writer/kernel_operations_x86.c
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
+#include <asm/elf.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
 
-#if defined(CONFIG_ARM)
+#include "kernel_operations.h"
 
-int get_args(unsigned long args[], int cnt, struct pt_regs *regs)
-{
-       /* All args, except first 4, are passed on the stack */
-       enum { stack_args = 4 };
-       int i, args_in_regs;
-
-       args_in_regs = cnt < 3 ? cnt : 3;
-
-       /* Get first 4 args from registers */
-       switch (args_in_regs) {
-               case 3:
-                       args[3] = regs->ARM_r3;
-               case 2:
-                       args[2] = regs->ARM_r2;
-               case 1:
-                       args[1] = regs->ARM_r1;
-               case 0:
-                       args[0] = regs->ARM_r0;
-       }
-
-       /* Get other args from stack */
-       for (i = stack_args; i < cnt; ++i) {
-               unsigned long *args_in_sp = (unsigned long *)regs->ARM_sp +
-                                           i - stack_args;
-               if (get_user(args[i], args_in_sp))
-                       printk("failed to dereference a pointer, addr=%p\n",
-                              args_in_sp);
-       }
-
-       return 0;
-}
 
-#elif defined(CONFIG_X86_32)
+/* ======================= ARGS ========================== */
 
 int get_args(unsigned long args[], int cnt, struct pt_regs *regs)
 {
@@ -103,4 +75,25 @@ int get_args(unsigned long args[], int cnt, struct pt_regs *regs)
        return 0;
 }
 
-#endif /* CONFIG_arch */
+
+/* ================== KERNEL SHARED MEM ===================== */
+
+const char *get_shared_kmem(struct mm_struct *mm, unsigned long *start,
+                           unsigned long *end)
+{
+       unsigned long vdso;
+       struct vm_area_struct *vma_vdso;
+
+       vdso = (unsigned long)mm->context.vdso;
+       vma_vdso = find_vma_intersection(mm, vdso, vdso + 1);
+
+       if (vma_vdso == NULL) {
+               print_err("Cannot get VDSO mapping\n");
+               return NULL;
+       }
+
+       *start = vma_vdso->vm_start;
+       *end = vma_vdso->vm_end;
+
+       return "[vdso]";
+}
index efbd930..046b23b 100644 (file)
@@ -268,26 +268,59 @@ out:
        return vma;
 }
 
-static char *pack_proc_info_part(char *end_path, struct mm_struct *mm)
+static char *pack_shared_kmem(char *lib_obj, struct mm_struct *mm,
+                              u32 *lib_cnt_p)
 {
-       struct proc_info_part *pip;
-       struct vm_area_struct *vma;
-       char *lib_obj;
-       int lib_cnt = 0;
+       struct lib_obj *so = (struct lib_obj *)lib_obj;
+       char *so_obj;
+       unsigned long start = 0, end = 0;
 
-       pip = (struct proc_info_part *)end_path;
-       lib_obj = pip->libs;
+       const char *kmem_name = get_shared_kmem(mm, &start, &end);
+       size_t name_len;
+
+       if (kmem_name == NULL)
+               return lib_obj;
+
+       name_len = strlen(kmem_name) + 1;
+       so->low_addr = (u64)start;
+       so->high_addr = (u64)end;
+       memcpy(so->lib_path, kmem_name, name_len);
+       (*lib_cnt_p)++;
+       so_obj = so->lib_path + name_len;
+
+       return so_obj;
+}
+
+static char *pack_libs(char *lib_obj, struct mm_struct *mm, u32 *lib_cnt_p)
+{
+       struct vm_area_struct *vma;
 
        down_read(&mm->mmap_sem);
        for (vma = mm->mmap; vma; vma = vma->vm_next) {
                if (check_vma(vma)) {
                        lib_obj = pack_lib_obj(lib_obj, vma);
-                       ++lib_cnt;
+                       ++(*lib_cnt_p);
                }
        }
        up_read(&mm->mmap_sem);
 
-       pip->lib_cnt = lib_cnt;
+       return lib_obj;
+}
+
+static char *pack_proc_info_part(char *end_path, struct mm_struct *mm)
+{
+       struct proc_info_part *pip;
+       char *lib_obj;
+       u32 *lib_cnt_p;
+
+       pip = (struct proc_info_part *)end_path;
+       pip->lib_cnt = 0;
+       lib_obj = pip->libs;
+       lib_cnt_p = &pip->lib_cnt;
+
+       lib_obj = pack_libs(lib_obj, mm, lib_cnt_p);
+       lib_obj = pack_shared_kmem(lib_obj, mm, lib_cnt_p);
+
        return lib_obj;
 }