所有 strncpy() 已被五个语义明确的函数取代,一个贯穿 6 年的安全工程画上句号。
Linux 7.2 合并窗口已完成最终清理,内核源码库不再出现 strncpy()。

━━━ ━━━ ━━━
2026 年 6 月 20 日,Last merge commit 落地——Linux 内核中最后一处 strncpy() 调用被替换,标志着这个函数在内核中彻底消失。
这场清理历时 6 年,动用 超过 360 个补丁,参与的开发者遍布内核各子系统:从文件系统、网络栈,到驱动层、架构代码——每一个 strncpy() 都被审计、替换、测试,然后删除。
Linus Torvalds 对这个函数的态度可以用两个字概括:「危险」。在内核文档中,strncpy() 被直接标记为「主动危险」——不是「不推荐」,是「actively dangerous」。
strncpy(src, dst, n) 的语义复杂且反直觉:
src 长度 ≥ n——不追加 NUL 终止符,dst 末尾没有 \0,使用时必然越界。src 长度 < n——剩余字节全部用 \0 填充,性能浪费。dst,不是拷贝的字符数,你根本不知道实际拷贝了多少。这三个问题导致了内核中大量「默认不 NUL 终止」的隐式未定义行为:
char buf[8];
strncpy(buf, "hello world", sizeof(buf));
// buf = "hello w" → 没有 \0
printf("%s", buf); // 读越界,打印垃圾数据甚至更隐蔽的是,内核经常用 strncpy 来「顺便做清 0」,导致代码意图完全模糊。维护者看到 strncpy,无法判断作者到底想做什么。
分析发现,内核中 strncpy() 实际上被用于 5 种完全不同的语义场景,只是当时都用同一个函数糊弄过去了:
| 原始用法 | 实际意图 | 替代函数 |
|---|---|---|
| 拷贝并确保 NUL 终止但不填充 | 安全字符串拷贝 | strscpy() |
| 拷贝 + 尾部零填充 | 安全拷贝 + 静态清零 | strscpy_pad() |
| 拷贝定长字段(不需要 NUL) | 固定宽度内存拷贝 | strtomem_pad() |
| 带显式填充的有界拷贝 | 缓冲区安全填充 | memcpy_and_pad() |
| 明确已知长度的内存拷贝 | 普通内存复制 | memcpy() |
关键设计思路是:用函数名暴露开发者意图。
看代码的人不再需要猜测「这里要不要 NUL?填充用不用?目标多大?」——函数签名本身就告诉你了。
这个清理工程的主要推动者是 Kees Cook(内核安全团队核心成员,也是 Chrome OS 安全负责人)。他从 2020 年左右就开始逐步推进这项工作,逐个子系统、逐个文件地替换 strncpy()。
Linus Torvalds 曾在 2021 年评论 strncpy:「我讨厌这个函数,它应该被扔进语言的垃圾堆。」
六年过去,它真的被扔进去了。
如果你写内核模块或驱动,从现在起 strncpy() 在编译时会报错。请按以下规则选择替代品:
strscpy() 就优先用——它保证 NUL 终止,返回实际拷贝长度(负数=截断)strscpy_pad()strtomem_pad()memcpy() 或 memcpy_and_pad()一个简单的迁移对照:
// ❌ 旧:意图不明
strncpy(dev->name, src, IFNAMSIZ);
// ✅ 新:显式语义
strscpy(dev->name, src, IFNAMSIZ);360 个补丁,6 年时间,换来的是一行 #include 的删除——以及内核安全水位线的整体抬升。
在 C 语言的世界里,字符串处理永远是 Bug 的温床。strncpy 被清退不只是「换个函数名」,更是内核社区对 代码可读性即安全性 理念的一次集体实践。
函数名就是文档。别让阅读者猜你的意图。
━━━ ━━━ ━━━
📝 文末互动:你在工作中写过 strncpy 的 Bug 吗?用 strscpy 之后有没有踩过其他坑?留言说说你的经历。
🔜 下期预告:Linux 7.2 还有哪些重量级合并?SPOILER:BPF 模块化、Rust for Linux 又有新进展。
一个字符就能提权到 root?Linux 内核 CVE-2026-23111 深度剖析
Linux SLUB 分配器深度拆解:malloc 背后内核在干什么?
Copy Fail 内核漏洞已经在各大主流发行版 Ubuntu, Debian 修复,请尽快升级!
Jens Axboe 操刀新款 Linux 内核补丁:拟将单核 I/O 吞吐性能飙升 60%