All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/2] Consolidate patch_instruction
@ 2017-05-16  3:49 Balbir Singh
  2017-05-16  3:49 ` [RFC 1/2] powerpc/lib/code-patching: Enhance code patching Balbir Singh
                   ` (3 more replies)
  0 siblings, 4 replies; 12+ messages in thread
From: Balbir Singh @ 2017-05-16  3:49 UTC (permalink / raw)
  To: linuxppc-dev, mpe; +Cc: naveen.n.rao, ananth, Balbir Singh

patch_instruction is enhanced in this RFC to support
patching via a different virtual address (text_poke_area).
The mapping of text_poke_area->addr is RW and not RWX.
This way the mapping allows write for patching and then we tear
down the mapping. The downside is that we introduce a spinlock
which serializes our patching to one patch at a time.

In this patchset we also consolidate instruction changes
in kprobes to use patch_instruction().

Balbir Singh (2):
  powerpc/lib/code-patching: Enhance code patching
  powerpc/kprobes: Move kprobes over to patch_instruction

 arch/powerpc/kernel/kprobes.c    |  4 +-
 arch/powerpc/lib/code-patching.c | 88 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 86 insertions(+), 6 deletions(-)

-- 
2.9.3

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [RFC 1/2] powerpc/lib/code-patching: Enhance code patching
  2017-05-16  3:49 [RFC 0/2] Consolidate patch_instruction Balbir Singh
@ 2017-05-16  3:49 ` Balbir Singh
  2017-05-16  3:49 ` [RFC 2/2] powerpc/kprobes: Move kprobes over to patch_instruction Balbir Singh
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 12+ messages in thread
From: Balbir Singh @ 2017-05-16  3:49 UTC (permalink / raw)
  To: linuxppc-dev, mpe; +Cc: naveen.n.rao, ananth, Balbir Singh

Today our patching happens via direct copy and
patch_instruction. The patching code is well
contained in the sense that copying bits are limited.

While considering implementation of CONFIG_STRICT_RWX,
the first requirement is to a create another mapping
that will allow for patching. We create the window using
text_poke_area, allocated via get_vm_area(), which might
be an overkill. We can do per-cpu stuff as well. The
downside of these patches that patch_instruction is
now synchornized using a lock. Other arches do similar
things, but use fixmaps. The reason for not using
fixmaps is to make use of any randomization in the
future. The code also relies on set_pte_at and pte_clear
to do the appropriate tlb flushing.

Signed-off-by: Balbir Singh <bsingharora@gmail.com>
---
 arch/powerpc/lib/code-patching.c | 88 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 84 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 500b0f6..4aae016 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -16,19 +16,98 @@
 #include <asm/code-patching.h>
 #include <linux/uaccess.h>
 #include <linux/kprobes.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
 
+struct vm_struct *text_poke_area;
+static DEFINE_RAW_SPINLOCK(text_poke_lock);
 
-int patch_instruction(unsigned int *addr, unsigned int instr)
+/*
+ * This is an early_initcall and early_initcalls happen at the right time
+ * for us, after slab is enabled and before we mark ro pages R/O. In the
+ * future if get_vm_area is randomized, this will be more flexible than
+ * fixmap
+ */
+static int __init setup_text_poke_area(void)
 {
+	text_poke_area = get_vm_area(PAGE_SIZE, VM_ALLOC);
+	if (!text_poke_area) {
+		WARN_ONCE(1, "could not create area for mapping kernel addrs"
+				" which allow for patching kernel code\n");
+		return 0;
+	}
+	pr_info("text_poke area ready...\n");
+	raw_spin_lock_init(&text_poke_lock);
+	return 0;
+}
+
+/*
+ * This can be called for kernel text or a module.
+ */
+static int kernel_map_addr(void *addr)
+{
+	unsigned long pfn;
 	int err;
 
-	__put_user_size(instr, addr, 4, err);
+	if (is_vmalloc_addr(addr))
+		pfn = vmalloc_to_pfn(addr);
+	else
+		pfn = __pa_symbol(addr) >> PAGE_SHIFT;
+
+	err = map_kernel_page((unsigned long)text_poke_area->addr,
+				(pfn << PAGE_SHIFT), _PAGE_KERNEL_RW | _PAGE_PRESENT);
+	pr_devel("Mapped addr %p with pfn %lx\n", text_poke_area->addr, pfn);
 	if (err)
-		return err;
-	asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (addr));
+		return -1;
 	return 0;
 }
 
