All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vitaly Chikunov <vt@altlinux.org>
To: Christian Schoenebeck <qemu_oss@crudebyte.com>
Cc: qemu-stable@nongnu.org, "Dmitry V. Levin" <ldv@altlinux.org>,
	qemu-devel@nongnu.org, Greg Kurz <groug@kaod.org>
Subject: Re: [PATCH v2] 9pfs: Fix segfault in do_readdir_many caused by struct dirent overread
Date: Thu, 3 Feb 2022 09:20:05 +0300	[thread overview]
Message-ID: <20220203062005.chsjk5bb3pftlapn@altlinux.org> (raw)
In-Reply-To: <20220203045540.3wmae6mp7cnjtzxm@altlinux.org>

On Thu, Feb 03, 2022 at 07:55:41AM +0300, Vitaly Chikunov wrote:
> Christian,
> 
> On Wed, Feb 02, 2022 at 05:55:45PM +0100, Christian Schoenebeck wrote:
> > On Freitag, 28. Januar 2022 23:33:26 CET Vitaly Chikunov wrote:
> > > `struct dirent' returned from readdir(3) could be shorter than
> > > `sizeof(struct dirent)', thus memcpy of sizeof length will overread
> > > into unallocated page causing SIGSEGV. Example stack trace:
> > > 
> > >  #0  0x00005555559ebeed v9fs_co_readdir_many (/usr/bin/qemu-system-x86_64 +
> > > 0x497eed) #1  0x00005555559ec2e9 v9fs_readdir (/usr/bin/qemu-system-x86_64
> > > + 0x4982e9) #2  0x0000555555eb7983 coroutine_trampoline
> > > (/usr/bin/qemu-system-x86_64 + 0x963983) #3  0x00007ffff73e0be0 n/a (n/a +
> > > 0x0)
> > > 
> > > While fixing, provide a helper for any future `struct dirent' cloning.
> > > 
> > > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/841
> > > Cc: qemu-stable@nongnu.org
> > > Co-authored-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> > > Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
> > > ---
> > > Tested on x86-64 Linux.
> > 
> > I was too optimistic. Looks like this needs more work. With this patch applied
> > the 9p test cases [1] are crashing now:
> > 
> > $ gdb --args tests/qtest/qos-test -m slow
> > ...
> > # Start of flush tests
> > ok 50 /x86_64/pc/i440FX-pcihost/pci-bus-pc/pci-bus/virtio-9p-pci/virtio-9p/virtio-9p-tests/synth/flush/success
> > ok 51 /x86_64/pc/i440FX-pcihost/pci-bus-pc/pci-bus/virtio-9p-pci/virtio-9p/virtio-9p-tests/synth/flush/ignored
> > # End of flush tests
> > # Start of readdir tests
> 
> I changed implementation from the one using dent->d_reclen to the one using
> strlen(dent->d_name) and it's passed readdir tests, but failed later:
> 
>   # Start of readdir tests
>   ok 53 /x86_64/pc/i440FX-pcihost/pci-bus-pc/pci-bus/virtio-9p-pci/virtio-9p/virtio-9p-tests/synth/readdir/basic
>   ok 54 /x86_64/pc/i440FX-pcihost/pci-bus-pc/pci-bus/virtio-9p-pci/virtio-9p/virtio-9p-tests/synth/readdir/split_512
>   ok 55 /x86_64/pc/i440FX-pcihost/pci-bus-pc/pci-bus/virtio-9p-pci/virtio-9p/virtio-9p-tests/synth/readdir/split_256
>   ok 56 /x86_64/pc/i440FX-pcihost/pci-bus-pc/pci-bus/virtio-9p-pci/virtio-9p/virtio-9p-tests/synth/readdir/split_128
>   # End of readdir tests
>   # End of synth tests
>   # Start of local tests
>   # starting QEMU: exec x86_64-softmmu/qemu-system-x86_64 -qtest unix:/tmp/qtest-2822967.sock -qtest-log /dev/null -chardev socket,path=/tmp/qtest-2822967.qmp,id=char0 -mon chardev=char0,mode=control -display none -M pc  -fsdev local,id=fsdev0,path='/usr/src/RPM/BUILD/qemu-6.2.0/build-dynamic/qtest-9p-local-NpcZCR',security_model=mapped-xattr -device virtio-9p-pci,fsdev=fsdev0,addr=04.0,mount_tag=qtest -accel qtest
>   # GLib-DEBUG: setenv()/putenv() are not thread-safe and should not be used after threads are created
>   ok 57 /x86_64/pc/i440FX-pcihost/pci-bus-pc/pci-bus/virtio-9p-pci/virtio-9p/virtio-9p-tests/local/config
>   Received response 7 (RLERROR) instead of 73 (RMKDIR)
>   Rlerror has errno 95 (Operation not supported)
>   **
>   ERROR:../tests/qtest/virtio-9p-test.c:305:v9fs_req_recv: assertion failed (hdr.id == id): (7 == 73)
>   Bail out! ERROR:../tests/qtest/virtio-9p-test.c:305:v9fs_req_recv: assertion failed (hdr.id == id): (7 == 73)
>   Aborted

I added some debugging output and in the bug case `d_reclen` is 0. Thus
this is not readdir's struct dirent, but something else (test-only
simulated dirent without accounting that we now have d_reclen logic).

This maybe related to the other bug in 

  static void synth_direntry(V9fsSynthNode *node,
				  struct dirent *entry, off_t off)
  {
      strcpy(entry->d_name, node->name);
      entry->d_ino = node->attr->inode;
      entry->d_off = off + 1;
  }

Where `d_reclen` is not updated.

Thanks,


> 
> Thanks,
> 
> > Broken pipe
> > 
> > Thread 1 "qos-test" received signal SIGABRT, Aborted.
> > __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
> > 50      ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
> > (gdb) bt
> > #0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
> > #1  0x00007ffff7b7d537 in __GI_abort () at abort.c:79
> > #2  0x00005555555ba495 in qtest_client_socket_recv_line (s=0x5555557663c0) at ../tests/qtest/libqtest.c:503
> > #3  0x00005555555ba5b3 in qtest_rsp_args (s=0x5555557663c0, expected_args=2) at ../tests/qtest/libqtest.c:523
> > #4  0x00005555555bbdb4 in qtest_clock_rsp (s=0x5555557663c0) at ../tests/qtest/libqtest.c:970
> > #5  0x00005555555bbe55 in qtest_clock_step (s=0x5555557663c0, step=100) at ../tests/qtest/libqtest.c:985
> > #6  0x00005555555cdc21 in qvirtio_wait_used_elem (qts=0x5555557663c0, d=0x555555779b48, vq=0x5555557b0480, desc_idx=8, len=0x0, timeout_us=10000000)
> >     at ../tests/qtest/libqos/virtio.c:220
> > #7  0x00005555555ae79f in v9fs_req_wait_for_reply (req=0x5555557899a0, len=0x0) at ../tests/qtest/virtio-9p-test.c:278
> > #8  0x00005555555b03bf in fs_readdir (obj=0x555555779bb0, data=0x0, t_alloc=0x5555557448b8) at ../tests/qtest/virtio-9p-test.c:851
> > #9  0x00005555555990c4 in run_one_test (arg=0x5555557ac600) at ../tests/qtest/qos-test.c:182
> > #10 0x00007ffff7f02b9e in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
> > #11 0x00007ffff7f0299b in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
> > #12 0x00007ffff7f0299b in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
> > #13 0x00007ffff7f0299b in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
> > #14 0x00007ffff7f0299b in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
> > #15 0x00007ffff7f0299b in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
> > #16 0x00007ffff7f0299b in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
> > #17 0x00007ffff7f0299b in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
> > #18 0x00007ffff7f0299b in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
> > #19 0x00007ffff7f0299b in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
> > #20 0x00007ffff7f0299b in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
> > #21 0x00007ffff7f0308a in g_test_run_suite () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
> > #22 0x00007ffff7f030a1 in g_test_run () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
> > #23 0x00005555555995a3 in main (argc=1, argv=0x7fffffffe508, envp=0x7fffffffe528) at ../tests/qtest/qos-test.c:338
> > (gdb)
> > 
> > [1] https://wiki.qemu.org/Documentation/9p#Test_Cases
> > 
> > Best regards,
> > Christian Schoenebeck
> > 
> > 


  reply	other threads:[~2022-02-03  6:25 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-28 22:33 [PATCH v2] 9pfs: Fix segfault in do_readdir_many caused by struct dirent overread Vitaly Chikunov
2022-01-31 13:45 ` Christian Schoenebeck
2022-02-02 16:55 ` Christian Schoenebeck
2022-02-03  4:55   ` Vitaly Chikunov
2022-02-03  6:20     ` Vitaly Chikunov [this message]
2022-02-03 12:31       ` Christian Schoenebeck
2022-02-03 12:42 ` Christian Schoenebeck
2022-02-04  0:15   ` Vitaly Chikunov
2022-02-04  0:22     ` Dmitry V. Levin
2022-02-04 12:12       ` Christian Schoenebeck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220203062005.chsjk5bb3pftlapn@altlinux.org \
    --to=vt@altlinux.org \
    --cc=groug@kaod.org \
    --cc=ldv@altlinux.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-stable@nongnu.org \
    --cc=qemu_oss@crudebyte.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.