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) ...@@ -201,6 +201,7 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
unsigned long error; unsigned long error;
unsigned long fd_offset; unsigned long fd_offset;
unsigned long rlim; unsigned long rlim;
unsigned long orig_thr_flags;
int retval; int retval;
ex = *((struct exec *) bprm->buf); /* exec-header */ ex = *((struct exec *) bprm->buf); /* exec-header */
...@@ -305,8 +306,14 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -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); 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); retval = setup_arg_pages(bprm);
if (retval < 0) { if (retval < 0) {
current_thread_info()->flags = orig_thr_flags;
/* Someone check-me: is this error path enough? */ /* Someone check-me: is this error path enough? */
send_sig(SIGKILL, current, 0); send_sig(SIGKILL, current, 0);
return retval; return retval;
...@@ -314,7 +321,7 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -314,7 +321,7 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
current->mm->start_stack = current->mm->start_stack =
(unsigned long) create_aout32_tables((char *)bprm->p, bprm); (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; unsigned long pgd_cache;
pgd_cache = ((unsigned long)current->mm->pgd[0])<<11UL; 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) ...@@ -323,7 +330,6 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
: /* no outputs */ : /* no outputs */
: "r" (pgd_cache), : "r" (pgd_cache),
"r" (TSB_REG), "i" (ASI_DMMU)); "r" (TSB_REG), "i" (ASI_DMMU));
set_thread_flag(TIF_32BIT);
} }
start_thread32(regs, ex.a_entry, current->mm->start_stack); start_thread32(regs, ex.a_entry, current->mm->start_stack);
if (current->ptrace & PT_PTRACED) if (current->ptrace & PT_PTRACED)
......
...@@ -428,6 +428,9 @@ void flush_thread(void) ...@@ -428,6 +428,9 @@ void flush_thread(void)
{ {
struct thread_info *t = current_thread_info(); struct thread_info *t = current_thread_info();
if (t->flags & _TIF_ABI_PENDING)
t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT);
if (t->task->mm) { if (t->task->mm) {
unsigned long pgd_cache = 0UL; unsigned long pgd_cache = 0UL;
if (test_thread_flag(TIF_32BIT)) { if (test_thread_flag(TIF_32BIT)) {
......
...@@ -99,10 +99,15 @@ typedef struct { ...@@ -99,10 +99,15 @@ typedef struct {
#ifdef __KERNEL__ #ifdef __KERNEL__
#define SET_PERSONALITY(ex, ibcs2) \ #define SET_PERSONALITY(ex, ibcs2) \
do { if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ do { unsigned long new_flags = current_thread_info()->flags; \
set_thread_flag(TIF_32BIT); \ new_flags &= _TIF_32BIT; \
if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
new_flags |= _TIF_32BIT; \
else \ 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 */ \ /* flush_thread will update pgd cache */ \
if (ibcs2) \ if (ibcs2) \
set_personality(PER_SVR4); \ set_personality(PER_SVR4); \
......
...@@ -195,6 +195,7 @@ register struct thread_info *current_thread_info_reg asm("g6"); ...@@ -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_BLKCOMMIT 9 /* use ASI_BLK_COMMIT_* in copy_user_page */
#define TIF_POLLING_NRFLAG 10 #define TIF_POLLING_NRFLAG 10
#define TIF_ABI_PENDING 11
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
...@@ -207,6 +208,7 @@ register struct thread_info *current_thread_info_reg asm("g6"); ...@@ -207,6 +208,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
#define _TIF_NEWCHILD (1<<TIF_NEWCHILD) #define _TIF_NEWCHILD (1<<TIF_NEWCHILD)
#define _TIF_BLKCOMMIT (1<<TIF_BLKCOMMIT) #define _TIF_BLKCOMMIT (1<<TIF_BLKCOMMIT)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) #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) | \ #define _TIF_USER_WORK_MASK ((0xff << TI_FLAG_WSAVED_SHIFT) | \
(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \ (_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