How to Audit a Device for GPL Compliance: A Practical Hardware Teardown

If you’re holding a piece of industrial IoT hardware or a consumer router and wondering whether the vendor is actually honouring the GPL, the only way to know for sure is to open it up and look. Not at the marketing slicks. Not at the shrink-wrap license. At the firmware. At the build scripts. At the exact kernel configuration that shipped on the device. I’ve spent the better part of a decade doing exactly this—tearing down embedded Linux products, diffing kernel sources, and catching the shortcuts that manufacturers hope nobody will notice. This is a concrete, step-by-step audit methodology that moves from physical inspection to filesystem forensics, and it ends with a clear verdict: compliant, or not.

Why a GPL Audit Matters for Industrial and Consumer Devices

Embedded Linux is the quiet backbone of modern hardware. It runs on programmable logic controllers, smart cameras, home routers, medical displays, and automotive infotainment stacks. The GPL—particularly GPLv2, which still dominates the Linux kernel—requires that anyone distributing a binary version of the covered code must also provide the corresponding source, including any modifications and the scripts used to control compilation. This isn’t a suggestion. It’s a condition of the license. When a vendor ships a locked-down IoT gateway with a modified kernel and no source offer, they’re not just being uncooperative; they’re violating a legal contract that gives them permission to use that code in the first place.

An audit is the process of systematically verifying that a device’s software distribution matches its source code offer. It sits at the intersection of reverse engineering, build-system forensics, and legal analysis. For an engineering team, the output of a proper audit is a clear, evidence-backed report that either confirms compliance or identifies specific violations. For a legal team, that same report becomes the foundation for a demand letter or a settlement negotiation. The audit itself is technical, but the stakes are legal and commercial.

Phase 1: Physical Inspection and Interface Discovery

Before touching any software, document the hardware. The goal is to identify every interface that could provide access to the device’s firmware, bootloader, or filesystem. This is where many audits fail prematurely—they rely on the vendor’s documentation, which often omits debug ports, unpopulated headers, or hidden recovery modes.

What to Look For on the Board

Remove the enclosure carefully. Use an anti-static mat. Photograph both sides of the main PCB under good light. Look for:

  • UART headers: Often a 4-pin or 6-pin header, sometimes unpopulated. Pins will typically be labelled TX, RX, GND, VCC. Even if unlabelled, you can identify them with a multimeter or logic analyser. A UART almost always gives you a bootloader console, and that console is your first window into the kernel command line and the boot process.
  • JTAG/SWD headers: Less common on consumer gear, but standard on industrial boards. A JTAG interface lets you halt the CPU, dump flash contents, and bypass any userspace restrictions entirely.
  • Unpopulated storage footprints: Empty pads for an SD card slot, eMMC, or SPI NOR flash. These tell you what the SoC supports and hint at how the vendor may have developed and tested the board before cost-reducing it.
  • Serial console labels: Look for silkscreen text like “CONSOLE”, “DEBUG”, “UART0”, or “J3”. Even if the header isn’t populated, the label confirms the interface exists.

Connect a USB-to-serial adapter (3.3V TTL is the safe default; never assume 5V unless the board explicitly states it) and watch the output during power-on. Capture the entire boot log. The bootloader prints valuable information: the exact kernel version, the kernel command line, memory mappings, and sometimes the build date and toolchain version. Save this log. It’s Exhibit A.

Phase 2: Extracting the Firmware Image

You need the exact binary firmware that the device runs. There are several paths to get it, and a vendor’s compliance often breaks down at this very step because they don’t provide the exact source corresponding to the exact binary they shipped.

Method 1: Download from the Vendor’s Website

Many vendors post firmware updates publicly. Download every version available. Check the file headers with binwalk or file. A compliant vendor will also post a corresponding source archive. If the source archive is missing, or if it’s a different version than the latest binary, that’s a red flag. If the source archive contains only tarballs of upstream projects with no indication of which patches were applied, that’s another red flag.

Method 2: Dump from the Device’s Flash

If no firmware is available online, you’ll need to dump it directly. Common approaches:

  • Via bootloader: If U-Boot is accessible and not locked down, use commands like md (memory display), mmc read, or sf read to dump flash regions over the serial console. This is slow but works on many devices.
  • Via a running system: If you can get a root shell (more on that later), read directly from /dev/mtd* or /dev/mmcblk* and transfer the image over the network.
  • Via hardware: Desolder the flash chip and read it with a programmer. This is the nuclear option, but it guarantees you get every byte, including bootloader and hidden partitions.

Once you have the firmware image, extract it. Use binwalk -e to carve out filesystems, or use tools like jefferson for JFFS2, unsquashfs for SquashFS, and ubireader for UBI/UBIFS. The goal is to reconstruct the root filesystem exactly as it appears on the device.

Phase 3: Kernel and Module Analysis

The Linux kernel is the heart of the GPL compliance question. Almost every embedded device runs a modified kernel—vendors add drivers, tweak board support, and apply out-of-tree patches. The GPL requires that all these modifications be provided in source form.