+static inline void kernel_unmap_addr(void *addr)
+{
+	pte_t *pte;
+	unsigned long kaddr = (unsigned long)addr;
+
+	pte = pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(kaddr),
+				kaddr), kaddr), kaddr);
+	pr_devel("clearing mm %p, pte %p, kaddr %lx\n", &init_mm, pte, kaddr);
+	pte_clear(&init_mm, kaddr, pte);
+}
+
+int patch_instruction(unsigned int *addr, unsigned int instr)
+{
+	int err;
+	unsigned int *dest = NULL;
+	unsigned long flags;
+	unsigned long kaddr = (unsigned long)addr;
+
+	/*
+	 * During early early boot patch_instruction is called
+	 * when text_poke_area is not ready, but we still need
+	 * to allow patching. We just do the plain old patching
+	 */
+	if (!text_poke_area) {
+		__put_user_size(instr, addr, 4, err);
+		asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (addr));
+		return 0;
+	}
+
+	raw_spin_lock_irqsave(&text_poke_lock, flags);
+	if (kernel_map_addr(addr)) {
+		err = -1;
+		goto out;
+	}
+
+	dest = (unsigned int *)(text_poke_area->addr) +
+		((kaddr & ~PAGE_MASK) / sizeof(unsigned int));
+	__put_user_size(instr, dest, 4, err);
+	asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (dest));
+	kernel_unmap_addr(text_poke_area->addr);
+out:
+	raw_spin_unlock_irqrestore(&text_poke_lock, flags);
+	return err;
+}
+NOKPROBE_SYMBOL(patch_instruction);
+
 int patch_branch(unsigned int *addr, unsigned long target, int flags)
 {
 	return patch_instruction(addr, create_branch(addr, target, flags));
@@ -514,3 +593,4 @@ static int __init test_code_patching(void)
 late_initcall(test_code_patching);
 
 #endif /* CONFIG_CODE_PATCHING_SELFTEST */
+early_initcall(setup_text_poke_area);
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [RFC 2/2] powerpc/kprobes: Move kprobes over to patch_instruction
  2017-05-16  3:49 [RFC 0/2] Consolidate patch_instruction Balbir Singh
  2017-05-16  3:49 ` [RFC 1/2] powerpc/lib/code-patching: Enhance code patching Balbir Singh
@ 2017-05-16  3:49 ` Balbir Singh
  2017-05-16 13:35   ` Naveen N. Rao
  2017-05-16  5:26 ` [RFC 0/2] Consolidate patch_instruction Anshuman Khandual
  2017-05-16 20:20 ` LEROY Christophe
  3 siblings, 1 reply; 12+ messages in thread
From: Balbir Singh @ 2017-05-16  3:49 UTC (permalink / raw)
  To: linuxppc-dev, mpe; +Cc: naveen.n.rao, ananth, Balbir Singh

arch_arm/disarm_probe use direct assignment for copying
instructions, replace them with patch_instruction

Signed-off-by: Balbir Singh <bsingharora@gmail.com>
---
 arch/powerpc/kernel/kprobes.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 160ae0f..5e1fa86 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -158,7 +158,7 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe);
 
 void arch_arm_kprobe(struct kprobe *p)
 {
-	*p->addr = BREAKPOINT_INSTRUCTION;
+	patch_instruction(p->addr, BREAKPOINT_INSTRUCTION);
 	flush_icache_range((unsigned long) p->addr,
 			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
 }
@@ -166,7 +166,7 @@ NOKPROBE_SYMBOL(arch_arm_kprobe);
 
 void arch_disarm_kprobe(struct kprobe *p)
 {
-	*p->addr = p->opcode;
+	patch_instruction(p->addr, BREAKPOINT_INSTRUCTION);
 	flush_icache_range((unsigned long) p->addr,
 			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
 }
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [RFC 0/2] Consolidate patch_instruction
  2017-05-16  3:49 [RFC 0/2] Consolidate patch_instruction Balbir Singh
  2017-05-16  3:49 ` [RFC 1/2] powerpc/lib/code-patching: Enhance code patching Balbir Singh
  2017-05-16  3:49 ` [RFC 2/2] powerpc/kprobes: Move kprobes over to patch_instruction Balbir Singh
@ 2017-05-16  5:26 ` Anshuman Khandual
  2017-05-16 13:41   ` Naveen N. Rao
  2017-05-16 20:20 ` LEROY Christophe
  3 siblings, 1 reply; 12+ messages in thread
From: Anshuman Khandual @ 2017-05-16  5:26 UTC (permalink / raw)
  To: Balbir Singh, linuxppc-dev, mpe; +Cc: naveen.n.rao

On 05/16/2017 09:19 AM, Balbir Singh wrote:
> patch_instruction is enhanced in this RFC to support
> patching via a different virtual address (text_poke_area).

Why writing instruction directly into the address is not
sufficient and need to go through this virtual address ?

> The mapping of text_poke_area->addr is RW and not RWX.
> This way the mapping allows write for patching and then we tear
> down the mapping. The downside is that we introduce a spinlock
> which serializes our patching to one patch at a time.

So whats the benifits we get otherwise in this approach when
we are adding a new lock into the equation.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC 2/2] powerpc/kprobes: Move kprobes over to patch_instruction
  2017-05-16  3:49 ` [RFC 2/2] powerpc/kprobes: Move kprobes over to patch_instruction Balbir Singh
@ 2017-05-16 13:35   ` Naveen N. Rao
  2017-05-17  1:40     ` Balbir Singh
  0 siblings, 1 reply; 12+ messages in thread
From: Naveen N. Rao @ 2017-05-16 13:35 UTC (permalink / raw)
  To: Balbir Singh; +Cc: linuxppc-dev, mpe, ananth

On 2017/05/16 01:49PM, Balbir Singh wrote:
> arch_arm/disarm_probe use direct assignment for copying
> instructions, replace them with patch_instruction

Thanks for doing this!

We will also have to convert optprobes and ftrace to use 
patch_instruction, but that can be done once the basic infrastructure is 
in.

Regards,
Naveen

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC 0/2] Consolidate patch_instruction
  2017-05-16  5:26 ` [RFC 0/2] Consolidate patch_instruction Anshuman Khandual
