sh: fix unaligned and nonexistent address handling
unaligned and nonexistent address causes wrong exception handling in traps_32.c(handle_unaligned_access). 'handle_unalinged_ins' should return -EFAULT if address error is fixed up with kernel exception table, otherwise 'handle_unaligned_access' increases already fixed program counter and then crash. for example ioctl(fd, TCGETA, (struct termio *)-1) never return and stay in TASK_UNINTERRUPTIBLE state forever in my kernel. Signed-off-by: SUGIOKA Toshinobu <sugioka@itonet.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
parent
eb6434d9e7
commit
2afb447f33
@ -125,20 +125,18 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs,
|
||||
* - userspace errors just cause EFAULT to be returned, resulting in SEGV
|
||||
* - kernel/userspace interfaces cause a jump to an appropriate handler
|
||||
* - other kernel errors are bad
|
||||
* - return 0 if fixed-up, -EFAULT if non-fatal (to the kernel) fault
|
||||
*/
|
||||
static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
|
||||
static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
|
||||
{
|
||||
if (!user_mode(regs)) {
|
||||
const struct exception_table_entry *fixup;
|
||||
fixup = search_exception_tables(regs->pc);
|
||||
if (fixup) {
|
||||
regs->pc = fixup->fixup;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
die(str, regs, err);
|
||||
}
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static inline void sign_extend(unsigned int count, unsigned char *dst)
|
||||
@ -314,7 +312,8 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs,
|
||||
/* Argh. Address not only misaligned but also non-existent.
|
||||
* Raise an EFAULT and see if it's trapped
|
||||
*/
|
||||
return die_if_no_fixup("Fault in unaligned fixup", regs, 0);
|
||||
die_if_no_fixup("Fault in unaligned fixup", regs, 0);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user