Identify the Exact Kernel Version

From the boot log or by running uname -a on the device, get the full kernel version string. It will look something like Linux version 4.9.84-custom-v1.2 (builder@buildhost) (gcc version 7.3.0) #1 SMP PREEMPT Thu Mar 15 10:22:45 UTC 2022. The “custom-v1.2” part is the vendor’s local version suffix. This is critical: it tells you that the vendor modified the kernel. If the source they provide doesn’t produce a kernel with this exact version string, they’re not compliant.

Check for Non-Standard Kernel Modules

List the loaded modules with lsmod or by examining /lib/modules/. Look for modules that aren’t part of the standard mainline kernel. Common examples: out-of-tree wireless drivers, custom GPIO controllers, proprietary filesystem modules. If a module’s license tag is “Proprietary” (check with modinfo), that’s a clear GPL violation unless the vendor has a separate commercial license from the kernel copyright holders—which is almost never the case. Even if the module is tagged “GPL”, the vendor must provide the source code. A binary-only GPL module is still a violation.

Verify the Kernel Configuration

The GPL requires that the vendor provide the exact kernel configuration used to build the running kernel. On the device, look for /proc/config.gz. If it exists, decompress it and save it. If it doesn’t, the vendor has explicitly disabled CONFIG_IKCONFIG, which is a common trick to hide the configuration. In that case, you’ll need to extract the configuration from the kernel image itself using tools like extract-ikconfig from the kernel source tree. Compare this configuration against the one provided in the vendor’s source package. They must match exactly. Mismatches—especially in security-relevant options like CONFIG_MODULE_SIG_FORCE or CONFIG_STRICT_DEVMEM—indicate that the vendor is not providing the true source.

Phase 4: Userspace and Copyleft Libraries

The kernel isn’t the only GPL-licensed component. Many userspace programs and libraries are covered by the GPL, LGPL, or other copyleft licenses. BusyBox, uClibc, glibc, iptables, and numerous other standard embedded components are GPLv2 or LGPLv2.1. The vendor must provide the exact source for the versions they ship.

Build a Bill of Materials

Extract the root filesystem and catalogue every binary. Use file to identify ELF binaries, then use strings to search for copyright and license notices. Many GPL binaries embed a reference to the source, like “BusyBox v1.24.2”. Cross-reference these versions against the source code the vendor provides. If the vendor ships source for BusyBox 1.24.1 but the binary is 1.24.2, that’s a violation. The source must correspond to the exact binary on the device.

Check for Scripts and Build Infrastructure

The GPL requires more than just the source code of the GPL components. It requires “the scripts used to control compilation and installation of the executable.” This means the vendor must provide any Makefiles, build scripts, toolchain wrappers, and configuration files needed to reproduce the binary. If the vendor ships a tarball of the Linux kernel source but doesn’t include the cross-compiler configuration, the defconfig, or the build script that sets the LOCALVERSION, they’re not compliant. You cannot reproduce the binary, and that’s the test.

Phase 4: Spotting Obfuscation and Bad-Faith Compliance

Some vendors know they’re violating the GPL and actively try to hide it. Others provide “source” that is technically present but practically useless. Here are the patterns I’ve seen repeatedly in the field:

  • The “Source” CD That Contains Only Upstream Tarballs: You request source and receive a disc with linux-4.9.tar.xz and busybox-1.24.2.tar.bz2, straight from kernel.org and busybox.net. No patches, no defconfig, no build scripts. This is not compliance; it’s a stall tactic.
  • The Mismatched Defconfig: The provided defconfig builds a kernel that boots but doesn’t match the running kernel’s feature set. Drivers are missing, filesystem support is different, the kernel version string is wrong. This is a partial source release, which is still a violation.
  • Stripped Binaries with Hidden License Strings: The vendor strips all symbols and strings from binaries to make analysis harder. This is a deliberate attempt to obscure the use of GPL code. You can still identify GPL components through fingerprinting—comparing the binary’s behaviour, size, and remaining strings against known builds—but it’s a clear sign of bad faith.
  • Locked Bootloaders Preventing Kernel Replacement: The GPL doesn’t require that the device be unlockable, but if the vendor ships a modified kernel and then locks the bootloader so you can’t run your own build, they’re violating the spirit of the license and possibly the letter, depending on jurisdiction. The Software Freedom Conservancy has successfully enforced cases where locked bootloaders prevented users from exercising their right to modify and reinstall GPL software.

Phase 5: Building and Comparing

The gold standard of a GPL audit is to take the vendor-provided source, build it using their instructions, and compare the resulting binary against the binary on the device. This is a bit-for-bit comparison. If the binaries don’t match, you need to understand why. Legitimate reasons for a mismatch include different build timestamps, different toolchain versions (if the vendor didn’t provide the exact toolchain), or non-deterministic build processes. But if the vendor provided the exact toolchain and the build scripts, the binaries should match. If they don’t, the vendor is withholding something—likely proprietary drivers or modifications they don’t want to release.

