All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Dumazet <eric.dumazet@gmail.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Jens Rosenboom <jens@mcbone.net>,
	Peter Zijlstra <peterz@infradead.org>,
	Sonny Rao <sonnyrao@us.ibm.com>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Ingo Molnar <mingo@elte.hu>, Thomas Gleixner <tglx@linutronix.de>,
	Ulrich Drepper <drepper@redhat.com>
Subject: [ PATCH]  execve: must clear current->clear_child_tid
Date: Fri, 31 Jul 2009 12:00:03 +0200	[thread overview]
Message-ID: <4A72C0A3.1070508@gmail.com> (raw)
In-Reply-To: <4A702AC2.2060003@gmail.com>

While looking at Jens Rosenboom bug report about strange sys_futex call done
from a dying "ps" program, we found following problem.

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.

Fix is straightforward and should not break any sane program.

Reported-by: Jens Rosenboom <jens@mcbone.net>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Tested-by: Jens Rosenboom <jens@mcbone.net>
---
 fs/compat.c |    1 +
 fs/exec.c   |    1 +
 2 files changed, 2 insertions(+)

diff --git a/fs/compat.c b/fs/compat.c
index 94502da..deb1049 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1550,6 +1550,7 @@ int compat_do_execve(char * filename,
 	mutex_unlock(&current->cred_guard_mutex);
 	acct_update_integrals(current);
 	free_bprm(bprm);
+	current->clear_child_tid = NULL;
 	if (displaced)
 		put_files_struct(displaced);
 	return retval;
diff --git a/fs/exec.c b/fs/exec.c
index 4a8849e..e275652 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1343,6 +1343,7 @@ int do_execve(char * filename,
 	mutex_unlock(&current->cred_guard_mutex);
 	acct_update_integrals(current);
 	free_bprm(bprm);
+	current->clear_child_tid = NULL;
 	if (displaced)
 		put_files_struct(displaced);
 	return retval;

      parent reply	other threads:[~2009-07-31 10:01 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-07-27  8:00 futexes: Still infinite loop in get_futex_key() in 2.6.31-rc4 Jens Rosenboom
2009-07-27 11:31 ` Peter Zijlstra
2009-07-27 12:16   ` Jens Rosenboom
2009-07-27 12:23     ` Peter Zijlstra
2009-07-27 12:45       ` Jens Rosenboom
2009-07-27 13:36         ` Peter Zijlstra
2009-07-27 13:41           ` Eric Dumazet
2009-07-27 14:00           ` Jens Rosenboom
2009-07-27 16:00             ` Ray Lee
2009-07-29  6:22           ` Jens Rosenboom
2009-07-29  9:57             ` Jens Rosenboom
2009-07-29 10:01               ` Peter Zijlstra
2009-07-29 10:26               ` Eric Dumazet
2009-07-29 10:56                 ` Eric Dumazet
2009-07-29 14:29                   ` Jens Rosenboom
2009-07-30 14:13                   ` Jens Rosenboom
2009-07-31 10:00                   ` Eric Dumazet [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4A72C0A3.1070508@gmail.com \
    --to=eric.dumazet@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=drepper@redhat.com \
    --cc=jens@mcbone.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=peterz@infradead.org \
    --cc=sonnyrao@us.ibm.com \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.