Linux finally killed strncpy(): 360 patches, six years, one footgun gone

5 min read 1 source clear_take
├── "Deprecated APIs can actually be eradicated from massive codebases — but only through sustained, multi-year grinding work"
│  └── top10.dev editorial (top10.dev) → read below

The editorial frames the milestone less as a security win and more as a demonstration of organizational willpower. Most 'deprecated' APIs in long-lived projects are deprecated in documentation only; this 360-patch, six-year, cross-subsystem effort by Kees Cook and KSPP proves that full removal from a 30-million-line codebase is achievable if someone is willing to own the grind.

├── "strncpy() is fundamentally broken by design and deserves removal"
│  ├── top10.dev editorial (top10.dev) → read below

Argues that strncpy() is simultaneously unsafe and slow — it fails to NUL-terminate when the source is too long, yet pads the entire destination with NULs when the source is short, producing O(n) writes even for tiny copies. This combination of footguns makes it a function that 'does not do what its name suggests' and justifies wholesale replacement with strscpy() or memcpy().

│  └── @simonpure (Hacker News, 134 pts) → view

By submitting the Phoronix piece under the framing 'Linux eliminates the strncpy API after six years of work,' the submitter endorses the view that eliminating strncpy is a noteworthy positive milestone worth surfacing to the HN audience. The 134-point score and 111 comments suggest broad community agreement that this API's removal is overdue.

└── "The Kernel Self-Protection Project's incremental hardening approach is the model for securing legacy C code"
  └── top10.dev editorial (top10.dev) → read below

Credits Kees Cook and KSPP for driving the conversion through the normal per-subsystem review process rather than attempting a flag-day rewrite. The piece highlights that this patient, per-call-site approach — converting each site to strscpy() or memcpy() based on actual semantics — is what made it tractable across networking, filesystems, drivers, and arch code maintained by hundreds of different people.

What happened

With the merge of commit `1a3746ccbb0a` into Linus Torvalds' tree, the Linux kernel removed its final use of `strncpy()`. Phoronix flagged the milestone for the upcoming 7.2 release: the function that has shipped in every Unix since the late 1970s is now gone from the largest, most-deployed C codebase on Earth.

This was not a single patch. It was roughly 360 patches over six years, driven primarily by Kees Cook and the Kernel Self-Protection Project (KSPP), grinding through every subsystem — networking, filesystems, drivers, arch code — and converting each call site to either `strscpy()` (when a NUL-terminated copy was actually wanted) or `memcpy()` (when the caller really did want a fixed-width, possibly-unterminated buffer fill). The work touched code maintained by hundreds of different people across dozens of trees, each conversion landing through the normal review process.

The motivation is the same one every C programmer has internalized and then forgotten at 2 a.m.: `strncpy()` does not do what its name suggests. If the source string is longer than `n`, the destination is not NUL-terminated. If the source is shorter than `n`, the destination is padded with NULs all the way out — an O(n) write even when you copy two bytes into a 4KB buffer. It is simultaneously unsafe and slow, a combination C rarely manages.

Why it matters

The interesting part of this story is not that `strncpy()` is bad. Every C textbook printed since roughly 1995 has said so. The interesting part is the demonstration that you can actually delete a deprecated primitive from a 30-million-line codebase if you are willing to grind.

Most "deprecated" APIs in long-lived projects are deprecated in documentation only. The function stays. New code is told not to call it. Old code is left alone because nobody owns a refactor that spans 47 subsystems and risks breaking the boot path on three architectures nobody has hardware for anymore. The deprecation notice sits there for a decade, a quiet monument to a battle nobody wanted to fight.

KSPP fought it. They built `strscpy()` as a drop-in replacement with sane semantics — always NUL-terminates, returns the length copied or `-E2BIG` on truncation, doesn't pad — then systematically routed every `strncpy()` site through review. The patches were small, mechanical, and reviewable in isolation. That is the whole trick: you cannot land a 360-patch series, but you can land 360 patches.

