diff options
| author | Alex Markuze <amarkuze@redhat.com> | 2026-08-24 18:50:03 +0000 |
|---|---|---|
| committer | Ilya Dryomov <idryomov@gmail.com> | 2026-10-26 14:15:47 +0100 |
| commit | 00a0d7f377f6af59bc559b2e07dffff63eaa5544 (patch) | |
| tree | 8b3053a7a9e75f3a18afb2382ecf770bd1f63a98 | |
| parent | 6ce5143eea0566512923591a4a3cb0872ee42e4d (diff) | |
| download | linux-00a0d7f377f6af59bc559b2e07dffff63eaa5544.tar.gz linux-00a0d7f377f6af59bc559b2e07dffff63eaa5544.zip | |
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 <amarkuze@redhat.com>
Reviewed-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
| -rw-r--r-- | fs/ceph/addr.c | 11 |
1 files changed, 11 insertions, 0 deletions
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; } |
