linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "J. Bruce Fields" <bfields-uC3wQj2KruNg9hUCZPvPmw@public.gmane.org>
To: Linus Torvalds
	<torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
Cc: trond.myklebust-41N18TsMXrtuMpJDpNschA@public.gmane.org,
	eshel-6kx38NOBMPqrIzol8Bc5pA@public.gmane.org,
	neilb-l3A5Bk7waGM@public.gmane.org,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org,
	linux-nfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Miklos Szeredi <mszeredi-AlSwsSmVLrQ@public.gmane.org>,
	stable-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org
Subject: [PATCH] locks: fix possible infinite loop in fcntl(F_SETLKW) over nfs
Date: Mon, 14 Apr 2008 15:03:02 -0400	[thread overview]
Message-ID: <20080414190302.GM15950@fieldses.org> (raw)
In-Reply-To: <E1JkxKz-0003A8-9V-8f8m9JG5TPIdUIPVzhDTVZP2KDSNp7ea@public.gmane.org>

From: J. Bruce Fields <bfields-vtMw8L3fJ9vSiEDVxGk4TQ@public.gmane.org>

Miklos Szeredi found the bug:

	"Basically what happens is that on the server nlm_fopen() calls
	nfsd_open() which returns -EACCES, to which nlm_fopen() returns
	NLM_LCK_DENIED.

	"On the client this will turn into a -EAGAIN (nlm_stat_to_errno()),
	which in will cause fcntl_setlk() to retry forever."

So, for example, opening a file on an nfs filesystem, changing
permissions to forbid further access, then trying to lock the file,
could result in an infinite loop.

And Trond Myklebust identified the culprit, from Marc Eshel and I:

	7723ec9777d9832849b76475b1a21a2872a40d20 "locks: factor out
	generic/filesystem switch from setlock code"

That commit claimed to just be reshuffling code, but actually introduced
a behavioral change by calling the lock method repeatedly as long as it
returned -EAGAIN.

We assumed this would be safe, since we assumed a lock of type SETLKW
would only return with either success or an error other than -EAGAIN.
However, nfs does can in fact return -EAGAIN in this situation, and
independently of whether that behavior is correct or not, we don't
actually need this change, and it seems far safer not to depend on such
assumptions about the filesystem's ->lock method.

Therefore, revert the problematic part of the original commit.  This
leaves vfs_lock_file() and its other callers unchanged, while returning
fcntl_setlk and fcntl_setlk64 to their former behavior.

Signed-off-by: J. Bruce Fields <bfields-vtMw8L3fJ9vSiEDVxGk4TQ@public.gmane.org>
Tested-by: Miklos Szeredi <mszeredi-AlSwsSmVLrQ@public.gmane.org>
Cc: Trond Myklebust <trond.myklebust-41N18TsMXrtuMpJDpNschA@public.gmane.org>
Cc: Marc Eshel <eshel-6kx38NOBMPqrIzol8Bc5pA@public.gmane.org>
---
 fs/locks.c |   48 ++++++++++++++++++++++++++++--------------------
 1 files changed, 28 insertions(+), 20 deletions(-)

This is appropriate for 2.6.25 (as well as older stable kernels--the bug
was introduced in 2.6.22).

--b.

diff --git a/fs/locks.c b/fs/locks.c
index d83fab1..43c0af2 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1801,17 +1801,21 @@ again:
 	if (error)
 		goto out;
 
