Subject: Kernel related (?) user space crash at ARM11 MPCore

From: [email-masked] (Jamie Lokier)
Date: Mon, 21 Sep 2009 23:12:29 +0100

Catalin Marinas wrote:
> A possible scenario (though more code analysis is needed to be entirely 
> sure) with writing instructions and not calling sys_cacheflush():
> 
> - application mmap's a file (shared mapping, otherwise the data written 
> to private mappings is lost when unmapping)
> - app writes some instructions to text pages. We don't get CoW because 
> of the shared mapping but we don't get D-cache cleaning either
> - app unmap's the page but the kernel keeps the physical page in its 
> page cache. The flush_cache_page() on non-aliasing VIPT doesn't do 
> anything on ARM
> - app mmap's the page with PROT_READ|PROT_EXEC
> - app executes from the page generating a prefetch abort. The kernel 
> finds the page in its page cache and maps it into user space, calling 
> update_mmu_cache(). However, the dirty bit isn't set (since the kernel 
> hasn't touched the page) and the lazy D-cache flushing in 
> update_mmu_cache isn't triggered, leaving the I-cache with old entries 
> directly from RAM.

Why isn't the dirty bit set by the last step?

The dirty bit must be set by the writes in the second step, otherwise
how does the kernel know not to discard those writes under memory
pressure?

Btw, regarding "non-aliasing", it's pretty clear that it does alias
the I-cache ;-), in much the same way as different addresses alias in
the D-cache with an "aliasing" cache.  That may well be a clue as to
clean, systematic and sane way of ensuring all the cache ops are in
all the right places.

-- Jamie