summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>2014-09-16 19:26:46 +0400
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>2014-09-17 16:01:32 +0400
commitc59399ef27a3e432c6f791eb5b271d1b7d96b90e (patch)
treec0b85ef9f58e0f6d36208ffc92b65e9a284c25e9
parent66b1325405ffddc21e692acfc9f07583d34017ec (diff)
downloadswap-modules-c59399ef27a3e432c6f791eb5b271d1b7d96b90e.tar.gz
swap-modules-c59399ef27a3e432c6f791eb5b271d1b7d96b90e.tar.bz2
swap-modules-c59399ef27a3e432c6f791eb5b271d1b7d96b90e.zip
[FIX] use mem_text_write_kernel_word()
Change-Id: Ieaabaf496f5ec1df67304c2ac310fc5ef1cf7bfe Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
-rw-r--r--kprobe/Kbuild10
-rw-r--r--kprobe/arch/asm-arm/memory_rwx.c96
-rw-r--r--kprobe/arch/asm-arm/memory_rwx.h35
-rw-r--r--kprobe/arch/asm-arm/swap_kprobes.c29
4 files changed, 155 insertions, 15 deletions
diff --git a/kprobe/Kbuild b/kprobe/Kbuild
index b5a9a098..4a71126c 100644
--- a/kprobe/Kbuild
+++ b/kprobe/Kbuild
@@ -5,4 +5,12 @@ swap_kprobe-y := swap_kprobes.o \
swap_kprobes_deps.o \
arch/asm/swap_kprobes.o \
swap_slots.o
-swap_kprobe-$(CONFIG_ARM) += arch/asm/trampoline_arm.o
+
+ifeq ($(CONFIG_ARM), y)
+swap_kprobe-y += arch/asm/trampoline_arm.o
+
+ifeq ($(CONFIG_STRICT_MEMORY_RWX), y)
+swap_kprobe-y += arch/asm/memory_rwx.o
+endif # CONFIG_STRICT_MEMORY_RWX
+
+endif # CONFIG_ARM \ No newline at end of file
diff --git a/kprobe/arch/asm-arm/memory_rwx.c b/kprobe/arch/asm-arm/memory_rwx.c
new file mode 100644
index 00000000..d120872c
--- /dev/null
+++ b/kprobe/arch/asm-arm/memory_rwx.c
@@ -0,0 +1,96 @@
+/*
+ * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com> new memory allocator for slots
+ *
+ * @section LICENSE
+ *
+ * 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.
+ *
+ * @section COPYRIGHT
+ *
+ * Copyright (C) Samsung Electronics, 2014
+ */
+
+
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/mmu_writeable.h>
+
+
+#include <ksyms/ksyms.h>
+
+
+static unsigned long get_init_mm(void)
+{
+ static unsigned long addr = 0;
+
+ if (addr == 0)
+ addr = swap_ksyms("init_mm");
+
+ return addr;
+}
+
+static int get_pte_cb(pte_t *ptep, pgtable_t token,
+ unsigned long addr, void *data)
+{
+ *(pte_t *)data = *ptep;
+
+ return 1;
+}
+
+static pte_t get_pte(unsigned long page_addr)
+{
+ struct mm_struct *mm = (struct mm_struct *)get_init_mm();
+ pte_t pte = 0;
+
+ apply_to_page_range(mm, page_addr, PAGE_SIZE, get_pte_cb, &pte);
+
+ return pte;
+}
+
+static void write_to_module(unsigned long addr, unsigned long val)
+{
+ unsigned long *maddr = (unsigned long *)addr;
+ unsigned long page_addr = addr & PAGE_MASK;
+ pte_t pte;
+
+ pte = get_pte(page_addr);
+ if (pte_write(pte) == 0) {
+ unsigned long flags;
+ DEFINE_SPINLOCK(mem_lock);
+
+ spin_lock_irqsave(&mem_lock, flags);
+ set_memory_rw(page_addr, 1);
+ *maddr = val;
+ set_memory_ro(page_addr, 1);
+ spin_unlock_irqrestore(&mem_lock, flags);
+ } else {
+ *maddr = val;
+ }
+
+ flush_icache_range(addr, addr + sizeof(long));
+}
+
+void mem_rwx_write_u32(unsigned long addr, unsigned long val)
+{
+ if (addr < MODULES_VADDR || addr >= MODULES_END) {
+ /*
+ * if addr doesn't belongs kernel space,
+ * segmentation fault will occur
+ */
+ mem_text_write_kernel_word((long *)addr, val);
+ } else {
+ write_to_module(addr, val);
+ }
+}
diff --git a/kprobe/arch/asm-arm/memory_rwx.h b/kprobe/arch/asm-arm/memory_rwx.h
new file mode 100644
index 00000000..a083a3b2
--- /dev/null
+++ b/kprobe/arch/asm-arm/memory_rwx.h
@@ -0,0 +1,35 @@
+/**
+ * @file kprobe/arch/asm-arm/memory_rwx.h
+ *
+ * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com> new memory allocator for slots
+ *
+ * @section LICENSE
+ *
+ * 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.
+ *
+ * @section COPYRIGHT
+ *
+ * Copyright (C) Samsung Electronics, 2014
+ */
+
+
+#ifndef _MEMORY_RWX_H
+#define _MEMORY_RWX_H
+
+
+void mem_rwx_write_u32(unsigned long addr, unsigned long val);
+
+
+#endif /* _MEMORY_RWX_H */
diff --git a/kprobe/arch/asm-arm/swap_kprobes.c b/kprobe/arch/asm-arm/swap_kprobes.c
index df1bfe49..9b223735 100644
--- a/kprobe/arch/asm-arm/swap_kprobes.c
+++ b/kprobe/arch/asm-arm/swap_kprobes.c
@@ -530,8 +530,19 @@ int swap_longjmp_break_handler (struct kprobe *p, struct pt_regs *regs)
EXPORT_SYMBOL_GPL(swap_longjmp_break_handler);
#ifdef CONFIG_STRICT_MEMORY_RWX
-extern void mem_text_write_kernel_word(unsigned long *addr, unsigned long word);
-#endif
+#include "memory_rwx.h"
+
+static void write_u32(unsigned long addr, unsigned long val)
+{
+ mem_rwx_write_u32(addr, val);
+}
+#else /* CONFIG_STRICT_MEMORY_RWX */
+static void write_u32(unsigned long addr, unsigned long val)
+{
+ *(long *)addr = BREAKPOINT_INSTRUCTION;
+ flush_icache_range(addr, addr + sizeof(long));
+}
+#endif /* CONFIG_STRICT_MEMORY_RWX */
/**
* @brief Arms kprobe.
@@ -541,12 +552,7 @@ extern void mem_text_write_kernel_word(unsigned long *addr, unsigned long word);
*/
void swap_arch_arm_kprobe(struct kprobe *p)
{
-#ifdef CONFIG_STRICT_MEMORY_RWX
- mem_text_write_kernel_word(p->addr, BREAKPOINT_INSTRUCTION);
-#else
- *p->addr = BREAKPOINT_INSTRUCTION;
- flush_icache_range((unsigned long)p->addr, (unsigned long)p->addr + sizeof(kprobe_opcode_t));
-#endif
+ write_u32((long)p->addr, BREAKPOINT_INSTRUCTION);
}
/**
@@ -557,12 +563,7 @@ void swap_arch_arm_kprobe(struct kprobe *p)
*/
void swap_arch_disarm_kprobe(struct kprobe *p)
{
-#ifdef CONFIG_STRICT_MEMORY_RWX
- mem_text_write_kernel_word(p->addr, p->opcode);
-#else
- *p->addr = p->opcode;
- flush_icache_range((unsigned long)p->addr, (unsigned long)p->addr + sizeof(kprobe_opcode_t));
-#endif
+ write_u32((long)p->addr, p->opcode);
}
/**