Changeset - ea9a59c551f8
[Not reviewed]
0 1 0
Bradley Kuhn (bkuhn) - 9 years ago 2015-03-21 14:31:07
bkuhn@ebb.org
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.
1 file changed with 134 insertions and 20 deletions:
0 comments (0 inline, 0 general)
www/conservancy/static/linux-compliance/vmware-lawsuit-faq.html
Show inline comments
...
 
@@ -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 &ldquo;vmkernel&rdquo; in a tightly coupled manner.</p>
 
    </dd>
 

	
 
   <dt id="shim-meaningless">Is Conservancy proposing a &ldquo;shim
 
      layer&rdquo; 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
 
        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>
 

	
 
     <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
 
       many others as well into their kernel.</p>
 

	
 
       <h4>Example of &ldquo;vmkernel&rdquo;'s combination with Linux code</h4>
 
       <p>As one example, examine the file
 
       <h3>Example of &ldquo;vmkernel&rdquo;'s combination with Linux code</h3>
 
       <p>Our example begins with examination of the file
 
           called <code>vmkdrivers/src_92/vmklinux_92/vmware/linux_pci.c</code>,
 
           which can be found in the &ldquo;Open Source&rdquo; release for
 
           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>
 

	
 
<pre>
 
if (unlikely(
 
  /* NOTE: vmk_PCIGetDeviceName is defined in vmvisor64-vmkernel */
 
  vmk_PCIGetDeviceName(vmkDev, vmkDevName, sizeof(vmkDevName)-1) != VMK_OK))
 
#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)
 
{
 
    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);
 
</pre>        
 

	
 
<h4>Combination of &ldquo;vmkernel&rdquo; code with &ldquo;vmkdrivers&rdquo;</h4>
 

	
 
<p>The function, <code>vmk_PCIGetDeviceName()</code> must be defined, with an
 
      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>,
...
 
@@ -286,28 +297,131 @@ VMKAPI_MODULE_CALL_VOID(pciDevExt->moduleID,
 
<p>&hellip; which indicated these binary file contains the function body
 
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
 
  to <code>vmk_PCIGetDeviceName</code>.  This provides a strong indication
 
  that this function's primary purpose is to combine Linux code with
 
  &ldquo;vmkernel&rdquo;.  Conservancy also found other functions where similar analysis
 
  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 &ldquo;vmkernel&rdquo;</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 &ldquo;vmkernel&rdquo;</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
 
  conclusions are:</p>
 
    <ul><li><code>vmklinux_9</code>, as a binary object, dynamically links
 
 with <code>k.b00</code>, another binary object, to form a single running
 
 binary.</li>
 
      <li>That binary contains code licensed under the GPLv2, and can be
 
       distributed in binary form only under permissions provided under
 
        GPLv2 &mdash; in particular <a href="https://gnu.org/licenses/gpl-2.0.html#section2">GPLv2&sect;2</a> and <a href="https://gnu.org/licenses/gpl-2.0.html#section3">GPLv2&sect;3</a>.</li>
 
    <ul><li><code>vmklinux_9</code>, a binary object, dynamically links with
 
        the binary objects: <code>k.b00</code> and <code>tg3</code> (the
 
        driver built from <code>tg3.c</code>'s source).  These three binary
 
        objects together form a single running binary (likely along with many
 
        other binary objects as well).</li>
 
      <li>That single running binary contains code licensed under the GPLv2
 
       &mdash; 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
 
       &mdash; in
 
       particular <a href="https://gnu.org/licenses/gpl-2.0.html#section2">GPLv2&sect;2</a>
 
       and <a href="https://gnu.org/licenses/gpl-2.0.html#section3">GPLv2&sect;3</a>.</li>
 
      <li>GPLv2&sect;3(a&ndash;b) requires that <q>complete corresponding
 
          machine-readable source code</q> must accompany binary
 
          distributions such as these.  GPLv2&sect;3 further states
 
          that <q>for an executable work, complete source code means all the
 
          source code for all modules it contains</q>.</li>
 
      <li>The binary work in question contains modules from <code>k.b00</code> and
 
        <code>vmlinux_9</code>.</li>
 
      <li>The binary work in question contains modules from <code>k.b00</code>,
 
        <code>vmlinux_9</code> and <code>tg3</code>.</li>
 
      <li>VMware did not provide source code for any modules found in
 
        <code>k.b00</code>.</li>
 
      <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>
 
    </ul>
 
<p>The above is but one piece of evidence among many, but hopefully it helps
 
  to explain the types of &ldquo;combined work&rdquo; violations found in
 
  to explain some of the &ldquo;combined work&rdquo; violations found in
 
  VMware's ESXi product.</p>
 

	
 
<dt id="verify">How can I verify Conservancy's technical findings above?</dt>
0 comments (0 inline, 0 general)