1. 21 6月, 2018 11 次提交
  2. 22 5月, 2018 12 次提交
    • G
      spapr: register dummy ICPs later · 72cc467a
      Greg Kurz 提交于
      Some older machine types create more ICPs than needed. We hence
      need to register up to xics_max_server_number() dummy ICPs to
      accomodate the migration of these machine types.
      
      Recent VSMT rework changed xics_max_server_number() to return
      
          DIV_ROUND_UP(max_cpus * spapr->vsmt, smp_threads)
      
      instead of
      
          DIV_ROUND_UP(max_cpus * kvmppc_smt_threads(), smp_threads);
      
      The change is okay but it requires spapr->vsmt to be set, which
      isn't the case with the current code. This causes the formula to
      return zero and we don't create dummy ICPs. This breaks migration
      of older guests as reported here:
      
          https://bugzilla.redhat.com/show_bug.cgi?id=1549087
      
      The dummy ICP workaround doesn't really have a dependency on XICS
      itself. But it does depend on proper VCPU id numbering and it must
      be applied before creating vCPUs (ie, creating real ICPs). So this
      patch moves the workaround to spapr_init_cpus(), which already
      assumes VSMT to be set.
      
      Fixes: 72194664 ("spapr: use spapr->vsmt to compute VCPU ids")
      Reported-by: NLukas Doktor <ldoktor@redhat.com>
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      Signed-off-by: NDavid Gibson <david@gibson.dropbear.id.au>
      (cherry picked from commit 72fdd4de)
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      72cc467a
    • G
      spapr: fix missing CPU core nodes in DT when running with TCG · 184da186
      Greg Kurz 提交于
      Commit 5d0fb150 "spapr: consolidate the VCPU id numbering logic
      in a single place" introduced a helper to detect thread0 of a virtual
      core based on its VCPU id. This is used to create CPU core nodes in
      the DT, but it is broken in TCG.
      
      $ qemu-system-ppc64 -nographic -accel tcg -machine dumpdtb=dtb.bin \
                          -smp cores=16,maxcpus=16,threads=1
      $ dtc -f -O dts dtb.bin | grep POWER8
                      PowerPC,POWER8@0 {
                      PowerPC,POWER8@8 {
      
      instead of the expected 16 cores that we get with KVM:
      
      $ dtc -f -O dts dtb.bin | grep POWER8
                      PowerPC,POWER8@0 {
                      PowerPC,POWER8@8 {
                      PowerPC,POWER8@10 {
                      PowerPC,POWER8@18 {
                      PowerPC,POWER8@20 {
                      PowerPC,POWER8@28 {
                      PowerPC,POWER8@30 {
                      PowerPC,POWER8@38 {
                      PowerPC,POWER8@40 {
                      PowerPC,POWER8@48 {
                      PowerPC,POWER8@50 {
                      PowerPC,POWER8@58 {
                      PowerPC,POWER8@60 {
                      PowerPC,POWER8@68 {
                      PowerPC,POWER8@70 {
                      PowerPC,POWER8@78 {
      
      This happens because spapr_get_vcpu_id() maps VCPU ids to
      cs->cpu_index in TCG mode. This confuses the code in
      spapr_is_thread0_in_vcore(), since it assumes thread0 VCPU
      ids to have a spapr->vsmt spacing.
      
          spapr_get_vcpu_id(cpu) % spapr->vsmt == 0
      
      Actually, there's no real reason to expose cs->cpu_index instead
      of the VCPU id, since we also generate it with TCG. Also we already
      set it explicitly in spapr_set_vcpu_id(), so there's no real reason
      either to call kvm_arch_vcpu_id() with KVM.
      
      This patch unifies spapr_get_vcpu_id() to always return the computed
      VCPU id both in TCG and KVM. This is one step forward towards KVM<->TCG
      migration.
      
      Fixes: 5d0fb150Reported-by: NCédric Le Goater <clg@kaod.org>
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      Signed-off-by: NDavid Gibson <david@gibson.dropbear.id.au>
      (cherry picked from commit b1a568c1)
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      184da186
    • G
      spapr: consolidate the VCPU id numbering logic in a single place · e676038e
      Greg Kurz 提交于
      Several places in the code need to calculate a VCPU id:
      
          (cpu_index / smp_threads) * spapr->vsmt + cpu_index % smp_threads
          (core_id / smp_threads) * spapr->vsmt (1 user)
          index * spapr->vsmt (2 users)
      
      or guess that the VCPU id of a given VCPU is the first thread of a virtual
      core:
      
          index % spapr->vsmt != 0
      
      Even if the numbering logic isn't that complex, it is rather fragile to
      have these assumptions open-coded in several places. FWIW this was
      proved with recent issues related to VSMT.
      
      This patch moves the VCPU id formula to a single function to be called
      everywhere the code needs to compute one. It also adds an helper to
      guess if a VCPU is the first thread of a VCORE.
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      [dwg: Rename spapr_is_vcore() to spapr_is_thread0_in_vcore() for clarity]
      Signed-off-by: NDavid Gibson <david@gibson.dropbear.id.au>
      (cherry picked from commit 5d0fb150)
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      e676038e
    • G
      spapr: rename spapr_vcpu_id() to spapr_get_vcpu_id() · 094706e6
      Greg Kurz 提交于
      The spapr_vcpu_id() function is an accessor actually. Let's rename it
      for symmetry with the recently added spapr_set_vcpu_id() helper.
      
      The motivation behind this is that a later patch will consolidate
      the VCPU id formula in a function and spapr_vcpu_id looks like an
      appropriate name.
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      Signed-off-by: NDavid Gibson <david@gibson.dropbear.id.au>
      (cherry picked from commit 14bb4486)
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      094706e6
    • D
      target/ppc: Clarify compat mode max_threads value · 8c0ec3c3
      David Gibson 提交于
      We recently had some discussions that were sidetracked for a while, because
      nearly everyone misapprehended the purpose of the 'max_threads' field in
      the compatiblity modes table.  It's all about guest expectations, not host
      expectations or support (that's handled elsewhere).
      
      In an attempt to avoid a repeat of that confusion, rename the field to
      'max_vthreads' and add an explanatory comment.
      Signed-off-by: NDavid Gibson <david@gibson.dropbear.id.au>
      Reviewed-by: NLaurent Vivier <lvivier@redhat.com>
      Reviewed-by: NGreg Kurz <groug@kaod.org>
      Reviewed-by: NJose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
      (cherry picked from commit abbc1247)
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      8c0ec3c3
    • G
      spapr: move VCPU calculation to core machine code · a8074a58
      Greg Kurz 提交于
      The VCPU ids are currently computed and assigned to each individual
      CPU threads in spapr_cpu_core_realize(). But the numbering logic
      of VCPU ids is actually a machine-level concept, and many places
      in hw/ppc/spapr.c also have to compute VCPU ids out of CPU indexes.
      
      The current formula used in spapr_cpu_core_realize() is:
      
          vcpu_id = (cc->core_id * spapr->vsmt / smp_threads) + i
      
      where:
      
          cc->core_id is a multiple of smp_threads
          cpu_index = cc->core_id + i
          0 <= i < smp_threads
      
      So we have:
      
          cpu_index % smp_threads == i
          cc->core_id / smp_threads == cpu_index / smp_threads
      
      hence:
      
          vcpu_id =
              (cpu_index / smp_threads) * spapr->vsmt + cpu_index % smp_threads;
      
      This formula was used before VSMT at the time VCPU ids where computed
      at the target emulation level. It has the advantage of being useable
      to derive a VPCU id out of a CPU index only. It is fitted for all the
      places where the machine code has to compute a VCPU id.
      
      This patch introduces an accessor to set the VCPU id in a PowerPCCPU object
      using the above formula. It is a first step to consolidate all the VCPU id
      logic in a single place.
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      Signed-off-by: NDavid Gibson <david@gibson.dropbear.id.au>
      (cherry picked from commit 648edb64)
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      a8074a58
    • G
      spapr: use spapr->vsmt to compute VCPU ids · cc86c467
      Greg Kurz 提交于
      Since the introduction of VSMT in 2.11, the spacing of VCPU ids
      between cores is controllable through a machine property instead
      of being only dictated by the SMT mode of the host:
      
          cpu->vcpu_id = (cc->core_id * spapr->vsmt / smp_threads) + i
      
      Until recently, the machine code would try to change the SMT mode
      of the host to be equal to VSMT or exit. This allowed the rest of
      the code to assume that kvmppc_smt_threads() == spapr->vsmt is
      always true.
      
      Recent commit "8904e5a7 spapr: Adjust default VSMT value for
      better migration compatibility" relaxed the rule. If the VSMT
      mode cannot be set in KVM for some reasons, but the requested
      CPU topology is compatible with the current SMT mode, then we
      let the guest run with  kvmppc_smt_threads() != spapr->vsmt.
      
      This breaks quite a few places in the code, in particular when
      calculating DRC indexes.
      
      This is what happens on a POWER host with subcores-per-core=2 (ie,
      supports up to SMT4) when passing the following topology:
      
          -smp threads=4,maxcpus=16 \
          -device host-spapr-cpu-core,core-id=4,id=core1 \
          -device host-spapr-cpu-core,core-id=8,id=core2
      
      qemu-system-ppc64: warning: Failed to set KVM's VSMT mode to 8 (errno -22)
      
      This is expected since KVM is limited to SMT4, but the guest is started
      anyway because this topology can run on SMT4 even with a VSMT8 spacing.
      
      But when we look at the DT, things get nastier:
      
      cpus {
              ...
              ibm,drc-indexes = <0x4 0x10000000 0x10000004 0x10000008 0x1000000c>;
      
      This means that we have the following association:
      
       CPU core device |     DRC    | VCPU id
      -----------------+------------+---------
         boot core     | 0x10000000 | 0
         core1         | 0x10000004 | 4
         core2         | 0x10000008 | 8
         core3         | 0x1000000c | 12
      
      But since the spacing of VCPU ids is 8, the DRC for core1 points to a
      VCPU that doesn't exist, the DRC for core2 points to the first VCPU of
      core1 and and so on...
      
              ...
      
              PowerPC,POWER8@0 {
                      ...
                      ibm,my-drc-index = <0x10000000>;
                      ...
              };
      
              PowerPC,POWER8@8 {
                      ...
                      ibm,my-drc-index = <0x10000008>;
                      ...
              };
      
              PowerPC,POWER8@10 {
                      ...
      
      No ibm,my-drc-index property for this core since 0x10000010 doesn't
      exist in ibm,drc-indexes above.
      
                      ...
              };
      };
      
      ...
      
      interrupt-controller {
              ...
              ibm,interrupt-server-ranges = <0x0 0x10>;
      
      With a spacing of 8, the highest VCPU id for the given topology should be:
              16 * 8 / 4 = 32 and not 16
      
              ...
              linux,phandle = <0x7e7323b8>;
              interrupt-controller;
      };
      
      And CPU hot-plug/unplug is broken:
      
      (qemu) device_del core1
      pseries-hotplug-cpu: Cannot find CPU (drc index 10000004) to remove
      
      (qemu) device_del core2
      cpu 4 (hwid 8) Ready to die...
      cpu 5 (hwid 9) Ready to die...
      cpu 6 (hwid 10) Ready to die...
      cpu 7 (hwid 11) Ready to die...
      
      These are the VCPU ids of core1 actually
      
      (qemu) device_add host-spapr-cpu-core,core-id=12,id=core3
      (qemu) device_del core3
      pseries-hotplug-cpu: Cannot find CPU (drc index 1000000c) to remove
      
      This patches all the code in hw/ppc/spapr.c to assume the VSMT
      spacing when manipulating VCPU ids.
      
      Fixes: 8904e5a7Signed-off-by: NGreg Kurz <groug@kaod.org>
      Signed-off-by: NDavid Gibson <david@gibson.dropbear.id.au>
      
      (cherry picked from commit 72194664)
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      cc86c467
    • L
      spapr: set vsmt to MAX(8, smp_threads) · c30b366d
      Laurent Vivier 提交于
      We ignore silently the value of smp_threads when we set
      the default VSMT value, and if smp_threads is greater than VSMT
      kernel is going into trouble later.
      
      Fixes: 8904e5a7
      ("spapr: Adjust default VSMT value for better migration compatibility")
      Signed-off-by: NLaurent Vivier <lvivier@redhat.com>
      Reviewed-by: NGreg Kurz <groug@kaod.org>
      Signed-off-by: NDavid Gibson <david@gibson.dropbear.id.au>
      (cherry picked from commit 4ad64cbd)
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      c30b366d
    • D
      spapr: Adjust default VSMT value for better migration compatibility · af65bce4
      David Gibson 提交于
      fa98fbfc "PC: KVM: Support machine option to set VSMT mode" introduced the
      "vsmt" parameter for the pseries machine type, which controls the spacing
      of the vcpu ids of thread 0 for each virtual core.  This was done to bring
      some consistency and stability to how that was done, while still allowing
      backwards compatibility for migration and otherwise.
      
      The default value we used for vsmt was set to the max of the host's
      advertised default number of threads and the number of vthreads per vcore
      in the guest.  This was done to continue running without extra parameters
      on older KVM versions which don't allow the VSMT value to be changed.
      
      Unfortunately, even that smaller than before leakage of host configuration
      into guest visible configuration still breaks things.  Specifically a guest
      with 4 (or less) vthread/vcore will get a different vsmt value when
      running on a POWER8 (vsmt==8) and POWER9 (vsmt==4) host.  That means the
      vcpu ids don't line up so you can't migrate between them, though you should
      be able to.
      
      Long term we really want to make vsmt == smp_threads for sufficiently
      new machine types.  However, that means that qemu will then require a
      sufficiently recent KVM (one which supports changing VSMT) - that's still
      not widely enough deployed to be really comfortable to do.
      
      In the meantime we need some default that will work as often as
      possible.  This patch changes that default to 8 in all circumstances.
      This does change guest visible behaviour (including for existing
      machine versions) for many cases - just not the most common/important
      case.
      
      Following is case by case justification for why this is still the least
      worst option.  Note that any of the old behaviours can still be duplicated
      after this patch, it's just that it requires manual intervention by
      setting the vsmt property on the command line.
      
      KVM HV on POWER8 host:
         This is the overwhelmingly common case in production setups, and is
         unchanged by design.  POWER8 hosts will advertise a default VSMT mode
         of 8, and > 8 vthreads/vcore isn't permitted
      
      KVM HV on POWER7 host:
         Will break, but POWER7s allowing KVM were never released to the public.
      
      KVM HV on POWER9 host:
         Not yet released to the public, breaking this now will reduce other
         breakage later.
      
      KVM HV on PowerPC 970:
         Will theoretically break it, but it was barely supported to begin with
         and already required various user visible hacks to work.  Also so old
         that I just don't care.
      
      TCG:
         This is the nastiest one; it means migration of TCG guests (without
         manual vsmt setting) will break.  Since TCG is rarely used in production
         I think this is worth it for the other benefits.  It does also remove
         one more barrier to TCG<->KVM migration which could be interesting for
         debugging applications.
      
      KVM PR:
         As with TCG, this will break migration of existing configurations,
         without adding extra manual vsmt options.  As with TCG, it is rare in
         production so I think the benefits outweigh breakages.
      Signed-off-by: NDavid Gibson <david@gibson.dropbear.id.au>
      Reviewed-by: NLaurent Vivier <lvivier@redhat.com>
      Reviewed-by: NJose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
      Reviewed-by: NGreg Kurz <groug@kaod.org>
      (cherry picked from commit 8904e5a7)
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      af65bce4
    • D
      spapr: Allow some cases where we can't set VSMT mode in the kernel · ad484114
      David Gibson 提交于
      At present if we require a vsmt mode that's not equal to the kernel's
      default, and the kernel doesn't let us change it (e.g. because it's an old
      kernel without support) then we always fail.
      
      But in fact we can cope with the kernel having a different vsmt as long as
        a) it's >= the actual number of vthreads/vcore (so that guest threads
           that are supposed to be on the same core act like it)
        b) it's a submultiple of the requested vsmt mode (so that guest threads
           spaced by the vsmt value will act like they're on different cores)
      
      Allowing this case gives us a bit more freedom to adjust the vsmt behaviour
      without breaking existing cases.
      Signed-off-by: NDavid Gibson <david@gibson.dropbear.id.au>
      Reviewed-by: NLaurent Vivier <lvivier@redhat.com>
      Tested-by: NGreg Kurz <groug@kaod.org>
      Reviewed-by: NGreg Kurz <groug@kaod.org>
      (cherry picked from commit 1f20f2e0)
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      ad484114
    • G
      sdl: workaround bug in sdl 2.0.8 headers · 0a30cae5
      Gerd Hoffmann 提交于
      https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=892087Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      Reviewed-by: NDaniel P. Berrangé <berrange@redhat.com>
      Message-id: 20180307154258.9313-1-kraxel@redhat.com
      (cherry picked from commit 2ca5c430)
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      0a30cae5
    • P
      memfd: fix configure test · 5892b5a9
      Paolo Bonzini 提交于
      Recent glibc added memfd_create in sys/mman.h.  This conflicts with
      the definition in util/memfd.c:
      
          /builddir/build/BUILD/qemu-2.11.0-rc1/util/memfd.c:40:12: error: static declaration of memfd_create follows non-static declaration
      
      Fix the configure test, and remove the sys/memfd.h inclusion since the
      file actually does not exist---it is a typo in the memfd_create(2) man
      page.
      
      Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
      Signed-off-by: NPaolo Bonzini <pbonzini@redhat.com>
      (cherry picked from commit 75e5b70e)
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      5892b5a9
  3. 15 2月, 2018 1 次提交
  4. 13 2月, 2018 16 次提交
    • G
      spapr: add missing break in h_get_cpu_characteristics() · 00e9fba2
      Greg Kurz 提交于
      Detected by Coverity (CID 1385702). This fixes the recently added hypercall
      to let guests properly apply Spectre and Meltdown workarounds.
      
      Fixes: c59704b2 "target/ppc/spapr: Add H-Call H_GET_CPU_CHARACTERISTICS"
      Reported-by: NPaolo Bonzini <pbonzini@redhat.com>
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      Reviewed-by: NSuraj Jitindar Singh <sjitindarsingh@gmail.com>
      Signed-off-by: NDavid Gibson <david@gibson.dropbear.id.au>
      (cherry picked from commit fa86f592)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      00e9fba2
    • L
      vga: check the validation of memory addr when draw text · 63112b16
      linzhecheng 提交于
      Start a vm with qemu-kvm -enable-kvm -vnc :66 -smp 1 -m 1024 -hda
      redhat_5.11.qcow2  -device pcnet -vga cirrus,
      then use VNC client to connect to VM, and excute the code below in guest
      OS will lead to qemu crash:
      
      int main()
       {
          iopl(3);
          srand(time(NULL));
          int a,b;
          while(1){
      	a = rand()%0x100;
      	b = 0x3c0 + (rand()%0x20);
              outb(a,b);
          }
          return 0;
      }
      
      The above code is writing the registers of VGA randomly.
      We can write VGA CRT controller registers index 0x0C or 0x0D
      (which is the start address register) to modify the
      the display memory address of the upper left pixel
      or character of the screen. The address may be out of the
      range of vga ram. So we should check the validation of memory address
      when reading or writing it to avoid segfault.
      Signed-off-by: Nlinzhecheng <linzhecheng@huawei.com>
      Message-id: 20180111132724.13744-1-linzhecheng@huawei.com
      Fixes: CVE-2018-5683
      Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      (cherry picked from commit 191f59dc)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      63112b16
    • L
      input: fix memory leak · 30c3b482
      linzhecheng 提交于
      If kbd_queue is not empty and queue_count >= queue_limit,
      we should free evt.
      
      Change-Id: Ieeacf90d5e7e370a40452ec79031912d8b864d83
      Signed-off-by: Nlinzhecheng <linzhecheng@huawei.com>
      Message-id: 20171225023730.5512-1-linzhecheng@huawei.com
      Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      (cherry picked from commit fca4774a)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      30c3b482
    • D
      ui: correctly advance output buffer when writing SASL data · 88ab8538
      Daniel P. Berrangé 提交于
      In this previous commit:
      
        commit 8f61f1c5
        Author: Daniel P. Berrange <berrange@redhat.com>
        Date:   Mon Dec 18 19:12:20 2017 +0000
      
          ui: track how much decoded data we consumed when doing SASL encoding
      
      I attempted to fix a flaw with tracking how much data had actually been
      processed when encoding with SASL. With that flaw, the VNC server could
      mistakenly discard queued data that had not been sent.
      
      The fix was not quite right though, because it merely decremented the
      vs->output.offset value. This is effectively discarding data from the
      end of the pending output buffer. We actually need to discard data from
      the start of the pending output buffer. We also want to free memory that
      is no longer required. The correct way to handle this is to use the
      buffer_advance() helper method instead of directly manipulating the
      offset value.
      Reported-by: NLaszlo Ersek <lersek@redhat.com>
      Signed-off-by: NDaniel P. Berrangé <berrange@redhat.com>
      Reviewed-by: NEric Blake <eblake@redhat.com>
      Reviewed-by: NLaszlo Ersek <lersek@redhat.com>
      Message-id: 20180201155841.27509-1-berrange@redhat.com
      Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      (cherry picked from commit 627ebec2)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      88ab8538
    • D
      ui: avoid sign extension using client width/height · 64653b7f
      Daniel P. Berrange 提交于
      Pixman returns a signed int for the image width/height, but the VNC
      protocol only permits a unsigned int16. Effective framebuffer size
      is determined by the guest, limited by the video RAM size, so the
      dimensions are unlikely to exceed the range of an unsigned int16,
      but this is not currently validated.
      
      With the current use of 'int' for client width/height, the calculation
      of offsets in vnc_update_throttle_offset() suffers from integer size
      promotion and sign extension, causing coverity warnings
      
      *** CID 1385147:  Integer handling issues  (SIGN_EXTENSION)
      /ui/vnc.c: 979 in vnc_update_throttle_offset()
      973      * than that the client would already suffering awful audio
      974      * glitches, so dropping samples is no worse really).
      975      */
      976     static void vnc_update_throttle_offset(VncState *vs)
      977     {
      978         size_t offset =
      >>>     CID 1385147:  Integer handling issues  (SIGN_EXTENSION)
      >>>     Suspicious implicit sign extension:
          "vs->client_pf.bytes_per_pixel" with type "unsigned char" (8 bits,
          unsigned) is promoted in "vs->client_width * vs->client_height *
          vs->client_pf.bytes_per_pixel" to type "int" (32 bits, signed), then
          sign-extended to type "unsigned long" (64 bits, unsigned).  If
          "vs->client_width * vs->client_height * vs->client_pf.bytes_per_pixel"
          is greater than 0x7FFFFFFF, the upper bits of the result will all be 1.
      979             vs->client_width * vs->client_height * vs->client_pf.bytes_per_pixel;
      
      Change client_width / client_height to be a size_t to avoid sign
      extension and integer promotion. Then validate that dimensions are in
      range wrt the RFB protocol u16 limits.
      Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
      Message-id: 20180118155254.17053-1-berrange@redhat.com
      Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      (cherry picked from commit 4c956bd8)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      64653b7f
    • D
      ui: mix misleading comments & return types of VNC I/O helper methods · 9a26ca6b
      Daniel P. Berrange 提交于
      While the QIOChannel APIs for reading/writing data return ssize_t, with negative
      value indicating an error, the VNC code passes this return value through the
      vnc_client_io_error() method. This detects the error condition, disconnects the
      client and returns 0 to indicate error. Thus all the VNC helper methods should
      return size_t (unsigned), and misleading comments which refer to the possibility
      of negative return values need fixing.
      Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
      Reviewed-by: NDarren Kenny <darren.kenny@oracle.com>
      Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-id: 20171218191228.31018-14-berrange@redhat.com
      Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      (cherry picked from commit 30b80fd5)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      9a26ca6b
    • D
      ui: add trace events related to VNC client throttling · 172f4e5a
      Daniel P. Berrange 提交于
      The VNC client throttling is quite subtle so will benefit from having trace
      points available for live debugging.
      Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
      Reviewed-by: NDarren Kenny <darren.kenny@oracle.com>
      Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-id: 20171218191228.31018-13-berrange@redhat.com
      Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      (cherry picked from commit 6aa22a29)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      172f4e5a
    • D
      ui: place a hard cap on VNC server output buffer size · 0c85a40e
      Daniel P. Berrange 提交于
      The previous patches fix problems with throttling of forced framebuffer updates
      and audio data capture that would cause the QEMU output buffer size to grow
      without bound. Those fixes are graceful in that once the client catches up with
      reading data from the server, everything continues operating normally.
      
      There is some data which the server sends to the client that is impractical to
      throttle. Specifically there are various pseudo framebuffer update encodings to
      inform the client of things like desktop resizes, pointer changes, audio
      playback start/stop, LED state and so on. These generally only involve sending
      a very small amount of data to the client, but a malicious guest might be able
      to do things that trigger these changes at a very high rate. Throttling them is
      not practical as missed or delayed events would cause broken behaviour for the
      client.
      
      This patch thus takes a more forceful approach of setting an absolute upper
      bound on the amount of data we permit to be present in the output buffer at
      any time. The previous patch set a threshold for throttling the output buffer
      by allowing an amount of data equivalent to one complete framebuffer update and
      one seconds worth of audio data. On top of this it allowed for one further
      forced framebuffer update to be queued.
      
      To be conservative, we thus take that throttling threshold and multiply it by
      5 to form an absolute upper bound. If this bound is hit during vnc_write() we
      forceably disconnect the client, refusing to queue further data. This limit is
      high enough that it should never be hit unless a malicious client is trying to
      exploit the sever, or the network is completely saturated preventing any sending
      of data on the socket.
      
      This completes the fix for CVE-2017-15124 started in the previous patches.
      Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
      Reviewed-by: NDarren Kenny <darren.kenny@oracle.com>
      Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-id: 20171218191228.31018-12-berrange@redhat.com
      Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      (cherry picked from commit f887cf16)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      0c85a40e
    • D
      ui: fix VNC client throttling when forced update is requested · f9e53c77
      Daniel P. Berrange 提交于
      The VNC server must throttle data sent to the client to prevent the 'output'
      buffer size growing without bound, if the client stops reading data off the
      socket (either maliciously or due to stalled/slow network connection).
      
      The current throttling is very crude because it simply checks whether the
      output buffer offset is zero. This check is disabled if the client has requested
      a forced update, because we want to send these as soon as possible.
      
      As a result, the VNC client can cause QEMU to allocate arbitrary amounts of RAM.
      They can first start something in the guest that triggers lots of framebuffer
      updates eg play a youtube video. Then repeatedly send full framebuffer update
      requests, but never read data back from the server. This can easily make QEMU's
      VNC server send buffer consume 100MB of RAM per second, until the OOM killer
      starts reaping processes (hopefully the rogue QEMU process, but it might pick
      others...).
      
      To address this we make the throttling more intelligent, so we can throttle
      full updates. When we get a forced update request, we keep track of exactly how
      much data we put on the output buffer. We will not process a subsequent forced
      update request until this data has been fully sent on the wire. We always allow
      one forced update request to be in flight, regardless of what data is queued
      for incremental updates or audio data. The slight complication is that we do
      not initially know how much data an update will send, as this is done in the
      background by the VNC job thread. So we must track the fact that the job thread
      has an update pending, and not process any further updates until this job is
      has been completed & put data on the output buffer.
      
      This unbounded memory growth affects all VNC server configurations supported by
      QEMU, with no workaround possible. The mitigating factor is that it can only be
      triggered by a client that has authenticated with the VNC server, and who is
      able to trigger a large quantity of framebuffer updates or audio samples from
      the guest OS. Mostly they'll just succeed in getting the OOM killer to kill
      their own QEMU process, but its possible other processes can get taken out as
      collateral damage.
      
      This is a more general variant of the similar unbounded memory usage flaw in
      the websockets server, that was previously assigned CVE-2017-15268, and fixed
      in 2.11 by:
      
        commit a7b20a8e
        Author: Daniel P. Berrange <berrange@redhat.com>
        Date:   Mon Oct 9 14:43:42 2017 +0100
      
          io: monitor encoutput buffer size from websocket GSource
      
      This new general memory usage flaw has been assigned CVE-2017-15124, and is
      partially fixed by this patch.
      Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
      Reviewed-by: NDarren Kenny <darren.kenny@oracle.com>
      Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-id: 20171218191228.31018-11-berrange@redhat.com
      Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      (cherry picked from commit ada8d2e4)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      f9e53c77
    • D
      ui: fix VNC client throttling when audio capture is active · f9c87678
      Daniel P. Berrange 提交于
      The VNC server must throttle data sent to the client to prevent the 'output'
      buffer size growing without bound, if the client stops reading data off the
      socket (either maliciously or due to stalled/slow network connection).
      
      The current throttling is very crude because it simply checks whether the
      output buffer offset is zero. This check must be disabled if audio capture is
      enabled, because when streaming audio the output buffer offset will rarely be
      zero due to queued audio data, and so this would starve framebuffer updates.
      
      As a result, the VNC client can cause QEMU to allocate arbitrary amounts of RAM.
      They can first start something in the guest that triggers lots of framebuffer
      updates eg play a youtube video. Then enable audio capture, and simply never
      read data back from the server. This can easily make QEMU's VNC server send
      buffer consume 100MB of RAM per second, until the OOM killer starts reaping
      processes (hopefully the rogue QEMU process, but it might pick others...).
      
      To address this we make the throttling more intelligent, so we can throttle
      when audio capture is active too. To determine how to throttle incremental
      updates or audio data, we calculate a size threshold. Normally the threshold is
      the approximate number of bytes associated with a single complete framebuffer
      update. ie width * height * bytes per pixel. We'll send incremental updates
      until we hit this threshold, at which point we'll stop sending updates until
      data has been written to the wire, causing the output buffer offset to fall
      back below the threshold.
      
      If audio capture is enabled, we increase the size of the threshold to also
      allow for upto 1 seconds worth of audio data samples. ie nchannels * bytes
      per sample * frequency. This allows the output buffer to have a mixture of
      incremental framebuffer updates and audio data queued, but once the threshold
      is exceeded, audio data will be dropped and incremental updates will be
      throttled.
      
      This unbounded memory growth affects all VNC server configurations supported by
      QEMU, with no workaround possible. The mitigating factor is that it can only be
      triggered by a client that has authenticated with the VNC server, and who is
      able to trigger a large quantity of framebuffer updates or audio samples from
      the guest OS. Mostly they'll just succeed in getting the OOM killer to kill
      their own QEMU process, but its possible other processes can get taken out as
      collateral damage.
      
      This is a more general variant of the similar unbounded memory usage flaw in
      the websockets server, that was previously assigned CVE-2017-15268, and fixed
      in 2.11 by:
      
        commit a7b20a8e
        Author: Daniel P. Berrange <berrange@redhat.com>
        Date:   Mon Oct 9 14:43:42 2017 +0100
      
          io: monitor encoutput buffer size from websocket GSource
      
      This new general memory usage flaw has been assigned CVE-2017-15124, and is
      partially fixed by this patch.
      Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
      Reviewed-by: NDarren Kenny <darren.kenny@oracle.com>
      Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-id: 20171218191228.31018-10-berrange@redhat.com
      Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      (cherry picked from commit e2b72cb6)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      f9c87678
    • D
      ui: refactor code for determining if an update should be sent to the client · 5af9f250
      Daniel P. Berrange 提交于
      The logic for determining if it is possible to send an update to the client
      will become more complicated shortly, so pull it out into a separate method
      for easier extension later.
      Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
      Reviewed-by: NDarren Kenny <darren.kenny@oracle.com>
      Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-id: 20171218191228.31018-9-berrange@redhat.com
      Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      (cherry picked from commit 0bad8342)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      5af9f250
    • D
      ui: correctly reset framebuffer update state after processing dirty regions · 2e6571e6
      Daniel P. Berrange 提交于
      According to the RFB protocol, a client sends one or more framebuffer update
      requests to the server. The server can reply with a single framebuffer update
      response, that covers all previously received requests. Once the client has
      read this update from the server, it may send further framebuffer update
      requests to monitor future changes. The client is free to delay sending the
      framebuffer update request if it needs to throttle the amount of data it is
      reading from the server.
      
      The QEMU VNC server, however, has never correctly handled the framebuffer
      update requests. Once QEMU has received an update request, it will continue to
      send client updates forever, even if the client hasn't asked for further
      updates. This prevents the client from throttling back data it gets from the
      server. This change fixes the flawed logic such that after a set of updates are
      sent out, QEMU waits for a further update request before sending more data.
      Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
      Reviewed-by: NDarren Kenny <darren.kenny@oracle.com>
      Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-id: 20171218191228.31018-8-berrange@redhat.com
      Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      (cherry picked from commit 728a7ac9)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      2e6571e6
    • D
      ui: introduce enum to track VNC client framebuffer update request state · 126617e6
      Daniel P. Berrange 提交于
      Currently the VNC servers tracks whether a client has requested an incremental
      or forced update with two boolean flags. There are only really 3 distinct
      states to track, so create an enum to more accurately reflect permitted states.
      Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
      Reviewed-by: NDarren Kenny <darren.kenny@oracle.com>
      Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-id: 20171218191228.31018-7-berrange@redhat.com
      Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      (cherry picked from commit fef1bbad)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      126617e6
    • D
      ui: track how much decoded data we consumed when doing SASL encoding · 8a9c5c34
      Daniel P. Berrange 提交于
      When we encode data for writing with SASL, we encode the entire pending output
      buffer. The subsequent write, however, may not be able to send the full encoded
      data in one go though, particularly with a slow network. So we delay setting the
      output buffer offset back to zero until all the SASL encoded data is sent.
      
      Between encoding the data and completing sending of the SASL encoded data,
      however, more data might have been placed on the pending output buffer. So it
      is not valid to set offset back to zero. Instead we must keep track of how much
      data we consumed during encoding and subtract only that amount.
      
      With the current bug we would be throwing away some pending data without having
      sent it at all. By sheer luck this did not previously cause any serious problem
      because appending data to the send buffer is always an atomic action, so we
      only ever throw away complete RFB protocol messages. In the case of frame buffer
      updates we'd catch up fairly quickly, so no obvious problem was visible.
      Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
      Reviewed-by: NDarren Kenny <darren.kenny@oracle.com>
      Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-id: 20171218191228.31018-6-berrange@redhat.com
      Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      (cherry picked from commit 8f61f1c5)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      8a9c5c34
    • D
      ui: avoid pointless VNC updates if framebuffer isn't dirty · 616d64ac
      Daniel P. Berrange 提交于
      The vnc_update_client() method checks the 'has_dirty' flag to see if there are
      dirty regions that are pending to send to the client. Regardless of this flag,
      if a forced update is requested, updates must be sent. For unknown reasons
      though, the code also tries to sent updates if audio capture is enabled. This
      makes no sense as audio capture state does not impact framebuffer contents, so
      this check is removed.
      Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
      Reviewed-by: NDarren Kenny <darren.kenny@oracle.com>
      Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-id: 20171218191228.31018-5-berrange@redhat.com
      Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      (cherry picked from commit 3541b084)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      616d64ac
    • D
      ui: remove redundant indentation in vnc_client_update · a7b2537f
      Daniel P. Berrange 提交于
      Now that previous dead / unreachable code has been removed, we can simplify
      the indentation in the vnc_client_update method.
      Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
      Reviewed-by: NDarren Kenny <darren.kenny@oracle.com>
      Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-id: 20171218191228.31018-4-berrange@redhat.com
      Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
      (cherry picked from commit b939eb89)
      Signed-off-by: NMichael Roth <mdroth@linux.vnet.ibm.com>
      a7b2537f