The problem discovered by Wojciech Purczynski is:
A 64bit user can say putreg(TIF_IA32) to kernel
and the kernel will enter at the if and do:
value &= 0xffffffff;
ok, lets practice 1100 & 1111 = 1100 The value remain Ok
What happens if we are in 64bits, 0xffffffff is actually 0x00000000ffffffff
Well, the beginning of value will be erased :/
Let see the explotation details.
#define TIF_IA32 17 /* 32bit process */
We know the constant value, lets see the sched function:
static inline int test_tsk_thread_flag
(struct task_struct *tsk, int flag)
{
return test_ti_thread_flag(task_thread_info(tsk), flag);
}
static inline int test_ti_thread_flag
(struct thread_info *ti, int flag)
{
return test_bit(flag,&ti->flags);
}
quite obvious the bypass :)
Let's see the ptrace call:
When we invoke the PTRACE_SETREGS, we can see that putreg is invoked for each register.
We can do
putreg(child, <register>, <value>);
by calling
ptrace(PTRACE_SETREGS, <somepid>, NULL, <user_regs_struct>)
The key: We can have a 64bits process ptracing a 32bits one, then we can exploit this flaw.
We can erase the registers, is that a potentially priviledge scalation?
Finally: Don't let the user give us a data we know yet, because the user is a motherfucker.
Comentarios