xtensa: use XCHAL_NUM_AREGS as pt_regs::areg size
struct pt_regs is used to access both kernel and user exception frames. User exception frames may contain up to XCHAL_NUM_AREG registers that task creation and signal delivery code may access, but pt_regs::areg array has only 16 entries that cover only the kernel exception frame. This results in the following build error: arch/xtensa/kernel/process.c: In function 'copy_thread': arch/xtensa/kernel/process.c:262:52: error: array subscript 53 is above array bounds of 'long unsigned int[16]' [-Werror=array-bounds] 262 | put_user(regs->areg[caller_ars+1], Change struct pt_regs::areg size to XCHAL_NUM_AREGS so that it covers the whole user exception frame. Adjust task_pt_regs and drop additional register copying code from copy_thread now that the whole user exception stack frame is copied. Reported-by: Kees Cook <keescook@chromium.org> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Reviewed-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
parent
6fad9ddc7d
commit
5b835d4cad
|
@ -44,6 +44,7 @@
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#include <asm/coprocessor.h>
|
#include <asm/coprocessor.h>
|
||||||
|
#include <asm/core.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This struct defines the way the registers are stored on the
|
* This struct defines the way the registers are stored on the
|
||||||
|
@ -77,14 +78,12 @@ struct pt_regs {
|
||||||
/* current register frame.
|
/* current register frame.
|
||||||
* Note: The ESF for kernel exceptions ends after 16 registers!
|
* Note: The ESF for kernel exceptions ends after 16 registers!
|
||||||
*/
|
*/
|
||||||
unsigned long areg[16];
|
unsigned long areg[XCHAL_NUM_AREGS];
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <asm/core.h>
|
|
||||||
|
|
||||||
# define arch_has_single_step() (1)
|
# define arch_has_single_step() (1)
|
||||||
# define task_pt_regs(tsk) ((struct pt_regs*) \
|
# define task_pt_regs(tsk) ((struct pt_regs*) \
|
||||||
(task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
|
(task_stack_page(tsk) + KERNEL_STACK_SIZE) - 1)
|
||||||
# define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
|
# define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
|
||||||
# define instruction_pointer(regs) ((regs)->pc)
|
# define instruction_pointer(regs) ((regs)->pc)
|
||||||
# define return_pointer(regs) (MAKE_PC_FROM_RA((regs)->areg[0], \
|
# define return_pointer(regs) (MAKE_PC_FROM_RA((regs)->areg[0], \
|
||||||
|
|
|
@ -232,10 +232,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
|
||||||
p->thread.ra = MAKE_RA_FOR_CALL(
|
p->thread.ra = MAKE_RA_FOR_CALL(
|
||||||
(unsigned long)ret_from_fork, 0x1);
|
(unsigned long)ret_from_fork, 0x1);
|
||||||
|
|
||||||
/* This does not copy all the regs.
|
|
||||||
* In a bout of brilliance or madness,
|
|
||||||
* ARs beyond a0-a15 exist past the end of the struct.
|
|
||||||
*/
|
|
||||||
*childregs = *regs;
|
*childregs = *regs;
|
||||||
childregs->areg[1] = usp;
|
childregs->areg[1] = usp;
|
||||||
childregs->areg[2] = 0;
|
childregs->areg[2] = 0;
|
||||||
|
@ -265,14 +261,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
|
||||||
childregs->wmask = 1;
|
childregs->wmask = 1;
|
||||||
childregs->windowstart = 1;
|
childregs->windowstart = 1;
|
||||||
childregs->windowbase = 0;
|
childregs->windowbase = 0;
|
||||||
} else {
|
|
||||||
int len = childregs->wmask & ~0xf;
|
|
||||||
memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4],
|
|
||||||
®s->areg[XCHAL_NUM_AREGS - len/4], len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
childregs->syscall = regs->syscall;
|
|
||||||
|
|
||||||
if (clone_flags & CLONE_SETTLS)
|
if (clone_flags & CLONE_SETTLS)
|
||||||
childregs->threadptr = tls;
|
childregs->threadptr = tls;
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue