oss-sec mailing list archives
Re: CVE request - kernel: execve: must clear current->clear_child_tid
From: "Michael K. Johnson" <johnsonm () rpath com>
Date: Wed, 5 Aug 2009 15:26:21 -0400
This seems to me a potential security issue specifically because as
far as I can see clear_child_tid isn't reset on exec of set{u,g}id
executables. (Otherwise it would just be a bug...) Regarding a
non-threaded setuid program, a direct attack seems hard since the
maps and smaps files are hidden to other users. Am I missing some
of the potential impact here?
On Tue, Aug 04, 2009 at 04:09:09PM +0800, Eugene Teo wrote:
clone() syscall has special support for TID of created threads. This
support includes two features.
One (CLONE_CHILD_SETTID) is to set an integer into user memory with the
TID value.
One (CLONE_CHILD_CLEARTID) is to clear this same integer once the
created thread dies.
The integer location is a user provided pointer, provided at clone() time.
kernel keeps this pointer value into current->clear_child_tid.
At execve() time, we should make sure kernel doesnt keep this user
provided pointer, as full user memory is replaced by a new one.
As glibc fork() actually uses clone() syscall with CLONE_CHILD_SETTID
and CLONE_CHILD_CLEARTID set, chances are high that we might corrupt
user memory in forked processes.
Following sequence could happen:
1) bash (or any program) starts a new process, by a fork() call that
glibc maps to a clone( ... CLONE_CHILD_SETTID |
CLONE_CHILD_CLEARTID...) syscall
2) When new process starts, its current->clear_child_tid is set to a
location that has a meaning only in bash (or initial program) context
(&THREAD_SELF->tid)
3) This new process does the execve() syscall to start a new program.
current->clear_child_tid is left unchanged (a non NULL value)
4) If this new program creates some threads, and initial thread exits,
kernel will attempt to clear the integer pointed by
current->clear_child_tid from mm_release() :
if (tsk->clear_child_tid
&& !(tsk->flags & PF_SIGNALED)
&& atomic_read(&mm->mm_users) > 1) {
u32 __user * tidptr = tsk->clear_child_tid;
tsk->clear_child_tid = NULL;
/*
* We don't check the error code - if userspace has
* not set up a proper pointer then tough luck.
*/
<< here >> put_user(0, tidptr);
sys_futex(tidptr, FUTEX_WAKE, 1, NULL, NULL, 0);
}
5) OR : if new program is not multi-threaded, but spied by /proc/pid
users (ps command for example), mm_users > 1, and the exiting program
could corrupt 4 bytes in a persistent memory area (shm or memory mapped
file)
If current->clear_child_tid points to a writeable portion of memory of
the new program, kernel happily and silently corrupts 4 bytes of memory,
with unexpected effects.
References:
http://article.gmane.org/gmane.linux.kernel/871942
https://bugzilla.redhat.com/show_bug.cgi?id=515423
Patch is not in upstream kernel yet.
Thanks, Eugene
Current thread:
- CVE request - kernel: execve: must clear current->clear_child_tid Eugene Teo (Aug 04)
- Re: CVE request - kernel: execve: must clear current->clear_child_tid Michael K. Johnson (Aug 05)
- Re: CVE request - kernel: execve: must clear current->clear_child_tid Steven M. Christey (Aug 18)
