lkml.org 
[lkml]   [2000]   [Aug]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
SubjectRe: SCO: "thread creation is about a thousand times faster than on
Date
In article <20000827051241.A24890@hq.fsmlabs.com>,
<yodaiken@fsmlabs.com> wrote:
>POSIX says nothing, as far as I can tell, about the effect of exec on
>threads. However, it does say pending signals must be inherited. It's
>unclear what should happen in Linux, but it might be good for the new
>process to still be a thread in the thread group -- although it won't
>be sharing memory anymore.

No. Simply for security purposes we _definitely_ need to "de-thread" the
process when it does an exec. Otherwise we have "interesting" issues
with suid execs that are part of a non-suid thread group.

We could choose to just not allow suid execs, but I think they do
potentially make sense, and I don't see why Linux shouldn't allow a
thread to exec a suid binary (we break the shared VM part automatically,
we might as well break the shared thread part).

Note that for _pthreads_ this kind of exec is illegal anyway. Silly
POSIX threads standard had to take user-level threading models into
account, so under POSIX threads an execve() needs to kill off all other
threads. Another senseless limitation - one that we can _emulate_, of
course, but not one that we should consider part of the native thread
environment.

Btw, here's a simple thread-group patch. It doesn't actually _do_
anything with the thread group part, but this is the kind of frame-work
I've envisioned. Completely untested, of course, but with these kinds
of security issues taken into account.

Comments? At least it's small and simple..

Linus

----
diff -u --recursive --new-file penguin/linux/fs/exec.c linux/fs/exec.c
--- penguin/linux/fs/exec.c Mon Aug 14 10:19:55 2000
+++ linux/fs/exec.c Sun Aug 27 17:29:52 2000
@@ -496,6 +496,25 @@
write_unlock(&files->file_lock);
}

+/*
+ * An execve() will automatically "de-thread" the process.
+ * Note: we don't have to hold the tasklist_lock to test
+ * whether we migth need to do this. If we're not part of
+ * a thread group, there is no way we can become one
+ * dynamically. And if we are, we only need to protect the
+ * unlink - even if we race with the last other thread exit,
+ * at worst the list_del_init() might end up being a no-op.
+ */
+static inline void de_thread(struct task_struct *tsk)
+{
+ if (!list_empty(&tsk->thread_group)) {
+ write_lock_irq(&tasklist_lock);
+ list_del_init(&tsk->thread_group);
+ write_unlock_irq(&tasklist_lock);
+ }
+ tsk->tgid = tsk->pid;
+}
+
int flush_old_exec(struct linux_binprm * bprm)
{
char * name;
@@ -533,6 +552,8 @@
current->comm[i] = '\0';

flush_thread();
+
+ de_thread(current);

if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
permission(bprm->file->f_dentry->d_inode,MAY_READ))
diff -u --recursive --new-file penguin/linux/include/linux/sched.h linux/include/linux/sched.h
--- penguin/linux/include/linux/sched.h Wed Aug 23 11:35:07 2000
+++ linux/include/linux/sched.h Sun Aug 27 17:31:18 2000
@@ -38,6 +38,7 @@
#define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */
#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */
#define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */
+#define CLONE_THREAD 0x00010000 /* set if we want to clone the "thread group" */

/*
* These are the constant used to fake the fixed-point load-average
@@ -311,6 +312,7 @@
pid_t pgrp;
pid_t tty_old_pgrp;
pid_t session;
+ pid_t tgid;
/* boolean value for session group leader */
int leader;
/*
@@ -319,6 +321,7 @@
* p->p_pptr->pid)
*/
struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
+ struct list_head thread_group;

/* PID hash table linkage. */
struct task_struct *pidhash_next;
@@ -435,6 +438,7 @@
prev_task: &tsk, \
p_opptr: &tsk, \
p_pptr: &tsk, \
+ thread_group: LIST_HEAD_INIT(tsk.thread_group), \
wait_chldexit: __WAIT_QUEUE_HEAD_INITIALIZER(tsk.wait_chldexit),\
real_timer: { \
function: it_real_fn \
@@ -818,6 +822,7 @@
nr_threads--;
unhash_pid(p);
REMOVE_LINKS(p);
+ list_del(&p->thread_group);
write_unlock_irq(&tasklist_lock);
}

diff -u --recursive --new-file penguin/linux/kernel/fork.c linux/kernel/fork.c
--- penguin/linux/kernel/fork.c Wed Aug 23 11:33:48 2000
+++ linux/kernel/fork.c Sun Aug 27 17:32:08 2000
@@ -661,7 +661,13 @@
* Let it rip!
*/
retval = p->pid;
+ p->tgid = retval;
+ INIT_LIST_HEAD(&p->thread_group);
write_lock_irq(&tasklist_lock);
+ if (clone_flags & CLONE_THREAD) {
+ p->tgid = current->tgid;
+ list_add(&p->thread_group, &current->thread_group);
+ }
SET_LINKS(p);
hash_pid(p);
nr_threads++;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-03-22 12:38    [from the cache]
©2003-2011 Jasper Spaans