-	for (;;) {
-		error = vfs_lock_file(filp, cmd, file_lock, NULL);
-		if (error != -EAGAIN || cmd == F_SETLK)
-			break;
-		error = wait_event_interruptible(file_lock->fl_wait,
-				!file_lock->fl_next);
-		if (!error)
-			continue;
+	if (filp->f_op && filp->f_op->lock != NULL)
+		error = filp->f_op->lock(filp, cmd, file_lock);
+	else {
+		for (;;) {
+			error = posix_lock_file(filp, file_lock, NULL);
+			if (error != -EAGAIN || cmd == F_SETLK)
+				break;
+			error = wait_event_interruptible(file_lock->fl_wait,
+					!file_lock->fl_next);
+			if (!error)
+				continue;
 
-		locks_delete_block(file_lock);
-		break;
+			locks_delete_block(file_lock);
+			break;
+		}
 	}
 
 	/*
@@ -1925,17 +1929,21 @@ again:
 	if (error)
 		goto out;
 
-	for (;;) {
-		error = vfs_lock_file(filp, cmd, file_lock, NULL);
-		if (error != -EAGAIN || cmd == F_SETLK64)
-			break;
-		error = wait_event_interruptible(file_lock->fl_wait,
-				!file_lock->fl_next);
-		if (!error)
-			continue;
+	if (filp->f_op && filp->f_op->lock != NULL)
+		error = filp->f_op->lock(filp, cmd, file_lock);
+	else {
+		for (;;) {
+			error = posix_lock_file(filp, file_lock, NULL);
+			if (error != -EAGAIN || cmd == F_SETLK64)
+				break;
+			error = wait_event_interruptible(file_lock->fl_wait,
+					!file_lock->fl_next);
+			if (!error)
+				continue;
 
-		locks_delete_block(file_lock);
-		break;
+			locks_delete_block(file_lock);
+			break;
+		}
 	}
 
 	/*
-- 
1.5.5.rc1

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

  parent reply	other threads:[~2008-04-14 19:03 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-04-09 15:57 [patch] fix infinite loop in generic_file_splice_read() Miklos Szeredi
2008-04-09 17:05 ` Oliver Pinter
2008-04-09 18:57 ` Andrew Morton
2008-04-09 19:25   ` Miklos Szeredi
2008-04-09 19:52   ` Jens Axboe
2008-04-10  6:29   ` Allard Hoeve
2008-04-10 19:51 ` nfs: infinite loop in fcntl(F_SETLKW) Miklos Szeredi
2008-04-10 21:02   ` Trond Myklebust
2008-04-10 21:07     ` Trond Myklebust
     [not found]       ` <1207861661.8180.18.camel-rJ7iovZKK19ZJLDQqaL3InhyD016LWXt@public.gmane.org>
2008-04-10 21:20         ` Trond Myklebust
2008-04-10 21:54           ` J. Bruce Fields
2008-04-11 19:12             ` Miklos Szeredi
2008-04-11 19:19               ` J. Bruce Fields
     [not found]                 ` <20080411191910.GB16965-uC3wQj2KruNg9hUCZPvPmw@public.gmane.org>
2008-04-11 19:22                   ` Miklos Szeredi
2008-04-13  0:08               ` J. Bruce Fields
     [not found]                 ` <20080413000830.GF31789-uC3wQj2KruNg9hUCZPvPmw@public.gmane.org>
2008-04-13  8:13                   ` Miklos Szeredi
2008-04-14 17:07                     ` J. Bruce Fields
     [not found]                     ` <E1JkxKz-0003A8-9V-8f8m9JG5TPIdUIPVzhDTVZP2KDSNp7ea@public.gmane.org>
2008-04-14 19:03                       ` J. Bruce Fields [this message]
     [not found]             ` <20080410215410.GF22324-uC3wQj2KruNg9hUCZPvPmw@public.gmane.org>
2008-04-13  8:28               ` Miklos Szeredi
2008-04-14 17:19                 ` J. Bruce Fields
2008-04-14 21:15                   ` Miklos Szeredi
2008-04-15 18:58                     ` J. Bruce Fields
2008-04-16 16:28                       ` Miklos Szeredi
2008-04-17 22:26                         ` J. Bruce Fields
     [not found]                           ` <20080417222620.GL9912-uC3wQj2KruNg9hUCZPvPmw@public.gmane.org>
2008-04-18 12:47                             ` Miklos Szeredi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080414190302.GM15950@fieldses.org \
    --to=bfields-uc3wqj2krung9huczpvpmw@public.gmane.org \
    --cc=akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org \
    --cc=eshel-6kx38NOBMPqrIzol8Bc5pA@public.gmane.org \
    --cc=linux-fsdevel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-nfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=mszeredi-AlSwsSmVLrQ@public.gmane.org \
    --cc=neilb-l3A5Bk7waGM@public.gmane.org \
    --cc=stable-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
    --cc=torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org \
    --cc=trond.myklebust-41N18TsMXrtuMpJDpNschA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).