The second-order effect matters more than the function itself. The kernel now has a precedent and a playbook for excising whole categories of footguns. `strlcpy()` is next on the list (it's still around, but its return-value semantics have their own problems). The KSPP roadmap also targets variable-length arrays, unbounded `memcpy()` patterns flagged by `FORTIFY_SOURCE`, and the broader push toward `-Wstrict-flex-arrays=3`. Each one of those, treated as a six-year campaign rather than a single heroic patch, becomes tractable.

There is also a Rust subtext. A common argument against the kernel's incremental memory-safety work is that you cannot meaningfully harden C — the language is the bug. The `strncpy()` removal is a small, concrete counterpoint: you can, if you treat hardening as engineering work rather than ideology. The Rust-for-Linux effort and the KSPP hardening effort are complements, not substitutes. One bounds the blast radius of new code; the other shrinks the attack surface of the C that will exist for decades regardless.

The community reaction on the HN thread (134 points) is mostly the expected mix: C veterans nodding at a footgun finally retired, younger developers asking why it took so long, and at least one person pointing out that `strncpy()` was never actually designed as a safer `strcpy()` — it was designed in 1979 for fixed-width directory entries in the original Unix filesystem, where NUL-padding to a fixed length was the feature. The name was a historical accident that cost the industry billions of dollars in CVEs.

What this means for your stack

If you maintain a C or C++ codebase, the practical takeaways are direct:

Treat `strncpy()` as a build error, not a warning. Add it to your clang-tidy / cppcheck / Coverity rules with severity high. If you're on glibc, the `-D_FORTIFY_SOURCE=3` flag will catch a subset of the obvious misuses at runtime; static analysis catches the rest. The kernel built `strscpy()` because none of the standard alternatives (`strlcpy`, `snprintf`, BSD `strscpy`) were quite right for kernel constraints — you may need to do the same. The point is to have one blessed primitive with predictable semantics, and to make every other choice loud.

Audit your other "safe" string functions while you're there. `strlcpy()` looks safe but its return value is the source length, not the bytes copied, which is a different footgun. `snprintf()` is safe for the copy but its return value is what *would have been* written, which means the same naive truncation-detection idiom is wrong in a slightly different way. If you cannot describe, from memory, what each of these functions returns when the destination is too small, you have a latent bug waiting in your codebase.

For non-C stacks, the lesson generalizes. Every long-lived codebase accumulates a tail of "don't use this, use that instead" primitives — Python's `os.system`, Node's `Buffer()` constructor, Java's `Date`, JavaScript's `var`, Go's `ioutil`. The kernel just demonstrated that the tail can actually be removed, not just discouraged, if someone is willing to own the multi-year grind and the tooling is good enough to make each individual patch boring. Your codebase's deprecation list is a backlog, not a graveyard — treat it that way.

Looking ahead

The next KSPP targets — `strlcpy()`, unbounded `memcpy()`, VLAs — will land over the next few kernel cycles on roughly the same model. The broader bet is that C, treated as a language to be incrementally constrained rather than defended in its 1989 form, has another decade or two of useful service in security-critical infrastructure. The `strncpy()` removal is the first whole-codebase proof point. The kernel just demonstrated, in 360 patches, that the path from "deprecated" to "actually gone" is walkable. The question for everyone else maintaining old C is whether they're willing to walk it.

Hacker News 272 pts 288 comments

Linux eliminates the strncpy API after six years of work, 360 patches

<a href="https:&#x2F;&#x2F;git.kernel.org&#x2F;pub&#x2F;scm&#x2F;linux&#x2F;kernel&#x2F;git&#x2F;torvalds&#x2F;linux.git&#x2F;commit&#x2F;?id=1a3746ccbb0a97bed3c06ccde6b880013b1dddc1" rel="nofollow">h

→ read on Hacker News
sirwhinesalot · Hacker News

I have in the past made fun of the Linux kernel devs, supposedly some of the best C developers in the world, for not knowing how to make stringbuffer and stringview types, but to be fair to them we didn&#x27;t have the consensus we have today on the topic.You know who did have the right idea though?

WalterBright · Hacker News

&quot;The strncpy function within the Linux kernel has been a &quot;persistent source of bugs&quot; for years due to counter-intuitive semantics and behavior around NUL termination along with performance issues due to redundant zero-filling of the destination.&quot;Huh. Whenever I&#x27;ve been asked

rswail · Hacker News

Things that have bugged me for 40 years...* NUL terminated strings (and now, non UTF-8 encoded strings on input&#x2F;output)* Using LF or CR or CRLF as line terminators, and pipe&#x2F;comma-delimited fields when there were other unambiguous ASCII characters that could have been used (eg, GS, FS, RS)

thiht · Hacker News

&gt; In place of strncpy, Linux kernel code should use strscpy() for NUL terminated destinations, strscpy_pad() for NUl-terminated destinations with zero-padding, strtomem_pad() for non-NUL-terminated fixed-width fields, memcpy_and_pad() for bounded copies with explicit padding, or memcpy() for know

lambdaone · Hacker News

This sort of boring grind is where the real work of systems engineering is done. Big infrastructure projects like this work on making the Linux kernel more reliable while still keeping it workable throughout the process move on the scale of decades, not months.

// share this

// get daily digest

Top 10 dev stories every morning at 8am UTC. AI-curated. Retro terminal HTML email.