If you’ve ever cracked open a consumer router or a smart-home hub, you already know the secret: inside that plastic shell, Linux is doing the heavy lifting. And wherever Linux goes, the GPL follows. I’m Arjun Mehta, and I’ve spent more evenings than I’d like to count staring at hex dumps and half-baked source tarballs. Auditing a device for GPL compliance isn’t just a paperwork drill—it’s about making sure the open-source work that powers millions of products gets the respect it’s legally owed. This guide lays out a practical, step-by-step method to go from a sealed box to a documented compliance report.
What Are You Actually Auditing?
Before you reach for a screwdriver, get clear on the scope. A GPL audit homes in on the Linux kernel itself, any loadable kernel modules, and user-space programs covered by GPLv2, GPLv3, or LGPL. Proprietary apps that sit on top of the stack usually aren’t your target—unless they’re statically linked against GPL libraries. The real question is: can you get your hands on the exact, buildable source code for every GPL binary on the device, along with the scripts and toolchain pieces needed to compile and install it? If the answer is no, you’ve already found a problem.
Step 1: Get the Firmware and Paper Trail
Start by pulling the firmware image. For most routers, IoT gateways, and appliances, the vendor’s support site hosts downloadable updates. No public download? You might need to go hardware-level—dump the flash chip with a programmer or poke around the bootloader’s recovery mode. Note the firmware version, build date, and any checksums the manufacturer publishes. These details become your anchor when you later compare what’s promised with what’s actually running.

Next, hunt down the vendor’s open-source compliance page. Many companies maintain a GitHub org or a dedicated portal. Grab every archive tied to your device model and firmware revision. If all you find is a written offer buried in a manual, request the source formally and start a timer. The GPL says the source must be delivered on a medium “customarily used for software interchange.” A quick, complete response signals good faith; radio silence or a six-month delay does not.
Step 2: Unpack and Catalogue Every Binary
Now the fun begins. Use binwalk or firmware-mod-kit to tear apart the firmware image. These tools sniff out filesystems, compressed archives, and kernel images. Once you’ve got the root filesystem mounted, build a full file list with checksums. Zero in on the kernel image—zImage, uImage, or vmlinuz—plus all *.ko modules and shared libraries like libc, libpthread, and libstdc++. Don’t forget the executables sitting in /bin, /sbin, /usr/bin, and /usr/sbin.
For each binary, pin down the architecture and toolchain. The file command tells you the target CPU; readelf pulls out the GCC version and build ID. This is your fingerprint. If the source archive’s toolchain doesn’t match the binary’s build attributes, the vendor probably didn’t give you the exact code that produced the firmware.

Step 3: Verify the Kernel Source
The kernel is where most compliance headaches live. Extract the kernel image from the firmware. If it’s compressed, decompress it and run strings vmlinux | grep "Linux version" to grab the version string, compiler info, and any vendor-specific suffixes. Write it all down.
Now compare that against the vendor’s kernel source tree. The source should include a .config that matches the running kernel’s configuration. You can pull the config from a live device via /proc/config.gz if it’s enabled, or use extract-ikconfig on the kernel image. Mismatches between the provided .config and the actual config are a red flag—the vendor hasn’t released the complete, corresponding source.
Spotting Proprietary Kernel Modules
Vendors love to drop in out-of-tree modules for Wi-Fi chips or power management. That’s fine, as long as they aren’t statically linked into the kernel and don’t use GPL-only symbols while claiming a proprietary license. Run modinfo on each .ko file to check the license tag. Then dig into the kernel’s Module.symvers or use modprobe --dump-modversions to see if a “proprietary” module is secretly calling GPL-only functions. That’s a violation, plain and simple. Log every module and its license status.
Step 4: Audit User-Space GPL Components
Beyond the kernel, embedded devices often ship BusyBox, GNU Coreutils, or networking daemons under the GPL. Identify them by scanning binary names and using strings to hunt for copyright notices—strings /bin/busybox | grep "BusyBox" will spit out the version. Cross-check each GPL binary against the vendor’s source packages. The source must include the exact version, any patches, and the build scripts.
Look closely at how these programs were compiled. If the vendor used Buildroot or Yocto, the source offer should contain the full build environment: toolchain, rootfs overlay, and package recipes. A tarball of pristine upstream code isn’t enough if the vendor applied custom patches or linked against proprietary libraries. You need to be able to rebuild the binary and get a functionally equivalent result.

