Improve FAQ entry: VMware violation tech example
Add additional information and details about the technical details of the VMware violation. This extends the existing example with more detail and improves various other parts related in the FAQ.
This commit is contained in:
parent
83c97a0029
commit
ea9a59c551
1 changed files with 135 additions and 21 deletions
|
@ -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
|
whole was developed by modifying Linux code in tandem with
|
||||||
modifications to “vmkernel” in a tightly coupled manner.</p>
|
modifications to “vmkernel” in a tightly coupled manner.</p>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt id="shim-meaningless">Is Conservancy proposing a “shim
|
<dt id="shim-meaningless">Is Conservancy proposing a “shim
|
||||||
layer” as a viable solution for GPL compliance?</dt>
|
layer” as a viable solution for GPL compliance?</dt>
|
||||||
|
|
||||||
|
@ -190,7 +189,7 @@ Code, and for which (at least some) source code is provided.
|
||||||
technological manipulation that changes the outcome of a
|
technological manipulation that changes the outcome of a
|
||||||
combined/derivative work analysis.</dd>
|
combined/derivative work analysis.</dd>
|
||||||
|
|
||||||
<dt>Can you give a <em>specific</em> example, with code, showing how
|
<dt id="example">Can you give a <em>specific</em> example, with code, showing how
|
||||||
VMware combined Linux source code with their binary-only components?</dt>
|
VMware combined Linux source code with their binary-only components?</dt>
|
||||||
|
|
||||||
<dd><p>There are numerous examples available that show this. The
|
<dd><p>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
|
Hellwig's copyrights; VMware incorporated Linux code copyrighted by
|
||||||
many others as well into their kernel.</p>
|
many others as well into their kernel.</p>
|
||||||
|
|
||||||
<h4>Example of “vmkernel”'s combination with Linux code</h4>
|
<h3>Example of “vmkernel”'s combination with Linux code</h3>
|
||||||
<p>As one example, examine the file
|
<p>Our example begins with examination of the file
|
||||||
called <code>vmkdrivers/src_92/vmklinux_92/vmware/linux_pci.c</code>,
|
called <code>vmkdrivers/src_92/vmklinux_92/vmware/linux_pci.c</code>,
|
||||||
which can be found in the “Open Source” release for
|
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
|
ESXi 5.5.0 Update 2 (5.5U2). A small excerpt from that file, found in the
|
||||||
function <code>LinuxPCIDeviceRemoved()</code>, reads as follows:</p>
|
function <code>LinuxPCIDeviceRemoved()</code>, reads as follows:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
[...]
|
||||||
|
/*
|
||||||
|
* 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(
|
if (unlikely(
|
||||||
/* NOTE: vmk_PCIGetDeviceName is defined in vmvisor64-vmkernel */
|
|
||||||
vmk_PCIGetDeviceName(vmkDev, vmkDevName, sizeof(vmkDevName)-1) != VMK_OK))
|
vmk_PCIGetDeviceName(vmkDev, vmkDevName, sizeof(vmkDevName)-1) != VMK_OK))
|
||||||
{
|
{
|
||||||
vmkDevName[0] = 0;
|
vmkDevName[0] = 0;
|
||||||
}
|
}
|
||||||
[...]
|
[...]
|
||||||
/* VMKAPI_MODULE_CALL_VOID is a macro calling driver's remove() here */
|
|
||||||
VMKAPI_MODULE_CALL_VOID(pciDevExt->moduleID,
|
VMKAPI_MODULE_CALL_VOID(pciDevExt->moduleID,
|
||||||
linuxDev->driver->remove,
|
linuxDev->driver->remove,
|
||||||
linuxDev);
|
linuxDev);
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<h4>Combination of “vmkernel” code with “vmkdrivers”</h4>
|
||||||
|
|
||||||
<p>The function, <code>vmk_PCIGetDeviceName()</code> must be defined, with an
|
<p>The function, <code>vmk_PCIGetDeviceName()</code> must be defined, with an
|
||||||
implementation, for this code above to work, or even compile.
|
implementation, for this code above to work, or even compile.
|
||||||
Inside <code>BLD/build/HEADERS/vmkapi-current-all-public/vmkernel64/release/device/vmkapi_pci_incompat.h</code>,
|
Inside <code>BLD/build/HEADERS/vmkapi-current-all-public/vmkernel64/release/device/vmkapi_pci_incompat.h</code>,
|
||||||
|
@ -286,28 +297,131 @@ VMKAPI_MODULE_CALL_VOID(pciDevExt->moduleID,
|
||||||
<p>… which indicated these binary file contains the function body
|
<p>… which indicated these binary file contains the function body
|
||||||
for <code>vmk_PCIGetDeviceName</code>.</p>
|
for <code>vmk_PCIGetDeviceName</code>.</p>
|
||||||
|
|
||||||
<p>Finally, after detailed searching, Conservancy found no evidence that any
|
<p>Furthermore, after detailed searching, Conservancy found no evidence that any
|
||||||
other code (other than modified Linux code) makes calls
|
other code (other than modified Linux code) makes calls
|
||||||
to <code>vmk_PCIGetDeviceName</code>. This provides a strong indication
|
to <code>vmk_PCIGetDeviceName</code>. This provides a strong indication
|
||||||
that this function's primary purpose is to combine Linux code with
|
that this function's primary purpose is to combine Linux code with
|
||||||
“vmkernel”. Conservancy also found other functions where similar analysis
|
“vmkernel”. Conservancy also found other functions where similar analysis
|
||||||
yields similar results as above.</p>
|
yields similar results as above.</p>
|
||||||
|
|
||||||
|
<h4>Linux's <code>struct pci</code> combined with <code>LinuxPCIDeviceRemoved()</code></h4>
|
||||||
|
|
||||||
|
<p>Having established the direct and close combination
|
||||||
|
of <code>vmk_PCIGetDeviceName</code>
|
||||||
|
and <code>LinuxPCIDeviceRemoved()</code>, focus now on the
|
||||||
|
quoted code from <code>LinuxPCIDeviceRemoved()</code>. That code, note
|
||||||
|
that one of the local variables is <code>struct pci_dev *linuxDev;</code>.
|
||||||
|
A definition of <code>pci_dev</code> is found in
|
||||||
|
<code>vmkdrivers/src_92/include/linux/pci.h</code> (which
|
||||||
|
is <code>#include</code>'d above) reads:
|
||||||
|
<pre>
|
||||||
|
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__) */
|
||||||
|
};
|
||||||
|
</pre></p>
|
||||||
|
|
||||||
|
<p>These structures, and based on those from Linux itself
|
||||||
|
(<a href="http://lxr.free-electrons.com/source/include/linux/pci.h?v=2.6.24">a
|
||||||
|
similar version of this file can be seen in Linux 2.6.24</a>), and as can
|
||||||
|
be seen above, have been modified to work with “vmkernel”</p>
|
||||||
|
|
||||||
|
<p>In <code>LinuxPCIDeviceRemoved()</code>, we saw a macro called with a
|
||||||
|
variable, <code>linuxDev</code> which was of type <code>struct pci</code>.
|
||||||
|
Thus, the combination of code from Linux's <code>pci.h</code>
|
||||||
|
and VMware's <code>vmware/linux_pci.c</code> is very tightly coupled and
|
||||||
|
interdependent.</p>
|
||||||
|
|
||||||
|
<h4><code>VMKAPI_MODULE_CALL_VOID</code> macro calls driver's code</code></h4>
|
||||||
|
|
||||||
|
<p>The
|
||||||
|
file <code>BLD/build/HEADERS/vmkapi-current-all-public/vmkernel64/release/base/vmkapi_module.h</code>
|
||||||
|
contains the macro definition of <code>VMKAPI_MODULE_CALL_VOID</code>,
|
||||||
|
which is quoted below (with debug lines removed):
|
||||||
|
<pre>
|
||||||
|
#define VMKAPI_MODULE_CALL_VOID(moduleID, function, args...) \
|
||||||
|
do { \
|
||||||
|
vmk_ModInfoStack modStack; \
|
||||||
|
vmk_ModulePushId(moduleID, function, &modStack); \
|
||||||
|
(function)(args); \
|
||||||
|
) \
|
||||||
|
vmk_ModulePopId(); \
|
||||||
|
} while(0)
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>When the macro is expanded, it means that <code>(function)(args)</code> is
|
||||||
|
actually expanded to <code>linuxDev->driver->remove(linuxDev)</code>.
|
||||||
|
Therefore, we see <code>LinuxPCIDeviceRemoved()</code>, makes directs calls
|
||||||
|
to a driver's remove() function, by combining with Linux's <code>struct
|
||||||
|
pci</code>, 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.</p>
|
||||||
|
|
||||||
|
<h4>Combination of the tg3 driver with “vmkernel”</h4>
|
||||||
|
|
||||||
|
<p>VMware includes a file <code>vmkdrivers/src_9/drivers/net/tg3/tg3.c</code>
|
||||||
|
in their source release. This file appears to be Linux's tg3 driver. It
|
||||||
|
includes a definition of the <code>struct pci_dev</code> for this device,
|
||||||
|
which reads:
|
||||||
|
<pre>
|
||||||
|
static struct pci_driver tg3_driver = {
|
||||||
|
[...]
|
||||||
|
.remove = __devexit_p(tg3_remove_one),
|
||||||
|
</pre>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Therefore, when the code in <code>LinuxPCIDeviceRemoved()</code>
|
||||||
|
calls <code>linuxDev->driver->remove(linuxDev)</code>, the code ultimately
|
||||||
|
called (in the case where a tg3 card is driven by the kernel)
|
||||||
|
is <code>tg3_remove_one()</code>, which is found in <code>tg3.c</code> and
|
||||||
|
comes directly from Linux.</p>
|
||||||
|
|
||||||
|
<p>(Note: <code>__devexit_p</code> is a straightforward macro found
|
||||||
|
in <code>vmkdrivers/src_92/include/linux/init.h</code> (which also comes
|
||||||
|
from Linux) that will simply expand to its first argument in this
|
||||||
|
case.)</p>
|
||||||
|
|
||||||
|
<h4>VMware distribution of binary version of <code>tg3.c</code></h4>
|
||||||
|
|
||||||
|
<p>VMware furthermore distributes a modified version of <code>tg.c</code> in
|
||||||
|
binary form. This can be found in <code>usr/lib/vmware/vmkmod/tg3</code>,
|
||||||
|
which is extracted by un-vmtar'ing the file <code>net_tg3.v00</code> (found
|
||||||
|
on the ESXi 5.5U2 installer ISO image). Conservancy has confirmed that
|
||||||
|
file is a compiled version of <code>tg3.c</code></p>
|
||||||
|
|
||||||
|
<h4>Conclusions</h4>
|
||||||
|
|
||||||
<p>Given this evidence and related contextual clues, the only logical
|
<p>Given this evidence and related contextual clues, the only logical
|
||||||
conclusions are:</p>
|
conclusions are:</p>
|
||||||
<ul><li><code>vmklinux_9</code>, as a binary object, dynamically links
|
<ul><li><code>vmklinux_9</code>, a binary object, dynamically links with
|
||||||
with <code>k.b00</code>, another binary object, to form a single running
|
the binary objects: <code>k.b00</code> and <code>tg3</code> (the
|
||||||
binary.</li>
|
driver built from <code>tg3.c</code>'s source). These three binary
|
||||||
<li>That binary contains code licensed under the GPLv2, and can be
|
objects together form a single running binary (likely along with many
|
||||||
distributed in binary form only under permissions provided under
|
other binary objects as well).</li>
|
||||||
GPLv2 — in particular <a href="https://gnu.org/licenses/gpl-2.0.html#section2">GPLv2§2</a> and <a href="https://gnu.org/licenses/gpl-2.0.html#section3">GPLv2§3</a>.</li>
|
<li>That single running binary contains code licensed under the GPLv2
|
||||||
|
— namely the code derived from <code>tg3.c</code>
|
||||||
|
and <code>pci.h</code>. Thus, the single running binary may be
|
||||||
|
distributed in binary form only under permissions provided under GPLv2
|
||||||
|
— in
|
||||||
|
particular <a href="https://gnu.org/licenses/gpl-2.0.html#section2">GPLv2§2</a>
|
||||||
|
and <a href="https://gnu.org/licenses/gpl-2.0.html#section3">GPLv2§3</a>.</li>
|
||||||
<li>GPLv2§3(a–b) requires that <q>complete corresponding
|
<li>GPLv2§3(a–b) requires that <q>complete corresponding
|
||||||
machine-readable source code</q> must accompany binary
|
machine-readable source code</q> must accompany binary
|
||||||
distributions such as these. GPLv2§3 further states
|
distributions such as these. GPLv2§3 further states
|
||||||
that <q>for an executable work, complete source code means all the
|
that <q>for an executable work, complete source code means all the
|
||||||
source code for all modules it contains</q>.</li>
|
source code for all modules it contains</q>.</li>
|
||||||
<li>The binary work in question contains modules from <code>k.b00</code> and
|
<li>The binary work in question contains modules from <code>k.b00</code>,
|
||||||
<code>vmlinux_9</code>.</li>
|
<code>vmlinux_9</code> and <code>tg3</code>.</li>
|
||||||
<li>VMware did not provide source code for any modules found in
|
<li>VMware did not provide source code for any modules found in
|
||||||
<code>k.b00</code>.</li>
|
<code>k.b00</code>.</li>
|
||||||
<li>Therefore, VMware failed to comply with the GPLv2, as such
|
<li>Therefore, VMware failed to comply with the GPLv2, as such
|
||||||
|
@ -315,7 +429,7 @@ for <code>vmk_PCIGetDeviceName</code>.</p>
|
||||||
in <code>k.b00</code>.</li>
|
in <code>k.b00</code>.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>The above is but one piece of evidence among many, but hopefully it helps
|
<p>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.</p>
|
VMware's ESXi product.</p>
|
||||||
|
|
||||||
<dt id="verify">How can I verify Conservancy's technical findings above?</dt>
|
<dt id="verify">How can I verify Conservancy's technical findings above?</dt>
|
||||||
|
|
Loading…
Reference in a new issue