xfs
[Top] [All Lists]

Re: use-after-free in xfs_bawrite()

To: Andrew Morton <akpm@xxxxxxxx>
Subject: Re: use-after-free in xfs_bawrite()
From: Nathan Scott <nathans@xxxxxxx>
Date: Thu, 14 Aug 2003 12:54:12 +1000
Cc: linux-xfs@xxxxxxxxxxx
In-reply-to: <20030802013032.7a42a596.akpm@xxxxxxxx>
References: <20030802013032.7a42a596.akpm@xxxxxxxx>
Sender: linux-xfs-bounce@xxxxxxxxxxx
User-agent: Mutt/1.5.3i
On Sat, Aug 02, 2003 at 01:30:32AM -0700, Andrew Morton wrote:
> 
> Using Linus's current tree plus all the -mm gunk I get a fairly easy oops
> running dbench on XFS on SMP with CONFIG_DEBUG_PAGEALLOC=y:
> 
> Program received signal SIGEMT, Emulation trap.
> 0xc0282c9d in xfs_iflush (ip=0xc284a004, flags=2) at 
> fs/xfs/pagebuf/page_buf.h:397
> 397             if (!pb || atomic_read(&pb->pb_io_remaining))
> (gdb) p pb
> $1 = (page_buf_t *) 0xc98d1004
> (gdb) p *pb
> Cannot access memory at address 0xc98d1004
> ...
> The memory at 0xc98d1004 has been unmapped.
> 
> The oops is on the xfs_iflush() -> xfs_bawrite() -> pagebuf_run_queues() path.
> 
> It looks to me like pagebuf_iostart() has called pagebuf_iorequest() which 
> called
> _pagebuf_iodone() which called pagebuf_iodone() whuich threw away the pagebuf.

OK, I understand what is happening here now.  Not sure why
I haven't been able to trigger it, but there is clearly a
bug and I have a fix which I'm testing atm.  Affects both
2.4 and 2.6, but quite difficult to hit in practice.

The core of the problem is that this is an async IO and when an
async pagebuf IO is done, the completion handler can be the one
who releases the last hold on the pagebuf (in pagebuf_iodone_work).
So, if the async IO completes almost immediately, then the pagebuf
can be released by the time we try to do pagebuf_run_queues.

> If this is vaguely correct then this part of pagebuf_iostart():
> 
>       /* Wait for I/O if we are not an async request */
>       if ((status == 0) && (flags & PBF_ASYNC) == 0) {
> 
> also needs attention...

This looks safe - for all non async IO requests, the caller will
have a hold on the buffer and does the xfs_buf_relse themselves
when they are done with it.

cheers.

-- 
Nathan


<Prev in Thread] Current Thread [Next in Thread>