aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCatalin Marinas2013-05-07 10:57:06 -0500
committerGreg Kroah-Hartman2013-05-11 15:53:59 -0500
commita0ca61ff1b18a11e7e7d085aa282a5593fb25126 (patch)
tree8ea7a2cdc766f70f6060d63e1fe8be08c77352e3
parent1d3a7eb266a154bbb90da4c7a9b992c4a3d75c22 (diff)
downloadkernel-omap-a0ca61ff1b18a11e7e7d085aa282a5593fb25126.tar.gz
kernel-omap-a0ca61ff1b18a11e7e7d085aa282a5593fb25126.tar.xz
kernel-omap-a0ca61ff1b18a11e7e7d085aa282a5593fb25126.zip
arm64: Ignore the 'write' ESR flag on cache maintenance faults
commit 0e7f7bcc3fc87489cda5aa6aff8ce40eed912279 upstream. ESR.WnR bit is always set on data cache maintenance faults even though the page is not required to have write permission. If a translation fault (page not yet mapped) happens for read-only user address range, Linux incorrectly assumes a permission fault. This patch adds the check of the ESR.CM bit during the page fault handling to ignore the 'write' flag. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Reported-by: Tim Northover <Tim.Northover@arm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--arch/arm64/mm/fault.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index afadae6682ed..0782eaf49136 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -148,6 +148,7 @@ void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs)
148#define VM_FAULT_BADACCESS 0x020000 148#define VM_FAULT_BADACCESS 0x020000
149 149
150#define ESR_WRITE (1 << 6) 150#define ESR_WRITE (1 << 6)
151#define ESR_CM (1 << 8)
151#define ESR_LNX_EXEC (1 << 24) 152#define ESR_LNX_EXEC (1 << 24)
152 153
153/* 154/*
@@ -206,7 +207,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
206 struct task_struct *tsk; 207 struct task_struct *tsk;
207 struct mm_struct *mm; 208 struct mm_struct *mm;
208 int fault, sig, code; 209 int fault, sig, code;
209 int write = esr & ESR_WRITE; 210 bool write = (esr & ESR_WRITE) && !(esr & ESR_CM);
210 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | 211 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
211 (write ? FAULT_FLAG_WRITE : 0); 212 (write ? FAULT_FLAG_WRITE : 0);
212 213