📄 proc race fixes for 2.2.1.txt
字号:
@@ -389 +390,30 @@
-static unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr)
+/*
+ * Caller must release_mm the mm_struct later.
+ * You don't get any access to init_mm.
+ */
+static struct mm_struct * grab_mm(int pid)
+{
+ struct mm_struct * mm = NULL;
+ struct task_struct * tsk;
+
+ read_lock(&tasklist_lock);
+ tsk = find_task_by_pid(pid);
+ /*
+ * NOTE: this doesn't race because we are protected by the
+ * big kernel lock. -arca
+ */
+ if (tsk && tsk->mm && tsk->mm != &init_mm)
+ mmget(mm = tsk->mm);
+ read_unlock(&tasklist_lock);
+ if (mm)
+ down(&mm->mmap_sem);
+ return mm;
+}
+
+static void release_mm(struct mm_struct *mm)
+{
+ up(&mm->mmap_sem);
+ mmput(mm);
+}
+
+static unsigned long get_phys_addr(struct mm_struct *mm, unsigned long ptr)
@@ -395 +425 @@
- if (!p || !p->mm || ptr >= TASK_SIZE)
+ if (ptr >= TASK_SIZE)
@@ -398,2 +428,2 @@
- if (!p->mm->pgd) {
- printk("get_phys_addr: pid %d has NULL pgd!\n", p->pid);
+ if (!mm->pgd) {
+ printk(KERN_DEBUG "missing pgd for mm %p\n", mm);
@@ -403 +433 @@
- page_dir = pgd_offset(p->mm,ptr);
+ page_dir = pgd_offset(mm,ptr);
@@ -425 +455 @@
-static int get_array(struct task_struct *p, unsigned long start, unsigned long
nd, char * buffer)
+static int get_array(struct mm_struct *mm, unsigned long start, unsigned long e
d, char * buffer)
@@ -434 +464 @@
- addr = get_phys_addr(p, start);
+ addr = get_phys_addr(mm, start);
@@ -456,5 +486,2 @@
- struct task_struct *p;
-
- read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
- read_unlock(&tasklist_lock); /* FIXME!! This should be done after the
last use */
+ struct mm_struct *mm;
+ int res = 0;
@@ -462,3 +489,6 @@
- if (!p || !p->mm)
- return 0;
- return get_array(p, p->mm->env_start, p->mm->env_end, buffer);
+ mm = grab_mm(pid);
+ if (mm) {
+ res = get_array(mm, mm->env_start, mm->env_end, buffer);
+ release_mm(mm);
+ }
+ return res;
@@ -469 +499,2 @@
- struct task_struct *p;
+ struct mm_struct *mm;
+ int res = 0;
@@ -471,6 +502,6 @@
- read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
- read_unlock(&tasklist_lock); /* FIXME!! This should be done after the
last use */
- if (!p || !p->mm)
- return 0;
- return get_array(p, p->mm->arg_start, p->mm->arg_end, buffer);
+ mm = grab_mm(pid);
+ if (mm) {
+ res = get_array(mm, mm->arg_start, mm->arg_end, buffer);
+ release_mm(mm);
+ }
+ return res;
@@ -725 +707 @@
-static inline char * task_mem(struct task_struct *p, char *buffer)
+static inline char * task_mem(struct mm_struct * mm, char *buffer)
@@ -727,4 +709,2 @@
- struct mm_struct * mm = p->mm;
-
- if (mm && mm != &init_mm) {
- struct vm_area_struct * vma = mm->mmap;
+ if (mm) {
+ struct vm_area_struct * vma;
@@ -819,0 +800,39 @@
+static struct task_struct *grab_task(int pid, struct mm_struct ** mm)
+{
+ struct task_struct *tsk = current;
+
+ *mm = NULL;
+ read_lock(&tasklist_lock);
+ tsk = find_task_by_pid(pid);
+ if (tsk)
+ {
+ struct mm_struct * __mm;
+ struct page * page = mem_map + MAP_NR(tsk);
+ atomic_inc(&page->count);
+ /*
+ * NOTE: this doesn't race because we are protected
+ * by the big kernel lock. -arca
+ */
+ __mm = tsk->mm;
+ if (__mm && __mm != &init_mm)
+ {
+ mmget(__mm);
+ *mm = __mm;
+ }
+ }
+ read_unlock(&tasklist_lock);
+ if (*mm)
+ down(&(*mm)->mmap_sem);
+
+ return tsk;
+}
+
+static void release_task(struct task_struct *tsk, struct mm_struct * mm)
+{
+ if (mm)
+ {
+ up(&mm->mmap_sem);
+ mmput(mm);
+ }
+ free_pages((unsigned long) tsk, 1);
+}
@@ -825,4 +844,3 @@
-
- read_lock(&tasklist_lock);
- tsk = find_task_by_pid(pid);
- read_unlock(&tasklist_lock); /* FIXME!! This should be done after the
last use */
+ struct mm_struct * mm;
+
+ tsk = grab_task(pid, &mm);
@@ -833 +851 @@
- buffer = task_mem(tsk, buffer);
+ buffer = task_mem(mm, buffer);
@@ -835,0 +854 @@
+ release_task(tsk, mm);
@@ -841,0 +861 @@
+ struct mm_struct * mm;
@@ -846,0 +867 @@
+ int res;
@@ -848,3 +869 @@
- read_lock(&tasklist_lock);
- tsk = find_task_by_pid(pid);
- read_unlock(&tasklist_lock); /* FIXME!! This should be done after the
last use */
+ tsk = grab_task(pid, &mm);
@@ -855,3 +874,4 @@
- if (tsk->mm && tsk->mm != &init_mm) {
- struct vm_area_struct *vma = tsk->mm->mmap;
- while (vma) {
+ if (mm) {
+ struct vm_area_struct *vma;
+
+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
@@ -859 +878,0 @@
- vma = vma->vm_next;
@@ -860,0 +880 @@
+
@@ -881 +901 @@
- return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
+ res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
@@ -907 +927 @@
- tsk->mm ? tsk->mm->rss : 0, /* you might want to shift this left
3 */
+ mm ? mm->rss : 0, /* you might want to shift this left 3 */
@@ -909,3 +929,3 @@
- tsk->mm ? tsk->mm->start_code : 0,
- tsk->mm ? tsk->mm->end_code : 0,
- tsk->mm ? tsk->mm->start_stack : 0,
+ mm ? mm->start_code : 0,
+ mm ? mm->end_code : 0,
+ mm ? mm->start_stack : 0,
@@ -925,0 +946,3 @@
+
+ release_task(tsk, mm);
+ return res;
@@ -1003 +1025,0 @@
- struct task_struct *tsk;
@@ -1004,0 +1027 @@
+ struct mm_struct *mm;
@@ -1006,7 +1029,3 @@
- read_lock(&tasklist_lock);
- tsk = find_task_by_pid(pid);
- read_unlock(&tasklist_lock); /* FIXME!! This should be done after the
last use */
- if (!tsk)
- return 0;
- if (tsk->mm && tsk->mm != &init_mm) {
- struct vm_area_struct * vma = tsk->mm->mmap;
+ mm = grab_mm(pid);
+ if (mm) {
+ struct vm_area_struct * vma = mm->mmap;
@@ -1015 +1034 @@
- pgd_t *pgd = pgd_offset(tsk->mm, vma->vm_start);
+ pgd_t *pgd = pgd_offset(mm, vma->vm_start);
@@ -1032,0 +1052 @@
+ release_mm(mm);
@@ -1070 +1089,0 @@
-
@@ -1074 +1093,2 @@
- struct task_struct *p;
+ struct task_struct * p;
+ struct mm_struct * mm;
@@ -1079 +1098,0 @@
- int volatile_task;
@@ -1091,3 +1110 @@
- read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
- read_unlock(&tasklist_lock); /* FIXME!! This should be done after the
last use */
+ p = grab_task(pid, &mm);
@@ -1097 +1114 @@
- if (!p->mm || p->mm == &init_mm || count == 0)
+ if (!mm || count == 0)
@@ -1100,3 +1116,0 @@
- /* Check whether the mmaps could change if we sleep */
- volatile_task = (p != current || atomic_read(&p->mm->count) > 1);
-
@@ -1108 +1122 @@
- for (map = p->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next,
++)
+ for (map = mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++
@@ -1179,6 +1192,0 @@
-
- /* By writing to user space, we might have slept.
- * Stop the loop, to avoid a race condition.
- */
- if (volatile_task)
- break;
@@ -1190,0 +1199 @@
+ release_task(p, mm);
@@ -1202 +1211,2 @@
- struct task_struct * tsk = current ;
+ struct task_struct * tsk;
+ struct mm_struct * mm;
@@ -1205,6 +1215,2 @@
- read_lock(&tasklist_lock);
- if (pid != tsk->pid)
- tsk = find_task_by_pid(pid);
- read_unlock(&tasklist_lock); /* FIXME!! This should be done after the
last use */
-
- if (tsk == NULL)
+ tsk = grab_task(pid, &mm);
+ if (!tsk)
@@ -1223,0 +1230 @@
+ release_task(tsk, mm);
--
我问飘逝的风:来迟了?
风感慨:是的,他们已经宣战。
我问苏醒的大地:还有希望么?
大地揉了揉眼睛:还有,还有无数代的少年。
我问长空中的英魂:你们相信?
英魂带着笑意离去:相信,希望还在。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -