Commit 198627807a for qemu.org
commit 198627807a6b94e2aab157cf345f98edb1ac1a7a
Author: Christian Schoenebeck <qemu_oss@crudebyte.com>
Date: Mon May 18 19:36:03 2026 +0200
tests/9pfs: add deep absolute path test
Add fs_deep_absolute_path test that creates a deep directory
structure with an absolute path length exceeding 16-bit range
(i.e. >65536) to verify the previous buffer overflow fix.
This is a slow test (may take several seconds) and therefore
registered as "slow" test and not running by default.
Use -m slow to run this test.
Link: https://gitlab.com/qemu-project/qemu/-/issues/3358
Link: https://lore.kernel.org/qemu-devel/933552b2cfc2c442fac7f4e68c777dce20ee8d7e.1779126034.git.qemu_oss@crudebyte.com
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c
index ac38ccf595..1c69d41e33 100644
--- a/tests/qtest/virtio-9p-test.c
+++ b/tests/qtest/virtio-9p-test.c
@@ -14,6 +14,7 @@
#include "qemu/osdep.h"
#include "qemu/module.h"
+#include "libqos/virtio.h"
#include "libqos/virtio-9p-client.h"
#define twalk(...) v9fs_twalk((TWalkOpt) __VA_ARGS__)
@@ -752,6 +753,72 @@ static void fs_use_after_unlink(void *obj, void *data,
g_assert_cmpint(attr.size, ==, 2001);
}
+/* https://gitlab.com/qemu-project/qemu/-/issues/3358 */
+static void fs_deep_absolute_path(void *obj, void *data,
+ QGuestAllocator *t_alloc)
+{
+ QVirtio9P *v9p = obj;
+ v9fs_set_allocator(t_alloc);
+
+ if (!g_test_slow()) {
+ g_test_skip("This is a slow test, run with -m slow");
+ return;
+ }
+
+ GString *path = g_string_new("/");
+ char name[256];
+ uint32_t current_fid = 0;
+
+ tattach({ .client = v9p });
+
+ /* Create deep directory structure until absolute path length
+ * exceeds 16-bit range.
+ */
+ while (path->len <= 65536) {
+ /* use 255-byte name (NAME_MAX) to reduce iterations to ~257 */
+ memset(name, 'A', 255);
+ name[255] = '\0';
+
+ /* create the directory relative to current FID */
+ tmkdir({
+ .client = v9p,
+ .dfid = current_fid,
+ .name = name
+ });
+
+ /* just for locally tracking the current path length */
+ g_string_append(path, name);
+ g_string_append(path, "/");
+
+ /* acquire new FID for the newly created directory */
+ char *wnames[] = { name };
+ current_fid = twalk({
+ .client = v9p,
+ .fid = current_fid,
+ .nwname = 1,
+ .wnames = wnames
+ }).newfid;
+
+ /* Reset descriptor pool to avoid exhaustion. The simplified
+ * virtio test driver does never free descriptors back to the pool
+ * after use, so we must manually reset it for the required high
+ * amount of 9p requests here.
+ */
+ qvirtqueue_reset_pool(v9p->vq);
+ }
+
+ /* check if the deepest directory is accessible */
+ v9fs_attr attr = {};
+ tgetattr({
+ .client = v9p,
+ .fid = current_fid,
+ .request_mask = P9_GETATTR_BASIC,
+ .rgetattr.attr = &attr
+ });
+
+ g_string_free(path, TRUE);
+}
+
static void cleanup_9p_local_driver(void *data)
{
/* remove previously created test dir when test is completed */
@@ -819,6 +886,8 @@ static void register_virtio_9p_test(void)
&opts);
qos_add_test("local/use_after_unlink", "virtio-9p", fs_use_after_unlink,
&opts);
+ qos_add_test("local/deep_absolute_path", "virtio-9p",
+ fs_deep_absolute_path, &opts);
}
libqos_init(register_virtio_9p_test);