Commit be2fd156 authored by Trond Myklebust's avatar Trond Myklebust

NFS: Fix a use after free in nfs_direct_join_group()

Be more careful when tearing down the subrequests of an O_DIRECT write
as part of a retransmission.
Reported-by: default avatarChris Mason <clm@fb.com>
Fixes: ed5d588f ("NFS: Try to join page groups before an O_DIRECT retransmission")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 1cbc11aa
...@@ -472,20 +472,26 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter, ...@@ -472,20 +472,26 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
return result; return result;
} }
static void static void nfs_direct_join_group(struct list_head *list, struct inode *inode)
nfs_direct_join_group(struct list_head *list, struct inode *inode)
{ {
struct nfs_page *req, *next; struct nfs_page *req, *subreq;
list_for_each_entry(req, list, wb_list) { list_for_each_entry(req, list, wb_list) {
if (req->wb_head != req || req->wb_this_page == req) if (req->wb_head != req)
continue; continue;
for (next = req->wb_this_page; subreq = req->wb_this_page;
next != req->wb_head; if (subreq == req)
next = next->wb_this_page) { continue;
nfs_list_remove_request(next); do {
nfs_release_request(next); /*
} * Remove subrequests from this list before freeing
* them in the call to nfs_join_page_group().
*/
if (!list_empty(&subreq->wb_list)) {
nfs_list_remove_request(subreq);
nfs_release_request(subreq);
}
} while ((subreq = subreq->wb_this_page) != req);
nfs_join_page_group(req, inode); nfs_join_page_group(req, inode);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment