From ea9a59c551f8b022d2f44dc67789748389883ac0 Mon Sep 17 00:00:00 2001
From: "Bradley M. Kuhn"
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.
-As one example, examine the file +
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)) -{ - vmkDevName[0] = 0; -} +#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) +{ + 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);
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.
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 codeThe
+ 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.
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.)
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
Given this evidence and related contextual clues, the only logical conclusions are:
-vmklinux_9
, as a binary object, dynamically links
- with k.b00
, another binary object, to form a single running
- binary.vmklinux_9
, a binary object, dynamically links with
+ the binary objects: k.b00
and tg3
(the
+ driver built from tg3.c
's source). These three binary
+ objects together form a single running binary (likely along with many
+ other binary objects as well).tg3.c
+ and pci.h
. Thus, the single running binary may be
+ distributed in binary form only under permissions provided under GPLv2
+ — in
+ particular GPLv2§2
+ and GPLv2§3.complete corresponding machine-readable source codemust accompany binary distributions such as these. GPLv2§3 further states that
for an executable work, complete source code means all the source code for all modules it contains.
k.b00
and
- vmlinux_9
.k.b00
,
+ vmlinux_9
and tg3
.k.b00
.vmk_PCIGetDeviceName
.
in k.b00
.The above is but one piece of evidence among many, but hopefully it helps - to explain the types of “combined work” violations found in + to explain some of the “combined work” violations found in VMware's ESXi product.