[PATCH] 9pfs: fix missing rename lock in v9fs_co_readdir_many (CVE-2026-48004)

Christian Schoenebeck posted 1 patch 1 week, 2 days ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/E1wPkYi-000adH-4E@kylie.crudebyte.com
Maintainers: Christian Schoenebeck <qemu_oss@crudebyte.com>, Greg Kurz <groug@kaod.org>
hw/9pfs/codir.c | 3 +++
1 file changed, 3 insertions(+)
[PATCH] 9pfs: fix missing rename lock in v9fs_co_readdir_many (CVE-2026-48004)
Posted by Christian Schoenebeck 1 week, 2 days ago
From: sin99xx <sinxx198@gmail.com>

v9fs_co_readdir_many() dispatches do_readdir_many() to a worker thread
that reads V9fsFidState's path.data without holding a rename lock.

A concurrent rename request, e.g. of its parent dir, causes the FID's
absolute path to be altered by freeing the old path string and
assigning a new one. This causes a heap-use-after-free race condition
while do_readdir_many() is still accessing the old object.

This allows a DoS by an unprivileged guest user.

Fix this by wrapping the worker thread dispatch block within a pair of
v9fs_path_read_lock() and v9fs_path_unlock() calls, like it's done at
other places.

Fixes: 2149675b195f ("9pfs: add new function v9fs_co_readdir_many()")
Fixes: CVE-2026-48004
Reported-by: sin99xx <sinxx198@gmail.com>
[Christian Schoenebeck: add commit log message]
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
---
 hw/9pfs/codir.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
index bce7dd96e9..5568399343 100644
--- a/hw/9pfs/codir.c
+++ b/hw/9pfs/codir.c
@@ -220,13 +220,16 @@ int coroutine_fn v9fs_co_readdir_many(V9fsPDU *pdu, V9fsFidState *fidp,
                                       bool dostat)
 {
     int err = 0;
+    V9fsState *s = pdu->s;
 
     if (v9fs_request_cancelled(pdu)) {
         return -EINTR;
     }
+    v9fs_path_read_lock(s);
     v9fs_co_run_in_worker({
         err = do_readdir_many(pdu, fidp, entries, offset, maxsize, dostat);
     });
+    v9fs_path_unlock(s);
     return err;
 }
 
-- 
2.47.3
Re: [PATCH] 9pfs: fix missing rename lock in v9fs_co_readdir_many (CVE-2026-48004)
Posted by Christian Schoenebeck 2 days, 7 hours ago
On Wednesday, 20 May 2026 19:11:25 CEST Christian Schoenebeck wrote:
> From: sin99xx <sinxx198@gmail.com>
> 
> v9fs_co_readdir_many() dispatches do_readdir_many() to a worker thread
> that reads V9fsFidState's path.data without holding a rename lock.
> 
> A concurrent rename request, e.g. of its parent dir, causes the FID's
> absolute path to be altered by freeing the old path string and
> assigning a new one. This causes a heap-use-after-free race condition
> while do_readdir_many() is still accessing the old object.
> 
> This allows a DoS by an unprivileged guest user.
> 
> Fix this by wrapping the worker thread dispatch block within a pair of
> v9fs_path_read_lock() and v9fs_path_unlock() calls, like it's done at
> other places.
> 
> Fixes: 2149675b195f ("9pfs: add new function v9fs_co_readdir_many()")
> Fixes: CVE-2026-48004
> Reported-by: sin99xx <sinxx198@gmail.com>
> [Christian Schoenebeck: add commit log message]
> Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> ---

With updated author's email address, queued on 9p.next:
https://github.com/cschoenebeck/qemu/commits/9p.next

Thanks!

