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:
SUGIOKA Toshinobu 2009-01-21 09:42:10 +09:00 committed by Paul Mundt
parent eb6434d9e7
commit 2afb447f33

View File

@ -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 * - userspace errors just cause EFAULT to be returned, resulting in SEGV
* - kernel/userspace interfaces cause a jump to an appropriate handler * - kernel/userspace interfaces cause a jump to an appropriate handler
* - other kernel errors are bad * - 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)) { if (!user_mode(regs)) {
const struct exception_table_entry *fixup; const struct exception_table_entry *fixup;
fixup = search_exception_tables(regs->pc); fixup = search_exception_tables(regs->pc);
if (fixup) { if (fixup) {
regs->pc = fixup->fixup; regs->pc = fixup->fixup;
return 0; return;
} }
die(str, regs, err); die(str, regs, err);
} }
return -EFAULT;
} }
static inline void sign_extend(unsigned int count, unsigned char *dst) 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. /* Argh. Address not only misaligned but also non-existent.
* Raise an EFAULT and see if it's trapped * 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;
} }
/* /*