diff --git a/www/conservancy/static/linux-compliance/vmware-lawsuit-faq.html b/www/conservancy/static/linux-compliance/vmware-lawsuit-faq.html index 2efa3375dac203e91c5bd99c3292aa9a47959b70..c91a2988cee951fb89b1c5e9f710cf8cb9182845 100644 --- a/www/conservancy/static/linux-compliance/vmware-lawsuit-faq.html +++ b/www/conservancy/static/linux-compliance/vmware-lawsuit-faq.html @@ -180,7 +180,6 @@ Code, and for which (at least some) source code is provided. whole was developed by modifying Linux code in tandem with modifications to “vmkernel” in a tightly coupled manner.

-
Is Conservancy proposing a “shim layer” as a viable solution for GPL compliance?
@@ -190,7 +189,7 @@ Code, and for which (at least some) source code is provided. technological manipulation that changes the outcome of a combined/derivative work analysis. -
Can you give a specific example, with code, showing how +
Can you give a specific example, with code, showing how VMware combined Linux source code with their binary-only components?

There are numerous examples available that show this. The @@ -213,27 +212,39 @@ Code, and for which (at least some) source code is provided. Hellwig's copyrights; VMware incorporated Linux code copyrighted by many others as well into their kernel.

-

Example of “vmkernel”'s combination with Linux code

-

As one example, examine the file +

Example of “vmkernel”'s combination with Linux code

+

Our example begins with examination of the file called vmkdrivers/src_92/vmklinux_92/vmware/linux_pci.c, which can be found in the “Open Source” release for ESXi 5.5.0 Update 2 (5.5U2). A small excerpt from that file, found in the function LinuxPCIDeviceRemoved(), reads as follows:

-if (unlikely(
-  /* NOTE: vmk_PCIGetDeviceName is defined in vmvisor64-vmkernel */
-  vmk_PCIGetDeviceName(vmkDev, vmkDevName, sizeof(vmkDevName)-1) != VMK_OK))
+#include 
+[...]
+/*
+ * This function [...] is modelled after pci_remove_device, the function which would
+ * be called in a linux system.
+ */
+static void
+LinuxPCIDeviceRemoved(vmk_PCIDevice vmkDev)
 {
-    vmkDevName[0] = 0;
-}
+   LinuxPCIDevExt *pciDevExt;
+   struct pci_dev *linuxDev;
+[...]
+  if (unlikely(
+    vmk_PCIGetDeviceName(vmkDev, vmkDevName, sizeof(vmkDevName)-1) != VMK_OK))
+  {
+      vmkDevName[0] = 0;
+  }
 [...]
-/* VMKAPI_MODULE_CALL_VOID is a macro calling driver's remove() here */
 VMKAPI_MODULE_CALL_VOID(pciDevExt->moduleID,
                         linuxDev->driver->remove,
                         linuxDev);
 
+

Combination of “vmkernel” code with “vmkdrivers”

+

The function, vmk_PCIGetDeviceName() must be defined, with an implementation, for this code above to work, or even compile. Inside BLD/build/HEADERS/vmkapi-current-all-public/vmkernel64/release/device/vmkapi_pci_incompat.h, @@ -286,28 +297,131 @@ VMKAPI_MODULE_CALL_VOID(pciDevExt->moduleID,

… which indicated these binary file contains the function body for vmk_PCIGetDeviceName.

-

Finally, after detailed searching, Conservancy found no evidence that any +

Furthermore, after detailed searching, Conservancy found no evidence that any other code (other than modified Linux code) makes calls to vmk_PCIGetDeviceName. This provides a strong indication that this function's primary purpose is to combine Linux code with “vmkernel”. Conservancy also found other functions where similar analysis yields similar results as above.

+

Linux's struct pci combined with LinuxPCIDeviceRemoved()

+ +

Having established the direct and close combination + of vmk_PCIGetDeviceName + and LinuxPCIDeviceRemoved(), focus now on the + quoted code from LinuxPCIDeviceRemoved(). That code, note + that one of the local variables is struct pci_dev *linuxDev;. + A definition of pci_dev is found in + vmkdrivers/src_92/include/linux/pci.h (which + is #include'd above) reads: +

+struct pci_dev {
+[...]
+       struct pci_driver *driver;      /* which driver has allocated this device */
+[...]
+truct pci_driver {
+        char *name;
+[...]
+        void (*remove) (struct pci_dev *dev);   /* Device removed (NULL if not a hot-plug capable driver) */
+[...]
+#if defined(__VMKLNX__)
+        /* 2008: Update from Linux source */
+        u8              revision;       /* PCI revision, low byte of class word */
+#endif /* defined(__VMKLNX__) */
+  };
+

+ +

These structures, and based on those from Linux itself + (a + similar version of this file can be seen in Linux 2.6.24), and as can + be seen above, have been modified to work with “vmkernel”

+ +

In LinuxPCIDeviceRemoved(), we saw a macro called with a + variable, linuxDev which was of type struct pci. + Thus, the combination of code from Linux's pci.h + and VMware's vmware/linux_pci.c is very tightly coupled and + interdependent.

+ +

VMKAPI_MODULE_CALL_VOID macro calls driver's code

+ +

The + file BLD/build/HEADERS/vmkapi-current-all-public/vmkernel64/release/base/vmkapi_module.h + contains the macro definition of VMKAPI_MODULE_CALL_VOID, + which is quoted below (with debug lines removed): +

+#define VMKAPI_MODULE_CALL_VOID(moduleID, function, args...)  \
+do {                                                    \
+    vmk_ModInfoStack modStack;                          \
+    vmk_ModulePushId(moduleID, function, &modStack);    \
+    (function)(args);                                   \
+    )                                                   \
+    vmk_ModulePopId();                                  \
+} while(0)
+
+ +

When the macro is expanded, it means that (function)(args) is + actually expanded to linuxDev->driver->remove(linuxDev). + Therefore, we see LinuxPCIDeviceRemoved(), makes directs calls + to a driver's remove() function, by combining with Linux's struct + pci, and by VMware's introduction of this new calling code. + Conservancy has confirmed many drivers from Linux are incorporated via + these mechanisms; one specific example is discussed next.

+ +

Combination of the tg3 driver with “vmkernel”

+ +

VMware includes a file vmkdrivers/src_9/drivers/net/tg3/tg3.c + in their source release. This file appears to be Linux's tg3 driver. It + includes a definition of the struct pci_dev for this device, + which reads: +

+static struct pci_driver tg3_driver = {
+[...]
+        .remove         = __devexit_p(tg3_remove_one),
+
+

+ +

Therefore, when the code in LinuxPCIDeviceRemoved() + calls linuxDev->driver->remove(linuxDev), the code ultimately + called (in the case where a tg3 card is driven by the kernel) + is tg3_remove_one(), which is found in tg3.c and + comes directly from Linux.

+ +

(Note: __devexit_p is a straightforward macro found + in vmkdrivers/src_92/include/linux/init.h (which also comes + from Linux) that will simply expand to its first argument in this + case.)

+ +

VMware distribution of binary version of tg3.c

+ +

VMware furthermore distributes a modified version of tg.c in + binary form. This can be found in usr/lib/vmware/vmkmod/tg3, + which is extracted by un-vmtar'ing the file net_tg3.v00 (found + on the ESXi 5.5U2 installer ISO image). Conservancy has confirmed that + file is a compiled version of tg3.c

+ +

Conclusions

+

Given this evidence and related contextual clues, the only logical conclusions are:

-