hw/9pfs/cofile.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
v9fs_co_open2() is the only code that mutates a FID path from a worker
thread: inside its v9fs_co_run_in_worker() block it frees fidp->path
and copies in the new path under the held FID path write lock.
Every other FID path mutation in the 9p codebase happens on the main
thread, so main thread readers (v9fs_walk(), v9fs_xattrwalk(),
v9fs_stat(), v9fs_co_name_to_path()) rely on the same (main) thread
atomicity and don't take the path read lock themselves on main thread.
Fix this by making the worker thread block in v9fs_co_open2() read-only
with respect to the FID: render the new path into the local 'path'
variable only and copy it to fidp->path after the worker block returned
back to the main thread and still under the held write lock of the FID,
like every other FID path mutation does.
Fixes: 02cb7f3a25 ("hw/9pfs: Use read-write lock for protecting fid path.")
Fixes: CVE-2026-93834
Reported-by: Milad Nasr <https://gitlab.com/sirkhezr>
Suggested-by: Milad Nasr <https://gitlab.com/sirkhezr>
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4491
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
---
hw/9pfs/cofile.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
index 6e775c8e41..27fe5bfb20 100644
--- a/hw/9pfs/cofile.c
+++ b/hw/9pfs/cofile.c
@@ -144,10 +144,11 @@ int coroutine_fn v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp,
cred.fc_mode = mode & 07777;
cred.fc_uid = fidp->uid;
cred.fc_gid = gid;
+ v9fs_path_init(&path);
/*
* Hold the directory fid lock so that directory path name
- * don't change. Take the write lock to be sure this fid
- * cannot be used by another operation.
+ * don't change. Take the write lock since the fid path is
+ * mutated below on success.
*/
v9fs_path_write_lock(s);
v9fs_co_run_in_worker(
@@ -157,23 +158,30 @@ int coroutine_fn v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp,
if (err < 0) {
err = -errno;
} else {
- v9fs_path_init(&path);
err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
if (!err) {
err = s->ops->lstat(&s->ctx, &path, stbuf);
if (err < 0) {
err = -errno;
s->ops->close(&s->ctx, &fidp->fs);
- } else {
- v9fs_path_copy(&fidp->path, &path);
}
} else {
s->ops->close(&s->ctx, &fidp->fs);
}
- v9fs_path_free(&path);
}
});
+ /*
+ * The fid path must not be mutated from the worker thread: other
+ * requests may access the same fid on the main thread, and the main
+ * thread never takes the path lock for reads. Mutate the new path
+ * here, on the main thread and still under the held write lock, like
+ * every other mutation of a fid path.
+ */
+ if (!err) {
+ v9fs_path_copy(&fidp->path, &path);
+ }
v9fs_path_unlock(s);
+ v9fs_path_free(&path);
if (!err) {
total_open_fd++;
if (total_open_fd > open_fd_hw) {
--
2.47.3
On Monday, 21 September 2026 14:18:58 CEST Christian Schoenebeck wrote:
> v9fs_co_open2() is the only code that mutates a FID path from a worker
> thread: inside its v9fs_co_run_in_worker() block it frees fidp->path
> and copies in the new path under the held FID path write lock.
>
> Every other FID path mutation in the 9p codebase happens on the main
> thread, so main thread readers (v9fs_walk(), v9fs_xattrwalk(),
> v9fs_stat(), v9fs_co_name_to_path()) rely on the same (main) thread
> atomicity and don't take the path read lock themselves on main thread.
>
> Fix this by making the worker thread block in v9fs_co_open2() read-only
> with respect to the FID: render the new path into the local 'path'
> variable only and copy it to fidp->path after the worker block returned
> back to the main thread and still under the held write lock of the FID,
> like every other FID path mutation does.
>
> Fixes: 02cb7f3a25 ("hw/9pfs: Use read-write lock for protecting fid path.")
> Fixes: CVE-2026-93834
> Reported-by: Milad Nasr <https://gitlab.com/sirkhezr>
> Suggested-by: Milad Nasr <https://gitlab.com/sirkhezr>
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4491
> Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> ---
> hw/9pfs/cofile.c | 20 ++++++++++++++------
> 1 file changed, 14 insertions(+), 6 deletions(-)
Queued on 9p.next:
https://github.com/cschoenebeck/qemu/commits/9p.next
Thanks!
/Christian
On Mon, 21 Sep 2026 14:18:58 +0200
Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:
> v9fs_co_open2() is the only code that mutates a FID path from a worker
> thread: inside its v9fs_co_run_in_worker() block it frees fidp->path
> and copies in the new path under the held FID path write lock.
>
> Every other FID path mutation in the 9p codebase happens on the main
> thread, so main thread readers (v9fs_walk(), v9fs_xattrwalk(),
> v9fs_stat(), v9fs_co_name_to_path()) rely on the same (main) thread
> atomicity and don't take the path read lock themselves on main thread.
>
> Fix this by making the worker thread block in v9fs_co_open2() read-only
> with respect to the FID: render the new path into the local 'path'
> variable only and copy it to fidp->path after the worker block returned
> back to the main thread and still under the held write lock of the FID,
> like every other FID path mutation does.
>
> Fixes: 02cb7f3a25 ("hw/9pfs: Use read-write lock for protecting fid path.")
Wow, it's a long standing issue ! ;-)
> Fixes: CVE-2026-93834
Cannot find it... embargoed ?
> Reported-by: Milad Nasr <https://gitlab.com/sirkhezr>
> Suggested-by: Milad Nasr <https://gitlab.com/sirkhezr>
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4491
Cannot find that either...
> Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> ---
but fix looks good.
Reviewed-by: Greg Kurz <groug@kaod.org>
> hw/9pfs/cofile.c | 20 ++++++++++++++------
> 1 file changed, 14 insertions(+), 6 deletions(-)
>
> diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
> index 6e775c8e41..27fe5bfb20 100644
> --- a/hw/9pfs/cofile.c
> +++ b/hw/9pfs/cofile.c
> @@ -144,10 +144,11 @@ int coroutine_fn v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp,
> cred.fc_mode = mode & 07777;
> cred.fc_uid = fidp->uid;
> cred.fc_gid = gid;
> + v9fs_path_init(&path);
> /*
> * Hold the directory fid lock so that directory path name
> - * don't change. Take the write lock to be sure this fid
> - * cannot be used by another operation.
> + * don't change. Take the write lock since the fid path is
> + * mutated below on success.
> */
> v9fs_path_write_lock(s);
> v9fs_co_run_in_worker(
> @@ -157,23 +158,30 @@ int coroutine_fn v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp,
> if (err < 0) {
> err = -errno;
> } else {
> - v9fs_path_init(&path);
> err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
> if (!err) {
> err = s->ops->lstat(&s->ctx, &path, stbuf);
> if (err < 0) {
> err = -errno;
> s->ops->close(&s->ctx, &fidp->fs);
> - } else {
> - v9fs_path_copy(&fidp->path, &path);
> }
> } else {
> s->ops->close(&s->ctx, &fidp->fs);
> }
> - v9fs_path_free(&path);
> }
> });
> + /*
> + * The fid path must not be mutated from the worker thread: other
> + * requests may access the same fid on the main thread, and the main
> + * thread never takes the path lock for reads. Mutate the new path
> + * here, on the main thread and still under the held write lock, like
> + * every other mutation of a fid path.
> + */
> + if (!err) {
> + v9fs_path_copy(&fidp->path, &path);
> + }
> v9fs_path_unlock(s);
> + v9fs_path_free(&path);
> if (!err) {
> total_open_fd++;
> if (total_open_fd > open_fd_hw) {
--
Greg
On Tue, Sep 22, 2026 at 08:13:01AM +0200, Greg Kurz wrote:
> On Mon, 21 Sep 2026 14:18:58 +0200
> Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:
>
> > v9fs_co_open2() is the only code that mutates a FID path from a worker
> > thread: inside its v9fs_co_run_in_worker() block it frees fidp->path
> > and copies in the new path under the held FID path write lock.
> >
> > Every other FID path mutation in the 9p codebase happens on the main
> > thread, so main thread readers (v9fs_walk(), v9fs_xattrwalk(),
> > v9fs_stat(), v9fs_co_name_to_path()) rely on the same (main) thread
> > atomicity and don't take the path read lock themselves on main thread.
> >
> > Fix this by making the worker thread block in v9fs_co_open2() read-only
> > with respect to the FID: render the new path into the local 'path'
> > variable only and copy it to fidp->path after the worker block returned
> > back to the main thread and still under the held write lock of the FID,
> > like every other FID path mutation does.
> >
> > Fixes: 02cb7f3a25 ("hw/9pfs: Use read-write lock for protecting fid path.")
>
> Wow, it's a long standing issue ! ;-)
>
> > Fixes: CVE-2026-93834
>
> Cannot find it... embargoed ?
>
> > Reported-by: Milad Nasr <https://gitlab.com/sirkhezr>
> > Suggested-by: Milad Nasr <https://gitlab.com/sirkhezr>
> > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4491
>
> Cannot find that either...
Initially confidential, so only visible to maintainers with acccounts
added to the gitlab project. Bugs should be made public when their
patch is posted for review, so I've turned off the confidential flag
now.
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
On Tuesday, 22 September 2026 14:30:53 CEST Daniel P. Berrangé wrote:
> On Tue, Sep 22, 2026 at 08:13:01AM +0200, Greg Kurz wrote:
> > On Mon, 21 Sep 2026 14:18:58 +0200
> >
> > Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:
> > > v9fs_co_open2() is the only code that mutates a FID path from a worker
> > > thread: inside its v9fs_co_run_in_worker() block it frees fidp->path
> > > and copies in the new path under the held FID path write lock.
> > >
> > > Every other FID path mutation in the 9p codebase happens on the main
> > > thread, so main thread readers (v9fs_walk(), v9fs_xattrwalk(),
> > > v9fs_stat(), v9fs_co_name_to_path()) rely on the same (main) thread
> > > atomicity and don't take the path read lock themselves on main thread.
> > >
> > > Fix this by making the worker thread block in v9fs_co_open2() read-only
> > > with respect to the FID: render the new path into the local 'path'
> > > variable only and copy it to fidp->path after the worker block returned
> > > back to the main thread and still under the held write lock of the FID,
> > > like every other FID path mutation does.
> > >
> > > Fixes: 02cb7f3a25 ("hw/9pfs: Use read-write lock for protecting fid
> > > path.")
> >
> > Wow, it's a long standing issue ! ;-)
> >
> > > Fixes: CVE-2026-93834
> >
> > Cannot find it... embargoed ?
> >
> > > Reported-by: Milad Nasr <https://gitlab.com/sirkhezr>
> > > Suggested-by: Milad Nasr <https://gitlab.com/sirkhezr>
> > > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4491
> >
> > Cannot find that either...
>
> Initially confidential, so only visible to maintainers with acccounts
> added to the gitlab project. Bugs should be made public when their
> patch is posted for review, so I've turned off the confidential flag
> now.
Strange policies. I would have:
- Added Greg (reviewer and previous 9p maintainer for years) to the report
while it was still private. Instead I am the only one getting LLM generated
security reports thrown at me.
- Considering the severeness of the vulnerability, I would have waited for the
patch been pushed through stable branches before making the full report
public, or at least until merged on git.
/Christian
On Tue, Sep 22, 2026 at 05:10:58PM +0200, Christian Schoenebeck wrote:
> On Tuesday, 22 September 2026 14:30:53 CEST Daniel P. Berrangé wrote:
> > On Tue, Sep 22, 2026 at 08:13:01AM +0200, Greg Kurz wrote:
> > > On Mon, 21 Sep 2026 14:18:58 +0200
> > >
> > > Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:
> > > > v9fs_co_open2() is the only code that mutates a FID path from a worker
> > > > thread: inside its v9fs_co_run_in_worker() block it frees fidp->path
> > > > and copies in the new path under the held FID path write lock.
> > > >
> > > > Every other FID path mutation in the 9p codebase happens on the main
> > > > thread, so main thread readers (v9fs_walk(), v9fs_xattrwalk(),
> > > > v9fs_stat(), v9fs_co_name_to_path()) rely on the same (main) thread
> > > > atomicity and don't take the path read lock themselves on main thread.
> > > >
> > > > Fix this by making the worker thread block in v9fs_co_open2() read-only
> > > > with respect to the FID: render the new path into the local 'path'
> > > > variable only and copy it to fidp->path after the worker block returned
> > > > back to the main thread and still under the held write lock of the FID,
> > > > like every other FID path mutation does.
> > > >
> > > > Fixes: 02cb7f3a25 ("hw/9pfs: Use read-write lock for protecting fid
> > > > path.")
> > >
> > > Wow, it's a long standing issue ! ;-)
> > >
> > > > Fixes: CVE-2026-93834
> > >
> > > Cannot find it... embargoed ?
> > >
> > > > Reported-by: Milad Nasr <https://gitlab.com/sirkhezr>
> > > > Suggested-by: Milad Nasr <https://gitlab.com/sirkhezr>
> > > > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4491
> > >
> > > Cannot find that either...
> >
> > Initially confidential, so only visible to maintainers with acccounts
> > added to the gitlab project. Bugs should be made public when their
> > patch is posted for review, so I've turned off the confidential flag
> > now.
>
> Strange policies. I would have:
>
> - Added Greg (reviewer and previous 9p maintainer for years) to the report
> while it was still private. Instead I am the only one getting LLM generated
> security reports thrown at me.
While we primarily only intend to add people in the MAINTAINERS file
to the gitlab project, given Greg's long term involvement in QEMU I
see no problem with adding him as a member in gitlab, which would
allow for viewing all confidential bugs.
Greg, just ask one of the project owners listed:
https://gitlab.com/qemu-project/qemu/-/project_members?max_role=static-50
to add your gitlab account
> - Considering the severeness of the vulnerability, I would have waited for the
> patch been pushed through stable branches before making the full report
> public, or at least until merged on git.
Once a patch is posted on the public mailing list, we consider the
flaw to be public. Both the code and patch description provide
sufficient info about the flaw that keeping the bug private is a
false sense of protection. So it is documented that the confidential
flag is to be removed when posting to qemu-devel:
https://www.qemu.org/contribute/security-process/
If a maintainer really wants additional code review before a bug is
made public, then best to do that via private email, or the issue
tracker, as best fits the situation.
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
On Wednesday, 23 September 2026 10:15:04 CEST Daniel P. Berrangé wrote:
> On Tue, Sep 22, 2026 at 05:10:58PM +0200, Christian Schoenebeck wrote:
> > On Tuesday, 22 September 2026 14:30:53 CEST Daniel P. Berrangé wrote:
> > > On Tue, Sep 22, 2026 at 08:13:01AM +0200, Greg Kurz wrote:
> > > > On Mon, 21 Sep 2026 14:18:58 +0200
> > > >
> > > > Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:
> > > > > v9fs_co_open2() is the only code that mutates a FID path from a
> > > > > worker
> > > > > thread: inside its v9fs_co_run_in_worker() block it frees fidp->path
> > > > > and copies in the new path under the held FID path write lock.
> > > > >
> > > > > Every other FID path mutation in the 9p codebase happens on the main
> > > > > thread, so main thread readers (v9fs_walk(), v9fs_xattrwalk(),
> > > > > v9fs_stat(), v9fs_co_name_to_path()) rely on the same (main) thread
> > > > > atomicity and don't take the path read lock themselves on main
> > > > > thread.
> > > > >
> > > > > Fix this by making the worker thread block in v9fs_co_open2()
> > > > > read-only
> > > > > with respect to the FID: render the new path into the local 'path'
> > > > > variable only and copy it to fidp->path after the worker block
> > > > > returned
> > > > > back to the main thread and still under the held write lock of the
> > > > > FID,
> > > > > like every other FID path mutation does.
> > > > >
> > > > > Fixes: 02cb7f3a25 ("hw/9pfs: Use read-write lock for protecting fid
> > > > > path.")
> > > >
> > > > Wow, it's a long standing issue ! ;-)
> > > >
> > > > > Fixes: CVE-2026-93834
> > > >
> > > > Cannot find it... embargoed ?
> > > >
> > > > > Reported-by: Milad Nasr <https://gitlab.com/sirkhezr>
> > > > > Suggested-by: Milad Nasr <https://gitlab.com/sirkhezr>
> > > > > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4491
> > > >
> > > > Cannot find that either...
> > >
> > > Initially confidential, so only visible to maintainers with acccounts
> > > added to the gitlab project. Bugs should be made public when their
> > > patch is posted for review, so I've turned off the confidential flag
> > > now.
> >
> > Strange policies. I would have:
> >
> > - Added Greg (reviewer and previous 9p maintainer for years) to the report
> > while it was still private. Instead I am the only one getting LLM
> > generated
> > security reports thrown at me.
>
> While we primarily only intend to add people in the MAINTAINERS file
> to the gitlab project, given Greg's long term involvement in QEMU I
> see no problem with adding him as a member in gitlab, which would
> allow for viewing all confidential bugs.
>
> Greg, just ask one of the project owners listed:
>
> https://gitlab.com/qemu-project/qemu/-/project_members?max_role=static-50
>
> to add your gitlab account
>
> > - Considering the severeness of the vulnerability, I would have waited for
> > the patch been pushed through stable branches before making the full
> > report public, or at least until merged on git.
>
> Once a patch is posted on the public mailing list, we consider the
> flaw to be public. Both the code and patch description provide
> sufficient info about the flaw that keeping the bug private is a
> false sense of protection. So it is documented that the confidential
> flag is to be removed when posting to qemu-devel:
>
> https://www.qemu.org/contribute/security-process/
>
> If a maintainer really wants additional code review before a bug is
> made public, then best to do that via private email, or the issue
> tracker, as best fits the situation.
1. I explicitly *asked* on the private security report how to proceed and
emphasized the question under the circumstance of its severeness, and was told
to send the patch to public qemu-devel.
2. The patch alone neither exposes the severeness class, nor how to exploit.
Making the security report public OTOH provides anybody a turn-key solution
for existing production distributions, before these distros had any chance to
patch.
3. It is not trivial to generate a working exploit from the patch alone, as it
requires deep understanding of the target system's memory layout to construct
a working exploit. Many LLMS probably fail on that task. Would be interesting
to know from Milad Nasr how long the (supposedly frontier) LLM took to
construct the working exploits, but I guess it still took a while.
4. Current embargo policy says:
"Thus the QEMU maintainers will generally reject requests for arbitrary
embargoes unless high severity, extenuating circumstances can be
demonstrated."
-> It *was* high severity.
5. This rather relaxed handling, does not match with the very strict policy
OTOTH of denying official reviewers access to private security reports.
/Christian
On Tuesday, 22 September 2026 17:10:58 CEST Christian Schoenebeck wrote:
> On Tuesday, 22 September 2026 14:30:53 CEST Daniel P. Berrangé wrote:
> > On Tue, Sep 22, 2026 at 08:13:01AM +0200, Greg Kurz wrote:
> > > On Mon, 21 Sep 2026 14:18:58 +0200
> > >
> > > Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:
> > > > v9fs_co_open2() is the only code that mutates a FID path from a worker
> > > > thread: inside its v9fs_co_run_in_worker() block it frees fidp->path
> > > > and copies in the new path under the held FID path write lock.
> > > >
> > > > Every other FID path mutation in the 9p codebase happens on the main
> > > > thread, so main thread readers (v9fs_walk(), v9fs_xattrwalk(),
> > > > v9fs_stat(), v9fs_co_name_to_path()) rely on the same (main) thread
> > > > atomicity and don't take the path read lock themselves on main thread.
> > > >
> > > > Fix this by making the worker thread block in v9fs_co_open2()
> > > > read-only
> > > > with respect to the FID: render the new path into the local 'path'
> > > > variable only and copy it to fidp->path after the worker block
> > > > returned
> > > > back to the main thread and still under the held write lock of the
> > > > FID,
> > > > like every other FID path mutation does.
> > > >
> > > > Fixes: 02cb7f3a25 ("hw/9pfs: Use read-write lock for protecting fid
> > > > path.")
> > >
> > > Wow, it's a long standing issue ! ;-)
> > >
> > > > Fixes: CVE-2026-93834
> > >
> > > Cannot find it... embargoed ?
> > >
> > > > Reported-by: Milad Nasr <https://gitlab.com/sirkhezr>
> > > > Suggested-by: Milad Nasr <https://gitlab.com/sirkhezr>
> > > > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4491
> > >
> > > Cannot find that either...
> >
> > Initially confidential, so only visible to maintainers with acccounts
> > added to the gitlab project. Bugs should be made public when their
> > patch is posted for review, so I've turned off the confidential flag
> > now.
>
> Strange policies. I would have:
>
> - Added Greg (reviewer and previous 9p maintainer for years) to the report
> while it was still private. Instead I am the only one getting LLM generated
> security reports thrown at me.
>
> - Considering the severeness of the vulnerability, I would have waited for
> the patch been pushed through stable branches before making the full report
> public, or at least until merged on git.
CC-ing Peter Maydell for clarification on these QEMU policies:
Peter, context: this vulnerability was an unprivileged guest user sandbox
escape combined with arbitrary code execution on host.
/Christian
© 2016 - 2026 Red Hat, Inc.