@samitouri / QOSamiQemu / commits / 198627807a

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>

Christian Schoenebeck committed May 18, 2026 at 19:36 UTC 198627807a6b94e2aab157cf345f98edb1ac1a7a
1 file changed +69
tests/qtest/virtio-9p-test.c
+69
@@ -14,6 +14,7 @@
14
15 #include "qemu/osdep.h"
16 #include "qemu/module.h"
17 +#include "libqos/virtio.h"
18 #include "libqos/virtio-9p-client.h"
19
20 #define twalk(...) v9fs_twalk((TWalkOpt) __VA_ARGS__)
@@ -752,6 +753,72 @@ static void fs_use_after_unlink(void *obj, void *data,
753 g_assert_cmpint(attr.size, ==, 2001);
754 }
755
756 +/* https://gitlab.com/qemu-project/qemu/-/issues/3358 */
757 +static void fs_deep_absolute_path(void *obj, void *data,
758 + QGuestAllocator *t_alloc)
759 +{
760 + QVirtio9P *v9p = obj;
761 + v9fs_set_allocator(t_alloc);
762 +
763 + if (!g_test_slow()) {
764 + g_test_skip("This is a slow test, run with -m slow");
765 + return;
766 + }
767 +
768 + GString *path = g_string_new("/");
769 + char name[256];
770 + uint32_t current_fid = 0;
771 +
772 + tattach({ .client = v9p });
773 +
774 + /* Create deep directory structure until absolute path length
775 + * exceeds 16-bit range.
776 + */
777 + while (path->len <= 65536) {
778 + /* use 255-byte name (NAME_MAX) to reduce iterations to ~257 */
779 + memset(name, 'A', 255);
780 + name[255] = '\0';
781 +
782 + /* create the directory relative to current FID */
783 + tmkdir({
784 + .client = v9p,
785 + .dfid = current_fid,
786 + .name = name
787 + });
788 +
789 + /* just for locally tracking the current path length */
790 + g_string_append(path, name);
791 + g_string_append(path, "/");
792 +
793 + /* acquire new FID for the newly created directory */
794 + char *wnames[] = { name };
795 + current_fid = twalk({
796 + .client = v9p,
797 + .fid = current_fid,
798 + .nwname = 1,
799 + .wnames = wnames
800 + }).newfid;
801 +
802 + /* Reset descriptor pool to avoid exhaustion. The simplified
803 + * virtio test driver does never free descriptors back to the pool
804 + * after use, so we must manually reset it for the required high
805 + * amount of 9p requests here.
806 + */
807 + qvirtqueue_reset_pool(v9p->vq);
808 + }
809 +
810 + /* check if the deepest directory is accessible */
811 + v9fs_attr attr = {};
812 + tgetattr({
813 + .client = v9p,
814 + .fid = current_fid,
815 + .request_mask = P9_GETATTR_BASIC,
816 + .rgetattr.attr = &attr
817 + });
818 +
819 + g_string_free(path, TRUE);
820 +}
821 +
822 static void cleanup_9p_local_driver(void *data)
823 {
824 /* remove previously created test dir when test is completed */
@@ -819,6 +886,8 @@ static void register_virtio_9p_test(void)
886 &opts);
887 qos_add_test("local/use_after_unlink", "virtio-9p", fs_use_after_unlink,
888 &opts);
889 + qos_add_test("local/deep_absolute_path", "virtio-9p",
890 + fs_deep_absolute_path, &opts);
891 }
892
893 libqos_init(register_virtio_9p_test);