OSDN Git Service

security: insufficient range checks in certain fault handlers
authorWilly Tarreau <w@1wt.eu>
Sun, 3 Feb 2008 17:32:33 +0000 (18:32 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 11 Feb 2008 05:48:05 +0000 (06:48 +0100)
This is the 2.4 version of Nick Piggin's work on 2.6 fault handlers.
This deals with security vulnerability CVE-2008-0007.

Drivers that register a ->nopage handler, that does not range-check its
offset argument, must set VM_DONTEXPAND in the vm_flags to ensure the
offset is within bounds.

Signed-off-by: Willy Tarreau <w@1wt.eu>
drivers/char/drm-4.0/vm.c
drivers/char/drm/drm_vm.h
drivers/sound/via82cxxx_audio.c
fs/ncpfs/mmap.c

index f25aaa5..ef50f2d 100644 (file)
@@ -256,6 +256,7 @@ int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
 
        vma->vm_ops   = &drm_vm_dma_ops;
        vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
+       vma->vm_flags |= VM_DONTEXPAND;
        
 #if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
                                /* In Linux 2.2.3 and above, this is
@@ -358,6 +359,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
                return -EINVAL; /* This should never happen. */
        }
        vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
+       vma->vm_flags |= VM_DONTEXPAND;
 
 #if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
                                /* In Linux 2.2.3 and above, this is
index 4eadbf0..337a1a8 100644 (file)
@@ -342,6 +342,7 @@ 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)(vma);
        return 0;
@@ -475,6 +476,7 @@ int DRM(mmap)(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)(vma);
index 864f164..db5da3c 100644 (file)
@@ -2111,6 +2111,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;
@@ -2135,14 +2136,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 7d9bc34..dd8cb1a 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;