/Christian
Re: [PATCH] 9pfs: fix missing rename lock in v9fs_co_readdir_many (CVE-2026-48004)
Posted by Christian Schoenebeck 1 week, 2 days ago
On Wednesday, 20 May 2026 19:11:25 CEST Christian Schoenebeck wrote:
> From: sin99xx <sinxx198@gmail.com>
> 
> v9fs_co_readdir_many() dispatches do_readdir_many() to a worker thread
> that reads V9fsFidState's path.data without holding a rename lock.
> 
> A concurrent rename request, e.g. of its parent dir, causes the FID's
> absolute path to be altered by freeing the old path string and
> assigning a new one. This causes a heap-use-after-free race condition
> while do_readdir_many() is still accessing the old object.
> 
> This allows a DoS by an unprivileged guest user.
> 
> Fix this by wrapping the worker thread dispatch block within a pair of
> v9fs_path_read_lock() and v9fs_path_unlock() calls, like it's done at
> other places.
> 
> Fixes: 2149675b195f ("9pfs: add new function v9fs_co_readdir_many()")
> Fixes: CVE-2026-48004
> Reported-by: sin99xx <sinxx198@gmail.com>
> [Christian Schoenebeck: add commit log message]
> Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>

sin99xx, I forgot, may I add your Signed-off-by tag?

  Signed-off-by: sin99xx <sinxx198@gmail.com>

This is required [1] for making you the patch author:

"Your patches must include a Signed-off-by: line. This is a hard requirement 
because it’s how you say “I’m legally okay to contribute this and happy for it 
to go into QEMU”. For full guidance, read the Code provenance documentation."

[1] https://www.qemu.org/docs/master/devel/submitting-a-patch.html

> ---
>  hw/9pfs/codir.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
> index bce7dd96e9..5568399343 100644
> --- a/hw/9pfs/codir.c
> +++ b/hw/9pfs/codir.c
> @@ -220,13 +220,16 @@ int coroutine_fn v9fs_co_readdir_many(V9fsPDU *pdu,
> V9fsFidState *fidp, bool dostat)
>  {
>      int err = 0;
> +    V9fsState *s = pdu->s;
> 
>      if (v9fs_request_cancelled(pdu)) {
>          return -EINTR;
>      }
> +    v9fs_path_read_lock(s);
>      v9fs_co_run_in_worker({
>          err = do_readdir_many(pdu, fidp, entries, offset, maxsize, dostat);
> });
> +    v9fs_path_unlock(s);
>      return err;
>  }
Re: [PATCH] 9pfs: fix missing rename lock in v9fs_co_readdir_many (CVE-2026-48004)
Posted by sin99xx 1 week, 2 days ago
Yes, please go ahead and add my Signed-off-by tag. Also, if possible, could
you use this email instead?
Signed-off-by: sin99xx sin99xx@proton.me

Thanks.

On Wed, May 20, 2026 at 2:22 PM Christian Schoenebeck <
qemu_oss@crudebyte.com> wrote:

> On Wednesday, 20 May 2026 19:11:25 CEST Christian Schoenebeck wrote:
> > From: sin99xx <sinxx198@gmail.com>
> >
> > v9fs_co_readdir_many() dispatches do_readdir_many() to a worker thread
> > that reads V9fsFidState's path.data without holding a rename lock.
> >
> > A concurrent rename request, e.g. of its parent dir, causes the FID's
> > absolute path to be altered by freeing the old path string and
> > assigning a new one. This causes a heap-use-after-free race condition
> > while do_readdir_many() is still accessing the old object.
> >
> > This allows a DoS by an unprivileged guest user.
> >
> > Fix this by wrapping the worker thread dispatch block within a pair of
> > v9fs_path_read_lock() and v9fs_path_unlock() calls, like it's done at
> > other places.
> >
> > Fixes: 2149675b195f ("9pfs: add new function v9fs_co_readdir_many()")
> > Fixes: CVE-2026-48004
> > Reported-by: sin99xx <sinxx198@gmail.com>
> > [Christian Schoenebeck: add commit log message]
> > Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
>
> sin99xx, I forgot, may I add your Signed-off-by tag?
>
>   Signed-off-by: sin99xx <sinxx198@gmail.com>
>
> This is required [1] for making you the patch author:
>
> "Your patches must include a Signed-off-by: line. This is a hard
> requirement
> because it’s how you say “I’m legally okay to contribute this and happy
> for it
> to go into QEMU”. For full guidance, read the Code provenance
> documentation."
>
> [1] https://www.qemu.org/docs/master/devel/submitting-a-patch.html
>
> > ---
> >  hw/9pfs/codir.c | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
> > index bce7dd96e9..5568399343 100644
> > --- a/hw/9pfs/codir.c
> > +++ b/hw/9pfs/codir.c
> > @@ -220,13 +220,16 @@ int coroutine_fn v9fs_co_readdir_many(V9fsPDU *pdu,
> > V9fsFidState *fidp, bool dostat)
> >  {
> >      int err = 0;
> > +    V9fsState *s = pdu->s;
> >
> >      if (v9fs_request_cancelled(pdu)) {
> >          return -EINTR;
> >      }
> > +    v9fs_path_read_lock(s);
> >      v9fs_co_run_in_worker({
> >          err = do_readdir_many(pdu, fidp, entries, offset, maxsize,
> dostat);
> > });
> > +    v9fs_path_unlock(s);
> >      return err;
> >  }
>
>
>
Re: [PATCH] 9pfs: fix missing rename lock in v9fs_co_readdir_many (CVE-2026-48004)
Posted by Christian Schoenebeck 1 week, 2 days ago
On Wednesday, 20 May 2026 20:26:09 CEST sin99xx wrote:
> Yes, please go ahead and add my Signed-off-by tag. Also, if possible, could
> you use this email instead?
> Signed-off-by: sin99xx sin99xx@proton.me

