]> err.no Git - linux-2.6/commitdiff
memcg: fix possible panic when CONFIG_MM_OWNER=y
authorKOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Mon, 12 May 2008 21:02:31 +0000 (14:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 13 May 2008 15:02:25 +0000 (08:02 -0700)
When mm destruction happens, we should pass mm_update_next_owner() the old mm.
 But unfortunately new mm is passed in exec_mmap().

Thus, kernel panic is possible when a multi-threaded process uses exec().

Also, the owner member comment description is wrong.  mm->owner does not
necessarily point to the thread group leader.

[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Acked-by: Balbir Singh <balbir@linux.vnet.ibm.com>
Cc: "Paul Menage" <menage@google.com>
Cc: "KAMEZAWA Hiroyuki" <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/exec.c
include/linux/mm_types.h

index aeaa9791d8be2ed499aea2c314d939f385d76e54..1f8a24aa1f8bbbf4a88235cfdb0d1341b29fa79a 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -736,7 +736,7 @@ static int exec_mmap(struct mm_struct *mm)
        tsk->active_mm = mm;
        activate_mm(active_mm, mm);
        task_unlock(tsk);
-       mm_update_next_owner(mm);
+       mm_update_next_owner(old_mm);
        arch_pick_mmap_layout(mm);
        if (old_mm) {
                up_read(&old_mm->mmap_sem);
index eb7c16cc95596fae106848e0a66b3b04f6f6b68a..02a27ae78539cfe536106f46a8f89b50ea63985e 100644 (file)
@@ -226,8 +226,17 @@ struct mm_struct {
        rwlock_t                ioctx_list_lock;        /* aio lock */
        struct kioctx           *ioctx_list;
 #ifdef CONFIG_MM_OWNER
-       struct task_struct *owner;      /* The thread group leader that */
-                                       /* owns the mm_struct.          */
+       /*
+        * "owner" points to a task that is regarded as the canonical
+        * user/owner of this mm. All of the following must be true in
+        * order for it to be changed:
+        *
+        * current == mm->owner
+        * current->mm != mm
+        * new_owner->mm == mm
+        * new_owner->alloc_lock is held
+        */
+       struct task_struct *owner;
 #endif
 
 #ifdef CONFIG_PROC_FS