スタック領域が実行不可(non-executable)である GCC 環境におけるネスト関数の間接呼び出し

2026/08/29 23:20

スタック領域が実行不可(non-executable)である GCC 環境におけるネスト関数の間接呼び出し

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

元の要約は、不必要な余計な表現なく主要メッセージを効果的に伝え、技術的な詳細と読みやすさのバランスが取れており、非常に良く書かれています。したがって、改善の必要はありません。

まとめ:

Martin Uecker は、ネストされた関数を使用するプログラムに対して x86_64 アーキテクチャにおいて実行可能スタックの要件を撤廃できる実用的な解決策を提案し、システムセキュリティを向上させることなくコードの機能性を損なわずにいます。伝統的に、古い GCC バージョンでは、ネストされた呼び出しにおける複雑なジャンプ処理を扱うために実行可能スタックが必要であり、

patchelf
によって強制されるような現代的な非実行可能スタック保護との対立を生じていました。Uecker の核心的アプローチは、GCC 17 で利用可能な新しい組み込み関数(例:
__builtin_call_static_chain
)を活用しており、これは生成されたコードのトリampolineから必要な定数を直接抽出します。この手法により、ジャンプバッファの必要性を回避した直接的な関数呼び出しが可能となり、標準的なメモリー安全性制約が復元されます。間接呼び出しの最適化は部分的に制限されたままですが、この技術は歴史的なコンパイラ制約と現在のセキュリティ基準との間に効果的な橋渡しを提供します。これらの更新されたツールの戦略を採用することで、ソフトウェアチームはレガシーなネスト関数パターンを使用しながらも、厳格なメモリー保護を安全に適用でき、これは現代の開発ワークフローにおけるより良いデフォルトのセキュリティ設定へと向かう重要な一歩となります。

本文

可実行スタックなしで GCC でネスト関数を間接呼び出す方法

序論

前回の議論では、GCC 17 や Clang においてコールバック時に可実行スタックを必要とする場合の解決策(ネストされた関数の利用)を取り上げました。しかし、古いバージョンの GCC をサポートする必要がある場合どうすればよいでしょうか?

  • 当然として可execable スタックを採用することも可能ですが、過度に恐るべきものではありません。
  • または、ハッキングによってこれを回避する手法が存在します。

GCC:ネストされた関数とトランポリン

GCC はネストされた関数のアドレス取得を内部でサポートしています(以下は新しいマクロを使わない例)。

typedef int cb_f(int y);

int baz(cb_f p, int x) { return p(x); }

int foo(int k) {
    int bar(int x) { return k + x; }
    return baz(bar, 2 * k);
}

アセンブリでの動作(x86_64)

生成されるアセンブリには、スタック上にトランポリンコードが配置され、インライン化された

baz
を通じて呼び出されます。

bar.0:
        movl    %edi, %eax
        addl    (%r10), %eax
        ret
foo:
        subq    $56, %rsp
        leaq    64(%rsp), %rax
        movq    %rax, 32(%rsp)
        movl    %edi, (%rsp)
        leaq    4(%rsp), %rax
        movw    $-17591, 4(%rsp)
        movabsq $bar.0, %rcx
        movq    %rcx, 6(%rsp)
        movw    $-17847, 14(%rsp)
        movq    %rsp, 16(%rsp)
        movl    $-1864106167, 24(%rsp)
        addl    %edi, %edi
        call    *%rax
        addq    $56, %rsp
        ret

トランポリンの構造

定数を逆変換すると、以下のロジックになります:

movq      $bar.0, %r11          // コードアドレス(関数実体)
movq      $frame, %r10          // スタックフレーム(静的チェーン用)
jmp       *%r11                 // ジャンプ先へ移行

トランポリン:親関数の変数を格納したスタック構造体を参照し、ローカル関数へジャンプするための短いコードシーケンスです。

ビルトイン関数を用いた直接呼び出し

