From 00a0d7f377f6af59bc559b2e07dffff63eaa5544 Mon Sep 17 00:00:00 2001 From: Alex Markuze Date: Mon, 24 Aug 2026 18:50:03 +0000 Subject: [PATCH] ceph: fix page vector leak on encrypted netfs read EIO path 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") Signed-off-by: Alex Markuze Reviewed-by: Tal Zussman Signed-off-by: Ilya Dryomov --- fs/ceph/addr.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 31a3175fdd7a..cd6f0f578ead 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -450,6 +450,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; }