* vfork & co bugfix
@ 1999-01-10 6:48 Eric W. Biederman
1999-01-10 18:04 ` Linus Torvalds
0 siblings, 1 reply; 7+ messages in thread
From: Eric W. Biederman @ 1999-01-10 6:48 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel, linux-mm
Looking at vfork in 2.2.0-pre6 I was struck by how badly
looking at current, (to release a process) hacks up mmput.
It took a little while but eventually a case where
this really goes wrong.
In:
kernel/fork.c:copy_mm
fs/exec.c/exec_mmap
If the we can't allocate page tables, we currently erroneously
wake up a vfork waiter, and clear our segments, and set the ldt
to that of init.
To correct this I've added a companion function mm_release
that we call to remove any dangling references to the old
mm_struct of the current process.
This also ensures that segment and ldt clearing happen for every x86
process. Not just when the previous memory area was totally freed.
Eric
diff -uNrX linux-ignore-files linux-2.2.0-pre6/arch/i386/kernel/process.c linux-2.2.0-pre6.eb1/arch/i386/kernel/process.c
--- linux-2.2.0-pre6/arch/i386/kernel/process.c Sat Jan 9 13:33:02 1999
+++ linux-2.2.0-pre6.eb1/arch/i386/kernel/process.c Sun Jan 10 01:26:17 1999
@@ -475,22 +475,25 @@
void release_segments(struct mm_struct *mm)
{
- /* forget local segments */
- __asm__ __volatile__("movl %w0,%%fs ; movl %w0,%%gs"
- : /* no outputs */
- : "r" (0));
if (mm->segments) {
void * ldt = mm->segments;
-
- /*
- * Get the LDT entry from init_task.
- */
- current->tss.ldt = _LDT(0);
- load_ldt(0);
-
mm->segments = NULL;
vfree(ldt);
}
+}
+
+void forget_segments(struct task_struct *tsk)
+{
+ /* forget local segments */
+ __asm__ __volatile__("movl %w0,%%fs ; movl %w0,%%gs"
+ : /* no outputs */
+ : "r" (0));
+
+ /*
+ * Get the LDT entry from init_task.
+ */
+ tsk->tss.ldt = _LDT(0);
+ load_ldt(0);
}
/*
diff -uNrX linux-ignore-files linux-2.2.0-pre6/fs/exec.c linux-2.2.0-pre6.eb1/fs/exec.c
--- linux-2.2.0-pre6/fs/exec.c Fri Dec 25 17:43:18 1998
+++ linux-2.2.0-pre6.eb1/fs/exec.c Sun Jan 10 01:41:20 1999
@@ -383,6 +383,7 @@
exit_mmap(current->mm);
clear_page_tables(current);
flush_tlb_mm(current->mm);
+ mm_release(current);
return 0;
}
@@ -413,6 +414,7 @@
activate_context(current);
up(&mm->mmap_sem);
mmput(old_mm);
+ mm_release(current);
return 0;
/*
diff -uNrX linux-ignore-files linux-2.2.0-pre6/include/asm-alpha/processor.h linux-2.2.0-pre6.eb1/include/asm-alpha/processor.h
--- linux-2.2.0-pre6/include/asm-alpha/processor.h Fri Dec 25 17:41:47 1998
+++ linux-2.2.0-pre6.eb1/include/asm-alpha/processor.h Sun Jan 10 00:38:50 1999
@@ -113,6 +113,7 @@
#define copy_segments(nr, tsk, mm) do { } while (0)
#define release_segments(mm) do { } while (0)
+#define forget_segments(tsk) do { } while (0)
/* NOTE: The task struct and the stack go together! */
#define alloc_task_struct() \
diff -uNrX linux-ignore-files linux-2.2.0-pre6/include/asm-arm/processor.h linux-2.2.0-pre6.eb1/include/asm-arm/processor.h
--- linux-2.2.0-pre6/include/asm-arm/processor.h Sun Oct 11 14:16:42 1998
+++ linux-2.2.0-pre6.eb1/include/asm-arm/processor.h Sun Jan 10 01:15:50 1999
@@ -53,11 +53,9 @@
extern void release_thread(struct task_struct *);
/* Copy and release all segment info associated with a VM */
-extern void copy_segments(int nr, struct task_struct *p, struct mm_struct * mm);
-extern void release_segments(struct mm_struct * mm);
-
#define copy_segments(nr, tsk, mm) do { } while (0)
#define release_segments(mm) do { } while (0)
+#define forget_segments(tsk) do { } while (0)
#define init_task (init_task_union.task)
#define init_stack (init_task_union.stack)
diff -uNrX linux-ignore-files linux-2.2.0-pre6/include/asm-i386/processor.h linux-2.2.0-pre6.eb1/include/asm-i386/processor.h
--- linux-2.2.0-pre6/include/asm-i386/processor.h Wed Jan 6 23:51:10 1999
+++ linux-2.2.0-pre6.eb1/include/asm-i386/processor.h Sun Jan 10 01:16:30 1999
@@ -281,6 +281,7 @@
/* Copy and release all segment info associated with a VM */
extern void copy_segments(int nr, struct task_struct *p, struct mm_struct * mm);
extern void release_segments(struct mm_struct * mm);
+extern void forget_segments(struct task_struct * tsk);
/*
* FPU lazy state save handling..
diff -uNrX linux-ignore-files linux-2.2.0-pre6/include/asm-m68k/processor.h linux-2.2.0-pre6.eb1/include/asm-m68k/processor.h
--- linux-2.2.0-pre6/include/asm-m68k/processor.h Sun Oct 11 14:09:34 1998
+++ linux-2.2.0-pre6.eb1/include/asm-m68k/processor.h Sun Jan 10 00:41:10 1999
@@ -74,6 +74,7 @@
#define copy_segments(nr, tsk, mm) do { } while (0)
#define release_segments(mm) do { } while (0)
+#define forget_segments(tsk) do { } while (0)
/*
* Free current thread data structures etc..
diff -uNrX linux-ignore-files linux-2.2.0-pre6/include/asm-mips/processor.h linux-2.2.0-pre6.eb1/include/asm-mips/processor.h
--- linux-2.2.0-pre6/include/asm-mips/processor.h Fri Dec 25 17:41:48 1998
+++ linux-2.2.0-pre6.eb1/include/asm-mips/processor.h Sun Jan 10 00:42:10 1999
@@ -178,6 +178,7 @@
/* Copy and release all segment info associated with a VM */
#define copy_segments(nr, p, mm) do { } while(0)
#define release_segments(mm) do { } while(0)
+#define forget_segments(tsk) do { } while (0)
/*
* Return saved PC of a blocked thread.
diff -uNrX linux-ignore-files linux-2.2.0-pre6/include/asm-ppc/processor.h linux-2.2.0-pre6.eb1/include/asm-ppc/processor.h
--- linux-2.2.0-pre6/include/asm-ppc/processor.h Sun Oct 11 14:18:12 1998
+++ linux-2.2.0-pre6.eb1/include/asm-ppc/processor.h Sun Jan 10 00:42:32 1999
@@ -299,6 +299,7 @@
#define copy_segments(nr, tsk, mm) do { } while (0)
#define release_segments(mm) do { } while (0)
+#define forget_segments(tsk) do { } while (0)
/*
* NOTE! The task struct and the stack go together
diff -uNrX linux-ignore-files linux-2.2.0-pre6/include/asm-sparc/processor.h linux-2.2.0-pre6.eb1/include/asm-sparc/processor.h
--- linux-2.2.0-pre6/include/asm-sparc/processor.h Sun Oct 11 14:13:51 1998
+++ linux-2.2.0-pre6.eb1/include/asm-sparc/processor.h Sun Jan 10 00:43:45 1999
@@ -148,6 +148,7 @@
#define copy_segments(nr, tsk, mm) do { } while (0)
#define release_segments(mm) do { } while (0)
+#define forget_segments(tsk) do { } while (0)
#ifdef __KERNEL__
diff -uNrX linux-ignore-files linux-2.2.0-pre6/include/asm-sparc64/processor.h linux-2.2.0-pre6.eb1/include/asm-sparc64/processor.h
--- linux-2.2.0-pre6/include/asm-sparc64/processor.h Fri Dec 25 17:42:26 1998
+++ linux-2.2.0-pre6.eb1/include/asm-sparc64/processor.h Sun Jan 10 00:44:37 1999
@@ -208,6 +208,7 @@
#define copy_segments(nr, tsk, mm) do { } while (0)
#define release_segments(mm) do { } while (0)
+#define forget_segments(tsk) do { } while (0)
#ifdef __KERNEL__
/* Allocation and freeing of task_struct and kernel stack. */
diff -uNrX linux-ignore-files linux-2.2.0-pre6/include/linux/sched.h linux-2.2.0-pre6.eb1/include/linux/sched.h
--- linux-2.2.0-pre6/include/linux/sched.h Sat Jan 9 13:33:21 1999
+++ linux-2.2.0-pre6.eb1/include/linux/sched.h Sun Jan 10 01:16:53 1999
@@ -609,6 +609,8 @@
atomic_inc(&mm->count);
}
extern void mmput(struct mm_struct *);
+/* Remove the current tasks stale references to the old mm_struct */
+extern void mm_release(struct task_struct *);
extern int copy_thread(int, unsigned long, unsigned long, struct task_struct *, struct pt_regs *);
extern void flush_thread(void);
diff -uNrX linux-ignore-files linux-2.2.0-pre6/kernel/exit.c linux-2.2.0-pre6.eb1/kernel/exit.c
--- linux-2.2.0-pre6/kernel/exit.c Sat Jan 9 13:33:22 1999
+++ linux-2.2.0-pre6.eb1/kernel/exit.c Sun Jan 10 00:19:03 1999
@@ -259,6 +259,7 @@
tsk->swappable = 0;
SET_PAGE_DIR(tsk, swapper_pg_dir);
mmput(mm);
+ mm_release(tsk);
}
}
diff -uNrX linux-ignore-files linux-2.2.0-pre6/kernel/fork.c linux-2.2.0-pre6.eb1/kernel/fork.c
--- linux-2.2.0-pre6/kernel/fork.c Sat Jan 9 13:33:22 1999
+++ linux-2.2.0-pre6.eb1/kernel/fork.c Sun Jan 10 01:20:06 1999
@@ -278,14 +278,19 @@
return mm;
}
+void mm_release(struct task_struct *tsk)
+{
+ forget_segments(tsk);
+ /* Notify parent sleeping on vfork().
+ */
+ wake_up(&tsk->p_opptr->vfork_sleep);
+}
+
/*
* Decrement the use count and release all resources for an mm.
*/
void mmput(struct mm_struct *mm)
{
- /* notify parent sleeping on vfork() */
- wake_up(¤t->p_opptr->vfork_sleep);
-
if (atomic_dec_and_test(&mm->count)) {
release_segments(mm);
exit_mmap(mm);
--
This is a majordomo managed list. To unsubscribe, send a message with
the body 'unsubscribe linux-mm me@address' to: majordomo@kvack.org
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: vfork & co bugfix
1999-01-10 6:48 vfork & co bugfix Eric W. Biederman
@ 1999-01-10 18:04 ` Linus Torvalds
1999-01-10 21:34 ` Eric W. Biederman
1999-01-11 4:32 ` Eric W. Biederman
0 siblings, 2 replies; 7+ messages in thread
From: Linus Torvalds @ 1999-01-10 18:04 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: linux-kernel, linux-mm
On 10 Jan 1999, Eric W. Biederman wrote:
>
> Looking at vfork in 2.2.0-pre6 I was struck by how badly
> looking at current, (to release a process) hacks up mmput.
>
> It took a little while but eventually a case where
> this really goes wrong.
Note that the pre6 version has a number of cases where it can really screw
up, don't even look at them too closely. I think I've fixed them all - it
was really simple, but there was a few things I hadn't originally thought
of.
I'll make a pre7 once I've verified that the recursive semaphores work at
least to some degree, could you please take a look at that one?
Linus
--
This is a majordomo managed list. To unsubscribe, send a message with
the body 'unsubscribe linux-mm me@address' to: majordomo@kvack.org
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: vfork & co bugfix
1999-01-10 18:04 ` Linus Torvalds
@ 1999-01-10 21:34 ` Eric W. Biederman
1999-01-11 4:32 ` Eric W. Biederman
1 sibling, 0 replies; 7+ messages in thread
From: Eric W. Biederman @ 1999-01-10 21:34 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel, linux-mm
>>>>> "LT" == Linus Torvalds <torvalds@transmeta.com> writes:
LT> On 10 Jan 1999, Eric W. Biederman wrote:
>>
>> Looking at vfork in 2.2.0-pre6 I was struck by how badly
>> looking at current, (to release a process) hacks up mmput.
>>
>> It took a little while but eventually a case where
>> this really goes wrong.
LT> Note that the pre6 version has a number of cases where it can really screw
LT> up, don't even look at them too closely. I think I've fixed them all - it
LT> was really simple, but there was a few things I hadn't originally thought
LT> of.
LT> I'll make a pre7 once I've verified that the recursive semaphores work at
LT> least to some degree, could you please take a look at that one?
Will do.
The messing up of segments, and the ldt is much older than pre6 though.
The vfork release semaphore code just happened to make about the same assumption,
so I fixed them both at the same time.
Eric
--
This is a majordomo managed list. To unsubscribe, send a message with
the body 'unsubscribe linux-mm me@address' to: majordomo@kvack.org
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: vfork & co bugfix
1999-01-10 18:04 ` Linus Torvalds
1999-01-10 21:34 ` Eric W. Biederman
@ 1999-01-11 4:32 ` Eric W. Biederman
1999-01-11 6:35 ` Linus Torvalds
1 sibling, 1 reply; 7+ messages in thread
From: Eric W. Biederman @ 1999-01-11 4:32 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel, linux-mm
>>>>> "LT" == Linus Torvalds <torvalds@transmeta.com> writes:
LT> On 10 Jan 1999, Eric W. Biederman wrote:
>>
>> Looking at vfork in 2.2.0-pre6 I was struck by how badly
>> looking at current, (to release a process) hacks up mmput.
>>
>> It took a little while but eventually a case where
>> this really goes wrong.
LT> Note that the pre6 version has a number of cases where it can really screw
LT> up, don't even look at them too closely. I think I've fixed them all - it
LT> was really simple, but there was a few things I hadn't originally thought
LT> of.
Darn it I missed the easy bug (All children waking up the parent),
and found the hard one (waking up the parent if fork fails).
The problem in summary is that mmput gets called on error where we keep
the old mm, but get rid of the new one.
This introduces a second function that only gets called upon success.
Question. Why don't we let CLONE_VFORK be a standard clone flag?
Eric
diff -uNrX linux-ignore-files linux-pre-7/arch/i386/kernel/process.c linux-pre-7.eb1/arch/i386/kernel/process.c
--- linux-pre-7/arch/i386/kernel/process.c Sun Jan 10 22:44:04 1999
+++ linux-pre-7.eb1/arch/i386/kernel/process.c Sun Jan 10 22:46:08 1999
@@ -475,22 +475,25 @@
void release_segments(struct mm_struct *mm)
{
- /* forget local segments */
- __asm__ __volatile__("movl %w0,%%fs ; movl %w0,%%gs"
- : /* no outputs */
- : "r" (0));
if (mm->segments) {
void * ldt = mm->segments;
-
- /*
- * Get the LDT entry from init_task.
- */
- current->tss.ldt = _LDT(0);
- load_ldt(0);
-
mm->segments = NULL;
vfree(ldt);
}
+}
+
+void forget_segments(struct task_struct *tsk)
+{
+ /* forget local segments */
+ __asm__ __volatile__("movl %w0,%%fs ; movl %w0,%%gs"
+ : /* no outputs */
+ : "r" (0));
+
+ /*
+ * Get the LDT entry from init_task.
+ */
+ tsk->tss.ldt = _LDT(0);
+ load_ldt(0);
}
/*
diff -uNrX linux-ignore-files linux-pre-7/fs/exec.c linux-pre-7.eb1/fs/exec.c
--- linux-pre-7/fs/exec.c Fri Dec 25 17:43:18 1998
+++ linux-pre-7.eb1/fs/exec.c Sun Jan 10 22:46:08 1999
@@ -383,6 +383,7 @@
exit_mmap(current->mm);
clear_page_tables(current);
flush_tlb_mm(current->mm);
+ mm_release(current);
return 0;
}
@@ -413,6 +414,7 @@
activate_context(current);
up(&mm->mmap_sem);
mmput(old_mm);
+ mm_release(current);
return 0;
/*
diff -uNrX linux-ignore-files linux-pre-7/include/asm-alpha/processor.h linux-pre-7.eb1/include/asm-alpha/processor.h
--- linux-pre-7/include/asm-alpha/processor.h Fri Dec 25 17:41:47 1998
+++ linux-pre-7.eb1/include/asm-alpha/processor.h Sun Jan 10 22:46:08 1999
@@ -113,6 +113,7 @@
#define copy_segments(nr, tsk, mm) do { } while (0)
#define release_segments(mm) do { } while (0)
+#define forget_segments(tsk) do { } while (0)
/* NOTE: The task struct and the stack go together! */
#define alloc_task_struct() \
diff -uNrX linux-ignore-files linux-pre-7/include/asm-arm/processor.h linux-pre-7.eb1/include/asm-arm/processor.h
--- linux-pre-7/include/asm-arm/processor.h Sun Oct 11 14:16:42 1998
+++ linux-pre-7.eb1/include/asm-arm/processor.h Sun Jan 10 22:46:08 1999
@@ -53,11 +53,9 @@
extern void release_thread(struct task_struct *);
/* Copy and release all segment info associated with a VM */
-extern void copy_segments(int nr, struct task_struct *p, struct mm_struct * mm);
-extern void release_segments(struct mm_struct * mm);
-
#define copy_segments(nr, tsk, mm) do { } while (0)
#define release_segments(mm) do { } while (0)
+#define forget_segments(tsk) do { } while (0)
#define init_task (init_task_union.task)
#define init_stack (init_task_union.stack)
diff -uNrX linux-ignore-files linux-pre-7/include/asm-i386/processor.h linux-pre-7.eb1/include/asm-i386/processor.h
--- linux-pre-7/include/asm-i386/processor.h Wed Jan 6 23:51:10 1999
+++ linux-pre-7.eb1/include/asm-i386/processor.h Sun Jan 10 22:46:08 1999
@@ -281,6 +281,7 @@
/* Copy and release all segment info associated with a VM */
extern void copy_segments(int nr, struct task_struct *p, struct mm_struct * mm);
extern void release_segments(struct mm_struct * mm);
+extern void forget_segments(struct task_struct * tsk);
/*
* FPU lazy state save handling..
diff -uNrX linux-ignore-files linux-pre-7/include/asm-m68k/processor.h linux-pre-7.eb1/include/asm-m68k/processor.h
--- linux-pre-7/include/asm-m68k/processor.h Sun Oct 11 14:09:34 1998
+++ linux-pre-7.eb1/include/asm-m68k/processor.h Sun Jan 10 22:46:08 1999
@@ -74,6 +74,7 @@
#define copy_segments(nr, tsk, mm) do { } while (0)
#define release_segments(mm) do { } while (0)
+#define forget_segments(tsk) do { } while (0)
/*
* Free current thread data structures etc..
diff -uNrX linux-ignore-files linux-pre-7/include/asm-mips/processor.h linux-pre-7.eb1/include/asm-mips/processor.h
--- linux-pre-7/include/asm-mips/processor.h Fri Dec 25 17:41:48 1998
+++ linux-pre-7.eb1/include/asm-mips/processor.h Sun Jan 10 22:46:08 1999
@@ -178,6 +178,7 @@
/* Copy and release all segment info associated with a VM */
#define copy_segments(nr, p, mm) do { } while(0)
#define release_segments(mm) do { } while(0)
+#define forget_segments(tsk) do { } while (0)
/*
* Return saved PC of a blocked thread.
diff -uNrX linux-ignore-files linux-pre-7/include/asm-ppc/processor.h linux-pre-7.eb1/include/asm-ppc/processor.h
--- linux-pre-7/include/asm-ppc/processor.h Sun Oct 11 14:18:12 1998
+++ linux-pre-7.eb1/include/asm-ppc/processor.h Sun Jan 10 22:46:08 1999
@@ -299,6 +299,7 @@
#define copy_segments(nr, tsk, mm) do { } while (0)
#define release_segments(mm) do { } while (0)
+#define forget_segments(tsk) do { } while (0)
/*
* NOTE! The task struct and the stack go together
diff -uNrX linux-ignore-files linux-pre-7/include/asm-sparc/processor.h linux-pre-7.eb1/include/asm-sparc/processor.h
--- linux-pre-7/include/asm-sparc/processor.h Sun Oct 11 14:13:51 1998
+++ linux-pre-7.eb1/include/asm-sparc/processor.h Sun Jan 10 22:46:08 1999
@@ -148,6 +148,7 @@
#define copy_segments(nr, tsk, mm) do { } while (0)
#define release_segments(mm) do { } while (0)
+#define forget_segments(tsk) do { } while (0)
#ifdef __KERNEL__
diff -uNrX linux-ignore-files linux-pre-7/include/asm-sparc64/processor.h linux-pre-7.eb1/include/asm-sparc64/processor.h
--- linux-pre-7/include/asm-sparc64/processor.h Fri Dec 25 17:42:26 1998
+++ linux-pre-7.eb1/include/asm-sparc64/processor.h Sun Jan 10 22:46:08 1999
@@ -208,6 +208,7 @@
#define copy_segments(nr, tsk, mm) do { } while (0)
#define release_segments(mm) do { } while (0)
+#define forget_segments(tsk) do { } while (0)
#ifdef __KERNEL__
/* Allocation and freeing of task_struct and kernel stack. */
diff -uNrX linux-ignore-files linux-pre-7/include/linux/sched.h linux-pre-7.eb1/include/linux/sched.h
--- linux-pre-7/include/linux/sched.h Sun Jan 10 22:44:11 1999
+++ linux-pre-7.eb1/include/linux/sched.h Sun Jan 10 22:51:41 1999
@@ -33,7 +33,7 @@
#define CLONE_SIGHAND 0x00000800 /* set if signal handlers shared */
#define CLONE_PID 0x00001000 /* set if pid shared */
#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 mmput */
+#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */
/*
* These are the constant used to fake the fixed-point load-average
@@ -321,7 +321,7 @@
#define PF_DUMPCORE 0x00000200 /* dumped core */
#define PF_SIGNALED 0x00000400 /* killed by a signal */
#define PF_MEMALLOC 0x00000800 /* Allocating memory */
-#define PF_VFORK 0x00001000 /* Wake up parent in mmput */
+#define PF_VFORK 0x00001000 /* Wake up parent in mm_release */
#define PF_USEDFPU 0x00100000 /* task used FPU this quantum (SMP) */
#define PF_DTRACE 0x00200000 /* delayed trace (used on m68k, i386) */
@@ -608,6 +608,8 @@
atomic_inc(&mm->count);
}
extern void mmput(struct mm_struct *);
+/* Remove the current tasks stale references to the old mm_struct */
+extern void mm_release(struct task_struct *);
extern int copy_thread(int, unsigned long, unsigned long, struct task_struct *, struct pt_regs *);
extern void flush_thread(void);
diff -uNrX linux-ignore-files linux-pre-7/kernel/exit.c linux-pre-7.eb1/kernel/exit.c
--- linux-pre-7/kernel/exit.c Sun Jan 10 22:42:27 1999
+++ linux-pre-7.eb1/kernel/exit.c Sun Jan 10 22:46:09 1999
@@ -259,6 +259,7 @@
tsk->swappable = 0;
SET_PAGE_DIR(tsk, swapper_pg_dir);
mmput(mm);
+ mm_release(tsk);
}
}
diff -uNrX linux-ignore-files linux-pre-7/kernel/fork.c linux-pre-7.eb1/kernel/fork.c
--- linux-pre-7/kernel/fork.c Sun Jan 10 22:44:11 1999
+++ linux-pre-7.eb1/kernel/fork.c Sun Jan 10 22:58:20 1999
@@ -278,17 +278,34 @@
return mm;
}
-/*
- * Decrement the use count and release all resources for an mm.
+/* Please note the differences between mmput and mm_release.
+ * mmput is called whenever we stop holding onto a mm_struct,
+ * error success whatever.
+ *
+ * mm_release is called after a mm_struct has been removed
+ * from the current process.
+ *
+ * This difference is important for error handling, when we
+ * only half set up a mm_struct for a new process and need to restore
+ * the old one. Because we mmput the new mm_struct before
+ * restoring the old one. . .
+ * Eric Biederman 10 January 1998
*/
-void mmput(struct mm_struct *mm)
+void mm_release(struct task_struct *tsk)
{
+ forget_segments(tsk);
/* notify parent sleeping on vfork() */
- if (current->flags & PF_VFORK) {
+ if (tsk->flags & PF_VFORK) {
current->flags &= ~PF_VFORK;
up(current->p_opptr->vfork_sem);
}
+}
+/*
+ * Decrement the use count and release all resources for an mm.
+ */
+void mmput(struct mm_struct *mm)
+{
if (atomic_dec_and_test(&mm->count)) {
release_segments(mm);
exit_mmap(mm);
--
This is a majordomo managed list. To unsubscribe, send a message with
the body 'unsubscribe linux-mm me@address' to: majordomo@kvack.org
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: vfork & co bugfix
1999-01-11 4:32 ` Eric W. Biederman
@ 1999-01-11 6:35 ` Linus Torvalds
1999-01-11 6:59 ` Eric W. Biederman
0 siblings, 1 reply; 7+ messages in thread
From: Linus Torvalds @ 1999-01-11 6:35 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: linux-kernel, linux-mm
On 10 Jan 1999, Eric W. Biederman wrote:
>
> Darn it I missed the easy bug (All children waking up the parent),
> and found the hard one (waking up the parent if fork fails).
I missed it too, until I started thinking about all the possible
combinations.
> Question. Why don't we let CLONE_VFORK be a standard clone flag?
Because then we're back to the old problem: before doing a vfork(),
somebody could do a "clone(CLONE_VFORK)" (which would _not_ wait on the
semaphore like a real vfork() would), and now the wrong child can wake up
the parent and mess up the real vfork().
Linus
--
This is a majordomo managed list. To unsubscribe, send a message with
the body 'unsubscribe linux-mm me@address' to: majordomo@kvack.org
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: vfork & co bugfix
1999-01-11 6:35 ` Linus Torvalds
@ 1999-01-11 6:59 ` Eric W. Biederman
1999-01-11 7:31 ` Linus Torvalds
0 siblings, 1 reply; 7+ messages in thread
From: Eric W. Biederman @ 1999-01-11 6:59 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel, linux-mm
>>>>> "LT" == Linus Torvalds <torvalds@transmeta.com> writes:
LT> I missed it too, until I started thinking about all the possible
LT> combinations.
>> Question. Why don't we let CLONE_VFORK be a standard clone flag?
LT> Because then we're back to the old problem: before doing a vfork(),
LT> somebody could do a "clone(CLONE_VFORK)" (which would _not_ wait on the
LT> semaphore like a real vfork() would), and now the wrong child can wake up
LT> the parent and mess up the real vfork().
Sorry. I had the implicit assumption that if CLONE_VFORK was a
standard clone flag, do_fork would include the five lines of semaphore
code.
Eric
--
This is a majordomo managed list. To unsubscribe, send a message with
the body 'unsubscribe linux-mm me@address' to: majordomo@kvack.org
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: vfork & co bugfix
1999-01-11 6:59 ` Eric W. Biederman
@ 1999-01-11 7:31 ` Linus Torvalds
0 siblings, 0 replies; 7+ messages in thread
From: Linus Torvalds @ 1999-01-11 7:31 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: linux-kernel, linux-mm
On 11 Jan 1999, Eric W. Biederman wrote:
>
> >> Question. Why don't we let CLONE_VFORK be a standard clone flag?
>
> LT> Because then we're back to the old problem: before doing a vfork(),
> LT> somebody could do a "clone(CLONE_VFORK)" (which would _not_ wait on the
> LT> semaphore like a real vfork() would), and now the wrong child can wake up
> LT> the parent and mess up the real vfork().
>
> Sorry. I had the implicit assumption that if CLONE_VFORK was a
> standard clone flag, do_fork would include the five lines of semaphore
> code.
Oh, ok.
Sure, makes sense, and is probably the right thing to do - that way you
can (if you really want to) do some strange half-way vfork(), half-way
clone() thing where you share your file descriptors in a vfork().
I don't know how useful it would be, but it would be no uglier than doing
it any other way, and I see some advantages (no need for a separate
vfork() system call - clone() can do it directly).
I thus remove all my objections,
Linus
--
This is a majordomo managed list. To unsubscribe, send a message with
the body 'unsubscribe linux-mm me@address' to: majordomo@kvack.org
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~1999-01-11 7:31 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-01-10 6:48 vfork & co bugfix Eric W. Biederman
1999-01-10 18:04 ` Linus Torvalds
1999-01-10 21:34 ` Eric W. Biederman
1999-01-11 4:32 ` Eric W. Biederman
1999-01-11 6:35 ` Linus Torvalds
1999-01-11 6:59 ` Eric W. Biederman
1999-01-11 7:31 ` Linus Torvalds
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox