]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ceph: fix refcount leak in ceph_readdir()
authorWenTao Liang <vulab@iscas.ac.cn>
Thu, 11 Jun 2026 14:40:07 +0000 (22:40 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Thu, 23 Jul 2026 18:29:41 +0000 (20:29 +0200)
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>
fs/ceph/dir.c

index 27ce9e55e94768e4507f266cd132c743a9ccce5b..ef9e92e362d3ea02f92e7325349992eb8b2723d5 100644 (file)
@@ -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,