diff options
author | David S. Miller <davem@davemloft.net> | 2014-05-07 00:27:37 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-05-07 00:27:37 -0400 |
commit | e5c460f46ae7ee94831cb55cb980f942aa9e5a85 (patch) | |
tree | 5ba76a0a5386686445276b4345536492df60b787 | |
parent | 256cf4c438e60116785a83b060614c63c7477e84 (diff) |
sparc64: Don't bark so loudly about 32-bit tasks generating 64-bit fault addresses.
This was found using Dave Jone's trinity tool.
When a user process which is 32-bit performs a load or a store, the
cpu chops off the top 32-bits of the effective address before
translating it.
This is because we run 32-bit tasks with the PSTATE_AM (address
masking) bit set.
We can't run the kernel with that bit set, so when the kernel accesses
userspace no address masking occurs.
Since a 32-bit process will have no mappings in that region we will
properly fault, so we don't try to handle this using access_ok(),
which can safely just be a NOP on sparc64.
Real faults from 32-bit processes should never generate such addresses
so a bug check was added long ago, and it barks in the logs if this
happens.
But it also barks when a kernel user access causes this condition, and
that _can_ happen. For example, if a pointer passed into a system call
is "0xfffffffc" and the kernel access 4 bytes offset from that pointer.
Just handle such faults normally via the exception entries.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/sparc/mm/fault_64.c | 16 |
1 files changed, 1 insertions, 15 deletions
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index a8ff0d1a3b69..4ced3fc66130 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c | |||
@@ -281,18 +281,6 @@ static void noinline __kprobes bogus_32bit_fault_tpc(struct pt_regs *regs) | |||
281 | show_regs(regs); | 281 | show_regs(regs); |
282 | } | 282 | } |
283 | 283 | ||
284 | static void noinline __kprobes bogus_32bit_fault_address(struct pt_regs *regs, | ||
285 | unsigned long addr) | ||
286 | { | ||
287 | static int times; | ||
288 | |||
289 | if (times++ < 10) | ||
290 | printk(KERN_ERR "FAULT[%s:%d]: 32-bit process " | ||
291 | "reports 64-bit fault address [%lx]\n", | ||
292 | current->comm, current->pid, addr); | ||
293 | show_regs(regs); | ||
294 | } | ||
295 | |||
296 | asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | 284 | asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) |
297 | { | 285 | { |
298 | enum ctx_state prev_state = exception_enter(); | 286 | enum ctx_state prev_state = exception_enter(); |
@@ -322,10 +310,8 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | |||
322 | goto intr_or_no_mm; | 310 | goto intr_or_no_mm; |
323 | } | 311 | } |
324 | } | 312 | } |
325 | if (unlikely((address >> 32) != 0)) { | 313 | if (unlikely((address >> 32) != 0)) |
326 | bogus_32bit_fault_address(regs, address); | ||
327 | goto intr_or_no_mm; | 314 | goto intr_or_no_mm; |
328 | } | ||
329 | } | 315 | } |
330 | 316 | ||
331 | if (regs->tstate & TSTATE_PRIV) { | 317 | if (regs->tstate & TSTATE_PRIV) { |