On Montag, 6. Januar 2020 18:49:10 CET Greg Kurz wrote: > On Mon, 06 Jan 2020 16:10:28 +0100 > > Christian Schoenebeck <qemu_...@crudebyte.com> wrote: > > On Montag, 6. Januar 2020 13:30:24 CET Greg Kurz wrote: > > > On Wed, 18 Dec 2019 14:17:59 +0100 > > > > > > Christian Schoenebeck <qemu_...@crudebyte.com> wrote: > > > > A good 9p client sends T_readdir with "count" parameter that's > > > > sufficiently smaller than client's initially negotiated msize > > > > (maximum message size). We perform a check for that though to > > > > avoid the server to be interrupted with a "Failed to encode > > > > VirtFS reply type 41" error message by bad clients. > > > > > > Hmm... doesn't v9fs_do_readdir() already take care of that ? > > > > No, unfortunately it doesn't. It just looks at the "count" parameter > > transmitted with client's T_readdir request, but not at session's msize. > > Indeed. > > > So a bad client could send a T_readdir request with a "count" parameter > > that's substantially higher than session's msize, which would lead to > > that mentioned transport error ATM. Hence I suggested this patch here to > > address it. > > > > You can easily reproduce this issue: > > > > 1. Omit this patch 2 (since it would fix it). > > > > 2. Apply patch 3 and patch 4 of this patch set, which assemble a T_readdir > > > > test case combined, then stop patches here (i.e. don't apply subsequent > > patches of this patch set, since e.g. patch 6 would increase test > > client's > > msize). > > > > 3. Set QTEST_V9FS_SYNTH_READDIR_NFILES in hw/9pfs/9p-synth.h to a high > > number> > > (e.g. several thousands). > > > > 4. Run the T_readdir test case: > > cd build > > make && make tests/qos-test > > export QTEST_QEMU_BINARY=x86_64-softmmu/qemu-system-x86_64 > > tests/qos-test -p $(tests/qos-test -l | grep readdir/basic) > > > > Result: Since the test client's msize is quite small at this point (4kB), > > test client would transmit a very large "count" parameter with T_readdir > > request to retrieve all QTEST_V9FS_SYNTH_READDIR_NFILES files, and you'll > > end up getting the quoted transport error message on server (see precise > > error message above). > > I don't observe this behavior with: > > -#define QTEST_V9FS_SYNTH_READDIR_NFILES 100 > +#define QTEST_V9FS_SYNTH_READDIR_NFILES 20000 > > /x86_64/pc/i440FX-pcihost/pci-bus-pc/pci-bus/virtio-9p-pci/virtio-9p/virtio- > 9p-tests/fs/readdir/basic: ** > ERROR:/home/greg/Work/qemu/qemu-9p/tests/virtio-9p-test.c:597:fs_readdir: > assertion failed (nentries == QTEST_V9FS_SYNTH_READDIR_NFILES + 2): (101 == > 20002) > > The server didn't hit the transport error...
Ah sorry, I forgot I had this already defused on test case side. Change this as well to reproduce it: diff --git a/hw/9pfs/9p-synth.h b/hw/9pfs/9p-synth.h index 036d7e4a5b..7d6cedcdac 100644 --- a/hw/9pfs/9p-synth.h +++ b/hw/9pfs/9p-synth.h @@ -58,7 +58,7 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode, /* for READDIR test */ #define QTEST_V9FS_SYNTH_READDIR_DIR "ReadDirDir" #define QTEST_V9FS_SYNTH_READDIR_FILE "ReadDirFile%d" -#define QTEST_V9FS_SYNTH_READDIR_NFILES 100 +#define QTEST_V9FS_SYNTH_READDIR_NFILES 2000 /* Any write to the "FLUSH" file is handled one byte at a time by the * backend. If the byte is zero, the backend returns success (ie, 1), diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c index 48c0eca292..1d49d97a83 100644 --- a/tests/virtio-9p-test.c +++ b/tests/virtio-9p-test.c @@ -586,7 +586,7 @@ static void fs_readdir(void *obj, void *data, QGuestAllocator *t_alloc) v9fs_req_wait_for_reply(req, NULL); v9fs_rlopen(req, &qid, NULL); - req = v9fs_treaddir(v9p, 1, 0, P9_MAX_SIZE - P9_IOHDRSZ, 0); + req = v9fs_treaddir(v9p, 1, 0, 900000, 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rreaddir(req, &count, &nentries, &entries); Then run the test, which leads to this error here: /x86_64/pc/i440FX-pcihost/pci-bus-pc/pci-bus/virtio-9p-pci/virtio-9p/ virtio-9p-tests/fs/readdir/basic: qemu-system-x86_64: Failed to encode VirtFS reply type 41 -> Hang. Best regards, Christian Schoenebeck