Re: [Bugme-new] [Bug 14564] New: capture-example sleeping function called from invalid context at arch/x86/mm/fault.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 11 Nov 2009, Andrew Morton wrote:

> > http://bugzilla.kernel.org/show_bug.cgi?id=14564
> > 
> >            Summary: capture-example sleeping function called from invalid
> >                     context at arch/x86/mm/fault.c

> We oopsed in td_free() (see below).  But as part of that oops
> processing the kernel entered do_page_fault() and emitted a
> might_sleep() warning because we took a pagefault with local interrupts
> disabled.
> 
> This is undesirable behaviour from the low-level x86 fault code and I
> don't think it normally happens.
> 
> Did we break something in x86 land, or is this oops sufficiently weird
> and whacky to bypass existing checks for this false positive?

No, what happened was a structure containing a linked-list entry got
freed while it was still on the list.  Then when the driver walked
through the list, it attempted to dereference a list pointer that had
been poisoned.  More or less by coincidence, the poison value
represented a paged-out address rather than an invalid address, so a
page fault occurred.  That's what caused the oops.

> > BUG: unable to handle kernel paging request at a7a7a7c3                         
> > IP: [<c11c5cef>] td_free+0x23/0x75                                              

> >  [<c1155a42>] ? tty_ldisc_deref+0x8/0xa                                         
> >  [<c1150c1c>] ? tty_write+0x1b1/0x1c2                                           
> >  [<c1152d69>] ? n_tty_write+0x0/0x2e6                                           
> >  [<c1150a6b>] ? tty_write+0x0/0x1c2                                             
> >  [<c106431d>] ? vfs_write+0xe3/0xfa                                             
> >  [<c1002858>] ? restore_all_notrace+0x0/0x18                                    
> >  [<c106e3e2>] ? sys_ioctl+0x2c/0x45                                             
> >  [<c1002825>] ? syscall_call+0x7/0xb                                            
> > Code: e5 e8 bf 7b e9 ff 5d c3 55 89 e5 57 89 c7 56 89 d6 53 8b 42 28 89 c2 c1
> > ea 06 31 d0 83 e0 3f 8d 94 87 cc 00 00 00 eb 03 8d 50 1c <8b> 02 85 c0 74 0b 39 
> > EIP: [<c11c5cef>] td_free+0x23/0x75 SS:ESP 0068:c6785cb8                        
> > CR2: 00000000a7a7a7c3                                                           
> 
> And here's the real oops.  drivers/usb/host/ohci-mem.c:td_free()
> dereferenced a7a7a7c3.  Which looks like
> 
> /********** drivers/base/dmapool.c **********/
> #define	POOL_POISON_FREED	0xa7	/* !inuse */
> #define	POOL_POISON_ALLOCATED	0xa9	/* !initted */

If I'm reading this correctly, the bad dereference occurred in the
second source line:

		prev = &(*prev)->td_hash;
	if (*prev)

The original value in *prev was 0xa7a7a7a7 and the offset of td_hash is
0x1c, causing the offending address to be 0xa7a7a7c3.

I have no idea why a struct td would have been freed while it was still 
in use.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux