summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWenTao Liang <vulab@iscas.ac.cn>2026-06-11 22:40:07 +0800
committerIlya Dryomov <idryomov@gmail.com>2026-07-23 20:29:41 +0200
commitc3e64079d8b9663e3998d0caac9aba915b6b93ae (patch)
treea320dfdc4b912f10bdc914902f9fe6a7da2b32de
parentbbeae12fda3384a90fbebc8a19ba9d33f85b5361 (diff)
downloadlinux-c3e64079d8b9663e3998d0caac9aba915b6b93ae.tar.gz
linux-c3e64079d8b9663e3998d0caac9aba915b6b93ae.tar.bz2
linux-c3e64079d8b9663e3998d0caac9aba915b6b93ae.zip
ceph: fix refcount leak in ceph_readdir()
The ceph_readdir() function allocates a ceph_mds_request via ceph_mdsc_create_request() and stores it in dfi->last_readdir. In the directory entry processing loop, if the entry's offset is less than ctx->pos or if the inode pointer is unexpectedly NULL, the function returns -EIO without releasing the reference held by dfi->last_readdir, causing a refcount leak. Fix this by adding ceph_mdsc_put_request(dfi->last_readdir) before returning on these error paths. Also set dfi->last_readdir to NULL for safety, matching the cleanup done at the normal exit. Cc: stable@vger.kernel.org Fixes: af9ffa6df7e3 ("ceph: add support to readdir for encrypted names") Signed-off-by: WenTao Liang <vulab@iscas.ac.cn> Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com> Reviewed-by: Alex Markuze <amarkuze@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
-rw-r--r--fs/ceph/dir.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 27ce9e55e947..ef9e92e362d3 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -546,11 +546,16 @@ more:
pr_warn_client(cl,
"%p %llx.%llx rde->offset 0x%llx ctx->pos 0x%llx\n",
inode, ceph_vinop(inode), rde->offset, ctx->pos);
+ ceph_mdsc_put_request(dfi->last_readdir);
+ dfi->last_readdir = NULL;
return -EIO;
}
- if (WARN_ON_ONCE(!rde->inode.in))
+ if (WARN_ON_ONCE(!rde->inode.in)) {
+ ceph_mdsc_put_request(dfi->last_readdir);
+ dfi->last_readdir = NULL;
return -EIO;
+ }
ctx->pos = rde->offset;
doutc(cl, "%p %llx.%llx (%d/%d) -> %llx '%.*s' %p\n", inode,