Openwall Project   /home  Owl  JtR  Pro  crypt  pam_passwdqc  tcb  phpass  scanlogd  popa3d  msulogin  /  Linux  BIND  /  articles  presentations  /  services  donations  /  wordlists  passwords  /  NEWS  community  lists  Wiki  CVSweb  mirrors  signatures  /  books 
bringing security into open environments
 
Password Recovery Resources on the Net
[<prev] [next>] [<thread-prev] [thread-next>] [month] [year] [list]
Date: Wed, 5 Aug 2009 15:26:21 -0400
From: "Michael K. Johnson" <johnsonm@...th.com>
To: oss-security@...ts.openwall.com
Cc: "Steven M. Christey" <coley@...us.mitre.org>
Subject: Re: CVE request - kernel: execve: must clear current->clear_child_tid

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

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Powered by Openwall GNU/*/Linux - Powered by OpenVZ