Commit dc9dc2fe authored by Trond Myklebust's avatar Trond Myklebust

NFS: Fix use-after-free issues in nfs_pageio_add_request()

We need to ensure that we create the mirror requests before calling
nfs_pageio_add_request_mirror() on the request we are adding.
Otherwise, we can end up with a use-after-free if the call to
nfs_pageio_add_request_mirror() triggers I/O.

Fixes: c917cfaf ("NFS: Fix up NFS I/O subrequest creation")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 08ca8b21
...@@ -1191,38 +1191,38 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, ...@@ -1191,38 +1191,38 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
if (desc->pg_error < 0) if (desc->pg_error < 0)
goto out_failed; goto out_failed;
for (midx = 0; midx < desc->pg_mirror_count; midx++) { /* Create the mirror instances first, and fire them off */
if (midx) { for (midx = 1; midx < desc->pg_mirror_count; midx++) {
nfs_page_group_lock(req); nfs_page_group_lock(req);
/* find the last request */ /* find the last request */
for (lastreq = req->wb_head; for (lastreq = req->wb_head;
lastreq->wb_this_page != req->wb_head; lastreq->wb_this_page != req->wb_head;
lastreq = lastreq->wb_this_page) lastreq = lastreq->wb_this_page)
; ;
dupreq = nfs_create_subreq(req, lastreq, dupreq = nfs_create_subreq(req, lastreq,
pgbase, offset, bytes); pgbase, offset, bytes);
nfs_page_group_unlock(req); nfs_page_group_unlock(req);
if (IS_ERR(dupreq)) { if (IS_ERR(dupreq)) {
desc->pg_error = PTR_ERR(dupreq); desc->pg_error = PTR_ERR(dupreq);
goto out_failed; goto out_failed;
} }
} else
dupreq = req;
if (nfs_pgio_has_mirroring(desc)) desc->pg_mirror_idx = midx;
desc->pg_mirror_idx = midx;
if (!nfs_pageio_add_request_mirror(desc, dupreq)) if (!nfs_pageio_add_request_mirror(desc, dupreq))
goto out_cleanup_subreq; goto out_cleanup_subreq;
} }
desc->pg_mirror_idx = 0;
if (!nfs_pageio_add_request_mirror(desc, req))
goto out_failed;
return 1; return 1;
out_cleanup_subreq: out_cleanup_subreq:
if (req != dupreq) nfs_pageio_cleanup_request(desc, dupreq);
nfs_pageio_cleanup_request(desc, dupreq);
out_failed: out_failed:
nfs_pageio_error_cleanup(desc); nfs_pageio_error_cleanup(desc);
return 0; return 0;
......
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