]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
vm audit: add VM_DONTEXPAND to mmap for drivers that need it (CVE-2008-0007)
authorNick Piggin <npiggin@suse.de>
Sat, 2 Feb 2008 02:08:53 +0000 (03:08 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 6 Feb 2008 19:43:46 +0000 (11:43 -0800)
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>
drivers/char/drm/drm_vm.c
drivers/char/mspec.c
fs/ncpfs/mmap.c
kernel/relay.c
mm/mmap.c
sound/oss/via82cxxx_audio.c
sound/usb/usx2y/usX2Yhwdep.c
sound/usb/usx2y/usx2yhwdeppcm.c

index b5c5b9fa84c3cd55bf7e0c8343fe6e6dc15771c3..e2d7be943cceb5a783833512fe878c62e5691068 100644 (file)
@@ -520,6 +520,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);
@@ -669,6 +670,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);
index 7ac30612068b674e742fb5577ed169148347f03f..5685b7a77c38e955211184a479119eacad121aeb 100644 (file)
@@ -265,7 +265,8 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
        vdata->refcnt = ATOMIC_INIT(1);
        vma->vm_private_data = vdata;
 
-       vma->vm_flags |= (VM_IO | VM_LOCKED | VM_RESERVED | VM_PFNMAP);
+       vma->vm_flags |= (VM_IO | VM_LOCKED | 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;
index 70a69115500f1603b589fb3d65e72acc5eb771db..f87de971824268dbe32be8d421b2c2fc9f876cfe 100644 (file)
@@ -47,9 +47,6 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area,
        pos = address - area->vm_start + (area->vm_pgoff << PAGE_SHIFT);
 
        count = PAGE_SIZE;
-       if (address + PAGE_SIZE > area->vm_end) {
-               count = area->vm_end - address;
-       }
        /* what we can read in one go */
        bufsize = NCP_SERVER(inode)->buffer_size;
 
index 95db8c79fe8f3371249029a19e48e817ffc34d12..24db7e81cde4e6b235af935bf7cfdb8d801e7a21 100644 (file)
@@ -91,6 +91,7 @@ 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);
 
index 906ed402f7cabda336a73d6d0d297b862b0d2932..33fb6718d76d88e022d175131ab8cf6ad99d1730 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2157,7 +2157,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;
index 5d3c0372df3289211223afe4968ff50eb4109cbb..f95aa0946758eddee10d995cc233d05005a8ae71 100644 (file)
@@ -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 */
index b76b3dd9df25d48d878548238f040018c443b075..e617d7ec647890ee8c4a266d2ed646ee21988b00 100644 (file)
@@ -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;
 }
index a5e7bcd7ca2ec0c5b486ba0b56c5f8e8f9d41a75..6e70520b75c83043aeeb679fd9036fa11199d99e 100644 (file)
@@ -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;
 }