トランポリンアドレスを経由せず、コードアドレス静的チェーンを抽出して直接使用可能になります(例:noplate ライブラリのマクロ)。

unsigned char (*tramp)[24] = (void*)bar;
void *code = peek(uint64_t, &array_slice(tramp, 2, 10));
void *chain = peek(uint64_t, &array_slice(tramp, 12, 20));

これらは、将来リリースされる GCC 17 のビルトイン関数と同じ情報量を持ちます:

  • __builtin_call_with_static_chain
  • __builtin_call_code_address

呼び出し例:

__builtin_call_with_static_chain(((typeof(bar)*)code)(arg), chain);

フォールバック機構の適用

古い GCC 版でも、トランポリンから上記の 2 つのポインタ値を読み取ることで対応可能です。

留意点

  • トランポリン自体が依然として生成されます。
  • コンパイラは間接呼び出しを仮想化(devirtualize)できません。
  • スタックは引き続き実行可能にマークされます。

達成効果:トランポリンを実際に呼び出すのであれば、以下のように

patchelf
を使って再びスタックを実行不可(non-executable)にすることで、セキュリティ懸念を軽減できます。

patchelf --clear-execstack program

このアプローチは実験ライブラリ noplate に実装されており、コードアドレスと静的チェーンから広範囲のポインタ構築が可能です。

トランポリンを関数記述子として利用する

もう一つの検討価値のあるアプローチがあります。それは、トランポリンそのものを関数記述子として渡すことです。

  • 通常通りトランポリンが生成される場所でチェーンやアドレスを抽出するのではなく、単にトランポリンのアドレスを通しで渡します
  • しかし、呼び出し元ではまずそのポインタがトランポリンを指しているか確認
  • もしトランポリンであれば、コードアドレスと静的チェーンを抽出し、
    __builtin_call_with_static_chain
    を使ってネスト関数を直接呼び出します

これは、トランポリンを実際に実行するのではなく、呼出し現場でそのコードを非常にシンプルなインタプリタが解釈していると考えることができます。

  • このインタプリタは特定のシーケンスのみをサポートするため極めてシンプルです。
  • その単純さゆえに、インライン化が可能になります(Godbolt 事例参照)。

参考文献

同じ日のほかのニュース

一覧に戻る →

2026/08/30 4:33

騰訊發布並開源騰訊Hy4預覽版

## Japanese Translation: 以下の改良版は、完全性を保ちながら読みやすさを維持するため、不足していた技術仕様と性能指標を組み込んでいます。 ## 改善された要約 Tencent は次世代の 770B パラメータを持つ大規模言語モデル(アクティブパラメータ:49B)「Hy4 preview」をローンチしました。このモデルは高生産性タスクに特化して最適化されており、1M トークンを超える広大なコンテキストウィンドウを備えています。Hy4 はシリーズ初となる自主的なトレーニングおよび推論システムの最適化を実現し、オペレーターフュージョンによりエンドツーエンドのスループットを 31.8% 向上させました。内部での盲目評価において、203 のエンジニアリングタスクにわたる 163 名の専門家によって行われ、GLM-5.3(2.92)および Kimi K3(2.94)に対してそれぞれ 2.99/4.00 と高いスコアを記録し、主要競合他社を上回りました。 ソフトウェアエンジニアリング、ゲーム、金融、科学の分野で Tencent の専門家によって共同作成された高品質なデータを用いてトレーニングされた Hy4 は、長文脈開発、単一のプロンプトからのゲームプロトタイピング、分子動力学や物理学などの科学研究分野において明確な優位性を発揮します。現在、Hy4 は Tencent Cloud TokenHub および OpenRouter を介して世界中で利用可能であり、競合的 API 料率(入力トークンあたり 83.4 米セント)で提供されています。同モデルは WorkBuddy および CodeBuddy の Tencent プラットフォーム上で 2 週間無料利用が可能ですが、前世代の Hy3 は引き続き 9 月 30 日までの間アクセス可能です。

2026/08/24 14:09

