---
title: カーネルの堅牢化
url: https://doc.liz6.com/ja/linux-kernel/09-security-mechanisms/02-kernel-hardening
locale: ja
area: linux-kernel
tags:
- linux-kernel
- security-mechanisms
date: 2026-06-30
modified: 2026-07-16
description: '対応範囲: KASLR → stack protector → KPTI → KASAN/KMSAN/UBSAN → FORTIFY_SOURCE → lockdown → seccomp → SLAB_FREELIST_RANDOM → init_on_free / カーネルバージョン: 2.6 ~ 6.x'
---

# カーネルの堅牢化

> 対応範囲: KASLR → stack protector → KPTI → KASAN/KMSAN/UBSAN → FORTIFY_SOURCE → lockdown → seccomp → SLAB_FREELIST_RANDOM → init_on_free
> カーネルバージョン: 2.6 ~ 6.x

## アドレス空間のランダム化: KASLR

```
起動時にカーネルコード/データ/モジュールのベースアドレスをランダム化:
  → ROP/JOP攻撃ではgadgetsのアドレスが必要 → ベースアドレスが不明 → 攻撃が困難

実装: arch/x86/boot/compressed/kaslr.c
  ブートローダーの段階でランダムなベースアドレスを選択 → 再配置されたカーネルを解凍

kptr_restrict: /proc/kallsymsからのカーネルアドレス漏洩を制限
  /proc/sys/kernel/kptr_restrict = 2 → 非rootユーザーからはすべて0として表示
```

## Stack Protector

```c
// CONFIG_STACKPROTECTOR: コンパイラが各関数のスタックフレームにcanaryを挿入
// gcc: -fstack-protector-strong
//   → 保護対象: ローカル配列がある関数や、アドレス演算を行う関数
// canaryが書き換えられると → スタックオーバーフロー → __stack_chk_fail() → panic

// kernel/stackleak.c (オプション): より徹底的なスタッククリア
//   各システムコールの返却前に使用済みスタック領域を消去
//   → スタック情報の漏洩防止（未初期化のローカル変数など）
```

## KPTI: Meltdown対策

```
2018年のMeltdown脆弱性:
  CPUは予測実行中にページテーブルのU/S bitをチェックしない → ユーザーモードからカーネルメモリを読み取れる

KPTI (Kernel Page Table Isolation):
  各プロセスに2つのページテーブルを持つ:
    カーネルモード: 完全マッピング (user + kernel)
    ユーザーモード: 最小限 (user + trampoline)
  → ユーザーモードではカーネルメモリへの予測アクセスができない

パフォーマンスへの影響: ~5%~30% (システムコール集中型), PCIDにより一部緩和
現代のCPU (Cascade Lake以降, Zen2以降): ハードウェアで修正済み、KPTIは自動的に無効化
```

## Sanitizers: 実行時エラー検出

```c
// KASAN (Kernel Address Sanitizer):
//   検出: 境界外アクセス, use-after-free, double-free
//   シェードメモリに基づく (コンパイル時のインストルメンテーション)
//   オーバーヘッド: ~1.5-2倍の低速化, デバッグ用カーネルのみ

// KMSAN (Kernel Memory Sanitizer):
//   検出: 未初期化メモリへのアクセス
//   KASANよりも重い (~3倍), 開発用途のみ

// UBSAN (Undefined Behavior Sanitizer):
//   検出: 整数オーバーフロー, シフトの境界外, 空ポインタの逆参照
//   オーバーヘッドが低く、本番環境で有効化可能 (CONFIG_UBSAN_BOUNDS)
```

## FORTIFY_SOURCE

```c
// コンパイル時にmemcpy/strcpy/sprintfを置換:
//   バウンダリ情報がある場合 → チェック付き呼び出しを生成
//   コンパイル時に既知の境界外アクセス → コンパイルエラー
//   実行時の境界外アクセス → BUG() (エラーを返さない)
//
// ユーザー空間のFORTIFY_SOURCEと類似しているが、より多くの関数をカバー
```

## Kernel Lockdown

```
UEFI Secure Bootが有効化されると:
  → kernel lockdownが自動的に有効化される (integrityモード)
  → 禁止される操作:
    - /dev/mem, /dev/kmem (メモリ読み書き)
    - ioportへのアクセス
    - kexec (署名されていないカーネルの読み込み)
    - BPFによるカーネルメモリへの書き込み
    - ACPIテーブルの上書き

/proc/sys/kernel/lockdown:
 none / integrity / confidentiality
```

## seccomp

```c
// prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)
// プロセスが呼び出せるシステムコールを制限 (不可逆)

// BPFフィルター:
//   システムコール番号と引数をチェック → ALLOW / DENY / KILL / TRAP
//   Chromium, Docker, systemdなどが使用

// SECCOMP_RET_USER_NOTIF (5.0以降):
//   判断をカーネル内で行わず、ユーザー空間の監視プロセスに通知
//   例: コンテナマネージャが特定のシステムコールの承認/拒否を行う
```

## その他の堅牢化オプション

```bash
# 解放時にゼロクリア:
CONFIG_INIT_ON_FREE_DEFAULT_ON=y    # 解放されたslabオブジェクトをゼロクリア (UAFによる情報漏洩防止)

# slab freelistのランダム化:
CONFIG_SLAB_FREELIST_RANDOM=y      # slab freelistポインタをランダムにソート (ヒープエクスプロイト防止)

# ユーザーメモリコピーのハードニング:
CONFIG_HARDENED_USERCOPY=y         # usercopyのソース/ターゲットが有効なheap/slab領域内であることを検証

# スタックのランダム化 (既存, プロセス単位):
/proc/sys/kernel/randomize_va_space = 2  # ASLRを完全に有効化
```

## 参考

- **ソースコード**: `security/lockdown/`, `kernel/seccomp.c`, `mm/kasan/`, `lib/ubsan.c`
- **カーネルドキュメント**: `Documentation/admin-guide/kernel-parameters.txt`
- **LWN**: "Kernel address space layout randomization", "The kernel lockdown patches"

*キーワード: KASLR, stack protector, KPTI, KASAN, FORTIFY_SOURCE, lockdown, seccomp, init_on_free*
