From patchwork Sat Sep 29 16:11:13 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: mtd: kernel BUG at arch/x86/mm/pat.c:279! Date: Sat, 29 Sep 2012 06:11:13 -0000 From: David Woodhouse X-Patchwork-Id: 188037 Message-Id: <1348935073.2036.147.camel@shinybook.infradead.org> To: Linus Torvalds , Anatolij Gustschin , dhowells@redhat.com Cc: suresh.b.siddha@intel.com, "linux-kernel@vger.kernel.org" , linux-mm , linux-mtd@lists.infradead.org, Sasha Levin , Dave Jones , Andrew Morton On Fri, 2012-09-28 at 20:04 +0100, David Woodhouse wrote: > > I was really hoping it would go through the regular channels and come > > back to me that way, since I can't really test it, and it's bigger > > than the trivial obvious one-liners that I'm happy to commit. > > I can't test it on real hardware here either, but I can pull it through > my tree. Hmm... I don't have access to real hardware with mmapable flash right now (I haven't finished setting up the machine room since moving house last month). But you're seeing this in a case where you *don't* have mmapable flash either. If the value of map->phys is NO_XIP (-1UL), that should be taken to mean that you can't directly mmap it at all. That check seems to have been missing from David's commit 402d3265 in which he introduced the mtd_mmap() operation, and wasn't fixed in commit dd02b67d5 where Anatolij fixed things to actually *work* in the MMU code path. This should fix it: if ((vma->vm_end - vma->vm_start + off) > len) Now, we should ideally *also* handle the case where there genuinely *is* a mappable ROM device at the very top of physical memory, and not suffer from overflow. But that's a more esoteric case, and the patch above seems to be the one that we want to get merged into -stable. diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index f2f482b..27c2f57 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -1137,8 +1137,10 @@ static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma) u32 len; if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) { - off = vma->vm_pgoff << PAGE_SHIFT; start = map->phys; + if (map->phys == NO_XIP) + return -EINVAL; + off = vma->vm_pgoff << PAGE_SHIFT; len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size); start &= PAGE_MASK;