vmalloc/ioremap race fix.
Subsystems (4)
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