V9fsPath.size tracks the length of backend path data. Storing it in a
uint16_t truncates local backend paths longer than 65535 bytes, so later
path copies can end up much smaller than the string data they are
supposed to describe.
A guest can reach this with normal 9p filesystem operations by creating
and walking a sufficiently deep directory tree on the local backend. On
an ASan build, calling readdir() in that deep directory aborts the host
process with:
ERROR: AddressSanitizer: heap-buffer-overflow
#0 __interceptor_strrchr
#1 g_path_get_dirname
#2 local_lstat
#3 v9fs_co_lstat
#4 v9fs_getattr
Fix this by storing V9fsPath lengths in size_t.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3358
Cc: [email protected]
Signed-off-by: Jia Jia <[email protected]>
---
Runtime reproducer:
confirmed on current master (11.0.50) with an x86_64 ASan build and a
local 9p backend
guest actions:
- mount the 9p share
- create a 260-level directory tree with 255-byte names
- walk back to the deepest directory
- call readdir()
host abort:
ERROR: AddressSanitizer: heap-buffer-overflow
#0 __interceptor_strrchr
#1 g_path_get_dirname
#2 local_lstat
#3 v9fs_co_lstat
#4 v9fs_getattr
fsdev/file-op-9p.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index b85c9934def..e8d0661c4b5 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -112,7 +112,7 @@ struct FsContext {
};
struct V9fsPath {
- uint16_t size;
+ size_t size;
char *data;
};
P9ARRAY_DECLARE_TYPE(V9fsPath);
--
2.34.1