From: Greg Kroah-Hartman Date: Tue, 8 Jan 2013 20:21:20 +0000 (-0800) Subject: 3.7-stable patches X-Git-Tag: v3.0.58~23 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=dea302bdfbee852c6c6d002605db299bb0d96bcb;p=thirdparty%2Fkernel%2Fstable-queue.git 3.7-stable patches added patches: nfs-add-sequence_priviliged_ops-for-nfs4_proc_sequence.patch nfs-avoid-dereferencing-null-pointer-in-initiate_bulk_draining.patch nfs-avoid-null-dereference-in-nfs_destroy_server.patch nfsd4-fix-oops-on-unusual-readlike-compound.patch nfsd-avoid-permission-checks-on-exclusive_create-replay.patch nfsd-fix-v4-reply-caching.patch nfs-don-t-extend-writes-to-cover-entire-page-if-pagecache-is-invalid.patch nfs-don-t-use-setpageerror-in-the-nfs-writeback-code.patch nfs-don-t-zero-out-the-rest-of-the-page-if-we-hit-the-eof-on-a-dio-read.patch nfs-ensure-that-we-free-the-rpc_task-after-read-and-write-cleanups-are-done.patch nfs-fix-access-to-suid-sgid-executables.patch nfs-fix-calls-to-drop_nlink.patch nfs-fix-null-checking-in-nfs_get_option_str.patch nfs-fix-wrong-object-type-in-lockowner_slab.patch nfsv4-check-for-buffer-length-in-__nfs4_get_acl_uncached.patch pnfs-increase-the-refcount-when-layoutget-fails-the-first-time.patch --- diff --git a/queue-3.7/nfs-add-sequence_priviliged_ops-for-nfs4_proc_sequence.patch b/queue-3.7/nfs-add-sequence_priviliged_ops-for-nfs4_proc_sequence.patch new file mode 100644 index 00000000000..c00b900ef23 --- /dev/null +++ b/queue-3.7/nfs-add-sequence_priviliged_ops-for-nfs4_proc_sequence.patch @@ -0,0 +1,87 @@ +From 6bdb5f213c4344324f600dde885f25768fbd14db Mon Sep 17 00:00:00 2001 +From: Bryan Schumaker +Date: Mon, 12 Nov 2012 16:55:38 -0500 +Subject: NFS: Add sequence_priviliged_ops for nfs4_proc_sequence() + +From: Bryan Schumaker + +commit 6bdb5f213c4344324f600dde885f25768fbd14db upstream. + +If I mount an NFS v4.1 server to a single client multiple times and then +run xfstests over each mountpoint I usually get the client into a state +where recovery deadlocks. The server informs the client of a +cb_path_down sequence error, the client then does a +bind_connection_to_session and checks the status of the lease. + +I found that bind_connection_to_session sets the NFS4_SESSION_DRAINING +flag on the client, but this flag is never unset before +nfs4_check_lease() reaches nfs4_proc_sequence(). This causes the client +to deadlock, halting all NFS activity to the server. nfs4_proc_sequence() +is only called by the state manager, so I can change it to run in privileged +mode to bypass the NFS4_SESSION_DRAINING check and avoid the deadlock. + +Signed-off-by: Bryan Schumaker +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/nfs4proc.c | 21 +++++++++++++++++---- + 1 file changed, 17 insertions(+), 4 deletions(-) + +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -6138,13 +6138,26 @@ static void nfs41_sequence_prepare(struc + rpc_call_start(task); + } + ++static void nfs41_sequence_prepare_privileged(struct rpc_task *task, void *data) ++{ ++ rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); ++ nfs41_sequence_prepare(task, data); ++} ++ + static const struct rpc_call_ops nfs41_sequence_ops = { + .rpc_call_done = nfs41_sequence_call_done, + .rpc_call_prepare = nfs41_sequence_prepare, + .rpc_release = nfs41_sequence_release, + }; + +-static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) ++static const struct rpc_call_ops nfs41_sequence_privileged_ops = { ++ .rpc_call_done = nfs41_sequence_call_done, ++ .rpc_call_prepare = nfs41_sequence_prepare_privileged, ++ .rpc_release = nfs41_sequence_release, ++}; ++ ++static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred, ++ const struct rpc_call_ops *seq_ops) + { + struct nfs4_sequence_data *calldata; + struct rpc_message msg = { +@@ -6154,7 +6167,7 @@ static struct rpc_task *_nfs41_proc_sequ + struct rpc_task_setup task_setup_data = { + .rpc_client = clp->cl_rpcclient, + .rpc_message = &msg, +- .callback_ops = &nfs41_sequence_ops, ++ .callback_ops = seq_ops, + .flags = RPC_TASK_ASYNC | RPC_TASK_SOFT, + }; + +@@ -6181,7 +6194,7 @@ static int nfs41_proc_async_sequence(str + + if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) + return 0; +- task = _nfs41_proc_sequence(clp, cred); ++ task = _nfs41_proc_sequence(clp, cred, &nfs41_sequence_ops); + if (IS_ERR(task)) + ret = PTR_ERR(task); + else +@@ -6195,7 +6208,7 @@ static int nfs4_proc_sequence(struct nfs + struct rpc_task *task; + int ret; + +- task = _nfs41_proc_sequence(clp, cred); ++ task = _nfs41_proc_sequence(clp, cred, &nfs41_sequence_privileged_ops); + if (IS_ERR(task)) { + ret = PTR_ERR(task); + goto out; diff --git a/queue-3.7/nfs-avoid-dereferencing-null-pointer-in-initiate_bulk_draining.patch b/queue-3.7/nfs-avoid-dereferencing-null-pointer-in-initiate_bulk_draining.patch new file mode 100644 index 00000000000..1775004f9e5 --- /dev/null +++ b/queue-3.7/nfs-avoid-dereferencing-null-pointer-in-initiate_bulk_draining.patch @@ -0,0 +1,30 @@ +From ecf0eb9edbb607d74f74b73c14af8b43f3729528 Mon Sep 17 00:00:00 2001 +From: Nickolai Zeldovich +Date: Sat, 5 Jan 2013 14:19:51 -0500 +Subject: nfs: avoid dereferencing null pointer in initiate_bulk_draining + +From: Nickolai Zeldovich + +commit ecf0eb9edbb607d74f74b73c14af8b43f3729528 upstream. + +Fix an inverted null pointer check in initiate_bulk_draining(). + +Signed-off-by: Nickolai Zeldovich +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/callback_proc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfs/callback_proc.c ++++ b/fs/nfs/callback_proc.c +@@ -205,7 +205,7 @@ static u32 initiate_bulk_draining(struct + + list_for_each_entry(lo, &server->layouts, plh_layouts) { + ino = igrab(lo->plh_inode); +- if (ino) ++ if (!ino) + continue; + spin_lock(&ino->i_lock); + /* Is this layout in the process of being freed? */ diff --git a/queue-3.7/nfs-avoid-null-dereference-in-nfs_destroy_server.patch b/queue-3.7/nfs-avoid-null-dereference-in-nfs_destroy_server.patch new file mode 100644 index 00000000000..fd8a5b615eb --- /dev/null +++ b/queue-3.7/nfs-avoid-null-dereference-in-nfs_destroy_server.patch @@ -0,0 +1,45 @@ +From f259613a1e4b44a0cf85a5dafd931be96ee7c9e5 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Thu, 13 Dec 2012 15:14:36 +1100 +Subject: NFS: avoid NULL dereference in nfs_destroy_server + +From: NeilBrown + +commit f259613a1e4b44a0cf85a5dafd931be96ee7c9e5 upstream. + +In rare circumstances, nfs_clone_server() of a v2 or v3 server can get +an error between setting server->destory (to nfs_destroy_server), and +calling nfs_start_lockd (which will set server->nlm_host). + +If this happens, nfs_clone_server will call nfs_free_server which +will call nfs_destroy_server and thence nlmclnt_done(NULL). This +causes the NULL to be dereferenced. + +So add a guard to only call nlmclnt_done() if ->nlm_host is not NULL. + +The other guards there are irrelevant as nlm_host can only be non-NULL +if one of these flags are set - so remove those tests. (Thanks to Trond +for this suggestion). + +This is suitable for any stable kernel since 2.6.25. + +Signed-off-by: NeilBrown +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/client.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/fs/nfs/client.c ++++ b/fs/nfs/client.c +@@ -615,8 +615,7 @@ EXPORT_SYMBOL_GPL(nfs_create_rpc_client) + */ + static void nfs_destroy_server(struct nfs_server *server) + { +- if (!(server->flags & NFS_MOUNT_LOCAL_FLOCK) || +- !(server->flags & NFS_MOUNT_LOCAL_FCNTL)) ++ if (server->nlm_host) + nlmclnt_done(server->nlm_host); + } + diff --git a/queue-3.7/nfs-don-t-extend-writes-to-cover-entire-page-if-pagecache-is-invalid.patch b/queue-3.7/nfs-don-t-extend-writes-to-cover-entire-page-if-pagecache-is-invalid.patch new file mode 100644 index 00000000000..f05d6708f3e --- /dev/null +++ b/queue-3.7/nfs-don-t-extend-writes-to-cover-entire-page-if-pagecache-is-invalid.patch @@ -0,0 +1,67 @@ +From 81d9bce5309288086b58b4d97a644e495fef75f2 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Mon, 10 Dec 2012 09:25:48 -0500 +Subject: nfs: don't extend writes to cover entire page if pagecache is invalid + +From: Jeff Layton + +commit 81d9bce5309288086b58b4d97a644e495fef75f2 upstream. + +Jian reported that the following sequence would leave "testfile" with +corrupt data: + + # mount localhost:/export /mnt/nfs/ -o vers=3 + # echo abc > /mnt/nfs/testfile; echo def >> /export/testfile; echo ghi >> /mnt/nfs/testfile + # cat -v /export/testfile + abc + ^@^@^@^@ghi + +While there's no locking involved here, the operations are serialized, +so CTO should prevent corruption. + +The first write to the file is fine and writes 4 bytes. The file is then +extended on the server. When it's reopened a GETATTR is issued and the +size change is noticed. This causes NFS_INO_INVALID_DATA to be set on +the file. Because the file is opened for write only, +nfs_want_read_modify_write() returns 0 to nfs_write_begin(). +nfs_updatepage then calls nfs_write_pageuptodate() to see if it should +extend the nfs_page to cover the whole page. NFS_INO_INVALID_DATA is +still set on the file at that point, but that flag is ignored and +nfs_pageuptodate erroneously extends the write to cover the whole page, +with the write done on the server side filled in with zeroes. + +This patch just has that function check for NFS_INO_INVALID_DATA in +addition to NFS_INO_REVAL_PAGECACHE. This fixes the bug, but looking +over the code, I wonder if we might have a similar bug in +nfs_revalidate_size(). The difference between those two flags is very +subtle, so it seems like we ought to be checking for +NFS_INO_INVALID_DATA in most of the places that we look for +NFS_INO_REVAL_PAGECACHE. + +I believe this is regression introduced by commit 8d197a568. The code +did check for NFS_INO_INVALID_DATA prior to that patch. + +Original bug report is here: + + https://bugzilla.redhat.com/show_bug.cgi?id=885743 + +Reported-by: Jian Li +Signed-off-by: Jeff Layton +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/write.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfs/write.c ++++ b/fs/nfs/write.c +@@ -884,7 +884,7 @@ static bool nfs_write_pageuptodate(struc + { + if (nfs_have_delegated_attributes(inode)) + goto out; +- if (NFS_I(inode)->cache_validity & NFS_INO_REVAL_PAGECACHE) ++ if (NFS_I(inode)->cache_validity & (NFS_INO_INVALID_DATA|NFS_INO_REVAL_PAGECACHE)) + return false; + out: + return PageUptodate(page) != 0; diff --git a/queue-3.7/nfs-don-t-use-setpageerror-in-the-nfs-writeback-code.patch b/queue-3.7/nfs-don-t-use-setpageerror-in-the-nfs-writeback-code.patch new file mode 100644 index 00000000000..7e085e3fa4e --- /dev/null +++ b/queue-3.7/nfs-don-t-use-setpageerror-in-the-nfs-writeback-code.patch @@ -0,0 +1,53 @@ +From ada8e20d044c0fa5610e504ce6fb4578ebd3edd9 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Sat, 15 Dec 2012 17:12:14 -0500 +Subject: NFS: Don't use SetPageError in the NFS writeback code + +From: Trond Myklebust + +commit ada8e20d044c0fa5610e504ce6fb4578ebd3edd9 upstream. + +The writeback code is already capable of passing errors back to user space +by means of the open_context->error. In the case of ENOSPC, Neil Brown +is reporting seeing 2 errors being returned. + +Neil writes: + +"e.g. if /mnt2/ if an nfs mounted filesystem that has no space then + +strace dd if=/dev/zero conv=fsync >> /mnt2/afile count=1 + +reported Input/output error and the relevant parts of the strace output are: + +write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 512) = 512 +fsync(1) = -1 EIO (Input/output error) +close(1) = -1 ENOSPC (No space left on device)" + +Neil then shows that the duplication of error messages appears to be due to +the use of the PageError() mechanism, which causes filemap_fdatawait_range +to return the extra EIO. The regression was introduced by +commit 7b281ee026552f10862b617a2a51acf49c829554 (NFS: fsync() must exit +with an error if page writeback failed). + +Fix this by removing the call to SetPageError(), and just relying on +open_context->error reporting the ENOSPC back to fsync(). + +Reported-by: Neil Brown +Tested-by: Neil Brown +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/write.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/fs/nfs/write.c ++++ b/fs/nfs/write.c +@@ -202,7 +202,6 @@ out: + /* A writeback failed: mark the page as bad, and invalidate the page cache */ + static void nfs_set_pageerror(struct page *page) + { +- SetPageError(page); + nfs_zap_mapping(page_file_mapping(page)->host, page_file_mapping(page)); + } + diff --git a/queue-3.7/nfs-don-t-zero-out-the-rest-of-the-page-if-we-hit-the-eof-on-a-dio-read.patch b/queue-3.7/nfs-don-t-zero-out-the-rest-of-the-page-if-we-hit-the-eof-on-a-dio-read.patch new file mode 100644 index 00000000000..7650bda272f --- /dev/null +++ b/queue-3.7/nfs-don-t-zero-out-the-rest-of-the-page-if-we-hit-the-eof-on-a-dio-read.patch @@ -0,0 +1,46 @@ +From 67fad106a219e083c91c79695bd1807dde1bf7b9 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Wed, 12 Dec 2012 11:38:44 -0500 +Subject: nfs: don't zero out the rest of the page if we hit the EOF on a DIO READ + +From: Jeff Layton + +commit 67fad106a219e083c91c79695bd1807dde1bf7b9 upstream. + +Eryu provided a test program that would segfault when attempting to read +past the EOF on file that was opened O_DIRECT. The buffer given to the +read() call was on the stack, and when he attempted to read past it it +would scribble over the rest of the stack page. + +If we hit the end of the file on a DIO READ request, then we don't want +to zero out the rest of the buffer. These aren't pagecache pages after +all, and there's no guarantee that the buffers that were passed in +represent entire pages. + +Reported-by: Eryu Guan +Cc: Fred Isaman +Signed-off-by: Jeff Layton +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/direct.c | 8 -------- + 1 file changed, 8 deletions(-) + +--- a/fs/nfs/direct.c ++++ b/fs/nfs/direct.c +@@ -266,14 +266,6 @@ static void nfs_direct_read_completion(s + struct nfs_page *req = nfs_list_entry(hdr->pages.next); + struct page *page = req->wb_page; + +- if (test_bit(NFS_IOHDR_EOF, &hdr->flags)) { +- if (bytes > hdr->good_bytes) +- zero_user(page, 0, PAGE_SIZE); +- else if (hdr->good_bytes - bytes < PAGE_SIZE) +- zero_user_segment(page, +- hdr->good_bytes & ~PAGE_MASK, +- PAGE_SIZE); +- } + if (!PageCompound(page)) { + if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) { + if (bytes < hdr->good_bytes) diff --git a/queue-3.7/nfs-ensure-that-we-free-the-rpc_task-after-read-and-write-cleanups-are-done.patch b/queue-3.7/nfs-ensure-that-we-free-the-rpc_task-after-read-and-write-cleanups-are-done.patch new file mode 100644 index 00000000000..c722f5d0582 --- /dev/null +++ b/queue-3.7/nfs-ensure-that-we-free-the-rpc_task-after-read-and-write-cleanups-are-done.patch @@ -0,0 +1,68 @@ +From 6db6dd7d3fd8f7c765dabc376493d6791ab28bd6 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Fri, 4 Jan 2013 12:47:04 -0500 +Subject: NFS: Ensure that we free the rpc_task after read and write cleanups are done + +From: Trond Myklebust + +commit 6db6dd7d3fd8f7c765dabc376493d6791ab28bd6 upstream. + +This patch ensures that we free the rpc_task after the cleanup callbacks +are done in order to avoid a deadlock problem that can be triggered if +the callback needs to wait for another workqueue item to complete. + +Signed-off-by: Trond Myklebust +Cc: Weston Andros Adamson +Cc: Tejun Heo +Cc: Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/read.c | 10 +++++++--- + fs/nfs/write.c | 10 +++++++--- + 2 files changed, 14 insertions(+), 6 deletions(-) + +--- a/fs/nfs/read.c ++++ b/fs/nfs/read.c +@@ -91,12 +91,16 @@ void nfs_readdata_release(struct nfs_rea + put_nfs_open_context(rdata->args.context); + if (rdata->pages.pagevec != rdata->pages.page_array) + kfree(rdata->pages.pagevec); +- if (rdata != &read_header->rpc_data) +- kfree(rdata); +- else ++ if (rdata == &read_header->rpc_data) { + rdata->header = NULL; ++ rdata = NULL; ++ } + if (atomic_dec_and_test(&hdr->refcnt)) + hdr->completion_ops->completion(hdr); ++ /* Note: we only free the rpc_task after callbacks are done. ++ * See the comment in rpc_free_task() for why ++ */ ++ kfree(rdata); + } + EXPORT_SYMBOL_GPL(nfs_readdata_release); + +--- a/fs/nfs/write.c ++++ b/fs/nfs/write.c +@@ -126,12 +126,16 @@ void nfs_writedata_release(struct nfs_wr + put_nfs_open_context(wdata->args.context); + if (wdata->pages.pagevec != wdata->pages.page_array) + kfree(wdata->pages.pagevec); +- if (wdata != &write_header->rpc_data) +- kfree(wdata); +- else ++ if (wdata == &write_header->rpc_data) { + wdata->header = NULL; ++ wdata = NULL; ++ } + if (atomic_dec_and_test(&hdr->refcnt)) + hdr->completion_ops->completion(hdr); ++ /* Note: we only free the rpc_task after callbacks are done. ++ * See the comment in rpc_free_task() for why ++ */ ++ kfree(wdata); + } + EXPORT_SYMBOL_GPL(nfs_writedata_release); + diff --git a/queue-3.7/nfs-fix-access-to-suid-sgid-executables.patch b/queue-3.7/nfs-fix-access-to-suid-sgid-executables.patch new file mode 100644 index 00000000000..bd164db1c36 --- /dev/null +++ b/queue-3.7/nfs-fix-access-to-suid-sgid-executables.patch @@ -0,0 +1,92 @@ +From f8d9a897d4384b77f13781ea813156568f68b83e Mon Sep 17 00:00:00 2001 +From: Weston Andros Adamson +Date: Thu, 3 Jan 2013 16:42:29 -0500 +Subject: NFS: Fix access to suid/sgid executables + +From: Weston Andros Adamson + +commit f8d9a897d4384b77f13781ea813156568f68b83e upstream. + +nfs_open_permission_mask() should only check MAY_EXEC for files that +are opened with __FMODE_EXEC. + +Also fix NFSv4 access-in-open path in a similar way -- openflags must be +used because fmode will not always have FMODE_EXEC set. + +This patch fixes https://bugzilla.kernel.org/show_bug.cgi?id=49101 + +Signed-off-by: Weston Andros Adamson +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/dir.c | 16 ++++++++++------ + fs/nfs/nfs4proc.c | 18 +++++++++++------- + 2 files changed, 21 insertions(+), 13 deletions(-) + +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -2148,12 +2148,16 @@ static int nfs_open_permission_mask(int + { + int mask = 0; + +- if ((openflags & O_ACCMODE) != O_WRONLY) +- mask |= MAY_READ; +- if ((openflags & O_ACCMODE) != O_RDONLY) +- mask |= MAY_WRITE; +- if (openflags & __FMODE_EXEC) +- mask |= MAY_EXEC; ++ if (openflags & __FMODE_EXEC) { ++ /* ONLY check exec rights */ ++ mask = MAY_EXEC; ++ } else { ++ if ((openflags & O_ACCMODE) != O_WRONLY) ++ mask |= MAY_READ; ++ if ((openflags & O_ACCMODE) != O_RDONLY) ++ mask |= MAY_WRITE; ++ } ++ + return mask; + } + +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -1721,7 +1721,8 @@ static int _nfs4_recover_proc_open(struc + + static int nfs4_opendata_access(struct rpc_cred *cred, + struct nfs4_opendata *opendata, +- struct nfs4_state *state, fmode_t fmode) ++ struct nfs4_state *state, fmode_t fmode, ++ int openflags) + { + struct nfs_access_entry cache; + u32 mask; +@@ -1733,11 +1734,14 @@ static int nfs4_opendata_access(struct r + + mask = 0; + /* don't check MAY_WRITE - a newly created file may not have +- * write mode bits, but POSIX allows the creating process to write */ +- if (fmode & FMODE_READ) +- mask |= MAY_READ; +- if (fmode & FMODE_EXEC) +- mask |= MAY_EXEC; ++ * write mode bits, but POSIX allows the creating process to write. ++ * use openflags to check for exec, because fmode won't ++ * always have FMODE_EXEC set when file open for exec. */ ++ if (openflags & __FMODE_EXEC) { ++ /* ONLY check for exec rights */ ++ mask = MAY_EXEC; ++ } else if (fmode & FMODE_READ) ++ mask = MAY_READ; + + cache.cred = cred; + cache.jiffies = jiffies; +@@ -2009,7 +2013,7 @@ static int _nfs4_do_open(struct inode *d + if (server->caps & NFS_CAP_POSIX_LOCK) + set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); + +- status = nfs4_opendata_access(cred, opendata, state, fmode); ++ status = nfs4_opendata_access(cred, opendata, state, fmode, flags); + if (status != 0) + goto err_opendata_put; + diff --git a/queue-3.7/nfs-fix-calls-to-drop_nlink.patch b/queue-3.7/nfs-fix-calls-to-drop_nlink.patch new file mode 100644 index 00000000000..a82cfab56b4 --- /dev/null +++ b/queue-3.7/nfs-fix-calls-to-drop_nlink.patch @@ -0,0 +1,83 @@ +From 1f018458b30b0d5c535c94e577aa0acbb92e1395 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Fri, 14 Dec 2012 16:38:46 -0500 +Subject: NFS: Fix calls to drop_nlink() + +From: Trond Myklebust + +commit 1f018458b30b0d5c535c94e577aa0acbb92e1395 upstream. + +It is almost always wrong for NFS to call drop_nlink() after removing a +file. What we really want is to mark the inode's attributes for +revalidation, and we want to ensure that the VFS drops it if we're +reasonably sure that this is the final unlink(). +Do the former using the usual cache validity flags, and the latter +by testing if inode->i_nlink == 1, and clearing it in that case. + +This also fixes the following warning reported by Neil Brown and +Jeff Layton (among others). + +[634155.004438] WARNING: +at /home/abuild/rpmbuild/BUILD/kernel-desktop-3.5.0/lin [634155.004442] +Hardware name: Latitude E6510 [634155.004577] crc_itu_t crc32c_intel +snd_hwdep snd_pcm snd_timer snd soundcor [634155.004609] Pid: 13402, comm: +bash Tainted: G W 3.5.0-36-desktop # [634155.004611] Call Trace: +[634155.004630] [] dump_trace+0xaa/0x2b0 +[634155.004641] [] dump_stack+0x69/0x6f +[634155.004653] [] warn_slowpath_common+0x7b/0xc0 +[634155.004662] [] drop_nlink+0x34/0x40 +[634155.004687] [] nfs_dentry_iput+0x33/0x70 [nfs] +[634155.004714] [] dput+0x12e/0x230 +[634155.004726] [] __fput+0x170/0x230 +[634155.004735] [] filp_close+0x5f/0x90 +[634155.004743] [] sys_close+0x97/0x100 +[634155.004754] [] system_call_fastpath+0x16/0x1b +[634155.004767] [<00007f2a73a0d110>] 0x7f2a73a0d10f + +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/dir.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -1156,11 +1156,14 @@ static int nfs_dentry_delete(const struc + + } + ++/* Ensure that we revalidate inode->i_nlink */ + static void nfs_drop_nlink(struct inode *inode) + { + spin_lock(&inode->i_lock); +- if (inode->i_nlink > 0) +- drop_nlink(inode); ++ /* drop the inode if we're reasonably sure this is the last link */ ++ if (inode->i_nlink == 1) ++ clear_nlink(inode); ++ NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR; + spin_unlock(&inode->i_lock); + } + +@@ -1175,8 +1178,8 @@ static void nfs_dentry_iput(struct dentr + NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA; + + if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { +- drop_nlink(inode); + nfs_complete_unlink(dentry, inode); ++ nfs_drop_nlink(inode); + } + iput(inode); + } +@@ -1647,10 +1650,8 @@ static int nfs_safe_remove(struct dentry + if (inode != NULL) { + NFS_PROTO(inode)->return_delegation(inode); + error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); +- /* The VFS may want to delete this inode */ + if (error == 0) + nfs_drop_nlink(inode); +- nfs_mark_for_revalidate(inode); + } else + error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); + if (error == -ENOENT) diff --git a/queue-3.7/nfs-fix-null-checking-in-nfs_get_option_str.patch b/queue-3.7/nfs-fix-null-checking-in-nfs_get_option_str.patch new file mode 100644 index 00000000000..e24e81e03a2 --- /dev/null +++ b/queue-3.7/nfs-fix-null-checking-in-nfs_get_option_str.patch @@ -0,0 +1,39 @@ +From e25fbe380c4e3c09afa98bcdcd9d3921443adab8 Mon Sep 17 00:00:00 2001 +From: Xi Wang +Date: Fri, 4 Jan 2013 03:22:57 -0500 +Subject: nfs: fix null checking in nfs_get_option_str() + +From: Xi Wang + +commit e25fbe380c4e3c09afa98bcdcd9d3921443adab8 upstream. + +The following null pointer check is broken. + + *option = match_strdup(args); + return !option; + +The pointer `option' must be non-null, and thus `!option' is always false. +Use `!*option' instead. + +The bug was introduced in commit c5cb09b6f8 ("Cleanup: Factor out some +cut-and-paste code."). + +Signed-off-by: Xi Wang +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/super.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfs/super.c ++++ b/fs/nfs/super.c +@@ -1150,7 +1150,7 @@ static int nfs_get_option_str(substring_ + { + kfree(*option); + *option = match_strdup(args); +- return !option; ++ return !*option; + } + + static int nfs_get_option_ul(substring_t args[], unsigned long *option) diff --git a/queue-3.7/nfs-fix-wrong-object-type-in-lockowner_slab.patch b/queue-3.7/nfs-fix-wrong-object-type-in-lockowner_slab.patch new file mode 100644 index 00000000000..e4c4007c430 --- /dev/null +++ b/queue-3.7/nfs-fix-wrong-object-type-in-lockowner_slab.patch @@ -0,0 +1,31 @@ +From 3c40794b2dd0f355ef4e6bf8d85af5dcd7da7ece Mon Sep 17 00:00:00 2001 +From: Yanchuan Nian +Date: Wed, 24 Oct 2012 14:44:19 +0800 +Subject: nfs: fix wrong object type in lockowner_slab + +From: Yanchuan Nian + +commit 3c40794b2dd0f355ef4e6bf8d85af5dcd7da7ece upstream. + +The object type in the cache of lockowner_slab is wrong, and it is +better to fix it. + +Signed-off-by: Yanchuan Nian +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfsd/nfs4state.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -2340,7 +2340,7 @@ nfsd4_init_slabs(void) + if (openowner_slab == NULL) + goto out_nomem; + lockowner_slab = kmem_cache_create("nfsd4_lockowners", +- sizeof(struct nfs4_openowner), 0, 0, NULL); ++ sizeof(struct nfs4_lockowner), 0, 0, NULL); + if (lockowner_slab == NULL) + goto out_nomem; + file_slab = kmem_cache_create("nfsd4_files", diff --git a/queue-3.7/nfsd-avoid-permission-checks-on-exclusive_create-replay.patch b/queue-3.7/nfsd-avoid-permission-checks-on-exclusive_create-replay.patch new file mode 100644 index 00000000000..9100876cfcc --- /dev/null +++ b/queue-3.7/nfsd-avoid-permission-checks-on-exclusive_create-replay.patch @@ -0,0 +1,84 @@ +From 7007c90fb9fef593b4aeaeee57e6a6754276c97c Mon Sep 17 00:00:00 2001 +From: Neil Brown +Date: Fri, 7 Dec 2012 15:40:55 -0500 +Subject: nfsd: avoid permission checks on EXCLUSIVE_CREATE replay + +From: Neil Brown + +commit 7007c90fb9fef593b4aeaeee57e6a6754276c97c upstream. + +With NFSv4, if we create a file then open it we explicit avoid checking +the permissions on the file during the open because the fact that we +created it ensures we should be allow to open it (the create and the +open should appear to be a single operation). + +However if the reply to an EXCLUSIVE create gets lots and the client +resends the create, the current code will perform the permission check - +because it doesn't realise that it did the open already.. + +This patch should fix this. + +Note that I haven't actually seen this cause a problem. I was just +looking at the code trying to figure out a different EXCLUSIVE open +related issue, and this looked wrong. + +(Fix confirmed with pynfs 4.0 test OPEN4--bfields) + +Signed-off-by: NeilBrown +[bfields: use OWNER_OVERRIDE and update for 4.1] +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfsd/nfs4proc.c | 8 +++++--- + fs/nfsd/vfs.c | 10 ++++++++-- + 2 files changed, 13 insertions(+), 5 deletions(-) + +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -194,6 +194,7 @@ static __be32 + do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) + { + struct svc_fh *resfh; ++ int accmode; + __be32 status; + + resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL); +@@ -253,9 +254,10 @@ do_open_lookup(struct svc_rqst *rqstp, s + /* set reply cache */ + fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh, + &resfh->fh_handle); +- if (!open->op_created) +- status = do_open_permission(rqstp, resfh, open, +- NFSD_MAY_NOP); ++ accmode = NFSD_MAY_NOP; ++ if (open->op_created) ++ accmode |= NFSD_MAY_OWNER_OVERRIDE; ++ status = do_open_permission(rqstp, resfh, open, accmode); + set_change_info(&open->op_cinfo, current_fh); + fh_dup2(current_fh, resfh); + out: +--- a/fs/nfsd/vfs.c ++++ b/fs/nfsd/vfs.c +@@ -1485,13 +1485,19 @@ do_nfsd_create(struct svc_rqst *rqstp, s + case NFS3_CREATE_EXCLUSIVE: + if ( dchild->d_inode->i_mtime.tv_sec == v_mtime + && dchild->d_inode->i_atime.tv_sec == v_atime +- && dchild->d_inode->i_size == 0 ) ++ && dchild->d_inode->i_size == 0 ) { ++ if (created) ++ *created = 1; + break; ++ } + case NFS4_CREATE_EXCLUSIVE4_1: + if ( dchild->d_inode->i_mtime.tv_sec == v_mtime + && dchild->d_inode->i_atime.tv_sec == v_atime +- && dchild->d_inode->i_size == 0 ) ++ && dchild->d_inode->i_size == 0 ) { ++ if (created) ++ *created = 1; + goto set_attr; ++ } + /* fallthru */ + case NFS3_CREATE_GUARDED: + err = nfserr_exist; diff --git a/queue-3.7/nfsd-fix-v4-reply-caching.patch b/queue-3.7/nfsd-fix-v4-reply-caching.patch new file mode 100644 index 00000000000..94add2d2ce9 --- /dev/null +++ b/queue-3.7/nfsd-fix-v4-reply-caching.patch @@ -0,0 +1,33 @@ +From 57d276d71aef7d8305ff002a070cb98deb2edced Mon Sep 17 00:00:00 2001 +From: "J. Bruce Fields" +Date: Fri, 16 Nov 2012 15:22:43 -0500 +Subject: nfsd: fix v4 reply caching + +From: "J. Bruce Fields" + +commit 57d276d71aef7d8305ff002a070cb98deb2edced upstream. + +Very embarassing: 1091006c5eb15cba56785bd5b498a8d0b9546903 "nfsd: turn +on reply cache for NFSv4" missed a line, effectively leaving the reply +cache off in the v4 case. I thought I'd tested that, but I guess not. + +This time, wrote a pynfs test to confirm it works. + +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfsd/nfssvc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfsd/nfssvc.c ++++ b/fs/nfsd/nfssvc.c +@@ -640,7 +640,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __ + } + + /* Store reply in cache. */ +- nfsd_cache_update(rqstp, proc->pc_cachetype, statp + 1); ++ nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1); + return 1; + } + diff --git a/queue-3.7/nfsd4-fix-oops-on-unusual-readlike-compound.patch b/queue-3.7/nfsd4-fix-oops-on-unusual-readlike-compound.patch new file mode 100644 index 00000000000..ef99566acf3 --- /dev/null +++ b/queue-3.7/nfsd4-fix-oops-on-unusual-readlike-compound.patch @@ -0,0 +1,57 @@ +From d5f50b0c290431c65377c4afa1c764e2c3fe5305 Mon Sep 17 00:00:00 2001 +From: "J. Bruce Fields" +Date: Tue, 4 Dec 2012 18:25:10 -0500 +Subject: nfsd4: fix oops on unusual readlike compound + +From: "J. Bruce Fields" + +commit d5f50b0c290431c65377c4afa1c764e2c3fe5305 upstream. + +If the argument and reply together exceed the maximum payload size, then +a reply with a read-like operation can overlow the rq_pages array. + +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfsd/nfs4xdr.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -2946,11 +2946,16 @@ nfsd4_encode_read(struct nfsd4_compoundr + len = maxcount; + v = 0; + while (len > 0) { +- pn = resp->rqstp->rq_resused++; ++ pn = resp->rqstp->rq_resused; ++ if (!resp->rqstp->rq_respages[pn]) { /* ran out of pages */ ++ maxcount -= len; ++ break; ++ } + resp->rqstp->rq_vec[v].iov_base = + page_address(resp->rqstp->rq_respages[pn]); + resp->rqstp->rq_vec[v].iov_len = + len < PAGE_SIZE ? len : PAGE_SIZE; ++ resp->rqstp->rq_resused++; + v++; + len -= PAGE_SIZE; + } +@@ -2996,6 +3001,8 @@ nfsd4_encode_readlink(struct nfsd4_compo + return nfserr; + if (resp->xbuf->page_len) + return nfserr_resource; ++ if (!resp->rqstp->rq_respages[resp->rqstp->rq_resused]) ++ return nfserr_resource; + + page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); + +@@ -3045,6 +3052,8 @@ nfsd4_encode_readdir(struct nfsd4_compou + return nfserr; + if (resp->xbuf->page_len) + return nfserr_resource; ++ if (!resp->rqstp->rq_respages[resp->rqstp->rq_resused]) ++ return nfserr_resource; + + RESERVE_SPACE(NFS4_VERIFIER_SIZE); + savep = p; diff --git a/queue-3.7/nfsv4-check-for-buffer-length-in-__nfs4_get_acl_uncached.patch b/queue-3.7/nfsv4-check-for-buffer-length-in-__nfs4_get_acl_uncached.patch new file mode 100644 index 00000000000..39161554851 --- /dev/null +++ b/queue-3.7/nfsv4-check-for-buffer-length-in-__nfs4_get_acl_uncached.patch @@ -0,0 +1,43 @@ +From 7d3e91a89b7adbc2831334def9e494dd9892f9af Mon Sep 17 00:00:00 2001 +From: Sven Wegener +Date: Sat, 8 Dec 2012 15:30:18 +0100 +Subject: NFSv4: Check for buffer length in __nfs4_get_acl_uncached + +From: Sven Wegener + +commit 7d3e91a89b7adbc2831334def9e494dd9892f9af upstream. + +Commit 1f1ea6c "NFSv4: Fix buffer overflow checking in +__nfs4_get_acl_uncached" accidently dropped the checking for too small +result buffer length. + +If someone uses getxattr on "system.nfs4_acl" on an NFSv4 mount +supporting ACLs, the ACL has not been cached and the buffer suplied is +too short, we still copy the complete ACL, resulting in kernel and user +space memory corruption. + +Signed-off-by: Sven Wegener +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/nfs4proc.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -3937,8 +3937,13 @@ static ssize_t __nfs4_get_acl_uncached(s + goto out_free; + } + nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len); +- if (buf) ++ if (buf) { ++ if (res.acl_len > buflen) { ++ ret = -ERANGE; ++ goto out_free; ++ } + _copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len); ++ } + out_ok: + ret = res.acl_len; + out_free: diff --git a/queue-3.7/pnfs-increase-the-refcount-when-layoutget-fails-the-first-time.patch b/queue-3.7/pnfs-increase-the-refcount-when-layoutget-fails-the-first-time.patch new file mode 100644 index 00000000000..3c500c63857 --- /dev/null +++ b/queue-3.7/pnfs-increase-the-refcount-when-layoutget-fails-the-first-time.patch @@ -0,0 +1,31 @@ +From 39e88fcfb1d5c6c4b1ff76ca2ab76cf449b850e8 Mon Sep 17 00:00:00 2001 +From: Yanchuan Nian +Date: Fri, 4 Jan 2013 20:19:49 +0800 +Subject: pnfs: Increase the refcount when LAYOUTGET fails the first time + +From: Yanchuan Nian + +commit 39e88fcfb1d5c6c4b1ff76ca2ab76cf449b850e8 upstream. + +The layout will be set unusable if LAYOUTGET fails. Is it reasonable to +increase the refcount iff LAYOUTGET fails the first time? + +Signed-off-by: Yanchuan Nian +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/pnfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfs/pnfs.c ++++ b/fs/nfs/pnfs.c +@@ -254,7 +254,7 @@ static void + pnfs_layout_set_fail_bit(struct pnfs_layout_hdr *lo, int fail_bit) + { + lo->plh_retry_timestamp = jiffies; +- if (test_and_set_bit(fail_bit, &lo->plh_flags)) ++ if (!test_and_set_bit(fail_bit, &lo->plh_flags)) + atomic_inc(&lo->plh_refcount); + } + diff --git a/queue-3.7/series b/queue-3.7/series index 89a954fa39d..888d09b2a5e 100644 --- a/queue-3.7/series +++ b/queue-3.7/series @@ -36,3 +36,19 @@ usb-gadget-network-fix-bind-error-path.patch acpi-do-acpisleep-dmi-check-when-config_acpi_sleep-is-set.patch libata-restore-acpi-disable-functionality.patch acpi-scan-do-not-use-dummy-hid-for-system-bus-acpi-nodes.patch +nfs-add-sequence_priviliged_ops-for-nfs4_proc_sequence.patch +nfs-don-t-extend-writes-to-cover-entire-page-if-pagecache-is-invalid.patch +nfsv4-check-for-buffer-length-in-__nfs4_get_acl_uncached.patch +nfs-don-t-zero-out-the-rest-of-the-page-if-we-hit-the-eof-on-a-dio-read.patch +nfs-avoid-null-dereference-in-nfs_destroy_server.patch +nfs-fix-calls-to-drop_nlink.patch +nfs-don-t-use-setpageerror-in-the-nfs-writeback-code.patch +nfs-fix-wrong-object-type-in-lockowner_slab.patch +nfsd-fix-v4-reply-caching.patch +nfsd4-fix-oops-on-unusual-readlike-compound.patch +nfsd-avoid-permission-checks-on-exclusive_create-replay.patch +nfs-fix-access-to-suid-sgid-executables.patch +pnfs-increase-the-refcount-when-layoutget-fails-the-first-time.patch +nfs-fix-null-checking-in-nfs_get_option_str.patch +nfs-ensure-that-we-free-the-rpc_task-after-read-and-write-cleanups-are-done.patch +nfs-avoid-dereferencing-null-pointer-in-initiate_bulk_draining.patch