==== vm_io description ==== We've had a few bugs recently where device drivers were forgetting to set vma->vm_flags:VM_IO in their mmap() methods. This causes kernel deadlocks when applications which have the relevant device mapped try to dump core (the pagefault handler deadlocks on mmap_sem). Failing to set VM_IO also causes kernel oopses when PTRACE_PEEKUSR tries to read the device mapping - the region has no page structs, but access_process_vm() acts as if it does. This patch doesn't fix the PTRACE_PEEKUSR bug - for that we need this patch as well as the patch Andrea, Manfred and I pieced together - it's at http://www.kernel.org/pub/linux/kernel/people/andrea/kernels/v2.4/2.4.18pre7aa2/00_get_user_pages-2 I understand that Manfred will be sending you a version of that patch. The drivers which are forgetting to set VM_IO include a whole bunch of fbmem drivers, one or more AGP drivers and I don't know what else. It's simpler to make VM_IO default to `on', and to only clear it in places where we know that it's safe to dump the memory to a core file, and where it's safe to PTRACE_PEEKUSR it. That's what this patch does. We only clear VM_IO in generic_file_mmap() and in ncp_mmap() and in coda_file_mmap(). Any filesystem which implements its own mmap() method, and which does not call generic_file_mmap() needs to be changed to clear VM_IO inside its mmap function. All in-kernel filesystems are OK, as is XFS. And the only breakage this can cause to out-of-kernel filesystems is failure to include mappings in core files, and inability to use PEEKUSR. With this patch in place we can go through and remove the setting of VM_IO in all the drivers which _do_ remember to set it. But that's a cleanup which can await 2.4.19-pre. ===================================== --- 2.4.18-rc2/mm/mmap.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/mm/mmap.c Tue Feb 19 15:02:42 2002 @@ -534,6 +534,11 @@ munmap_back: } vma->vm_file = file; get_file(file); + /* + * Subdrivers can clear VM_IO if their mappings are + * valid pages inside mem_map[] + */ + vma->vm_flags |= VM_IO; error = file->f_op->mmap(file, vma); if (error) goto unmap_and_free_vma; --- 2.4.18-rc2/mm/filemap.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/mm/filemap.c Tue Feb 19 15:02:42 2002 @@ -2111,6 +2111,7 @@ int generic_file_mmap(struct file * file return -ENOEXEC; UPDATE_ATIME(inode); vma->vm_ops = &generic_file_vm_ops; + vma->vm_flags &= ~VM_IO; return 0; } --- 2.4.18-rc2/fs/ncpfs/mmap.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/fs/ncpfs/mmap.c Tue Feb 19 15:02:42 2002 @@ -119,5 +119,6 @@ int ncp_mmap(struct file *file, struct v } vma->vm_ops = &ncp_file_mmap; + vma->vm_flags &= ~VM_IO; return 0; } --- 2.4.18-rc2/ipc/shm.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/ipc/shm.c Tue Feb 19 15:02:42 2002 @@ -159,6 +159,7 @@ static int shm_mmap(struct file * file, { UPDATE_ATIME(file->f_dentry->d_inode); vma->vm_ops = &shm_vm_ops; + vma->vm_flags &= ~VM_IO; shm_inc(file->f_dentry->d_inode->i_ino); return 0; } --- 2.4.18-rc2/mm/shmem.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/mm/shmem.c Tue Feb 19 15:02:42 2002 @@ -657,6 +657,7 @@ static int shmem_mmap(struct file * file return -EACCES; UPDATE_ATIME(inode); vma->vm_ops = ops; + vma->vm_flags &= ~VM_IO; return 0; } --- 2.4.18-rc2/drivers/char/mem.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/char/mem.c Tue Feb 19 15:02:42 2002 @@ -198,10 +198,10 @@ static int mmap_mem(struct file * file, vma->vm_flags |= VM_RESERVED; /* - * Don't dump addresses that are not real memory to a core file. + * Dump addresses that are real memory to a core file. */ - if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC)) - vma->vm_flags |= VM_IO; + if (offset < __pa(high_memory) && !(file->f_flags & O_SYNC)) + vma->vm_flags &= ~VM_IO; if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start, vma->vm_page_prot)) @@ -473,6 +473,7 @@ static int mmap_zero(struct file * file, return shmem_zero_setup(vma); if (zeromap_page_range(vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; + vma->vm_flags &= ~VM_IO; return 0; } --- 2.4.18-rc2/net/socket.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/net/socket.c Tue Feb 19 15:02:42 2002 @@ -705,6 +705,7 @@ static int sock_mmap(struct file * file, { struct socket *sock = socki_lookup(file->f_dentry->d_inode); + vma->vm_flags &= ~VM_IO; return sock->ops->mmap(file, sock, vma); } --- 2.4.18-rc2/drivers/char/ftape/zftape/zftape-init.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/char/ftape/zftape/zftape-init.c Tue Feb 19 15:02:42 2002 @@ -204,6 +204,7 @@ static int zft_mmap(struct file *filep, sigfillset(¤t->blocked); lock_kernel(); if ((result = ftape_mmap(vma)) >= 0) { + vma->vm_flags &= ~VM_IO; #ifndef MSYNC_BUG_WAS_FIXED static struct vm_operations_struct dummy = { NULL, }; vma->vm_ops = &dummy; --- 2.4.18-rc2/drivers/sound/soundcard.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/sound/soundcard.c Tue Feb 19 15:02:42 2002 @@ -481,6 +481,7 @@ static int sound_mmap(struct file *file, return -EAGAIN; } + vma->vm_flags &= ~VM_IO; dmap->mapping_flags |= DMA_MAP_MAPPED; if( audio_devs[dev]->d->mmap) --- 2.4.18-rc2/drivers/sound/es1370.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/sound/es1370.c Tue Feb 19 15:02:42 2002 @@ -1377,6 +1377,7 @@ static int es1370_mmap(struct file *file ret = -EAGAIN; goto out; } + vma->vm_flags &= ~VM_IO; db->mapped = 1; out: up(&s->sem); --- 2.4.18-rc2/drivers/sound/maestro.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/sound/maestro.c Tue Feb 19 15:02:42 2002 @@ -2512,6 +2512,7 @@ static int ess_mmap(struct file *file, s ret = -EAGAIN; if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) goto out; + vma->vm_flags &= ~VM_IO; db->mapped = 1; ret = 0; out: --- 2.4.18-rc2/drivers/sound/trident.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/sound/trident.c Tue Feb 19 15:02:42 2002 @@ -2077,6 +2077,7 @@ static int trident_mmap(struct file *fil if (remap_page_range(vma->vm_start, virt_to_phys(dmabuf->rawbuf), size, vma->vm_page_prot)) goto out; + vma->vm_flags &= ~VM_IO; dmabuf->mapped = 1; ret = 0; out: --- 2.4.18-rc2/drivers/sound/es1371.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/sound/es1371.c Tue Feb 19 15:02:42 2002 @@ -1566,6 +1566,7 @@ static int es1371_mmap(struct file *file ret = -EAGAIN; goto out; } + vma->vm_flags &= ~VM_IO; db->mapped = 1; out: up(&s->sem); @@ -2133,6 +2134,7 @@ static int es1371_mmap_dac(struct file * ret = -EAGAIN; if (remap_page_range(vma->vm_start, virt_to_phys(s->dma_dac1.rawbuf), size, vma->vm_page_prot)) goto out; + vma->vm_flags &= ~VM_IO; s->dma_dac1.mapped = 1; ret = 0; out: --- 2.4.18-rc2/drivers/sound/cs4281/cs4281m.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/sound/cs4281/cs4281m.c Tue Feb 19 15:02:42 2002 @@ -3239,6 +3239,7 @@ static int cs4281_mmap(struct file *file if (remap_page_range (vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) return -EAGAIN; + vma->vm_flags &= ~VM_IO; db->mapped = 1; CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4, --- 2.4.18-rc2/drivers/sound/cmpci.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/sound/cmpci.c Tue Feb 19 15:02:42 2002 @@ -1754,6 +1754,7 @@ static int cm_mmap(struct file *file, st ret = -EINVAL; if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) goto out; + vma->vm_flags &= ~VM_IO; db->mapped = 1; ret = 0; out: --- 2.4.18-rc2/drivers/sound/i810_audio.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/sound/i810_audio.c Tue Feb 19 15:02:42 2002 @@ -1672,6 +1672,7 @@ static int i810_mmap(struct file *file, if (remap_page_range(vma->vm_start, virt_to_phys(dmabuf->rawbuf), size, vma->vm_page_prot)) goto out; + vma->vm_flags &= ~VM_IO; dmabuf->mapped = 1; dmabuf->trigger = 0; ret = 0; --- 2.4.18-rc2/drivers/sound/sonicvibes.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/sound/sonicvibes.c Tue Feb 19 15:02:42 2002 @@ -1551,6 +1551,7 @@ static int sv_mmap(struct file *file, st ret = -EAGAIN; if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) goto out; + vma->vm_flags &= ~VM_IO; db->mapped = 1; ret = 0; out: --- 2.4.18-rc2/drivers/sound/esssolo1.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/sound/esssolo1.c Tue Feb 19 15:02:42 2002 @@ -1247,6 +1247,7 @@ static int solo1_mmap(struct file *file, ret = -EAGAIN; if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) goto out; + vma->vm_flags &= ~VM_IO; db->mapped = 1; ret = 0; out: --- 2.4.18-rc2/drivers/sound/maestro3.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/sound/maestro3.c Tue Feb 19 15:02:42 2002 @@ -1557,6 +1557,7 @@ static int m3_mmap(struct file *file, st ret = -EAGAIN; if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) goto out; + vma->vm_flags &= ~VM_IO; db->mapped = 1; ret = 0; --- 2.4.18-rc2/drivers/sound/ymfpci.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/sound/ymfpci.c Tue Feb 19 15:02:42 2002 @@ -1507,6 +1507,7 @@ static int ymf_mmap(struct file *file, s if (remap_page_range(vma->vm_start, virt_to_phys(dmabuf->rawbuf), size, vma->vm_page_prot)) return -EAGAIN; + vma->vm_flags &= ~VM_IO; dmabuf->mapped = 1; /* P3 */ printk(KERN_INFO "ymfpci: using memory mapped sound, untested!\n"); --- 2.4.18-rc2/drivers/sound/cs46xx.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/sound/cs46xx.c Tue Feb 19 15:02:42 2002 @@ -2468,6 +2468,7 @@ static int cs_mmap(struct file *file, st ret = -EAGAIN; goto out; } + vma->vm_flags &= ~VM_IO; dmabuf->mapped = 1; CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mmap()-\n") ); --- 2.4.18-rc2/drivers/sound/rme96xx.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/sound/rme96xx.c Tue Feb 19 15:02:42 2002 @@ -1429,7 +1429,7 @@ static int rm96xx_mmap(struct file *file /* this is the mapping */ - + vma->vm_flags &= ~VM_IO; dma->mmapped = 1; unlock_kernel(); return 0; --- 2.4.18-rc2/drivers/sound/ite8172.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/sound/ite8172.c Tue Feb 19 15:02:42 2002 @@ -1111,6 +1111,7 @@ static int it8172_mmap(struct file *file unlock_kernel(); return -EAGAIN; } + vma->vm_flags &= ~VM_IO; db->mapped = 1; unlock_kernel(); return 0; --- 2.4.18-rc2/drivers/usb/audio.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/usb/audio.c Tue Feb 19 15:02:42 2002 @@ -2341,6 +2341,7 @@ static int usb_audio_mmap(struct file *f if (vma->vm_pgoff != 0) goto out; + vma->vm_flags &= ~VM_IO; ret = dmabuf_mmap(db, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot); out: unlock_kernel(); --- 2.4.18-rc2/drivers/media/video/videodev.c~vm_io Tue Feb 19 15:02:42 2002 +++ 2.4.18-rc2-akpm/drivers/media/video/videodev.c Tue Feb 19 15:02:42 2002 @@ -208,6 +208,7 @@ int video_mmap(struct file *file, struct lock_kernel(); ret = vfl->mmap(vfl, (char *)vma->vm_start, (unsigned long)(vma->vm_end-vma->vm_start)); + vma->vm_flags &= ~VM_IO; unlock_kernel(); } return ret;