When you buy a gadget that runs Linux—a router, a smart TV, maybe a car infotainment system—you’re not just getting hardware. You’re getting a whole software stack, and a big chunk of it is licensed under the GNU General Public License. The GPL gives you the right to run, study, share, and modify that code. But those rights are hollow if you can’t actually get the source. I’ve spent years cracking open consumer electronics to see if the manufacturers are playing by the rules. This guide walks you through a real, hands-on audit, from first glance to final report.
Understanding the Scope of Your Audit
Before you even plug the thing in, know what you’re hunting for. The GPL—especially versions 2 and 3—requires distributors to provide the “Corresponding Source.” That’s not just a link to kernel.org. It means the exact source code, build scripts, and configuration files used to create the binaries running on that specific device. A tarball of a generic Linux kernel is a dodge, not compliance. Your job is to prove the difference.
Phase 1: Initial Reconnaissance and Documentation
Start with the device as a black box. Note the model number, hardware revision, and the firmware version displayed in the UI. Check the manufacturer’s website for a source code offer—often a zip file buried in a “Legal” or “Open Source” page. Download it immediately and archive it. These links rot. Compare the date on that source package with the firmware build date on the device. A stale source archive is one of the most common violations I see.

Phase 2: Getting the Firmware Out
To do a real audit, you need to get inside. The approach depends on the hardware. For many routers and IoT devices, the firmware update file is sitting right on the support page. That’s the easy path. If there’s no download, you’ll need to pull the firmware directly from the hardware. This might mean connecting to UART serial headers, reading the flash chip with a Bus Pirate or Dediprog, or—if you’re lucky—finding an open ADB connection on an Android-based device.
Picking Apart the Firmware Update File
Got a firmware binary? Your first tool is binwalk. It scans for embedded file signatures. Run binwalk -Me firmware.bin and let it automatically extract filesystems, compressed archives, and kernels. The output usually reveals a multi-stage bootloader, a compressed Linux kernel, and a root filesystem—often SquashFS, JFFS2, or UBIFS. Mount that root filesystem on your analysis machine and you’re ready for the static audit.

Phase 3: Static Analysis of the Root Filesystem
With the root filesystem mounted, your goal is to catalog every GPL-covered executable and library. Start with the kernel. The uncompressed image usually sits in /boot or at the filesystem root. Run file on it to confirm. Then look for the GPL license text itself. GPLv2 requires a copy to be included with the distribution. Search for files named COPYING or LICENSE. Missing? That’s a clear violation right there.
Now, hunt down the GPL binaries. BusyBox is the prime target—it’s a single binary packing dozens of Unix tools, licensed under GPLv2. You’ll often find it in /bin or /sbin. Run strings busybox | grep -i "copyright" to confirm its origin. Also check for the Linux kernel itself, the U-Boot bootloader, and GPL libraries like libutil.so or libpthread.so. Document the exact version strings for each. You can grab these by running the binary with --version in a QEMU emulation environment or by grepping through strings output for version banners.
Phase 4: Verifying the Provided Source Code
Now turn to the source package the manufacturer gave you. The GPL demands the “preferred form of the work for making modifications.” A tarball of the raw root filesystem doesn’t count. You need the actual source files, build scripts, and toolchain details. Start by comparing the version strings you documented from the binaries with what’s in the source. Does the source package contain the exact same BusyBox version? Is the kernel source there, complete with the specific patches and the .config file used to build the running kernel? The kernel configuration is a big deal. You can sometimes pull it from the device via /proc/config.gz if the kernel was built with that option. If not, you must demand that exact .config from the manufacturer.
A thorough audit means trying to rebuild the binaries from the provided source. This is the acid test. Set up a cross-compilation toolchain for the device’s architecture—ARM, MIPS, whatever—and try to compile the kernel and key user-space components. The resulting binaries should be bit-for-bit identical to what’s on the device, or at least functionally identical with matching symbol tables. If the build fails, if files are missing, or if the linker throws errors, you’ve found a compliance gap. Pay close attention to proprietary kernel modules. The GPL allows them under some interpretations, but the kernel itself and any statically linked or derivative works must have source available. If a module’s license tag says “Proprietary” but it uses GPL-only exported symbols, that’s a red flag for a derivative work violation.

