From: Nick Piggin Subject: insufficient range checks of certain fault handlers (CVE-2008-0007) References: 353207 Patch-upstream: not yet This patch is a security fix for CVE-2008-0007. See bugzilla for details. --- Index: linux-2.6.22/drivers/char/drm/drm_vm.c =================================================================== --- linux-2.6.22.orig/drivers/char/drm/drm_vm.c +++ linux-2.6.22/drivers/char/drm/drm_vm.c @@ -520,6 +520,7 @@ static int drm_mmap_dma(struct file *fil 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 * 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: linux-2.6.22/kernel/relay.c =================================================================== --- linux-2.6.22.orig/kernel/relay.c +++ linux-2.6.22/kernel/relay.c @@ -91,6 +91,7 @@ int relay_mmap_buf(struct rchan_buf *buf 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: linux-2.6.22/mm/mmap.c =================================================================== --- linux-2.6.22.orig/mm/mmap.c +++ linux-2.6.22/mm/mmap.c @@ -2157,7 +2157,7 @@ int install_special_mapping(struct mm_st 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: linux-2.6.22/sound/oss/via82cxxx_audio.c =================================================================== --- linux-2.6.22.orig/sound/oss/via82cxxx_audio.c +++ linux-2.6.22/sound/oss/via82cxxx_audio.c @@ -2104,6 +2104,7 @@ static struct page * via_mm_nopage (stru { 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 (stru 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: linux-2.6.22/sound/usb/usx2y/usX2Yhwdep.c =================================================================== --- linux-2.6.22.orig/sound/usb/usx2y/usX2Yhwdep.c +++ linux-2.6.22/sound/usb/usx2y/usX2Yhwdep.c @@ -88,7 +88,7 @@ static int snd_us428ctls_mmap(struct snd 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: linux-2.6.22/sound/usb/usx2y/usx2yhwdeppcm.c =================================================================== --- linux-2.6.22.orig/sound/usb/usx2y/usx2yhwdeppcm.c +++ linux-2.6.22/sound/usb/usx2y/usx2yhwdeppcm.c @@ -728,7 +728,7 @@ static int snd_usX2Y_hwdep_pcm_mmap(stru 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; } Index: linux-2.6.22/drivers/char/mspec.c =================================================================== --- linux-2.6.22.orig/drivers/char/mspec.c +++ linux-2.6.22/drivers/char/mspec.c @@ -265,7 +265,7 @@ mspec_mmap(struct file *file, struct vm_ 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: linux-2.6.22/sound/oss/emu10k1/audio.c =================================================================== --- linux-2.6.22.orig/sound/oss/emu10k1/audio.c +++ linux-2.6.22/sound/oss/emu10k1/audio.c @@ -1111,7 +1111,7 @@ static int emu10k1_audio_mmap(struct fil if (pgoffset + n_pages > max_pages) return -EINVAL; - vma->vm_flags |= VM_RESERVED; + vma->vm_flags |= VM_RESERVED | VM_DONTEXPAND; vma->vm_ops = &emu10k1_mm_ops; vma->vm_private_data = wave_dev; return 0;