Step 5: Rebuild and Compare
The acid test is a reproducible build. Set up an environment that matches the toolchain you identified earlier. Compile the kernel and user-space pieces using the vendor’s source and config. Then compare your fresh binaries against the firmware originals. diffoscope is your friend here—it can see past timestamps and build paths to find meaningful differences. A bit-for-bit match is the gold standard, but functionally equivalent binaries that differ only in debug symbols or timestamps are usually acceptable.
If the build falls over, document every missing dependency, broken Makefile, or absent source file. A common headache: the vendor omitted proprietary toolchain components that are essential for compilation. The GPL doesn’t force a vendor to open-source their entire toolchain, but they must give you enough to build the GPL parts with a standard toolchain. If the build demands a secret compiler, the source offer is incomplete.
Step 6: Check the Written Offer and Legal Notices
Physical devices need a written offer for source code—usually in the manual or on a sticker. Make sure that offer is valid for at least three years and clearly states how to request the source. If the device has a screen, poke around for an “Open Source Licenses” page that lists every GPL component and its license. Missing notices? That’s a violation of GPLv2 Section 1 and GPLv3 Section 4.
For each GPL component, confirm the license text is included in the firmware or docs. The GPL requires recipients to get a copy of the license. If the device uses GPLv3 components, there are extra hoops: installation information that lets modified versions run on the hardware, and no anti-tivoization tricks that block a user from installing a custom kernel or app.
Common Pitfalls I’ve Seen
After years of doing this, I can spot the usual mistakes from a mile away. The “source dump” is a classic—a giant tarball with no build instructions. That doesn’t meet the “preferred form for making modifications” requirement. Another favorite: binary-only kernel modules that taint the kernel and quietly use GPL-only symbols. Sometimes vendors strip the license tag to hide it, but the symbol table doesn’t lie.
Watch for dead links on the vendor’s source page. A 404 or a download locked behind an NDA is a clear violation. The source must be publicly accessible to anyone who has the binary. If the vendor charges for physical media, the fee can’t exceed the cost of distribution. Inflated shipping or handling charges are just a way to discourage requests—and they’re not compliant.
Writing It All Down
An audit without a report is just a hobby. Document the device ID, firmware version, a list of every GPL binary, the corresponding source packages, and the rebuild results. For each violation, cite the specific GPL clause and attach the evidence. If you’re working for a copyright holder, this report becomes the backbone of a compliance notice. Even if you’re just auditing for your own knowledge, a solid report adds to the collective know-how that keeps the open-source world honest.
FAQ
What’s the bare minimum source code a vendor must provide under GPLv2?
GPLv2 Section 3 requires the complete corresponding source code: all source for all modules, plus interface definition files, plus the scripts that control compilation and installation. It must be in the preferred form for making modifications—real developer code, not obfuscated or preprocessed output.
How do I know if a kernel module is statically linked?
If the module is compiled into the kernel image instead of living as a separate .ko file, it’s statically linked. Check the kernel config: a y means built-in, an m means loadable. A proprietary driver baked into the kernel is a violation.
What if the vendor says the source code is lost?
The GPL doesn’t have a “lost source” exception. If the vendor can’t supply the code, they’re in breach and have no right to distribute the binary. Copyright holders can take legal action. In practice, a formal notice often pushes vendors to either release the code or pull the product.
Does the vendor have to provide the toolchain?
The GPL requires “scripts used to control compilation and installation.” If the build depends on a specific toolchain, the vendor must either provide it or make sure the source builds with a standard, publicly available toolchain. If they modified GCC for their toolchain, those modifications must be released under the GPL too.