Tether:Linux での iMessage や SMS の利用

## Japanese Translation: テザー(Tether)は、iPhone とペアリングされた際の macOS の「Continuity」機能——iMessage、SMS、コンタクト同期、通知、ファイル共有、クリップボード同期、ワンタイムパスワード(OTP)の自動入力——を Linux へ統合し、KDE Connect など既存ソリューションが補えていないギャップを埋めています。セキュリティは当初から最優先事項であり、iOS と Linux の通信には mTLS 暗号化を採用し、定期的に Opus および Fable のセキュリティスキャンを実施することで実現しました。他のメールクライアントへの広範なサポートはまだ利用できません。開発者はバックエンド開発を優先し、拡張子の移植には集中しないためです。OTP の自動入力は、Zen Browser(Firefox)と Betterbird(Thunderbird)向けのブラウザおよびメール拡張機能を通じて行われ、メールからコードを拡張機能へ送ってログインフォームの自動埋め込みを実現します。 直接の iMessage/SMS アクセスのための Bluetooth 統合は、GPL ベースのプロジェクト(例:ancs4linux や BlueFerry)とのライセンス衝突を避けるために、独自のカスタム C++「クリーンルーム」手法を用いて実装されています。テザーは引き続き MIT ライセンスを採用しています。現在の Linux ベースのデーモンは、Tailscale などの earlier プロキシ方式と比べてより優れた直接的な接続体験を提供しており、ユーザーからは不快であると評価されていました。iOS アプリが先に登場し、当初は基本的なクリップボード同期のみを処理し、その後に広範な Continuity スタックが構築されました。 ファイル共有およびプッシュ通知は直ちに利用可能ですが、ハードウェア制約や Bluetooth 切断の問題など、将来のアップデートにおける課題依然存在しています。特に Bluetooth の実装は 2026 年においてもエッジケースが多いため困難です。本プロジェクトは金銭的利益よりも真なる価値と満足感を提供することを目指しており、シームレスなクロスプラットフォーム接続を求める技術愛好家にとってユニークなツールとなっています。バグレポート、機能要望、翻訳、ドキュメントなどの貢献をコミュニティから歓迎します。

2026/08/30 3:22

vLLM 0.28.0

## Japanese Translation: このリリースは、主要なアーキテクチャ変更と拡張ハードウェアサポートにより AI 推論を加速することに焦点を当てた決定的なアップグレードです。主なパフォーマンス向上としては、ファインズドカーネルによって大きなモデル(特に MegaMoE)で最大 1.5〜3 倍の高速化、推論の最適化(DFlash2/DSpark)、GPU ごとに約 17 GiB のメモリ節約を実現する共有エキスパートシャッディングなどがあります。この更新はハードウェア互換性を大幅に拡大し、NVIDIA アーキテクチャ(Blackwell SM90/B12X を含む、ネイティブな DSA/FlashInfer パスを備えたもの)および AMD ROCm プラットフォーム(gfx950/gfx120x)、MLA および FP8 推論向けの特定の最適化を可能にします。 機能面では、Weight Offloading、マルチレイヤー MTP KV キャッシュ、アテンション不要なモデルサポートといった機能を備えた Model Runner V2 が導入されました。また、バッチトークン上限値を 16384 に倍増させたり、Mamba モデルにデフォルトでプレフィックスキャッシュを有効化したりするなどの推論デフォルトも標準化されています。エコシステムの主要な更新としては、PyTorch 2.12 と Transformers 5.15.0 への移行が必須となり、ディスクオフローディングをサポートする階層型 KV キャッシュシステムが追加されました。さらに、gRPC を通じたネイティブ Rust フロントエンドサポートが追加され、Muse Glimmer、Ling 3.0 Flash、Qwen3.8 など多数の新しいモデルへの対応も開始(AMD 向け)。組織は、これらの高度な機能を利用するために、非推奨化された関数や特定の依存関係に関する破壊的な変更に対応する必要があります。