Phase 5: Dynamic Analysis and Runtime Verification
Static analysis of the firmware image isn’t always enough. Some devices download extra GPL components at runtime or use loadable kernel modules that don’t show up in a static dump. To catch those, you need shell access on the running device. This often means a serial console, an exposed debug port, or exploiting a vulnerability. Once you have a shell, run cat /proc/version to see the exact kernel build string, lsmod to list loaded modules, and cat /proc/mounts to understand the filesystem layout. Use ps to list all running processes and spot any GPL-licensed daemons—dnsmasq or ntpd, for example—that you might have missed in the static image.
For each GPL binary you find running, check that its source is in the provided archive. If the manufacturer hasn’t provided any source at all, a simple request citing the GPL is your first move. Document the request carefully: device model, firmware version, and the specific GPL components you’ve identified. Silence or a refusal to hand over the complete corresponding source is a clear violation.
Common Compliance Pitfalls and How to Spot Them
Over the years, I’ve seen the same patterns of non-compliance pop up again and again. One is the “source dump” with no build scripts. You get a kernel tarball, but without the .config file and out-of-tree patches, it’s practically useless for exercising your freedom to modify and rebuild. Another is the “proprietary blob” problem: a manufacturer links a proprietary user-space app against a GPL library without providing the object files or source for the app, as the GPL’s linking provisions require. A third, more subtle issue is using GPLv3 components in a device that enforces secure boot restrictions, blocking you from running modified software. That’s a direct violation of GPLv3’s anti-tivoization clauses.
Checking for Anti-Tivoization Measures
If the device uses GPLv3 code—like the GRUB2 bootloader or certain coreutils—you need to check for installation restrictions. GPLv3 requires that the device let you deploy your own modified versions of that GPLv3 software. A locked bootloader that only accepts cryptographically signed kernels is a violation if it stops you from running a modified GPLv3 bootloader or kernel. To test this, try interrupting the boot process and loading a custom image via TFTP or a USB drive. If the bootloader is locked and the manufacturer won’t provide signing keys or a way to disable signature verification, they’re in breach of the license.
Documenting Your Findings and Taking Action
Your audit should end with a clear, factual report. For each GPL component, build a table with these columns: Component Name, Version Found on Device, Source Provided by Manufacturer, Source Completeness, and Compliance Status. Be precise. Instead of writing “source is incomplete,” write: “The provided BusyBox 1.30.1 source archive is missing the applets/applet_tables.c file, which is generated during the build process. The build script gen_build_files.sh is also absent, making a reproducible build impossible.” That level of detail is hard to argue with.
If you find violations, your first step is usually to contact the manufacturer’s designated GPL compliance officer or legal department. A firm, polite, and technically detailed email often gets results. If the manufacturer goes silent or refuses to comply, you can escalate to the copyright holders of the infringed software. Organizations like the Software Freedom Conservancy and the Free Software Foundation run enforcement programs and can bring legal pressure on behalf of developers. Remember, the GPL is a copyright license, and only the copyright holder has legal standing to enforce it. Your role as an auditor is to hand them the evidence they need.
FAQ: GPL Compliance Auditing
What is the first thing I should check when I receive a source code offer from a manufacturer?
The very first check is the completeness of the archive against the device’s firmware version. Verify that the source code package corresponds to the exact firmware version running on your device. A common tactic is to provide source for an older, generic version while the device runs a newer, modified build. Check the build dates and version strings meticulously.
How can I tell if a binary is statically or dynamically linked to a GPL library?
Use the file and readelf commands on the binary. file binary_name will tell you if it is “statically linked” or “dynamically linked.” For a deeper look, readelf -d binary_name | grep NEEDED will list the shared libraries it depends on. If any of those libraries are GPL-licensed, the binary’s license must be compatible. If the binary is statically linked and contains GPL code, the entire binary must be distributed under the GPL, and its source code must be provided.
What is the significance of the “written offer” in GPLv2, and how does it apply to physical devices?
GPLv2 Section 3(b) allows distributors to provide source code via a written offer, valid for three years, to give any third party a copy of the source on a physical medium. For a device, this means the offer must be included with the product, typically in the manual or on the packaging. The offer must be clear and conspicuous. If you buy a device and there is no written offer, the distributor is already in violation, even before you request the source. The offer must also be valid for anyone, not just the original purchaser.
How do I handle a situation where the manufacturer claims a GPL component is a “derivative work” of their proprietary code and thus exempt?
This is a complex legal area, but technically, you can analyze the binary. If a proprietary kernel module uses GPL-only exported symbols (check with modprobe --show-depends or by analyzing Module.symvers), it is a strong indicator that it is a derivative work of the kernel. The burden of proof is on the manufacturer to show that their code is not a derivative work. You can document the symbol usage and present it as evidence of a likely violation to the kernel copyright holders, who can then make the legal determination.