@ 2017-05-16 13:41   ` Naveen N. Rao
  2017-05-17  1:23     ` Balbir Singh
  0 siblings, 1 reply; 12+ messages in thread
From: Naveen N. Rao @ 2017-05-16 13:41 UTC (permalink / raw)
  To: Anshuman Khandual; +Cc: Balbir Singh, linuxppc-dev, mpe

On 2017/05/16 10:56AM, Anshuman Khandual wrote:
> On 05/16/2017 09:19 AM, Balbir Singh wrote:
> > patch_instruction is enhanced in this RFC to support
> > patching via a different virtual address (text_poke_area).
> 
> Why writing instruction directly into the address is not
> sufficient and need to go through this virtual address ?

To enable KERNEL_STRICT_RWX and map all of kernel text to be read-only?

> 
> > The mapping of text_poke_area->addr is RW and not RWX.
> > This way the mapping allows write for patching and then we tear
> > down the mapping. The downside is that we introduce a spinlock
> > which serializes our patching to one patch at a time.
> 
> So whats the benifits we get otherwise in this approach when
> we are adding a new lock into the equation.

Instruction patching isn't performance critical, so the slow down is 
likely not noticeable. Marking kernel text read-only helps harden the 
kernel by catching unintended code modifications whether through 
exploits or through bugs.

- Naveen

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC 0/2] Consolidate patch_instruction
  2017-05-16  3:49 [RFC 0/2] Consolidate patch_instruction Balbir Singh
                   ` (2 preceding siblings ...)
  2017-05-16  5:26 ` [RFC 0/2] Consolidate patch_instruction Anshuman Khandual
@ 2017-05-16 20:20 ` LEROY Christophe
  2017-05-17  2:10   ` Balbir Singh
  3 siblings, 1 reply; 12+ messages in thread
From: LEROY Christophe @ 2017-05-16 20:20 UTC (permalink / raw)
  To: Balbir Singh; +Cc: naveen.n.rao, mpe, linuxppc-dev

Balbir Singh <bsingharora@gmail.com> a =C3=A9crit=C2=A0:

> patch_instruction is enhanced in this RFC to support
> patching via a different virtual address (text_poke_area).
> The mapping of text_poke_area->addr is RW and not RWX.
> This way the mapping allows write for patching and then we tear
> down the mapping. The downside is that we introduce a spinlock
> which serializes our patching to one patch at a time.

