Skip to contentSkip to conversation

vmalloc/ioremap race fix.

PATCH New David Woodhouse 1 participant 1 message Sep 13, 2002

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 vmalloc/ioremap race fix.

CPU0 CPU1
---- ----
vfree() vmalloc()
remove vm_struct from list.
reallocate same virtual range set up page tables
tear down page tables

So we leave the vm_struct in the list but marked as being deleted, while we tear down the page tables.

===== fs/proc/kcore.c 1.4 vs edited =====

fs/proc/kcore.c +9 -5
@@ -119,12 +119,12 @@
 
 	*num_vma = 0;
 	size = ((size_t)high_memory - PAGE_OFFSET + PAGE_SIZE);
-	if (!vmlist) {
+	if (list_empty(&vmlist)) {
 		*elf_buflen = PAGE_SIZE;
 		return (size);
 	}
 
-	for (m=vmlist; m; m=m->next) {
+	list_for_each_entry(m, &vmlist, list) {
 		try = (size_t)m->addr + m->size;
 		if (try > size)
 			size = try;
@@ -244,7 +244,7 @@
 	phdr->p_align	= PAGE_SIZE;
 
 	/* setup ELF PT_LOAD program header for every vmalloc'd area */
-	for (m=vmlist; m; m=m->next) {
+	list_for_each_entry(m, &vmlist, list) {
 		if (m->flags & VM_IOREMAP) /* don't dump ioremap'd stuff! (TA) */
 			continue;
 
@@ -404,11 +404,15 @@
 			memset(elf_buf, 0, tsz);
 
 			read_lock(&vmlist_lock);
-			for (m=vmlist; m && cursize; m=m->next) {
+			list_for_each_entry(m, &vmlist, list) {
 				unsigned long vmstart;
 				unsigned long vmsize;
-				unsigned long msize = m->size - PAGE_SIZE;
+				unsigned long msize;
 
+				if (!cursize)
+					break;
+
+				msize = m->size - PAGE_SIZE;
 				if (((unsigned long)m->addr + msize) < 
 								curstart)
 					continue;

===== mm/vmalloc.c 1.19 vs edited =====

mm/vmalloc.c +29 -21

160 lines not on this page · raw message

===== include/linux/vmalloc.h 1.7 vs edited =====

include/linux/vmalloc.h +5 -3
@@ -2,11 +2,13 @@
 #define _LINUX_VMALLOC_H
 
 #include <linux/spinlock.h>
+#include <linux/list.h>
 
 /* bits in vm_struct->flags */
 #define VM_IOREMAP	0x00000001	/* ioremap() and friends */
 #define VM_ALLOC	0x00000002	/* vmalloc() */
 #define VM_MAP		0x00000004	/* vmap()ed pages */
+#define VM_DELETING	0x00000008	/* Being removed */
 
 struct vm_struct {
 	void			*addr;
@@ -15,7 +17,7 @@
 	struct page		**pages;
 	unsigned int		nr_pages;
 	unsigned long		phys_addr;
-	struct vm_struct	*next;
+	struct list_head	list;
 };
 
 /*
@@ -39,9 +41,9 @@
 extern void unmap_vm_area(struct vm_struct *area);
 
 /*
- *	Internals.  Dont't use..
+ *	Internals.  Don't use.
  */
 extern rwlock_t vmlist_lock;
-extern struct vm_struct *vmlist;
+extern struct list_head vmlist;
 
 #endif /* _LINUX_VMALLOC_H */

--
dwmw2