File valgrind.track-xenversion-for-unversioned-interfaces.patch of Package valgrind

From: Olaf Hering <olaf@aepfle.de>
Date: Wed, 26 Feb 2020 15:27:42 +0100
Subject: track xenversion for unversioned interfaces

Only domctl and sysctl contain a version info. Other interfaces lack
this essential info. But their layout of arguments may change across Xen
versions.

Track the current Xen version based on info obtained from domctl and
sysctl calls. In case these versioned interfaces are called prior calls
to unversioned interfaces, valgrind will have a chance to guess the
correct layout of arguments.

Upcoming changes will start to make use of this interface.

bz#390553
---
 coregrind/m_syswrap/syswrap-xen.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

--- a/coregrind/m_syswrap/syswrap-xen.c
+++ b/coregrind/m_syswrap/syswrap-xen.c
@@ -51,24 +51,75 @@
 #include "pub_core_scheduler.h"
 #include "pub_core_signals.h"
 #include "pub_core_syscall.h"
 #include "pub_core_syswrap.h"
 #include "pub_core_stacktrace.h"    // For VG_(get_and_pp_StackTrace)()
 
 #include "priv_types_n_macros.h"
 #include "priv_syswrap-generic.h"
 #include "priv_syswrap-xen.h"
 
 #include <inttypes.h>
 
+typedef enum {
+   vki_xenversion_unset = 0,
+   vki_xenversion_401,
+   vki_xenversion_402,
+   /* value shared between 4.3 and 4.4 */
+   vki_xenversion_404,
+   vki_xenversion_405,
+   vki_xenversion_406_or_407,
+   vki_xenversion_406,
+   vki_xenversion_407,
+   vki_xenversion_408,
+   vki_xenversion_409,
+   vki_xenversion_410,
+   vki_xenversion_4101,
+   vki_xenversion_411,
+   vki_xenversion_412_or_413,
+   vki_xenversion_412,
+   vki_xenversion_413,
+   vki_xenversion_414,
+} vki_assumed_xenversion_t;
+static vki_assumed_xenversion_t vki_assumed_xenversion;
+
+/*
+ * Some of the interfaces to Xen are versioned, like domctl and sysctl.
+ * Other interfaces lack a version number to derive the layout of arguments.
+ * Track the assumed Xen version for them, based on prior domctl or sysctl.
+ */
+static void vki_set_assumed_xenversion(vki_assumed_xenversion_t v)
+{
+   switch (vki_assumed_xenversion) {
+      case vki_xenversion_unset:
+         vki_assumed_xenversion = v;
+         break;
+      case vki_xenversion_406_or_407:
+         if (v == vki_xenversion_406 || v == vki_xenversion_407)
+            vki_assumed_xenversion = v;
+         break;
+      case vki_xenversion_412_or_413:
+         if (v == vki_xenversion_412 || v == vki_xenversion_413)
+            vki_assumed_xenversion = v;
+         break;
+      default:
+         break;
+   }
+}
+
+static void vki_report_unknown_xenversion(const char *str)
+{
+   VG_(dmsg)("WARNING: %s prior domctl/sysctl. Assuming latest interface version.\n", str);
+}
+
 #define PRE(name) static DEFN_PRE_TEMPLATE(xen, name)
 #define POST(name) static DEFN_POST_TEMPLATE(xen, name)
 
 static void bad_intf_version ( ThreadId              tid,
                                SyscallArgLayout*     layout,
                                /*MOD*/SyscallArgs*   args,
                                /*OUT*/SyscallStatus* status,
                                /*OUT*/UWord*         flags,
                                const HChar*          hypercall,
                                UWord                 version)
 {
    VG_(dmsg)("WARNING: %s version %#lx not supported\n",
@@ -570,27 +621,35 @@ PRE(sysctl) {
     *    uint32_t cmd;
     *    uint32_t interface_version;
     */
    PRE_MEM_READ("__HYPERVISOR_sysctl", ARG1,
                 sizeof(vki_uint32_t) + sizeof(vki_uint32_t));
 
    if (!sysctl)
       return;
 
    switch (sysctl->interface_version)
    {
    case 0x00000008:
+      vki_set_assumed_xenversion(vki_xenversion_401);
+	   break;
    case 0x00000009:
+      vki_set_assumed_xenversion(vki_xenversion_402);
+	   break;
    case 0x0000000a:
+      vki_set_assumed_xenversion(vki_xenversion_404);
+	   break;
    case 0x0000000b:
+      vki_set_assumed_xenversion(vki_xenversion_405);
+	   break;
    case 0x0000000c:
    case 0x0000000d:
    case 0x0000000e:
    case 0x0000000f:
    case 0x00000010:
    case 0x00000011:
    case 0x00000012:
 	   break;
    default:
       bad_intf_version(tid, layout, arrghs, status, flags,
                        "__HYPERVISOR_sysctl", sysctl->interface_version);
       return;
@@ -732,29 +791,41 @@ PRE(domctl)
     *    vki_xen_domid_t  domain;
     */
    PRE_MEM_READ("__HYPERVISOR_domctl", ARG1,
                 sizeof(vki_uint32_t) + sizeof(vki_uint32_t)
 		+ sizeof(vki_xen_domid_t));
 
    if (!domctl)
       return;
 
    switch (domctl->interface_version)
    {
    case 0x00000007:
+      vki_set_assumed_xenversion(vki_xenversion_401);
+	   break;
    case 0x00000008:
+      vki_set_assumed_xenversion(vki_xenversion_402);
+	   break;
    case 0x00000009:
+      vki_set_assumed_xenversion(vki_xenversion_404);
+	   break;
    case 0x0000000a:
+      vki_set_assumed_xenversion(vki_xenversion_405);
+	   break;
    case 0x0000000b:
+      vki_set_assumed_xenversion(vki_xenversion_406_or_407);
+	   break;
    case 0x0000000c:
+      vki_set_assumed_xenversion(vki_xenversion_408);
+	   break;
    case 0x0000000d:
    case 0x0000000f:
    case 0x00000010:
    case 0x00000011:
    case 0x00000012:
 	   break;
    default:
       bad_intf_version(tid, layout, arrghs, status, flags,
                        "__HYPERVISOR_domctl", domctl->interface_version);
       return;
    }
 
openSUSE Build Service is sponsored by