Skip to content

Commit

Permalink
NFS: Fix a use after free in nfs_direct_join_group()
Browse files Browse the repository at this point in the history
Be more careful when tearing down the subrequests of an O_DIRECT write
as part of a retransmission.

Reported-by: Chris Mason <[email protected]>
Fixes: ed5d588 ("NFS: Try to join page groups before an O_DIRECT retransmission")
Cc: [email protected]
Signed-off-by: Trond Myklebust <[email protected]>
  • Loading branch information
Trond Myklebust committed Aug 17, 2023
1 parent 1cbc11a commit be2fd15
Showing 1 changed file with 16 additions and 10 deletions.
26 changes: 16 additions & 10 deletions fs/nfs/direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,20 +472,26 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
return result;
}

static void
nfs_direct_join_group(struct list_head *list, struct inode *inode)
static void 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) {
if (req->wb_head != req || req->wb_this_page == req)
if (req->wb_head != req)
continue;
for (next = req->wb_this_page;
next != req->wb_head;
next = next->wb_this_page) {
nfs_list_remove_request(next);
nfs_release_request(next);
}
subreq = req->wb_this_page;
if (subreq == req)
continue;
do {
/*
* 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);
}
}
Expand Down

0 comments on commit be2fd15

Please sign in to comment.