• Darrick Wong's avatar
    [PATCH] Fix BUG in io_destroy · e2e83e40
    Darrick Wong authored
    With Suparna Bhattacharya <suparna@in.ibm.com>
    
    I was running a random system call generator against mainline the other 
    day and got this bug report about AIO in dmesg:
    
    kernel BUG at fs/aio.c:1249!
    
    Each ioctx structure has a "users" field that acts as a reference counter
    for the ioctx, and a "dead" flag that seems to indicate that the ioctx
    isn't associated with any particular list of IO requests.
    
    The problem, then, lies in aio.c:1247.  The io_destroy function checks the
    (old) value of the dead flag--if it's false (i.e.  the ioctx is alive),
    then the function calls put_ioctx to decrease the reference count on the
    assumption that the ioctx is no longer associated with any requests. 
    Later, it calls put_ioctx again, on the assumption that someone called
    lookup_ioctx to perform some operation at some point.
    
    This BUG is caused by the reference counts being off.  The testcase that
    I provided looks for a chunk of user memory that's read-only and passes
    that to the sys_io_setup syscall.  sys_io_setup checks that the pointer
    is readable, creates the ioctx and then tries to write the ioctx handle
    back to userland.  This is where the problems start to surface.
    
    Since the pointer points to a non-writable region of memory, the write
    fails.  The syscall handler then destroys the ioctx.  The dead flag is
    zero, so io_destroy calls put_ioctx...but wait!  Nobody ever put the ioctx
    into a request list.  The ioctx is alive but not in a list, yet the
    io_destroy code assumes that being alive implies being in a request list
    somewhere.  Hence, calling put_ioctx is bogus; the reference count becomes
    0, and the ioctx is freed.  Worse yet, put_ioctx is called again (on a
    freed pointer!) to clear up the lookup_ioctx that never happened. 
    put_ioctx sees that the reference count has become negative and BUGs.
    
    Suparna's patch simply takes that additional ref so that io_destroy() will
    dtrt.
    Signed-off-by: default avatarDarrick Wong <djwong@us.ibm.com>
    Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
    e2e83e40
aio.c 44 KB