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
/* ARCH-DEPENDED OPERATIONS */
+
+/* Regs manipulations */
#if defined(CONFIG_ARM)
#define get_regs_ip(regs) regs->ARM_pc
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__ */
--- /dev/null
+/*
+ * 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]";
+}
/*
* 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)
{
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]";
+}
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;
}