+ fix-wrong-error-code-on-interrupted-close-syscalls.patch added to -mm tree

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

 



The patch titled

     fix wrong error code on interrupted close syscalls

has been added to the -mm tree.  Its filename is

     fix-wrong-error-code-on-interrupted-close-syscalls.patch

See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find
out what to do about this

------------------------------------------------------
Subject: fix wrong error code on interrupted close syscalls
From: Ernie Petrides <petrides@xxxxxxxxxx>

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: Ernie Petrides <petrides@xxxxxxxxxx>
Signed-off-by: Andrew Morton <akpm@xxxxxxxx>
---

 fs/open.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletion(-)

diff -puN fs/open.c~fix-wrong-error-code-on-interrupted-close-syscalls fs/open.c
--- a/fs/open.c~fix-wrong-error-code-on-interrupted-close-syscalls
+++ a/fs/open.c
@@ -1172,6 +1172,7 @@ asmlinkage long sys_close(unsigned int f
 	struct file * filp;
 	struct files_struct *files = current->files;
 	struct fdtable *fdt;
+	int retval;
 
 	spin_lock(&files->file_lock);
 	fdt = files_fdtable(files);
@@ -1184,7 +1185,10 @@ asmlinkage long sys_close(unsigned int f
 	FD_CLR(fd, fdt->close_on_exec);
 	__put_unused_fd(files, fd);
 	spin_unlock(&files->file_lock);
-	return filp_close(filp, files);
+	retval = filp_close(filp, files);
+
+	/* can't restart close syscall because file table entry was cleared */
+	return (retval == -ERESTARTSYS) ? -EINTR : retval;
 
 out_unlock:
 	spin_unlock(&files->file_lock);
_

Patches currently in -mm which might be from petrides@xxxxxxxxxx are

fix-wrong-error-code-on-interrupted-close-syscalls.patch

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

[Index of Archives]     [Kernel Newbies FAQ]     [Kernel Archive]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Photo]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]

  Powered by Linux