Please confirm by replying with that proton email address then I will replace 
your email address on this patch.

CC-ing qemu-stable, as this patch should be applied on stable branches, too.

> On Wed, May 20, 2026 at 2:22 PM Christian Schoenebeck <
> 
> qemu_oss@crudebyte.com> wrote:
> > On Wednesday, 20 May 2026 19:11:25 CEST Christian Schoenebeck wrote:
> > > From: sin99xx <sinxx198@gmail.com>
> > > 
> > > v9fs_co_readdir_many() dispatches do_readdir_many() to a worker thread
> > > that reads V9fsFidState's path.data without holding a rename lock.
> > > 
> > > A concurrent rename request, e.g. of its parent dir, causes the FID's
> > > absolute path to be altered by freeing the old path string and
> > > assigning a new one. This causes a heap-use-after-free race condition
> > > while do_readdir_many() is still accessing the old object.
> > > 
> > > This allows a DoS by an unprivileged guest user.
> > > 
> > > Fix this by wrapping the worker thread dispatch block within a pair of
> > > v9fs_path_read_lock() and v9fs_path_unlock() calls, like it's done at
> > > other places.
> > > 
> > > Fixes: 2149675b195f ("9pfs: add new function v9fs_co_readdir_many()")
> > > Fixes: CVE-2026-48004
> > > Reported-by: sin99xx <sinxx198@gmail.com>
> > > [Christian Schoenebeck: add commit log message]
> > > Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> > 
> > sin99xx, I forgot, may I add your Signed-off-by tag?
> > 
> >   Signed-off-by: sin99xx <sinxx198@gmail.com>
> > 
> > This is required [1] for making you the patch author:
> > 
> > "Your patches must include a Signed-off-by: line. This is a hard
> > requirement
> > because it’s how you say “I’m legally okay to contribute this and happy
> > for it
> > to go into QEMU”. For full guidance, read the Code provenance
> > documentation."
> > 
> > [1] https://www.qemu.org/docs/master/devel/submitting-a-patch.html
> > 
> > > ---
> > > 
> > >  hw/9pfs/codir.c | 3 +++
> > >  1 file changed, 3 insertions(+)
> > > 
> > > diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
> > > index bce7dd96e9..5568399343 100644
> > > --- a/hw/9pfs/codir.c
> > > +++ b/hw/9pfs/codir.c
> > > @@ -220,13 +220,16 @@ int coroutine_fn v9fs_co_readdir_many(V9fsPDU
> > > *pdu,
> > > V9fsFidState *fidp, bool dostat)
> > > 
> > >  {
> > >  
> > >      int err = 0;
> > > 
> > > +    V9fsState *s = pdu->s;
> > > 
> > >      if (v9fs_request_cancelled(pdu)) {
> > >      
> > >          return -EINTR;
> > >      
> > >      }
> > > 
> > > +    v9fs_path_read_lock(s);
> > > 
> > >      v9fs_co_run_in_worker({
> > >      
> > >          err = do_readdir_many(pdu, fidp, entries, offset, maxsize,
> > 
> > dostat);
> > 
> > > });
> > > +    v9fs_path_unlock(s);
> > > 
> > >      return err;
> > >  
> > >  }
Re: [PATCH] 9pfs: fix missing rename lock in v9fs_co_readdir_many (CVE-2026-48004)
Posted by sin99xx 1 week, 2 days ago
my bad,

