Re: BUG: unable to handle kernel paging request at virtual address

Al Viro
2008-01-05T09:10:29Z

On Fri, Jan 04, 2008 at 09:38:12PM +0400, Alexander Shaduri wrote:
>
> I got the following message, shortly followed by a system hang.
> BUG: unable to handle kernel paging request at virtual address 48464443
>
> (see the oops below).

AFAICS, it's quicklist_alloc() called from pgd_alloc():

static inline void *quicklist_alloc(int nr, gfp_t flags, void (*ctor)(void *))
{
struct quicklist *q;
void **p = NULL;

q =&get_cpu_var(quicklist)[nr];
p = q->page;
if (likely(p)) {
q->page = p[0];

and we have q->page == 0x48464443. Seeing how we assign that sucker, that
smells like we've got a page on quicklist with {0x43, 0x44, 0x46, 0x48}
in its first 4 bytes. Instead of having address of the next page stored
in there...

Do other oopsen of the same kind give the same value? The shortest
scenario I can see for that is
* something accidentally frees a page
* pgd_alloc() grabs it
* pgd_free() releases it and puts on quicklist; the first 4 bytes
are zeroed.
* whatever used to hold that page modifies it, overwriting its
beginning
* next pgd_alloc() grabs that page and advances quicklist - sets
it to the first 4 bytes of that page. At that point we are well and truly
fucked - quicklist is corrupted and once we need more pgd we'll get that
oops.

The question is, what's losing and then overwriting that page in the
first place?