For the kernel, you can compare the vmlinux images. For userspace, compare individual binaries. Tools like vbindiff or radiff2 can help identify where the differences lie. If the differences are in a kernel module that handles a specific hardware peripheral, that’s a strong indicator of an unreleased driver.

Phase 5: Documenting the Findings

An audit isn’t complete until you’ve written it up. The report should be structured so that a legal team can act on it without needing to understand the technical details. Include:

  • Device identification: Model, hardware revision, firmware version, and any unique identifiers.
  • Evidence of GPL-covered code: Kernel version, BusyBox version, and any other copyleft components identified, with proof (e.g., strings output, boot log excerpts).
  • Source code analysis: What the vendor provided, what’s missing, and why it’s insufficient. Include a table mapping each binary to its source status: “Provided and matches,” “Provided but mismatched,” “Not provided.”
  • Build reproduction attempt: Step-by-step account of trying to build from the provided source, including any errors or missing dependencies.
  • Conclusion: A clear statement of whether the device is compliant, and if not, which specific GPL sections are violated.

This report is your advantage. It’s what you send to the vendor’s legal department, what you file with a court, or what you publish if the vendor refuses to engage. The facts, clearly presented, are hard to argue with.

Common Pitfalls and How to Avoid Them

Auditing embedded devices is detail work, and it’s easy to miss things. Here are the mistakes I see most often from engineers new to compliance work:

  • Assuming the vendor’s source archive is complete: Always verify. I’ve seen source packages that look correct at first glance but are missing a single critical patch that enables the device’s primary function.
  • Ignoring the toolchain: The GPL covers “scripts used to control compilation.” If the vendor used a custom GCC with proprietary optimizations, that toolchain must be provided. This is a contentious area, but the conservative interpretation is that the toolchain is part of the build infrastructure.
  • Overlooking dual-licensing: Some components are available under both GPL and commercial licenses. If the vendor paid for a commercial license, they don’t need to provide source for that component. But they must clearly document this, and the burden of proof is on them.
  • Not checking for license compatibility: A device can contain GPL code and still be non-compliant if the vendor combined it with code under an incompatible license. This is a more advanced analysis, but it’s worth flagging if you see it.

FAQ

What’s the first thing I should check when I suspect a GPL violation?

Start with the boot log. Connect a serial console and capture the full output during power-on. Look for the kernel version string, the bootloader version, and any references to proprietary modules. If the kernel version includes a vendor-specific suffix like “-custom” or “-vendor”, that’s a strong indicator of modifications that must be disclosed. Save the log immediately—it’s your baseline evidence.

Can a vendor comply by just pointing me to the upstream kernel source?

No. Pointing to kernel.org is not compliance. The GPL requires the vendor to provide the exact source code that corresponds to the binary they shipped, including any modifications, patches, and build scripts. If they modified the kernel—and almost every embedded device vendor does—they must provide those modifications. An upstream tarball with no patches is a clear violation.

What if the vendor claims their modifications are a trade secret?

The GPL does not recognize trade secrets as a valid reason to withhold source code. By choosing to use GPL-licensed code, the vendor accepted the obligation to share their modifications. If they want to keep their code proprietary, they must either write it from scratch without using GPL code, or negotiate a separate commercial license with the copyright holders. There is no middle ground.

How do I handle a device that uses a locked bootloader to prevent firmware replacement?

This is a grey area legally, but it’s increasingly being treated as a compliance issue. If the vendor ships a modified GPL kernel and then locks the bootloader so you cannot install your own version, they are effectively denying you the right to modify and run the software—a right the GPL explicitly grants. Document the locking mechanism, attempt to install a self-built kernel, and include the results in your audit report. Organizations like the Software Freedom Conservancy have successfully used this argument in enforcement actions.

Next Steps After the Audit

Once you have a clear finding of non-compliance, you have options. The most direct path is to send a formal notice to the vendor’s legal department, attaching the audit report and requesting the complete source code. Give them a reasonable deadline—30 days is standard. If they don’t respond, or if they respond with an incomplete source drop, you can escalate. In the United States, the copyright holders of the violated code (often the Linux kernel developers or the Software Freedom Conservancy) can bring a lawsuit. In Europe, the enforcement landscape is different but equally viable, with several successful cases in Germany under the jurisdiction of the Hamburg court.

For engineers, the audit is also a learning opportunity. Every teardown teaches you something about how embedded systems are built, how vendors cut corners, and how to design your own products for compliance from the start. The best way to avoid being on the receiving end of an audit is to build compliance into your development process: maintain a clean, reproducible build system, document every patch, and treat the source code as a deliverable, not an afterthought.

This article is part of a series on practical GPL compliance for embedded systems. The next piece will cover how to set up a reproducible build environment for Linux-based IoT devices, including containerized toolchains and automated compliance checks. If you have a device you’d like me to tear down, send the details through the contact page.

Close-up of a circuit board with exposed UART header pins and test probes attached
Engineer using a multimeter to test connectivity on an embedded Linux development board
Terminal screen displaying kernel boot log with version string and module loading messages