From: dave.long@linaro.org (David Long)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC PATCH] uprobes: copy to user-space xol page with proper cache flushing
Date: Thu, 10 Apr 2014 23:45:31 -0400 [thread overview]
Message-ID: <5347655B.3080307@linaro.org> (raw)
In-Reply-To: <CAA3XUr3w_9318mT2_9+J-nf3wDv5bic+v0H4nVfsYof7wWZs9Q@mail.gmail.com>
Replace memcpy and dcache flush in generic uprobes with a call to
copy_to_user_page(), which will do a proper flushing of kernel and
user cache. Also modify the inmplementation of copy_to_user_page
to assume a NULL vma pointer means the user icache corresponding
to this right is stale and needs to be flushed. Note that this patch
does not fix copy_to_user page for the sh, alpha, sparc, or mips
architectures (which do not currently support uprobes).
Signed-off-by: David A. Long <dave.long@linaro.org>
---
arch/arc/include/asm/cacheflush.h | 2 +-
arch/arm/mm/flush.c | 4 ++--
arch/arm64/mm/flush.c | 2 +-
arch/avr32/mm/cache.c | 2 +-
arch/hexagon/include/asm/cacheflush.h | 2 +-
arch/m68k/include/asm/cacheflush_mm.h | 2 +-
arch/microblaze/include/asm/cacheflush.h | 2 +-
arch/mips/mm/init.c | 2 +-
arch/parisc/include/asm/tlbflush.h | 4 ++++
arch/parisc/kernel/cache.c | 4 ++--
arch/score/include/asm/cacheflush.h | 2 +-
arch/score/mm/cache.c | 2 +-
arch/sh/mm/cache.c | 2 +-
arch/sparc/mm/leon_mm.c | 2 +-
arch/tile/include/asm/cacheflush.h | 2 +-
arch/unicore32/mm/flush.c | 2 +-
arch/xtensa/mm/cache.c | 4 ++--
kernel/events/uprobes.c | 7 +------
18 files changed, 24 insertions(+), 25 deletions(-)
diff --git a/arch/arc/include/asm/cacheflush.h b/arch/arc/include/asm/cacheflush.h
index 6abc497..64d67e4 100644
--- a/arch/arc/include/asm/cacheflush.h
+++ b/arch/arc/include/asm/cacheflush.h
@@ -110,7 +110,7 @@ static inline int cache_is_vipt_aliasing(void)
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \
memcpy(dst, src, len); \
- if (vma->vm_flags & VM_EXEC) \
+ if (!vma || vma->vm_flags & VM_EXEC) \
__sync_icache_dcache((unsigned long)(dst), vaddr, len); \
} while (0)
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 3387e60..dd19ad4 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -114,7 +114,7 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
unsigned long uaddr, void *kaddr, unsigned long len)
{
if (cache_is_vivt()) {
- if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) {
+ if (!vma || cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) {
unsigned long addr = (unsigned long)kaddr;
__cpuc_coherent_kern_range(addr, addr + len);
}
@@ -128,7 +128,7 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
}
/* VIPT non-aliasing D-cache */
- if (vma->vm_flags & VM_EXEC) {
+ if (!vma || vma->vm_flags & VM_EXEC) {
unsigned long addr = (unsigned long)kaddr;
if (icache_is_vipt_aliasing())
flush_icache_alias(page_to_pfn(page), uaddr, len);
diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
index e4193e3..cde3cb4 100644
--- a/arch/arm64/mm/flush.c
+++ b/arch/arm64/mm/flush.c
@@ -38,7 +38,7 @@ static void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
unsigned long uaddr, void *kaddr,
unsigned long len)
{
- if (vma->vm_flags & VM_EXEC) {
+ if (!vma || vma->vm_flags & VM_EXEC) {
unsigned long addr = (unsigned long)kaddr;
if (icache_is_aliasing()) {
__flush_dcache_area(kaddr, len);
diff --git a/arch/avr32/mm/cache.c b/arch/avr32/mm/cache.c
index 6a46ecd..cd3d378 100644
--- a/arch/avr32/mm/cache.c
+++ b/arch/avr32/mm/cache.c
@@ -156,7 +156,7 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long len)
{
memcpy(dst, src, len);
- if (vma->vm_flags & VM_EXEC)
+ if (!vma || vma->vm_flags & VM_EXEC)
flush_icache_range((unsigned long)dst,
(unsigned long)dst + len);
}
diff --git a/arch/hexagon/include/asm/cacheflush.h b/arch/hexagon/include/asm/cacheflush.h
index 49e0896..9bea768 100644
--- a/arch/hexagon/include/asm/cacheflush.h
+++ b/arch/hexagon/include/asm/cacheflush.h
@@ -86,7 +86,7 @@ static inline void copy_to_user_page(struct vm_area_struct *vma,
void *dst, void *src, int len)
{
memcpy(dst, src, len);
- if (vma->vm_flags & VM_EXEC) {
+ if (!vma || vma->vm_flags & VM_EXEC) {
flush_icache_range((unsigned long) dst,
(unsigned long) dst + len);
}
diff --git a/arch/m68k/include/asm/cacheflush_mm.h b/arch/m68k/include/asm/cacheflush_mm.h
index fa2c3d6..afefdeb 100644
--- a/arch/m68k/include/asm/cacheflush_mm.h
+++ b/arch/m68k/include/asm/cacheflush_mm.h
@@ -212,7 +212,7 @@ static inline void flush_cache_range(struct vm_area_struct *vma,
static inline void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
{
- if (vma->vm_mm == current->mm)
+ if (!vma || vma->vm_mm == current->mm)
__flush_cache_030();
}
diff --git a/arch/microblaze/include/asm/cacheflush.h b/arch/microblaze/include/asm/cacheflush.h
index ffea82a..9eef956 100644
--- a/arch/microblaze/include/asm/cacheflush.h
+++ b/arch/microblaze/include/asm/cacheflush.h
@@ -108,7 +108,7 @@ static inline void copy_to_user_page(struct vm_area_struct *vma,
{
u32 addr = virt_to_phys(dst);
memcpy(dst, src, len);
- if (vma->vm_flags & VM_EXEC) {
+ if (!vma || vma->vm_flags & VM_EXEC) {
invalidate_icache_range(addr, addr + PAGE_SIZE);
flush_dcache_range(addr, addr + PAGE_SIZE);
}
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 6b59617..e428551 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -232,7 +232,7 @@ void copy_to_user_page(struct vm_area_struct *vma,
if (cpu_has_dc_aliases)
SetPageDcacheDirty(page);
}
- if ((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc)
+ if ((!vma || vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc)
flush_cache_page(vma, vaddr, page_to_pfn(page));
}
diff --git a/arch/parisc/include/asm/tlbflush.h b/arch/parisc/include/asm/tlbflush.h
index 9d086a5..7aad1b6 100644
--- a/arch/parisc/include/asm/tlbflush.h
+++ b/arch/parisc/include/asm/tlbflush.h
@@ -68,6 +68,10 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
/* For one page, it's not worth testing the split_tlb variable */
mb();
+ if (!vma) {
+ flush_tlb_all();
+ return;
+ }
sid = vma->vm_mm->context;
purge_tlb_start(flags);
mtsp(sid, 1);
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index ac87a40..ff09f05 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -278,7 +278,7 @@ __flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
{
preempt_disable();
flush_dcache_page_asm(physaddr, vmaddr);
- if (vma->vm_flags & VM_EXEC)
+ if (!vma || vma->vm_flags & VM_EXEC)
flush_icache_page_asm(physaddr, vmaddr);
preempt_enable();
}
@@ -574,7 +574,7 @@ void flush_cache_range(struct vm_area_struct *vma,
void
flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
{
- BUG_ON(!vma->vm_mm->context);
+ BUG_ON(vma && !vma->vm_mm->context);
if (pfn_valid(pfn)) {
flush_tlb_page(vma, vmaddr);
diff --git a/arch/score/include/asm/cacheflush.h b/arch/score/include/asm/cacheflush.h
index 1d545d0..63e7b4e 100644
--- a/arch/score/include/asm/cacheflush.h
+++ b/arch/score/include/asm/cacheflush.h
@@ -41,7 +41,7 @@ static inline void flush_icache_page(struct vm_area_struct *vma,
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \
memcpy(dst, src, len); \
- if ((vma->vm_flags & VM_EXEC)) \
+ if (!vma || (vma->vm_flags & VM_EXEC)) \
flush_cache_page(vma, vaddr, page_to_pfn(page));\
} while (0)
diff --git a/arch/score/mm/cache.c b/arch/score/mm/cache.c
index f85ec1a..8464575 100644
--- a/arch/score/mm/cache.c
+++ b/arch/score/mm/cache.c
@@ -210,7 +210,7 @@ void flush_cache_range(struct vm_area_struct *vma,
void flush_cache_page(struct vm_area_struct *vma,
unsigned long addr, unsigned long pfn)
{
- int exec = vma->vm_flags & VM_EXEC;
+ int exec = !vma || vma->vm_flags & VM_EXEC;
unsigned long kaddr = 0xa0000000 | (pfn << PAGE_SHIFT);
flush_dcache_range(kaddr, kaddr + PAGE_SIZE);
diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c
index 616966a..ba2313a 100644
--- a/arch/sh/mm/cache.c
+++ b/arch/sh/mm/cache.c
@@ -70,7 +70,7 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
clear_bit(PG_dcache_clean, &page->flags);
}
- if (vma->vm_flags & VM_EXEC)
+ if (!vma || vma->vm_flags & VM_EXEC)
flush_cache_page(vma, vaddr, page_to_pfn(page));
}
diff --git a/arch/sparc/mm/leon_mm.c b/arch/sparc/mm/leon_mm.c
index 5bed085..dca5e18 100644
--- a/arch/sparc/mm/leon_mm.c
+++ b/arch/sparc/mm/leon_mm.c
@@ -192,7 +192,7 @@ void leon_flush_dcache_all(void)
void leon_flush_pcache_all(struct vm_area_struct *vma, unsigned long page)
{
- if (vma->vm_flags & VM_EXEC)
+ if (!vma || vma->vm_flags & VM_EXEC)
leon_flush_icache_all();
leon_flush_dcache_all();
}
diff --git a/arch/tile/include/asm/cacheflush.h b/arch/tile/include/asm/cacheflush.h
index 92ee4c8..7b7022c 100644
--- a/arch/tile/include/asm/cacheflush.h
+++ b/arch/tile/include/asm/cacheflush.h
@@ -66,7 +66,7 @@ static inline void copy_to_user_page(struct vm_area_struct *vma,
void *dst, void *src, int len)
{
memcpy(dst, src, len);
- if (vma->vm_flags & VM_EXEC) {
+ if (!vma || vma->vm_flags & VM_EXEC) {
flush_icache_range((unsigned long) dst,
(unsigned long) dst + len);
}
diff --git a/arch/unicore32/mm/flush.c b/arch/unicore32/mm/flush.c
index 6d4c096..10ddab3 100644
--- a/arch/unicore32/mm/flush.c
+++ b/arch/unicore32/mm/flush.c
@@ -36,7 +36,7 @@ static void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
unsigned long uaddr, void *kaddr, unsigned long len)
{
/* VIPT non-aliasing D-cache */
- if (vma->vm_flags & VM_EXEC) {
+ if (!vma || vma->vm_flags & VM_EXEC) {
unsigned long addr = (unsigned long)kaddr;
__cpuc_coherent_kern_range(addr, addr + len);
diff --git a/arch/xtensa/mm/cache.c b/arch/xtensa/mm/cache.c
index ba4c47f..d34c06c 100644
--- a/arch/xtensa/mm/cache.c
+++ b/arch/xtensa/mm/cache.c
@@ -221,10 +221,10 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
__flush_invalidate_dcache_range((unsigned long) dst, len);
- if ((vma->vm_flags & VM_EXEC) != 0)
+ if (!vma || (vma->vm_flags & VM_EXEC) != 0)
__invalidate_icache_page_alias(t, phys);
- } else if ((vma->vm_flags & VM_EXEC) != 0) {
+ } else if (!vma || (vma->vm_flags & VM_EXEC) != 0) {
__flush_dcache_range((unsigned long)dst,len);
__invalidate_icache_range((unsigned long) dst, len);
}
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 04709b6..2e976fb 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -241,7 +241,7 @@ static void copy_from_page(struct page *page, unsigned long vaddr, void *dst, in
static void copy_to_page(struct page *page, unsigned long vaddr, const void *src, int len)
{
void *kaddr = kmap_atomic(page);
- memcpy(kaddr + (vaddr & ~PAGE_MASK), src, len);
+ copy_to_user_page(NULL, page, vaddr, kaddr + (vaddr & ~PAGE_MASK), src, len);
kunmap_atomic(kaddr);
}
@@ -1299,11 +1299,6 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
/* Initialize the slot */
copy_to_page(area->page, xol_vaddr,
&uprobe->arch.ixol, sizeof(uprobe->arch.ixol));
- /*
- * We probably need flush_icache_user_range() but it needs vma.
- * This should work on supported architectures too.
- */
- flush_dcache_page(area->page);
return xol_vaddr;
}
--
1.8.1.2
next prev parent reply other threads:[~2014-04-11 3:45 UTC|newest]
Thread overview: 66+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-09 5:58 [PATCH v2] ARM: uprobes need icache flush after xol write Victor Kamensky
2014-04-09 5:58 ` Victor Kamensky
2014-04-09 18:23 ` David Long
2014-04-09 18:45 ` Oleg Nesterov
2014-04-09 19:13 ` Victor Kamensky
2014-04-09 19:19 ` Russell King - ARM Linux
2014-04-11 3:42 ` [RFC PATCH] uprobes: copy to user-space xol page with proper cache flushing David Long
2014-04-11 3:45 ` David Long [this message]
2014-04-11 4:36 ` David Miller
2014-04-11 14:26 ` Victor Kamensky
2014-04-11 14:35 ` Oleg Nesterov
2014-04-11 14:55 ` Victor Kamensky
2014-04-11 14:56 ` Oleg Nesterov
2014-04-11 15:22 ` Oleg Nesterov
2014-04-11 15:30 ` Russell King - ARM Linux
2014-04-11 17:24 ` Oleg Nesterov
2014-04-11 17:38 ` Oleg Nesterov
2014-04-11 18:00 ` David Miller
2014-04-11 18:25 ` Oleg Nesterov
2014-04-11 17:50 ` Linus Torvalds
2014-04-11 18:02 ` David Miller
2014-04-11 18:11 ` Linus Torvalds
2014-04-11 18:19 ` David Miller
2014-04-11 18:24 ` Linus Torvalds
2014-04-11 18:58 ` David Miller
2014-04-11 19:24 ` Linus Torvalds
2014-04-11 18:13 ` Victor Kamensky
2014-04-11 18:36 ` Oleg Nesterov
2014-04-14 18:59 ` Oleg Nesterov
2014-04-14 20:05 ` Victor Kamensky
2014-04-14 21:40 ` Victor Kamensky
2014-04-15 16:26 ` Oleg Nesterov
2014-04-15 15:46 ` Oleg Nesterov
2014-04-15 16:46 ` Victor Kamensky
2014-04-15 17:19 ` David Long
2014-04-15 17:38 ` David Miller
2014-04-15 17:49 ` Oleg Nesterov
2014-04-15 17:50 ` David Miller
2014-04-15 18:07 ` Oleg Nesterov
2014-04-15 18:27 ` David Miller
2014-04-15 18:46 ` Oleg Nesterov
2014-04-15 17:43 ` Oleg Nesterov
2014-04-15 17:46 ` David Miller
2014-04-15 18:03 ` Oleg Nesterov
2014-04-15 18:30 ` David Miller
2014-04-15 18:47 ` Russell King - ARM Linux
2014-04-15 18:53 ` David Miller
2014-04-15 18:50 ` David Miller
2014-04-15 19:29 ` Russell King - ARM Linux
2014-04-15 19:51 ` David Miller
2014-04-15 19:39 ` David Long
2014-04-15 19:53 ` David Miller
2014-04-16 1:42 ` Victor Kamensky
2014-04-16 2:22 ` David Miller
2014-04-16 2:24 ` David Miller
2014-04-16 3:06 ` Victor Kamensky
2014-04-16 3:17 ` David Miller
2014-04-11 17:43 ` David Miller
2014-04-11 15:32 ` Peter Zijlstra
2014-04-11 16:00 ` Russell King - ARM Linux
2014-04-11 18:39 ` Peter Zijlstra
2014-04-11 15:37 ` Victor Kamensky
2014-04-11 16:22 ` Oleg Nesterov
2014-04-11 15:42 ` Linus Torvalds
2014-04-11 13:08 ` Oleg Nesterov
2014-04-23 10:45 ` Catalin Marinas
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=5347655B.3080307@linaro.org \
--to=dave.long@linaro.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).