Commit 4b80752a authored by David S. Miller's avatar David S. Miller

Sparc64 pagetable leak fix:

- Defer changing personality until flush_old_exec has freed
up all the pagetables.
parent e7246c49
......@@ -201,6 +201,7 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
unsigned long error;
unsigned long fd_offset;
unsigned long rlim;
unsigned long orig_thr_flags;
int retval;
ex = *((struct exec *) bprm->buf); /* exec-header */
......@@ -305,8 +306,14 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
set_brk(current->mm->start_brk, current->mm->brk);
/* Make sure STACK_TOP returns the right thing. */
orig_thr_flags = current_thread_info()->flags;
current_thread_info()->flags |= _TIF_32BIT;
retval = setup_arg_pages(bprm);
if (retval < 0) {
current_thread_info()->flags = orig_thr_flags;
/* Someone check-me: is this error path enough? */
send_sig(SIGKILL, current, 0);
return retval;
......@@ -314,7 +321,7 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
current->mm->start_stack =
(unsigned long) create_aout32_tables((char *)bprm->p, bprm);
if (!(test_thread_flag(TIF_32BIT))) {
if (!(orig_thr_flags & _TIF_32BIT)) {
unsigned long pgd_cache;
pgd_cache = ((unsigned long)current->mm->pgd[0])<<11UL;
......@@ -323,7 +330,6 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
: /* no outputs */
: "r" (pgd_cache),
"r" (TSB_REG), "i" (ASI_DMMU));
set_thread_flag(TIF_32BIT);
}
start_thread32(regs, ex.a_entry, current->mm->start_stack);
if (current->ptrace & PT_PTRACED)
......
......@@ -428,6 +428,9 @@ void flush_thread(void)
{
struct thread_info *t = current_thread_info();
if (t->flags & _TIF_ABI_PENDING)
t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT);
if (t->task->mm) {
unsigned long pgd_cache = 0UL;
if (test_thread_flag(TIF_32BIT)) {
......
......@@ -99,10 +99,15 @@ typedef struct {
#ifdef __KERNEL__
#define SET_PERSONALITY(ex, ibcs2) \
do { if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
set_thread_flag(TIF_32BIT); \
do { unsigned long new_flags = current_thread_info()->flags; \
new_flags &= _TIF_32BIT; \
if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
new_flags |= _TIF_32BIT; \
else \
clear_thread_flag(TIF_32BIT); \
new_flags &= ~_TIF_32BIT; \
if ((current_thread_info()->flags & _TIF_32BIT) \
!= new_flags) \
set_thread_flag(TIF_ABI_PENDING); \
/* flush_thread will update pgd cache */ \
if (ibcs2) \
set_personality(PER_SVR4); \
......
......@@ -195,6 +195,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
#define TIF_BLKCOMMIT 9 /* use ASI_BLK_COMMIT_* in copy_user_page */
#define TIF_POLLING_NRFLAG 10
#define TIF_ABI_PENDING 11
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
......@@ -207,6 +208,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
#define _TIF_NEWCHILD (1<<TIF_NEWCHILD)
#define _TIF_BLKCOMMIT (1<<TIF_BLKCOMMIT)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
#define _TIF_USER_WORK_MASK ((0xff << TI_FLAG_WSAVED_SHIFT) | \
(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment