Developer working at multiple monitors with code and terminal windows open
Kernel Development
William  

How to Contribute to Linux: Start With Documentation

The fastest way to learn how to contribute to Linux isn't opening a pull request, it's reading. Pick one subsystem, build the kernel yourself, boot it under a debugger, and make your first patch a documentation fix or a checkpatch cleanup that you verified by hand. A pasted diff you don't understand gets you nowhere. A one-line fix you can explain to a maintainer gets you in.

Last updated: 2026-07-21

Contributing to the Linux kernel is both exciting and daunting. It's the heart of one of the most important software systems in the world, running on millions of devices, servers, and computers globally. Linux holds about 63.1% of the global server operating system market, so the code you touch runs almost everywhere that matters. But how do you go from simply using Linux to actually improving it? The idea of contributing to such a vast project can seem overwhelming. The truth is, anyone with the right mindset and a bit of patience can do it.

You don't need to be a programming wizard or have twenty years of kernel experience. You need a willingness to learn, attention to detail, and the discipline to understand a fix before you send it. In this guide I'll walk you through the process, explain what's actually involved, and share the things that trip up beginners. By the end you'll have a real roadmap for your first contribution.

What does it actually mean to contribute to Linux?

Contribution is a spectrum, not a single act. Most people picture writing a device driver, but the kernel needs far more than driver code. It needs documentation that isn't wrong, tests that catch regressions, and cleanups that keep the tree readable. All of it counts, and all of it gets your name in the git log.

Here is the honest range, from lowest barrier to highest:

Contribution typeSkill neededRisk if you get it wrong
Documentation fixesRead English, read codeAlmost none
Coding-style and checkpatch cleanupsBasic C, run one scriptLow
kselftest and test scriptsC or shell, know the subsystemLow to medium
Bug fixesC, debugging, root-cause skillsMedium
Driver developmentC, hardware access, subsystem depthHigh
Subsystem maintainershipAll of the above, plus years of trustYou own other people's mistakes

Start at the top of that table, not the bottom. The people who burn out are the ones who try to land a driver as patch number one. Small, correct, and finished beats big, broken, and abandoned every time.

What do you need to know before contributing to the Linux kernel?

You need three things before you write a line: C fluency, git, and an email-based workflow. Skip any one of them and you'll spend your first week fighting tooling instead of code.

The kernel is written in C, so you have to read and debug C comfortably. Not "I did a tutorial once" comfortable. You should understand pointers, memory layout, and why a NULL dereference panics a machine. If that's shaky, spend a month on plain C first. The kernel is a bad place to learn what a pointer is.

Next, learn git properly, because the whole project runs on it. And learn the mailing-list workflow, which is not GitHub. Patches go out as email, reviews come back as email, and nobody is going to accept your web pull request. Before anything else, read the process docs shipped in the tree under Documentation/process. Start with submitting-patches.rst and coding-style.rst. Those two files answer most of the questions beginners ask on the list.

One more thing nobody tells you: every patch needs a Signed-off-by line, and it's a legal statement, not a formality. It means you have the right to submit that code under the Developer Certificate of Origin. Read it once so you know what you're agreeing to.

How do you set up a Linux kernel development environment?

Terminal window displaying kernel compilation process and build output

Build the kernel before you change anything. A clean build proves your toolchain works, and it gives you a baseline so you know any breakage later is yours. Here is what I do, in order.

  1. Install a Linux system. Ubuntu or Fedora are fine for beginners. Run it on real hardware or in a virtual machine, whichever you're happy to break.
  2. Install the build tools. You need GCC, make, git, flex, bison, and the ncurses dev libraries for the config menus. An editor like Vim or VS Code, whatever you already know.
  3. Clone Torvalds' tree. This is the mainline source:
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

That URL is the official Linux kernel repository. Clone this one, not a random mirror.
4. Build it. From the source directory:

make defconfig
make -j$(nproc)

defconfig gives you a sane default config for your architecture. -j$(nproc) runs one job per CPU so the build finishes this year.

The step almost everyone skips is booting your build in a virtual machine instead of on bare metal. Boot the freshly built kernel under QEMU. If it panics, you rerun QEMU. If it panics on your laptop, you're reaching for a rescue USB stick. Point QEMU at your arch/x86/boot/bzImage and a small root image, and you can crash it fifty times before lunch.

Turn on debug options while you're here. Enable CONFIG_DEBUG_KERNEL, CONFIG_DEBUG_INFO, and friends so you can run the thing under gdb and read real symbols instead of raw addresses. My guide to enabling kernel config options covers where these live, and make menuconfig walks the menu if the config file overwhelms you. Verify your build boots and gives you a shell before you touch a single source file.

How do you choose a subsystem to focus on?

Pick one subsystem and go deep, because nobody contributes to "the kernel" in general. The tree is enormous, and every part has its own maintainers, style, and mailing list. Trying to float across all of it means you never learn any of it well.

Use three filters to choose:

  • Interest. What actually pulls you in? Filesystems, networking, a specific driver class, memory management. You'll read thousands of lines, so pick something you don't hate.
  • Hardware access. If you want to touch a driver, you need the device on your desk. You cannot meaningfully test a Wi-Fi driver for a card you don't own.
  • Activity. Open the MAINTAINERS file and find the subsystem's entry. A subsystem with active maintainers and a busy list will review your patch. A dormant one will leave it sitting for months.

Run ./scripts/get_maintainer.pl against a file you're curious about and see who owns it. Then go read that subsystem's mailing-list archive for a week before you write anything. You'll learn the local customs, the ongoing arguments, and what kinds of patches get accepted. That reconnaissance saves you from sending a patch that violates an unwritten rule everyone else already knows.

How do you make your first contribution as a beginner?

Make your first patch a documentation fix or a checkpatch cleanup, and nothing bigger. These are real, accepted contributions, and they teach the whole submission workflow without the risk of breaking a running kernel. You learn how to send a patch on a change that can't crash anyone's machine.

Documentation is the genuine low-hanging fruit. The docs drift out of date, examples go stale, and typos live for years. Fix one, and you've learned git format-patch and git send-email on a change where the worst case is a clearer sentence.

For code cleanups, run the style checker that ships in the tree:

./scripts/checkpatch.pl --file drivers/some/file.c

It prints style violations: bad whitespace, lines over the limit, missing braces. Fix them, rerun it until it's clean, and you have a valid patch. For a step up, learn Coccinelle, the kernel's pattern-based refactoring tool. The .cocci scripts under scripts/coccinelle find real classes of bugs and mechanical fixes across the whole tree.

Here is the trap. Do not blast out fifty auto-generated cleanup patches you don't understand. Maintainers have seen that a thousand times and it wastes their review time. Fix a few, read the diff line by line, and be ready to explain why each change is correct. One cleanup you can defend beats a script's output you can't.

The old "Kernel Janitors" effort and the Linux Kernel Mailing List archives are good places to find these small tasks and see how accepted patches read.

How do you find and fix real kernel bugs?

Find the root cause before you write the fix, or the bug comes back wearing a different hat. The kernel gives you strong tools for this, and none of them is "copy the patch someone posted to the list."

Start with the tools that show you what actually happened:

  • syzkaller is the kernel's automated fuzzer. It hammers system calls and reports crashes with reproducers. The public dashboard is full of open bugs with a ready-made way to trigger them, which is gold for a beginner. A reproducible crash is a bug you can actually fix.
  • ftrace traces kernel function calls so you can watch the code path that led to the failure instead of guessing.
  • dmesg and the kernel ring buffer hold the panic message and the stack trace. Read the top line first. NULL pointer dereference and a lockdep splat are different problems and want different fixes.

The whole point is understanding the failure. When you find a bug through syzkaller, don't stop at making the crash go away. Trace why the code reached that state. A patch that silences a symptom without fixing the cause gets rejected the moment a maintainer reads it, and rightly so.

If the bug lives in a module, my walkthrough on debugging a kernel module covers attaching gdb and reading the state at the crash. Write your patch so the commit message explains the cause, not just the change.

How do you contribute tests and scripts to the kernel?

Write a test, because it's high value and low risk, and maintainers love people who add coverage. The kernel's self-test suite, kselftest, lives under tools/testing/selftests. Each subsystem has tests there, and plenty of code paths have none. Adding a test that pins down real behavior is a genuine contribution that can't break production.

Tests earn trust fast. A good test catches a regression before it ships, which is exactly what a maintainer worries about. When you add a test alongside a bug fix, you prove the fix works and you stop the bug from ever coming back. That combination gets patches accepted quickly.

Static analysis scripts count too. If you write a Coccinelle rule that finds a real class of bug across the tree, that helps everyone, not just one file. Same with improvements to the existing test harnesses. This path has a lower barrier than driver work and a higher acceptance rate than random cleanups, so it's a smart place to build a track record.

How do you submit a patch and work with maintainers?

Developer reviewing kernel patches and code diffs on computer screen

Send patches with git send-email, formatted correctly, to the right people, and follow the etiquette in the process docs. The mechanics are simple once you've done them once. The etiquette is what separates accepted patches from ignored ones.

Here's the flow:

  1. Generate the patch. git format-patch -1 turns your most recent commit into a .patch file. For a series, use -N for the last N commits and add a cover letter with --cover-letter.
  2. Check it. Run ./scripts/checkpatch.pl against the patch file itself. Clean it up before a human ever sees it.
  3. Find the maintainers. ./scripts/get_maintainer.pl your.patch prints who to email and which lists to copy. Send to the maintainers, CC the list.
  4. Send it. git send-email handles the email formatting the list expects. Don't paste a diff into a webmail client. It mangles the whitespace and the patch won't apply.

Your commit message matters as much as the code. Explain what the change does and why, in plain terms, in the imperative mood. A one-line "fixed bug" message gets your patch bounced.

Then the reviews come, and this is where beginners flinch. Feedback will be blunt. It is not personal. When a maintainer says your locking is wrong, they're right more often than you'd like, and they just saved you from a deadlock in production. Read the criticism, fix the patch, and send a v2 with a changelog noting what you changed. That loop is the actual work of contributing.

How do you progress from contributor to driver developer or maintainer?

Owning a driver or a subsystem is earned through sustained, reliable work, not applied for. The path is boring and it works: keep sending good patches, keep showing up on the list, and keep reviewing other people's code. Trust in the kernel community is built one accepted patch at a time.

Once you know a subsystem well, driver work opens up. A driver is a bigger commitment because you're responsible for hardware you may be the only person testing. Maintainers will expect you to keep it working across kernel releases, not just land it and vanish.

Maintainership is the far end. You get there by being the person who already answers questions about a chunk of code, reviews patches touching it, and fixes its bugs. At some point a maintainer adds you to the MAINTAINERS entry because you're already doing the job. It comes with real weight: now you own other people's mistakes in that code, and your Reviewed-by carries responsibility. Nobody hands that out for volume. They hand it out for judgment shown over years.

Why do companies contribute to Linux, and how should you navigate corporate involvement?

Companies contribute because upstream code is cheaper to maintain than a private fork. When a company gets its driver or feature merged into mainline, the community maintains it across every future release. Keeping it out of tree means rebasing that patch forever, against a moving target. That math is why so much kernel work is paid work.

If you contribute on company time, keep two things straight. First, sort out who owns the copyright and whether your Signed-off-by is valid under your employment terms before you send anything. Getting that wrong creates a legal mess that's genuinely hard to unwind. Talk to whoever handles that at your job.

Second, watch your reputation, because on the mailing list you're a person, not a logo. Send low-quality patches to hit a quota and your name wears that, not the company's. The community remembers who does careful work and who doesn't. Align your patches with what the subsystem actually needs, not just what your manager wants shipped this quarter, and both interests usually end up in the same place.

The good news for an individual: the same skills that make you a solid upstream contributor make you employable. Kernel contributions on your resume are a strong signal, especially for infrastructure, cloud, and embedded roles where Linux expertise is the whole job.

FAQ

How long before my first patch gets accepted?

Anywhere from a day to never, depending on the patch and the subsystem. A clean documentation fix to an active subsystem can merge within a week. A bug fix that needs discussion takes several review rounds. If your patch sits with no reply, a polite ping after a couple of weeks is normal and expected.

Do I need my own hardware to contribute?

Not for docs, tests, or cleanups, which is another reason to start there. You do need the device for driver work, because you can't test a driver against hardware you don't have. Some subsystems have emulated targets in QEMU that let you develop without the physical chip, so check what's available before you buy anything.

Is GitHub used for kernel contributions at all?

No, not for mainline. The kernel runs on email and mailing lists, and patches sent as GitHub pull requests to the main tree get ignored. Some subsystems and out-of-tree projects use other tooling, but for the mainline tree you send patches with git send-email. Learn that workflow first.

What's the difference between checkpatch and Coccinelle?

checkpatch.pl flags coding-style issues in a single file or patch, like whitespace and line length. Coccinelle matches code patterns across the whole tree and can rewrite them, so it finds and fixes real bug classes, not just style. Beginners start with checkpatch; Coccinelle is the next step up once you're comfortable reading diffs.

Can I contribute if my C is only intermediate?

Yes, for documentation, tests, and small cleanups. Those teach the workflow while your C improves. Hold off on bug fixes and driver work until you can read a stack trace and reason about memory and locking, because a well-meaning patch with a subtle race does more harm than no patch at all.

Related: PostgreSQL vs MySQL: Pick the Right Linux Database