はじめに
この記事ではLinuxの新しいsandbox機構であるLandlockのサンプルの使い方を概説します。
詳細で正確な情報は公式のページ https://landlock.io/ やLinux kernelのソースコード中にありますので、必要な場合はそちらを参照してください。
サンドボックスが欲しいわけ
一般的なLinuxディストリビューションとスマートフォンOSの両方を使い、それぞれで様々なアプリを使っている方は大きな違いに気付くと思いますが、前者はユーザーのデータはホームディレクトリと呼ばれる共通のディレクトリに格納され、他のアプリのためのデータを自由に参照できます。それに対し、スマートフォンの場合は各アプリが独自のデータ領域を持ち、他のアプリのデータを参照するには手間のかかるプログラミングとユーザーの同意が必要になります(バイパスできてしまう場合は脆弱性とみなされます)。
Linux環境上でデータが共有されているのは便利なのですが、ブラウザやSSHが持つ認証情報、あるいは文書やコード等の意図しないアプリからの読み出し(そしてネットへの持ち出し)もしくは改変のリスクに対応する必要があります。
信用できる開発元やディストリビューター経由で入手したアプリしか動かさないというのも一つの方法ですが、サプライチェーンの脆弱性も現実的に存在すること、さらに開発者の場合は管理の緩いパッケージシステムから取得したリソースの利用と生産性のトレードオフを取ることが必要になると考えられます。
要するに、何かのインストール時に
$ curl https://…/install.sh | bash -s
ってのを見かけるとヤバい!と思いますよね。(普段良くても、運が悪いタイミングでの実行で何か起きるかもしれず)
使い方
ここではこの記事の執筆時点でのWindows上のWSL (Ubuntu 22.04.1) での流れを説明します。
Landlock自体はLinux 5.13(2021年6月にリリース)以降で使えます。
WSLなUbuntuでLinuxのAPIを使うにはkernelのヘッダファイルが必要なんで、入れてない人はインストールします。
$ sudo apt install linux-headers-5.15.0-58-generic
sandbox manager example ( https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/samples/landlock/sandboxer.c ) からsandboxer.cをコピーしてきてコンパイルします。
$ gcc sandboxer.c -o sandboxer
現時点でのWSLはカーネルがこのコードが想定している最新のものではないので、LANDLOCK_ACCESS_FS_TRUNCATE などの定数を数個コメントアウトします。
次にsandbox (sandboxer) の中で子プロセスとしてbashを動かそうとしてみます。環境変数のLL_FS_ROとLL_FS_RWに読んで良いディレクトリ、読み書きして良いディレクトリを複数指定できます。
$ LL_FS_RO="/" LL_FS_RW="" ./sandboxer bash -i
Hint: You should update the running kernel to leverage Landlock features provided by ABI version 3 (instead of 1).
bash: /dev/null: Permission denied
bashが/dev/nullに書けないと言ってるので書けるようにします。
$ LL_FS_RO="/" LL_FS_RW="/dev/null" ./sandboxer bash -i
こんどは大丈夫。
このプロセスから ~/.ssh/ のファイルが見られてネットに送られて心配!という気がするので隠しましょうか。ついでにホームディレクトリ上で開発を続けたいので
$ LL_FS_RO="/usr" LL_FS_RW="/tmp:/dev/null:/home/yusuke/llock" ./sandboxer bash -i
bash: /etc/bash.bashrc: Permission denied
bash: /home/yusuke/.bashrc: Permission denied
/etc/bash.bashrcは大したことが書かれてないんで、ホームディレクトリのbashrcは読めるようにしましょうか。(書けるようにもしてしまうと悪意のある何かを書き足されるのが心配ですよね)
$ LL_FS_RO="/usr:/home/yusuke/.bashrc" LL_FS_RW="/tmp:/dev/null:/home/yusuke/llock" ./sandboxer bash -i
bash: /etc/bash.bashrc: Permission denied
$ cat ~/.ssh/config
cat: /home/yusuke/ssh/.config: No such file or directory
$
$ さんどぼっくすのなかにいる
これでネットから来た何かのインストールスクリプトに対してもファイルシステム上は安全!という感じです。
まとめ
信用できないコードを動かす時は別のマシンを使うとか仮想化を使う、最近だとコンテナを利用するなどといった方法がありますが、ホームディレクトリ内のアクセス権の切り分けだけで簡単に改善できそうな方法であるLandlockの利用例を紹介しました。
将来的にはもっと普通に使える形が模索されるかと思いますが、PCがスマホみたいになるのもイヤだなと思う今日この頃です(だからといってリスクに対して開き直るのもイヤですが)。