qemu/linux-user
Laurent Vivier 7d61d89232 linux-user: fix netlink memory corruption
Netlink is byte-swapping data in the guest memory (it's bad).

It's ok when the data come from the host as they are generated by the
host.

But it doesn't work when data come from the guest: the guest can
try to reuse these data whereas they have been byte-swapped.

This is what happens in glibc:

glibc generates a sequence number in nlh.nlmsg_seq and calls
sendto() with this nlh. In sendto(), we byte-swap nlmsg.seq.

Later, after the recvmsg(), glibc compares nlh.nlmsg_seq with
sequence number given in return, and of course it fails (hangs),
because nlh.nlmsg_seq is not valid anymore.

The involved code in glibc is:

sysdeps/unix/sysv/linux/check_pf.c:make_request()
...
  req.nlh.nlmsg_seq = time (NULL);
...
  if (TEMP_FAILURE_RETRY (__sendto (fd, (void *) &req, sizeof (req), 0,
                                    (struct sockaddr *) &nladdr,
                                    sizeof (nladdr))) < 0)
<here req.nlh.nlmsg_seq has been byte-swapped>
...
  do
    {
...
      ssize_t read_len = TEMP_FAILURE_RETRY (__recvmsg (fd, &msg, 0));
...
      struct nlmsghdr *nlmh;
      for (nlmh = (struct nlmsghdr *) buf;
           NLMSG_OK (nlmh, (size_t) read_len);
           nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, read_len))
        {
<we compare nlmh->nlmsg_seq with corrupted req.nlh.nlmsg_seq>
          if (nladdr.nl_pid != 0 || (pid_t) nlmh->nlmsg_pid != pid
              || nlmh->nlmsg_seq != req.nlh.nlmsg_seq)
            continue;
...
          else if (nlmh->nlmsg_type == NLMSG_DONE)
            /* We found the end, leave the loop.  */
            done = true;
        }
    }
  while (! done);

As we have a continue on "nlmh->nlmsg_seq != req.nlh.nlmsg_seq",
"done" cannot be set to "true" and we have an infinite loop.

It's why commands like "apt-get update" or "dnf update hangs".

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
2016-07-19 15:20:59 +03:00
..
aarch64 linux-user: Clean up target_structs.h header guards 2016-07-12 16:19:16 +02:00
alpha linux-user: Clean up target_structs.h header guards 2016-07-12 16:19:16 +02:00
arm Clean up ill-advised or unusual header guards 2016-07-12 16:20:46 +02:00
cris linux-user: Clean up target_structs.h header guards 2016-07-12 16:19:16 +02:00
host linux-user: Clean up hostdep.h header guards 2016-07-12 16:19:16 +02:00
i386 linux-user: Clean up target_structs.h header guards 2016-07-12 16:19:16 +02:00
m68k linux-user: Clean up target_structs.h header guards 2016-07-12 16:19:16 +02:00
microblaze linux-user: Clean up target_structs.h header guards 2016-07-12 16:19:16 +02:00
mips linux-user: Clean up target_structs.h header guards 2016-07-12 16:19:16 +02:00
mips64 linux-user: Clean up target_signal.h header guards 2016-07-12 16:19:16 +02:00
openrisc linux-user: Clean up target_structs.h header guards 2016-07-12 16:19:16 +02:00
ppc linux-user: Clean up target_structs.h header guards 2016-07-12 16:19:16 +02:00
s390x linux-user: Clean up target_structs.h header guards 2016-07-12 16:19:16 +02:00
sh4 linux-user: Clean up target_structs.h header guards 2016-07-12 16:19:16 +02:00
sparc linux-user: Clean up target_structs.h header guards 2016-07-12 16:19:16 +02:00
sparc64 linux-user: Clean up target_structs.h header guards 2016-07-12 16:19:16 +02:00
tilegx Clean up ill-advised or unusual header guards 2016-07-12 16:20:46 +02:00
unicore32 linux-user: Clean up target_structs.h header guards 2016-07-12 16:19:16 +02:00
x86_64 linux-user: Clean up target_structs.h header guards 2016-07-12 16:19:16 +02:00
elfload.c os-posix: include sys/mman.h 2016-06-16 18:39:03 +02:00
errno_defs.h linux-user: Renumber TARGET_QEMU_ESIGRETURN, make it not arch-specific 2016-05-27 14:49:49 +03:00
flat.h Support for 32 bit ABI on 64 bit targets (only enabled Sparc64) 2007-10-14 16:27:31 +00:00
flatload.c Use #include "..." for our own headers, <...> for others 2016-07-12 16:19:16 +02:00
ioctls.h linux-user: Convert blkpg to use a special subop handler 2014-10-06 21:52:45 +03:00
linux_loop.h Clean up ill-advised or unusual header guards 2016-07-12 16:20:46 +02:00
linuxload.c linux-user: Clean up includes 2016-01-29 15:07:22 +00:00
m68k-sim.c linux-user: Clean up includes 2016-01-29 15:07:22 +00:00
main.c trace: Add per-vCPU tracing states for events with the 'vcpu' property 2016-07-18 18:23:12 +01:00
Makefile.objs linux-user: Provide safe_syscall for fixing races between signals and syscalls 2016-05-27 14:49:51 +03:00
mmap.c os-posix: include sys/mman.h 2016-06-16 18:39:03 +02:00
qemu.h linux-user: Make semihosting heap/stack fields abi_ulongs 2016-07-04 13:06:35 +01:00
safe-syscall.S linux-user: Provide safe_syscall for fixing races between signals and syscalls 2016-05-27 14:49:51 +03:00
signal.c linux-user: Don't use sigfillset() on uc->uc_sigmask 2016-06-26 13:17:20 +03:00
socket.h linux-user: support SO_PASSSEC setsockopt option 2014-06-29 14:19:59 +03:00
strace.c linux-user: fix clone() strace 2016-06-26 13:17:21 +03:00
strace.list linux-user: update get_thread_area/set_thread_area strace 2016-06-26 13:17:21 +03:00
syscall.c linux-user: fix netlink memory corruption 2016-07-19 15:20:59 +03:00
syscall_defs.h linux-user: Fix broken header guard in syscall_defs.h 2016-07-12 16:19:16 +02:00
syscall_types.h linux-user: Convert blkpg to use a special subop handler 2014-10-06 21:52:45 +03:00
target_flat.h linux-user/FLAT: allow targets to override FLAT processing 2011-02-09 10:33:54 +02:00
trace-events trace: split out trace events for linux-user/ directory 2016-06-20 17:22:17 +01:00
uaccess.c util: move declarations out of qemu-common.h 2016-03-22 22:20:17 +01:00
uname.c linux-user: Clean up includes 2016-01-29 15:07:22 +00:00
uname.h Clean up decorations and whitespace around header guards 2016-07-12 16:20:46 +02:00
vm86.c linux-user: Clean up includes 2016-01-29 15:07:22 +00:00