Landlock(非特権サンドボックス)
root権限もCAP_SYS_ADMINも要らず、プロセス自身がファイルアクセスを絞り込める。Landlockのルールセットとホワイトリスト方式を原理から解説します。
- 1.Landlockはroot権限なしに非特権プロセスが自分自身に対してアクセス制御ルールを課せるLSMで、ホワイトリスト方式でファイル階層ごとの許可権限を積み重ねる。
- 2.seccompがシステムコール番号という粒度で判定するのに対し、Landlockはパス・ファイル階層というリソース単位で判定し、同じopenでもアクセス先によって可否が変わる。
- 3.一度課したルールセットは緩められず、execveやforkを越えて子孫に継承されるため、権限を段階的に縮小しながら実行する多層防御の最終段として使われる。
なぜ「非特権」でアクセス制御が必要なのか
Linux Security Module(LSM) はSELinuxやAppArmorのように強力ですが、いずれもポリシーの設定・適用には管理者権限が要ります。一方でブラウザのレンダラプロセスや圧縮解凍ライブラリのような、信頼できない入力を扱うプログラムほど、実行時に「自分自身の権限を落としたい」ニーズがあります。しかし従来のLSMは管理者がホスト全体へ適用するもので、一般ユーザーが起動するアプリケーションが自発的に使える設計ではありませんでした。
Landlock はこの隙間を埋めるLSMです。カーネル5.13で導入され、root権限もCAP_SYS_ADMINのような強力なケーパビリティも持たない非特権プロセスが、landlock_create_ruleset・landlock_add_rule・landlock_restrict_self という3つのシステムコールだけでルールセットを組み立て、自分自身(と以降のfork/execve先)に適用できます。管理者が敷く全体ポリシーではなく、アプリケーション開発者がコードに埋め込む自己防衛策という位置づけです。
ルールセットとホワイトリスト方式
Landlockのモデルは一貫してホワイトリストです。まずlandlock_create_rulesetでアクセス権の集合を持つ空のルールセットを作ります。この時点で「今後読み書きファイルシステム操作をどこまで扱うか」というアクセス権のビットマスク(handled_access_fsなど)を宣言します。宣言しなかった権限種別は、以降ルールを足しても制御対象になりません。
次にlandlock_add_ruleを、制限したいファイル階層の数だけ繰り返し呼びます。各呼び出しは「このパス(とその配下)に対して、この権限セットを許可する」というルールを1本追加します。たとえば次のような擬似コードになります。
struct landlock_ruleset_attr attr = {
.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE
| LANDLOCK_ACCESS_FS_WRITE_FILE
| LANDLOCK_ACCESS_FS_EXECUTE,
};
int ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0);
struct landlock_path_beneath_attr path_beneath = {
.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE,
.parent_fd = open("/etc", O_PATH),
};
landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
&path_beneath, 0);
ここで重要なのは、handled_access_fsで宣言した権限のうち、どのパスにも許可ルールがない権限はすべて拒否されるという点です。「危険な操作だけ禁止する」ブラックリストではなく、「宣言した権限種別は原則拒否、明示的に許可したパス配下だけ通す」という設計だからこそ、未知の抜け道が生まれにくくなっています。
最後にlandlock_restrict_selfを呼ぶと、そのルールセットが呼び出しスレッドに適用されます。この瞬間から、宣言した権限種別に関するファイルアクセスはルールセットの許可リストでしか通らなくなります。
landlock_restrict_selfは複数回呼べます。すでに制限がかかった状態でさらに制限を課すと、両者の制約は論理積として重なり、後から緩めることはできません。これはseccompの「フィルタは積み重なるだけで緩まない」性質と同じ設計思想で、権限を段階的に縮小していく多層防御に向いています。
seccompとの違い:システムコール単位かリソース単位か
seccomp とLandlockはどちらも非特権プロセスが自身の攻撃面を削る仕組みですが、判定の粒度が根本的に異なります。
| 観点 | seccomp-bpf | Landlock |
|---|---|---|
| 判定の単位 | システムコール番号・引数レジスタの値 | ファイルパス・階層などのリソース |
| 見えるもの | レジスタの生の値のみ(ポインタ先は不可) | 実際に解決されたファイル階層構造 |
| 同じopenの扱い | 呼べば常に同じ判定(引数の値次第) | 呼び出し先パスにより許可・拒否が変わる |
| 典型的な穴 | パス文字列の中身では絞れない | パス自体を直接評価できる |
seccomp はBPFフィルタに渡されるseccomp_dataが「システムコール番号・引数の生の値」に限られるため、openの引数に渡されたパス文字列の中身を見て可否を決めることができません。フィルタが読めるのはレジスタの値だけで、ポインタが指す先のメモリ内容まで安全に検査するとTOCTOU(time-of-check to time-of-use)の問題が生じるからです。
Landlockはこの制約を迂回するのではなく、そもそも別の層で判定します。カーネルがパス解決やファイルオープンを実際に処理する経路にフックし、「このinodeはどのルールセットのどの許可に該当するか」をファイルシステムの内部データ構造の上で判定します。同じopenというシステムコールでも、/etc/passwdへのアクセスは拒否、/tmp/work配下は許可、というリソースに依存した判定ができるのは、seccompが原理的にできないことです。
seccompは「そもそもどのシステムコールを呼べるか」という入口を絞り、Landlockは「呼べたシステムコールが実際にどのリソースへ届くか」という奥を絞ります。両者は排他ではなく併用が前提で、コンテナ ランタイムの多くはseccompプロファイルとLandlock(またはAppArmor/SELinux)を重ねて使います。
段階的な権限縮小という設計
Landlockが想定する典型的な使い方は、プロセスの起動直後に必要な権限をすべて洗い出し、それ以外を即座に閉じるという段階的縮小です。設定ファイルを読み込む、ログファイルを開く、ソケットを張るといった初期化作業を終えたら、以後アクセスする必要があるパスの集合はほぼ確定します。そこでlandlock_restrict_selfを呼び、以降の実行区間ではその集合の外に一切出られないようにします。
Landlockのルールセットは、seccomp やLinuxケーパビリティのbounding集合と同様、一度課すと自分自身では解除できません。もし解除できてしまうと、脆弱性を突いた攻撃者がプロセスを乗っ取った後に自ら制限を外して振り出しに戻せてしまいます。「権限は縮む一方」という不可逆性こそが、乗っ取られた後の被害を上限付きに抑える根拠です。制限はforkやexecveをまたいで子孫にも継承されるため、子プロセスを生成しても抜け道になりません。
カーネルのバージョンによってサポートされるアクセス権の種類は増えており、landlock_create_rulesetにはカーネルが対応するABIバージョンを問い合わせる仕組みもあります。アプリケーション側は「利用可能な範囲で最大限絞り、対応していない権限種別は諦めて動作を継続する」というグレースフルデグラデーションを組み込むのが実務上の定石です。全か無かではなく、動いているカーネルの能力に応じて絞れるだけ絞る、という漸進的な設計がLandlockの思想に一貫しています。
問われやすいのは「Landlockとseccompの違いは何か」。答えは判定の粒度——seccompはシステムコール番号と引数の生の値、Landlockはファイルパス・階層というリソースそのものを評価する。もう一つの軸は「非特権プロセスが自分自身に課す」という主体で、管理者が敷くSELinux/AppArmorとは適用者が異なる。ルールセットはホワイトリスト方式(宣言した権限種別は許可リストにないパスをすべて拒否)で、不可逆かつfork/execveを越えて継承される点も頻出です。
まとめ
Landlockはroot権限も強力なケーパビリティも要らない非特権LSMで、プロセス自身がlandlock_create_ruleset・landlock_add_rule・landlock_restrict_selfの3システムコールでファイルアクセスのホワイトリストを組み立て、自分に適用できます。seccompがシステムコール番号という入口を絞るのに対し、Landlockはパス・ファイル階層というリソース単位で奥を絞り、同じ呼び出しでもアクセス先次第で可否が変わります。ルールセットは論理積で積み重なり不可逆、fork/execを越えて子孫に継承されるため、初期化を終えたプロセスが必要な権限だけを残して段階的に縮小していく設計に向いています。管理者が敷くLSMポリシーと違い、開発者がコードに埋め込む自己防衛の最終層——それがLandlockの本質です。
OS Article
Landlock(非特権サンドボックス)を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
Landlock
比較で見る軸
難易度: advanced / カテゴリ: OS / タグ数: 6
導入後に効く点
seccompがシステムコール番号という粒度で判定するのに対し、Landlockはパス・ファイル階層というリソース単位で判定し、同じopenでもアクセス先によって可否が変わる。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- OS
- タグ数
- 6
判断チェックリスト
- 自社の用途が「Landlock / LSM」に近いか確認する。
- 強みである「Landlockはroot権限なしに非特権プロセスが自分自身に対してアクセス制御ルールを課せるLSMで、ホワイトリスト方式でファイル階層ごとの許可権限を積み重ねる。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。