Very nice patch, would fit great with my patch for impmementing=20=20
CONFIG_DEBUG_RODATA=20(https://patchwork.ozlabs.org/patch/754289 ).
Would avoid having to set the text area back to RW for patching

Christophe

>
> In this patchset we also consolidate instruction changes
> in kprobes to use patch_instruction().
>
> Balbir Singh (2):
>   powerpc/lib/code-patching: Enhance code patching
>   powerpc/kprobes: Move kprobes over to patch_instruction
>
>  arch/powerpc/kernel/kprobes.c    |  4 +-
>  arch/powerpc/lib/code-patching.c | 88=20=20
>=20++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 86 insertions(+), 6 deletions(-)
>
> --
> 2.9.3

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC 0/2] Consolidate patch_instruction
  2017-05-16 13:41   ` Naveen N. Rao
@ 2017-05-17  1:23     ` Balbir Singh
  0 siblings, 0 replies; 12+ messages in thread
From: Balbir Singh @ 2017-05-17  1:23 UTC (permalink / raw)
  To: Naveen N. Rao, Anshuman Khandual; +Cc: linuxppc-dev, mpe

On Tue, 2017-05-16 at 19:11 +0530, Naveen N. Rao wrote:
> On 2017/05/16 10:56AM, Anshuman Khandual wrote:
> > On 05/16/2017 09:19 AM, Balbir Singh wrote:
> > > patch_instruction is enhanced in this RFC to support
> > > patching via a different virtual address (text_poke_area).
> > 
> > Why writing instruction directly into the address is not
> > sufficient and need to go through this virtual address ?
> 
> To enable KERNEL_STRICT_RWX and map all of kernel text to be read-only?
>

Precisely, the rest of the bits are still being developed.
 
> > 
> > > The mapping of text_poke_area->addr is RW and not RWX.
> > > This way the mapping allows write for patching and then we tear
> > > down the mapping. The downside is that we introduce a spinlock
> > > which serializes our patching to one patch at a time.
> > 
> > So whats the benifits we get otherwise in this approach when
> > we are adding a new lock into the equation.
> 
> Instruction patching isn't performance critical, so the slow down is 
> likely not noticeable. Marking kernel text read-only helps harden the 
> kernel by catching unintended code modifications whether through 
> exploits or through bugs.
>

Precisely!

Balbir Singh. 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC 2/2] powerpc/kprobes: Move kprobes over to patch_instruction
  2017-05-16 13:35   ` Naveen N. Rao
@ 2017-05-17  1:40     ` Balbir Singh
  2017-05-30 14:28       ` Naveen N. Rao
  0 siblings, 1 reply; 12+ messages in thread
From: Balbir Singh @ 2017-05-17  1:40 UTC (permalink / raw)
  To: Naveen N. Rao; +Cc: linuxppc-dev, mpe, ananth

On Tue, 2017-05-16 at 19:05 +0530, Naveen N. Rao wrote:
> On 2017/05/16 01:49PM, Balbir Singh wrote:
> > arch_arm/disarm_probe use direct assignment for copying
> > instructions, replace them with patch_instruction
> 
> Thanks for doing this!
> 
> We will also have to convert optprobes and ftrace to use 
> patch_instruction, but that can be done once the basic infrastructure is 
> in.
>

I think these patches can go in without even patch 1. I looked quickly at
optprobes and ftrace and thought they were already using patch_instruction
(ftrace_modify_code() and arch_optimize_kprobes()), are there other paths
I missed?

Balbir Singh
 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC 0/2] Consolidate patch_instruction
  2017-05-16 20:20 ` LEROY Christophe
@ 2017-05-17  2:10   ` Balbir Singh
  2017-05-17  7:04     ` LEROY Christophe
  0 siblings, 1 reply; 12+ messages in thread
From: Balbir Singh @ 2017-05-17  2:10 UTC (permalink / raw)
  To: LEROY Christophe; +Cc: naveen.n.rao, mpe, linuxppc-dev

