Skip to content

Commit 5f590d4

Browse files
cschoenebeckMichael Tokarev
authored andcommitted
9pfs: fix crash on 'Treaddir' request
A bad (broken or malicious) 9p client (guest) could cause QEMU host to crash by sending a 9p 'Treaddir' request with a numeric file ID (FID) that was previously opened for a file instead of an expected directory: #0 0x0000762aff8f4919 in __GI___rewinddir (dirp=0xf) at ../sysdeps/unix/sysv/linux/rewinddir.c:29 #1 0x0000557b7625fb40 in do_readdir_many (pdu=0x557bb67d2eb0, fidp=0x557bb67955b0, entries=0x762afe9fff58, offset=0, maxsize=131072, dostat=<optimized out>) at ../hw/9pfs/codir.c:101 #2 v9fs_co_readdir_many (pdu=pdu@entry=0x557bb67d2eb0, fidp=fidp@entry=0x557bb67955b0, entries=entries@entry=0x762afe9fff58, offset=0, maxsize=131072, dostat=false) at ../hw/9pfs/codir.c:226 #3 0x0000557b7625c1f9 in v9fs_do_readdir (pdu=0x557bb67d2eb0, fidp=0x557bb67955b0, offset=<optimized out>, max_count=<optimized out>) at ../hw/9pfs/9p.c:2488 #4 v9fs_readdir (opaque=0x557bb67d2eb0) at ../hw/9pfs/9p.c:2602 That's because V9fsFidOpenState was declared as union type. So the same memory region is used for either an open POSIX file handle (int), or a POSIX DIR* pointer, etc., so 9p server incorrectly used the previously opened (valid) POSIX file handle (0xf) as DIR* pointer, eventually causing a crash in glibc's rewinddir() function. Root cause was therefore a missing check in 9p server's 'Treaddir' request handler, which must ensure that the client supplied FID was really opened as directory stream before trying to access the aforementioned union and its DIR* member. Cc: qemu-stable@nongnu.org Fixes: d62dbb5 ("virtio-9p: Add fidtype so that we can do type ...") Reported-by: Akihiro Suda <suda.kyoto@gmail.com> Tested-by: Akihiro Suda <suda.kyoto@gmail.com> Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com> Reviewed-by: Greg Kurz <groug@kaod.org> Message-Id: <E1t8GnN-002RS8-E2@kylie.crudebyte.com> (cherry picked from commit 042b4eb) Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
1 parent 1bb5f8d commit 5f590d4

1 file changed

Lines changed: 5 additions & 0 deletions

File tree

hw/9pfs/9p.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2587,6 +2587,11 @@ static void coroutine_fn v9fs_readdir(void *opaque)
25872587
retval = -EINVAL;
25882588
goto out_nofid;
25892589
}
2590+
if (fidp->fid_type != P9_FID_DIR) {
2591+
warn_report_once("9p: bad client: T_readdir on non-directory stream");
2592+
retval = -ENOTDIR;
2593+
goto out;
2594+
}
25902595
if (!fidp->fs.dir.stream) {
25912596
retval = -EINVAL;
25922597
goto out;

0 commit comments

Comments
 (0)