この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
Linuxカーネルから strncpy() が完全に削除されました。しかも一晩の作業ではなく、6年・362コミットをかけた長い掃除の末の達成です。Linux 7.2 のマージウィンドウで、Kernel Self Protection Project(KSPP)を率いる Kees Cook 氏が、最後に残っていた箇所を自ら片付けて完了しました。
20年以上 Linux サーバーの現場にいますが、「教科書的に安全」とされてきた関数が、これほどの労力をかけて駆逐されるのは珍しい出来事です。この記事では、攻撃手法の話ではなく、なぜ strncpy が危ないのか、そして自分のCコードで何を使えばいいのかという、文字列関数の現実解を整理します。
・Linuxカーネルから strncpy() が完全に削除された。6年・362コミット(一部報道は360超と表記)をかけた長期プロジェクトで、Linux 7.2 のマージウィンドウで完了。
・主導したのは KSPP(Kernel Self Protection Project)を率いる Kees Cook 氏。最後の残り箇所は本人が処理した。
・strncpy の問題は「NUL終端が保証されない」こと。コピー元が指定サイズ以上だと終端文字が付かず、その後の文字列操作が暴走する温床になる。
・一括置換できなかったのは、各呼び出し箇所の「意図」を読まないと正しい代替を選べないため。だから6年かかった。
・代替は strscpy()(NUL終端する安全な版)が基本。用途に応じて strscpy_pad() / strtomem_pad() / memcpy_and_pad() を使い分ける。
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
strncpy() の何が問題だったのか
「安全そうな名前」の落とし穴
strncpy は名前に「n」が付いているため、コピーするバイト数を指定でき、バッファオーバーフローを防げる安全な関数だと誤解されがちです。実際には、これは 固定長フィールドを埋めるための関数であって、いわゆる「安全な文字列コピー」とは設計思想が違います。最大の落とし穴は NUL終端(文字列の終わりを示す \0)が保証されないことです。挙動を整理すると、こうなります。
| コピー元の長さ | strncpyの挙動 |
|---|---|
| 指定サイズより短い | 残りを \0 で埋める(ゼロ埋め) |
| 指定サイズと同じか長い | NUL終端が付かない |
つまり、コピー元がちょうど収まる、あるいは溢れる長さだったとき、終端文字のない「壊れた文字列」が出来上がります。これを後続のコードが普通の文字列として扱うと、メモリの隣の領域まで読み続けてしまい、情報漏えいやクラッシュにつながります。
性能面でも損をしている
もう一つ見落とされがちなのが性能の話です。strncpy はコピー元が短いと、残りのバッファを すべて \0 で埋め尽くす仕様です。長いバッファに短い文字列をコピーするだけのつもりが、内部では大量のゼロ埋めが走っている、ということが起こります。直感に反する挙動とこの冗長なゼロ埋めの2点が、strncpy が「バグの温床であり、性能も悪い」と評価され続けてきた理由です。だからカーネル開発者たちは、これを使い続けるのではなく そもそも使わない方向へ舵を切りました。
なぜ削除に6年・362コミットもかかったのか
機械的な一括置換ができなかった
「危険な関数なら、sed で一括置換すればいいのでは」と思うかもしれません。実際、私も最初はそう感じました。ところが、それができなかったのが今回の作業が長引いた核心です。strncpy には前述のとおり「短ければゼロ埋め、長ければ終端なし」という二面性があります。ある呼び出し箇所では「終端付きの文字列が欲しい」、別の箇所では「固定長フィールドをゼロ埋めしたい」と、意図がまったく違う。この意図を1箇所ずつ読み解かないと、正しい代替関数を選べません。
だからこそ、巨大なカーネルのコードベース全体にわたって、数百箇所を1つずつ判断していく必要がありました。6年・362コミット、そして多数の貢献者の手が入ったのは、この「機械化できない判断の積み重ね」だったわけです。
KSPPという地道な取り組みの成果
この削除を主導したのは、Google のエンジニアで Kernel Self Protection Project(KSPP、カーネル自己防衛プロジェクト)を率いる Kees Cook 氏です。KSPP は、攻撃そのものを追いかけるのではなく、バグのクラスごと根絶するという発想でカーネルを地道に堅牢化してきたチームです。最後に残った数件は Kees Cook 氏が自ら片付け、Linux 7.2 のマージウィンドウで strncpy の利用箇所がゼロになりました。派手さはありませんが、こうした「バグの温床を構造的に潰す」取り組みこそが、長期的なセキュリティを支えています。
現実解:今のCコードで何を使うべきか
基本は strscpy()
カーネル開発における置き換えの基本は strscpy() です。これは「必ず NUL終端する」「コピー先サイズを超えない」という、本来 strncpy に期待されていた振る舞いを正しく実装したものです。// avoid this: terminator may be missing
strncpy(dst, src, sizeof(dst));
// use this: always NUL-terminated, never overruns dst
strscpy(dst, src, sizeof(dst));
strscpy は終端を保証するうえに、コピーした長さ(またはエラー)を返してくれるので、終端漏れによる事故が構造的に起きません。
用途別の使い分け
すべてを strscpy に置き換えれば終わり、ではないのが今回の難しさでした。元の strncpy が「固定長フィールドのゼロ埋め」目的で使われていた箇所では、別の関数が適切です。| 関数 | 用途 |
|---|---|
strscpy() | NUL終端の文字列が欲しいとき(基本形) |
strscpy_pad() | NUL終端+残りをゼロ埋めしたいとき |
strtomem_pad() | 非NUL終端の固定長フィールドへ詰めるとき |
memcpy_and_pad() | 固定長へコピーし残りをパディングするとき |
ポイントは、「この箇所は終端が欲しいのか、固定長フィールドを埋めたいのか」を毎回考えることです。これはカーネルに限らず、自分でユーザー空間のCコードを書くときにもそのまま通じる判断軸です。
Cの文字列まわりは、こうした細かな挙動の差が事故に直結します。背景から腰を据えて学び直したい方には、定番の解説書を1冊手元に置くことをおすすめします。
PR
C言語と文字列・ポインタの土台を、原典で押さえ直せる定番中の定番。strncpy のような関数の「設計意図」を理解する出発点になります。
自分のCコードでstrncpyを使っている場合の対処
strncpyを使っている既存コードをどう直すか
ユーザー空間のCコードで strncpy を使っている場合、いきなり全削除する必要はありません。ただし、NUL終端を自分で保証しているかは必ず確認すべきです。よくあるのが、終端を付け忘れたまま放置されているパターンです。# grep existing usages in your codebase
grep -rn "strncpy" ./src
// quick safety net if you must keep strncpy
strncpy(dst, src, sizeof(dst) - 1);
dst[sizeof(dst) - 1] = '\0';
上のように、最後の1バイトを必ず \0 にしておけば、終端漏れによる暴走は防げます。とはいえ、これは応急処置です。新規コードでは、終端を保証してくれる安全な関数(環境によっては strlcpy なども候補)を選ぶ方が筋がいいです。
「nが付いているから安全」という思い込みを捨てる
今回の件で現場として持ち帰るべき教訓は、関数名の印象で安全性を判断しないことに尽きます。strncpy だけでなく、strncat や snprintf にも、それぞれ固有の落とし穴があります。注意すべきは「名前」ではなく「終端とサイズの扱い」です。本番で動くコードのレビューでは、文字列関数を見かけたら「終端は保証されているか」「サイズはバッファを超えないか」をその場で確認する。この習慣があるだけで、メモリ系のバグはかなり減らせます。
まとめ:strncpy削除が示す「安全なC」の現実解
今回の strncpy 完全削除を一覧で整理します。| 項目 | 内容 |
|---|---|
| 何が起きた | Linuxカーネルから strncpy() を完全削除(Linux 7.2) |
| 規模 | 6年・362コミット、多数の貢献者 |
| 主導 | KSPP を率いる Kees Cook 氏 |
| 問題点 | NUL終端が保証されない+冗長なゼロ埋めで性能も悪い |
| 現実解 | 基本は strscpy()。用途で strscpy_pad / strtomem_pad / memcpy_and_pad を使い分け |
「安全なC」とは、特定の魔法の関数を1つ覚えることではありません。各関数の挙動を正しく理解し、用途に合った道具を選ぶこと。6年・362コミットという数字は、その地道さがいかに重いかを示しています。自分のコードでも、文字列関数を見かけたら一度立ち止まる。それが現実解です。
Cのセキュアコーディングを体系的に身につけたい方には、原理から押さえられる定番書も役立ちます。
「安全なC」、根っこから理解できていますか?
文字列関数の終端とサイズの扱い、メモリの境界、システムコールの挙動。読むだけでなく、実機のLinux上で繰り返し手を動かすことで初めて身につきます。
ネットの切れ端の情報をコピペするだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
登録10秒/合わなければ解除3秒 / 詳細はこちら
- 前のページへ:CVE-2026-12249(ADSys/CVSS9.0)徹底解説|UbuntuのAD連携で起きる通信乗っ取りと対処
- この記事の属するカテゴリ:Linux情報・技術・セキュリティへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。
登録無料・いつでも解除できます