On Tue, 2017-05-16 at 22:20 +0200, LEROY Christophe wrote:
> Balbir Singh <bsingharora@gmail.com> a écrit :
> 
> > patch_instruction is enhanced in this RFC to support
> > patching via a different virtual address (text_poke_area).
> > The mapping of text_poke_area->addr is RW and not RWX.
> > This way the mapping allows write for patching and then we tear
> > down the mapping. The downside is that we introduce a spinlock
> > which serializes our patching to one patch at a time.
> 
> Very nice patch, would fit great with my patch for impmementing  
> CONFIG_DEBUG_RODATA (https://patchwork.ozlabs.org/patch/754289 ).
> Would avoid having to set the text area back to RW for patching
> 

Awesome! It seems like you have some of the work for CONFIG_STRICT_KERNEL_RWX
any reason why this is under CONFIG_DEBUG_RODATA? But I think there is
reuse capability across the future patches and the current set.

Cheers,
Balbir  Singh.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC 0/2] Consolidate patch_instruction
  2017-05-17  2:10   ` Balbir Singh
@ 2017-05-17  7:04     ` LEROY Christophe
  0 siblings, 0 replies; 12+ messages in thread
From: LEROY Christophe @ 2017-05-17  7:04 UTC (permalink / raw)
  To: Balbir Singh; +Cc: linuxppc-dev, mpe, naveen.n.rao

Balbir Singh <bsingharora@gmail.com> a =C3=A9crit=C2=A0:

> On Tue, 2017-05-16 at 22:20 +0200, LEROY Christophe wrote:
>> Balbir Singh <bsingharora@gmail.com> a =C3=A9crit=C2=A0:
>>
>> > patch_instruction is enhanced in this RFC to support
>> > patching via a different virtual address (text_poke_area).
>> > The mapping of text_poke_area->addr is RW and not RWX.
>> > This way the mapping allows write for patching and then we tear
>> > down the mapping. The downside is that we introduce a spinlock
>> > which serializes our patching to one patch at a time.
>>
>> Very nice patch, would fit great with my patch for impmementing
>> CONFIG_DEBUG_RODATA (https://patchwork.ozlabs.org/patch/754289 ).
>> Would avoid having to set the text area back to RW for patching
>>
>
> Awesome! It seems like you have some of the work for CONFIG_STRICT_KERNEL=
_RWX
> any reason why this is under CONFIG_DEBUG_RODATA? But I think there is
> reuse capability across the future patches and the current set.
>

Indeed it looks the same, see https://patchwork.kernel.org/patch/9554881

Christophe


> Cheers,
> Balbir  Singh.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC 2/2] powerpc/kprobes: Move kprobes over to patch_instruction
  2017-05-17  1:40     ` Balbir Singh
@ 2017-05-30 14:28       ` Naveen N. Rao
  0 siblings, 0 replies; 12+ messages in thread
From: Naveen N. Rao @ 2017-05-30 14:28 UTC (permalink / raw)
  To: Balbir Singh; +Cc: linuxppc-dev, mpe, ananth

On 2017/05/17 11:40AM, Balbir Singh wrote:
> On Tue, 2017-05-16 at 19:05 +0530, Naveen N. Rao wrote:
> > On 2017/05/16 01:49PM, Balbir Singh wrote:
> > > arch_arm/disarm_probe use direct assignment for copying
> > > instructions, replace them with patch_instruction
> > 
> > Thanks for doing this!
> > 
> > We will also have to convert optprobes and ftrace to use 
> > patch_instruction, but that can be done once the basic infrastructure is 
> > in.
> >
> 
> I think these patches can go in without even patch 1. I looked quickly at
> optprobes and ftrace and thought they were already using patch_instruction
> (ftrace_modify_code() and arch_optimize_kprobes()), are there other paths
> I missed?

[Sorry for the delay...]

Yes, all the patch_*_insns() functions need to be converted since the 
area they patch comes from .text. There is also a memcpy() where we copy 
the instruction template in, so perhaps a patch_instructions() helper 
may be useful too.

- Naveen

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-05-30 14:29 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-16  3:49 [RFC 0/2] Consolidate patch_instruction Balbir Singh
2017-05-16  3:49 ` [RFC 1/2] powerpc/lib/code-patching: Enhance code patching Balbir Singh
2017-05-16  3:49 ` [RFC 2/2] powerpc/kprobes: Move kprobes over to patch_instruction Balbir Singh
2017-05-16 13:35   ` Naveen N. Rao
2017-05-17  1:40     ` Balbir Singh
2017-05-30 14:28       ` Naveen N. Rao
2017-05-16  5:26 ` [RFC 0/2] Consolidate patch_instruction Anshuman Khandual
2017-05-16 13:41   ` Naveen N. Rao
2017-05-17  1:23     ` Balbir Singh
2017-05-16 20:20 ` LEROY Christophe
2017-05-17  2:10   ` Balbir Singh
2017-05-17  7:04     ` LEROY Christophe

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.