Skip to content

Commit 5f590d4

Browse files
cschoenebeckMichael Tokarev
authored and
Michael Tokarev
committed
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: [email protected] Fixes: d62dbb5 ("virtio-9p: Add fidtype so that we can do type ...") Reported-by: Akihiro Suda <[email protected]> Tested-by: Akihiro Suda <[email protected]> Signed-off-by: Christian Schoenebeck <[email protected]> Reviewed-by: Greg Kurz <[email protected]> Message-Id: <[email protected]> (cherry picked from commit 042b4eb) Signed-off-by: Michael Tokarev <[email protected]>
1 parent 1bb5f8d commit 5f590d4

File tree

1 file changed

+5
-0
lines changed

1 file changed

+5
-0
lines changed

hw/9pfs/9p.c

+5
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)