diff options
author | Nick Piggin <npiggin@suse.de> | 2008-02-02 03:08:53 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-02-08 12:01:45 -0800 |
commit | d4dd8e3a7287146e479c77e0456eaa315875972a (patch) | |
tree | 60af474e387a51cada420be207f4a13b96c83edd | |
parent | 5f8d005f5ee726ec8b6b3ddd9920a3e609740320 (diff) |
vm audit: add VM_DONTEXPAND to mmap for drivers that need it (CVE-2008-0007)
Drivers that register a ->fault handler, but do not range-check the
offset argument, must set VM_DONTEXPAND in the vm_flags in order to
prevent an expanding mremap from overflowing the resource.
I've audited the tree and attempted to fix these problems (usually by
adding VM_DONTEXPAND where it is not obvious).
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/char/drm/drm_vm.c | 2 | ||||
-rw-r--r-- | drivers/char/mspec.c | 2 | ||||
-rw-r--r-- | fs/ncpfs/mmap.c | 4 | ||||
-rw-r--r-- | kernel/relay.c | 1 | ||||
-rw-r--r-- | mm/mmap.c | 2 | ||||
-rw-r--r-- | sound/oss/via82cxxx_audio.c | 14 | ||||
-rw-r--r-- | sound/usb/usx2y/usX2Yhwdep.c | 2 | ||||
-rw-r--r-- | sound/usb/usx2y/usx2yhwdeppcm.c | 2 |
8 files changed, 13 insertions, 16 deletions
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index 68e36e51ba0..caa0bcee37f 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c @@ -506,6 +506,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) vma->vm_ops = &drm_vm_dma_ops; vma->vm_flags |= VM_RESERVED; /* Don't swap */ + vma->vm_flags |= VM_DONTEXPAND; vma->vm_file = filp; /* Needed for drm_vm_open() */ drm_vm_open_locked(vma); @@ -655,6 +656,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) return -EINVAL; /* This should never happen. */ } vma->vm_flags |= VM_RESERVED; /* Don't swap */ + vma->vm_flags |= VM_DONTEXPAND; vma->vm_file = filp; /* Needed for drm_vm_open() */ drm_vm_open_locked(vma); diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index 04ac155d3a0..ada142a01b2 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c @@ -283,7 +283,7 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, vdata->refcnt = ATOMIC_INIT(1); vma->vm_private_data = vdata; - vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP); + vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP | VM_DONTEXPAND); if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); vma->vm_ops = &mspec_vm_ops; diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c index a94473d3072..5d8dcb9ee32 100644 --- a/fs/ncpfs/mmap.c +++ b/fs/ncpfs/mmap.c @@ -50,10 +50,6 @@ static int ncp_file_mmap_fault(struct vm_area_struct *area, pos = vmf->pgoff << PAGE_SHIFT; count = PAGE_SIZE; - if ((unsigned long)vmf->virtual_address + PAGE_SIZE > area->vm_end) { - WARN_ON(1); /* shouldn't happen? */ - count = area->vm_end - (unsigned long)vmf->virtual_address; - } /* what we can read in one go */ bufsize = NCP_SERVER(inode)->buffer_size; diff --git a/kernel/relay.c b/kernel/relay.c index ad855017bc5..91bbfb725e8 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -92,6 +92,7 @@ static int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma) return -EINVAL; vma->vm_ops = &relay_file_mmap_ops; + vma->vm_flags |= VM_DONTEXPAND; vma->vm_private_data = buf; buf->chan->cb->buf_mapped(buf, filp); diff --git a/mm/mmap.c b/mm/mmap.c index 94326cb74f9..f6058f662c3 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2217,7 +2217,7 @@ int install_special_mapping(struct mm_struct *mm, vma->vm_start = addr; vma->vm_end = addr + len; - vma->vm_flags = vm_flags | mm->def_flags; + vma->vm_flags = vm_flags | mm->def_flags | VM_DONTEXPAND; vma->vm_page_prot = protection_map[vma->vm_flags & 7]; vma->vm_ops = &special_mapping_vmops; diff --git a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c index 5d3c0372df3..f95aa094675 100644 --- a/sound/oss/via82cxxx_audio.c +++ b/sound/oss/via82cxxx_audio.c @@ -2104,6 +2104,7 @@ static struct page * via_mm_nopage (struct vm_area_struct * vma, { struct via_info *card = vma->vm_private_data; struct via_channel *chan = &card->ch_out; + unsigned long max_bufs; struct page *dmapage; unsigned long pgoff; int rd, wr; @@ -2127,14 +2128,11 @@ static struct page * via_mm_nopage (struct vm_area_struct * vma, rd = card->ch_in.is_mapped; wr = card->ch_out.is_mapped; -#ifndef VIA_NDEBUG - { - unsigned long max_bufs = chan->frag_number; - if (rd && wr) max_bufs *= 2; - /* via_dsp_mmap() should ensure this */ - assert (pgoff < max_bufs); - } -#endif + max_bufs = chan->frag_number; + if (rd && wr) + max_bufs *= 2; + if (pgoff >= max_bufs) + return NOPAGE_SIGBUS; /* if full-duplex (read+write) and we have two sets of bufs, * then the playback buffers come first, sez soundcard.c */ diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c index b76b3dd9df2..e617d7ec647 100644 --- a/sound/usb/usx2y/usX2Yhwdep.c +++ b/sound/usb/usx2y/usX2Yhwdep.c @@ -88,7 +88,7 @@ static int snd_us428ctls_mmap(struct snd_hwdep * hw, struct file *filp, struct v us428->us428ctls_sharedmem->CtlSnapShotLast = -2; } area->vm_ops = &us428ctls_vm_ops; - area->vm_flags |= VM_RESERVED; + area->vm_flags |= VM_RESERVED | VM_DONTEXPAND; area->vm_private_data = hw->private_data; return 0; } diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index a5e7bcd7ca2..6e70520b75c 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -728,7 +728,7 @@ static int snd_usX2Y_hwdep_pcm_mmap(struct snd_hwdep * hw, struct file *filp, st return -ENODEV; } area->vm_ops = &snd_usX2Y_hwdep_pcm_vm_ops; - area->vm_flags |= VM_RESERVED; + area->vm_flags |= VM_RESERVED | VM_DONTEXPAND; area->vm_private_data = hw->private_data; return 0; } |