• Ernie Petrides's avatar
    [PATCH] fix wrong error code on interrupted close syscalls · ee731f4f
    Ernie Petrides authored
    The problem is that close() syscalls can call a file system's flush
    handler, which in turn might sleep interruptibly and ultimately pass back
    an -ERESTARTSYS return value.  This happens for files backed by an
    interruptible NFS mount under nfs_file_flush() when a large file has just
    been written and nfs_wait_bit_interruptible() detects that there is a
    signal pending.
    
    I have a test case where the "strace" command is used to attach to a
    process sleeping in such a close().  Since the SIGSTOP is forced onto the
    victim process (removing it from the thread's "blocked" mask in
    force_sig_info()), the RPC wait is interrupted and the close() is
    terminated early.
    
    But the file table entry has already been cleared before the flush handler
    was called.  Thus, when the syscall is restarted, the file descriptor
    appears closed and an EBADF error is returned (which is wrong).  What's
    worse, there is the hypothetical case where another thread of a
    multi-threaded application might have reused the file descriptor, in which
    case that file would be mistakenly closed.
    
    The bottom line is that close() syscalls are not restartable, and thus
    -ERESTARTSYS return values should be mapped to -EINTR.  This is consistent
    with the close(2) manual page.  The fix is below.
    Signed-off-by: default avatarErnie Petrides <petrides@redhat.com>
    Cc: Roland McGrath <roland@redhat.com>
    Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
    ee731f4f
open.c 27.8 KB