From: lauraa@codeaurora.org (Laura Abbott)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCHv3 6/7] arm64: use fixmap for text patching when text is RO
Date: Wed, 20 Aug 2014 18:20:38 -0700 [thread overview]
Message-ID: <1408584039-12735-7-git-send-email-lauraa@codeaurora.org> (raw)
In-Reply-To: <1408584039-12735-1-git-send-email-lauraa@codeaurora.org>
When kernel text is marked as read only, it cannot be modified directly.
Use a fixmap to modify the text instead in a similar manner to
x86 and arm.
Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
---
I think there were some questions on spinlocks for the arm version, not
sure if similar concerns apply here.
---
arch/arm64/include/asm/fixmap.h | 1 +
arch/arm64/include/asm/insn.h | 2 ++
arch/arm64/kernel/insn.c | 74 +++++++++++++++++++++++++++++++++++++++--
arch/arm64/kernel/jump_label.c | 2 +-
4 files changed, 75 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h
index db26a2f2..2cd4b0d 100644
--- a/arch/arm64/include/asm/fixmap.h
+++ b/arch/arm64/include/asm/fixmap.h
@@ -48,6 +48,7 @@ enum fixed_addresses {
FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
+ FIX_TEXT_POKE0,
__end_of_fixed_addresses
};
diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index dc1f73b..07ac29b 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -92,6 +92,7 @@ bool aarch64_insn_is_nop(u32 insn);
int aarch64_insn_read(void *addr, u32 *insnp);
int aarch64_insn_write(void *addr, u32 insn);
+int aarch64_insn_write_early(void *addr, u32 insn);
enum aarch64_insn_encoding_class aarch64_get_insn_class(u32 insn);
u32 aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type,
u32 insn, u64 imm);
@@ -103,6 +104,7 @@ u32 aarch64_insn_gen_nop(void);
bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
int aarch64_insn_patch_text_nosync(void *addr, u32 insn);
+int __aarch64_insn_patch_text_nosync(void *addr, u32 insn, bool early);
int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt);
int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);
#endif /* __ASSEMBLY__ */
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 92f3683..b25f8db 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -17,10 +17,13 @@
#include <linux/bitops.h>
#include <linux/compiler.h>
#include <linux/kernel.h>
+#include <linux/mm.h>
#include <linux/smp.h>
+#include <linux/spinlock.h>
#include <linux/stop_machine.h>
#include <linux/uaccess.h>
#include <asm/cacheflush.h>
+#include <asm/fixmap.h>
#include <asm/insn.h>
static int aarch64_insn_encoding_class[] = {
@@ -65,6 +68,36 @@ bool __kprobes aarch64_insn_is_nop(u32 insn)
}
}
+static DEFINE_SPINLOCK(patch_lock);
+
+static void __kprobes *patch_map(void *addr, int fixmap, unsigned long *flags)
+{
+ unsigned long uintaddr = (uintptr_t) addr;
+ bool module = !core_kernel_text(uintaddr);
+ struct page *page;
+
+ if (module && IS_ENABLED(CONFIG_DEBUG_SET_MODULE_RONX))
+ page = vmalloc_to_page(addr);
+ else if (!module && IS_ENABLED(CONFIG_DEBUG_RODATA))
+ page = virt_to_page(addr);
+ else
+ return addr;
+
+ if (flags)
+ spin_lock_irqsave(&patch_lock, *flags);
+
+ set_fixmap(fixmap, page_to_phys(page));
+
+ return (void *) (__fix_to_virt(fixmap) + (uintaddr & ~PAGE_MASK));
+}
+
+static void __kprobes patch_unmap(int fixmap, unsigned long *flags)
+{
+ clear_fixmap(fixmap);
+
+ if (flags)
+ spin_unlock_irqrestore(&patch_lock, *flags);
+}
/*
* In ARMv8-A, A64 instructions have a fixed length of 32 bits and are always
* little-endian.
@@ -81,10 +114,36 @@ int __kprobes aarch64_insn_read(void *addr, u32 *insnp)
return ret;
}
+static int __kprobes __aarch64_insn_write(void *addr, u32 insn, bool patch)
+{
+ void *waddr = addr;
+ unsigned long flags;
+ int ret;
+
+ if (patch)
+ waddr = patch_map(addr, FIX_TEXT_POKE0, &flags);
+
+ ret = probe_kernel_write(waddr, &insn, AARCH64_INSN_SIZE);
+
+ if (waddr != addr) {
+ __flush_dcache_area(waddr, AARCH64_INSN_SIZE);
+ patch_unmap(FIX_TEXT_POKE0, &flags);
+ }
+
+ return ret;
+}
+
int __kprobes aarch64_insn_write(void *addr, u32 insn)
{
insn = cpu_to_le32(insn);
- return probe_kernel_write(addr, &insn, AARCH64_INSN_SIZE);
+ return __aarch64_insn_write(addr, insn, true);
+}
+
+int __kprobes aarch64_insn_write_early(void *addr, u32 insn)
+{
+ insn = cpu_to_le32(insn);
+ return __aarch64_insn_write(addr, insn, false);
+
}
static bool __kprobes __aarch64_insn_hotpatch_safe(u32 insn)
@@ -117,7 +176,7 @@ bool __kprobes aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn)
__aarch64_insn_hotpatch_safe(new_insn);
}
-int __kprobes aarch64_insn_patch_text_nosync(void *addr, u32 insn)
+int __kprobes __aarch64_insn_patch_text_nosync(void *addr, u32 insn, bool early)
{
u32 *tp = addr;
int ret;
@@ -126,7 +185,11 @@ int __kprobes aarch64_insn_patch_text_nosync(void *addr, u32 insn)
if ((uintptr_t)tp & 0x3)
return -EINVAL;
- ret = aarch64_insn_write(tp, insn);
+ if (early)
+ ret = aarch64_insn_write_early(tp, insn);
+ else
+ ret = aarch64_insn_write(tp, insn);
+
if (ret == 0)
flush_icache_range((uintptr_t)tp,
(uintptr_t)tp + AARCH64_INSN_SIZE);
@@ -134,6 +197,11 @@ int __kprobes aarch64_insn_patch_text_nosync(void *addr, u32 insn)
return ret;
}
+int __kprobes aarch64_insn_patch_text_nosync(void *addr, u32 insn)
+{
+ return __aarch64_insn_patch_text_nosync(addr, insn, false);
+}
+
struct aarch64_insn_patch {
void **text_addrs;
u32 *new_insns;
diff --git a/arch/arm64/kernel/jump_label.c b/arch/arm64/kernel/jump_label.c
index 263a166..9ac30bb 100644
--- a/arch/arm64/kernel/jump_label.c
+++ b/arch/arm64/kernel/jump_label.c
@@ -38,7 +38,7 @@ static void __arch_jump_label_transform(struct jump_entry *entry,
}
if (is_static)
- aarch64_insn_patch_text_nosync(addr, insn);
+ __aarch64_insn_patch_text_nosync(addr, insn, true);
else
aarch64_insn_patch_text(&addr, &insn, 1);
}
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
next prev parent reply other threads:[~2014-08-21 1:20 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-21 1:20 [PATCHv3 0/7] Better page protections for arm64 Laura Abbott
2014-08-21 1:20 ` [PATCHv3 1/7] arm64: Treat handle_arch_irq as a function pointer Laura Abbott
[not found] ` <CAGXu5jLur_gdXs2X5BCmxB6L5HwgyP12jkrufK7bpS0Cxhp_+Q@mail.gmail.com>
2014-08-25 18:23 ` Laura Abbott
2014-08-28 17:02 ` Catalin Marinas
2014-08-21 1:20 ` [PATCHv3 2/7] arm64: Switch to ldr for loading the stub vectors Laura Abbott
2014-08-21 9:30 ` Mark Rutland
2014-08-21 1:20 ` [PATCHv3 3/7] arm64: Move cpu_resume into the text section Laura Abbott
2014-08-25 20:34 ` Stephen Boyd
2014-08-26 0:43 ` Laura Abbott
2014-08-26 1:08 ` Stephen Boyd
2014-08-21 1:20 ` [PATCHv3 4/7] arm64: Move some head.text functions to executable section Laura Abbott
2014-08-21 10:34 ` Mark Rutland
2014-08-21 21:42 ` Laura Abbott
2014-08-22 9:48 ` Mark Rutland
2014-08-26 0:32 ` Laura Abbott
2014-08-26 17:45 ` Mark Rutland
2014-08-21 1:20 ` [PATCHv3 5/7] arm64: Factor out fixmap initialiation from ioremap Laura Abbott
2014-08-23 5:45 ` Kees Cook
2014-08-25 18:34 ` Laura Abbott
2014-08-21 1:20 ` Laura Abbott [this message]
2014-08-23 5:51 ` [PATCHv3 6/7] arm64: use fixmap for text patching when text is RO Kees Cook
2014-08-25 18:38 ` Laura Abbott
2014-08-26 18:36 ` Mark Rutland
2014-08-21 1:20 ` [PATCHv3 7/7] arm64: add better page protections to arm64 Laura Abbott
2014-08-23 5:59 ` Kees Cook
2014-08-25 19:04 ` Laura Abbott
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1408584039-12735-7-git-send-email-lauraa@codeaurora.org \
--to=lauraa@codeaurora.org \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.