Confirmed — please use this address (sin99xx@proton.me) for the
Signed-off-by and From lines on the patch.

Signed-off-by: sin99xx sin99xx@proton.me

Regards,
sin99xx


Sent from Proton Mail for iOS.

-------- Original Message --------
On Thursday, 05/21/26 at 04:30 Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:
On Wednesday, 20 May 2026 20:26:09 CEST sin99xx wrote:
> Yes, please go ahead and add my Signed-off-by tag. Also, if possible, could
> you use this email instead?
> Signed-off-by: sin99xx sin99xx@proton.me

Please confirm by replying with that proton email address then I will replace
your email address on this patch.

CC-ing qemu-stable, as this patch should be applied on stable branches, too.

> On Wed, May 20, 2026 at 2:22 PM Christian Schoenebeck <
>
> qemu_oss@crudebyte.com> wrote:
> > On Wednesday, 20 May 2026 19:11:25 CEST Christian Schoenebeck wrote:
> > > From: sin99xx <sinxx198@gmail.com>
> > >
> > > v9fs_co_readdir_many() dispatches do_readdir_many() to a worker thread
> > > that reads V9fsFidState's path.data without holding a rename lock.
> > >
> > > A concurrent rename request, e.g. of its parent dir, causes the FID's
> > > absolute path to be altered by freeing the old path string and
> > > assigning a new one. This causes a heap-use-after-free race condition
> > > while do_readdir_many() is still accessing the old object.
> > >
> > > This allows a DoS by an unprivileged guest user.
> > >
> > > Fix this by wrapping the worker thread dispatch block within a pair of
> > > v9fs_path_read_lock() and v9fs_path_unlock() calls, like it's done at
> > > other places.
> > >
> > > Fixes: 2149675b195f ("9pfs: add new function v9fs_co_readdir_many()")
> > > Fixes: CVE-2026-48004
> > > Reported-by: sin99xx <sinxx198@gmail.com>
> > > [Christian Schoenebeck: add commit log message]
> > > Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> >
> > sin99xx, I forgot, may I add your Signed-off-by tag?
> >
> >   Signed-off-by: sin99xx <sinxx198@gmail.com>
> >
> > This is required [1] for making you the patch author:
> >
> > "Your patches must include a Signed-off-by: line. This is a hard
> > requirement
> > because it’s how you say “I’m legally okay to contribute this and happy
> > for it
> > to go into QEMU”. For full guidance, read the Code provenance
> > documentation."
> >
> > [1] https://www.qemu.org/docs/master/devel/submitting-a-patch.html
> >
> > > ---
> > >
> > >  hw/9pfs/codir.c | 3 +++
> > >  1 file changed, 3 insertions(+)
> > >
> > > diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
> > > index bce7dd96e9..5568399343 100644
> > > --- a/hw/9pfs/codir.c
> > > +++ b/hw/9pfs/codir.c
> > > @@ -220,13 +220,16 @@ int coroutine_fn v9fs_co_readdir_many(V9fsPDU
> > > *pdu,
> > > V9fsFidState *fidp, bool dostat)
> > >
> > >  {
> > >
> > >      int err = 0;
> > >
> > > +    V9fsState *s = pdu->s;
> > >
> > >      if (v9fs_request_cancelled(pdu)) {
> > >
> > >          return -EINTR;
> > >
> > >      }
> > >
> > > +    v9fs_path_read_lock(s);
> > >
> > >      v9fs_co_run_in_worker({
> > >
> > >          err = do_readdir_many(pdu, fidp, entries, offset, maxsize,
> >
> > dostat);
> >
> > > });
> > > +    v9fs_path_unlock(s);
> > >
> > >      return err;
> > >
> > >  }