[PATCH] ceph: fix page vector leak on encrypted netfs read EIO path
Alex Markuze <[email protected]>
| Newsgroups | org.kernel.vger.stable,org.kernel.vger.ceph-devel |
|---|---|
| Message-ID | <[email protected]> |
ceph_netfs_issue_read() pins pages with iov_iter_get_pages_alloc2() for
encrypted inodes and attaches them with own_pages=false. If
ceph_inc_osd_stopping_blocker() then fails, the request is dropped
without calling finish_netfs_read(), so the page array and the
references taken on those pages leak: ceph_osd_data_release() only
frees pages when own_pages is true, and __free_pages() would be the
wrong destructor for GUP-pinned pages.
Release the vector with put_page() and kvfree() on that error path,
matching finish_netfs_read(). Unencrypted ITER reads are unaffected.
Fixes: 1464de9f813e ("ceph: wait for OSD requests' callbacks to finish when unmounting")
Cc: [email protected]
Signed-off-by: Alex Markuze <[email protected]>
---
fs/ceph/addr.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index c05bdf5d7273..8b009e354d30 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -442,6 +442,17 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq)
osd_req_op_extent_osd_iter(req, 0, &subreq->io_iter);
}
if (!ceph_inc_osd_stopping_blocker(fsc->mdsc)) {
+ struct ceph_osd_data *osd_data =
+ osd_req_op_extent_osd_data(req, 0);
+
+ if (osd_data->type == CEPH_OSD_DATA_TYPE_PAGES) {
+ int num_pages = calc_pages_for(osd_data->alignment,
+ osd_data->length);
+
+ for (int i = 0; i < num_pages; i++)
+ put_page(osd_data->pages[i]);
+ kvfree(osd_data->pages);
+ }
err = -EIO;
goto out;
}
--
2.34.1