セキュリティーの強化とセキュリティーの新機能
「Ubuntu 21.10」は「Linux kernel 5.13」ベースの「Linux kernel」を採用しています。これによりセキュリティーが強化されています。
リリース情報
「Ubuntu 21.10」のリリース情報は、以下を参照してください。Linux kernelの変更点
前バージョンの「Ubuntu 21.04」では「Linux kernel 5.11」が採用されており、「Ubuntu 21.10」では2回分のメジャーアップデートが行われています。「Linux kernel 5.12」及び「Linux kernel 5.13」の主要な変更点は、以下を参照してください。
Kernel Electric-Fence(KFENCE)
「Kernel Electric-Fence(KFENCE)」はメモリーデータの破損やエラーを検出する仕組みです。「KFENCE」はパフォーマンスにほとんど影響を与えない低オーバーヘッドな仕組みであり、サンプリングベースのアプローチでメモリーのエラーを検出します。
「KFENCE」はヒープ領域で発生する境界を超えたアクセスや、解放済みメモリーへのアクセス、無効なメモリーの解放を検出します。
「KASAN」と比較すると検出精度の代わりにパフォーマンスを優先した仕組みになります。
デフォルトで有効に
「Ubuntu 21.10」では「KFENCE」がデフォルトで有効になっており、様々な実行時のメモリーエラーを検出できるようになりました。エラーレポート
例えば割り当てられたメモリー領域外にアクセスすると、以下のようなレポートが生成されます。==================================================================
BUG: KFENCE: out-of-bounds read in test_out_of_bounds_read+0xa6/0x234
Out-of-bounds read at 0xffff8c3f2e291fff (1B left of kfence-#72):
test_out_of_bounds_read+0xa6/0x234
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
kfence-#72: 0xffff8c3f2e292000-0xffff8c3f2e29201f, size=32, cache=kmalloc-32
allocated by task 484 on cpu 0 at 32.919330s:
test_alloc+0xfe/0x738
test_out_of_bounds_read+0x9b/0x234
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
CPU: 0 PID: 484 Comm: kunit_try_catch Not tainted 5.13.0-rc3+ #7
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014
==================================================================
BUG: KFENCE: out-of-bounds read in test_out_of_bounds_read+0xa6/0x234
Out-of-bounds read at 0xffff8c3f2e291fff (1B left of kfence-#72):
test_out_of_bounds_read+0xa6/0x234
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
kfence-#72: 0xffff8c3f2e292000-0xffff8c3f2e29201f, size=32, cache=kmalloc-32
allocated by task 484 on cpu 0 at 32.919330s:
test_alloc+0xfe/0x738
test_out_of_bounds_read+0x9b/0x234
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
CPU: 0 PID: 484 Comm: kunit_try_catch Not tainted 5.13.0-rc3+ #7
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014
==================================================================
例えば解放済みメモリーへアクセスすると、以下のようなレポートが生成されます。
==================================================================
BUG: KFENCE: use-after-free read in test_use_after_free_read+0xb3/0x143
Use-after-free read at 0xffff8c3f2e2a0000 (in kfence-#79):
test_use_after_free_read+0xb3/0x143
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
kfence-#79: 0xffff8c3f2e2a0000-0xffff8c3f2e2a001f, size=32, cache=kmalloc-32
allocated by task 488 on cpu 2 at 33.871326s:
test_alloc+0xfe/0x738
test_use_after_free_read+0x76/0x143
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
freed by task 488 on cpu 2 at 33.871358s:
test_use_after_free_read+0xa8/0x143
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
CPU: 2 PID: 488 Comm: kunit_try_catch Tainted: G B 5.13.0-rc3+ #7
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014
==================================================================
BUG: KFENCE: use-after-free read in test_use_after_free_read+0xb3/0x143
Use-after-free read at 0xffff8c3f2e2a0000 (in kfence-#79):
test_use_after_free_read+0xb3/0x143
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
kfence-#79: 0xffff8c3f2e2a0000-0xffff8c3f2e2a001f, size=32, cache=kmalloc-32
allocated by task 488 on cpu 2 at 33.871326s:
test_alloc+0xfe/0x738
test_use_after_free_read+0x76/0x143
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
freed by task 488 on cpu 2 at 33.871358s:
test_use_after_free_read+0xa8/0x143
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
CPU: 2 PID: 488 Comm: kunit_try_catch Tainted: G B 5.13.0-rc3+ #7
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014
==================================================================
例えば解放済みのメモリーを再度解放すると、以下のようなレポートが生成されます。
==================================================================
BUG: KFENCE: invalid free in test_double_free+0xdc/0x171
Invalid free of 0xffff8c3f2e2a4000 (in kfence-#81):
test_double_free+0xdc/0x171
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
kfence-#81: 0xffff8c3f2e2a4000-0xffff8c3f2e2a401f, size=32, cache=kmalloc-32
allocated by task 490 on cpu 1 at 34.175321s:
test_alloc+0xfe/0x738
test_double_free+0x76/0x171
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
freed by task 490 on cpu 1 at 34.175348s:
test_double_free+0xa8/0x171
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
CPU: 1 PID: 490 Comm: kunit_try_catch Tainted: G B 5.13.0-rc3+ #7
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014
==================================================================
BUG: KFENCE: invalid free in test_double_free+0xdc/0x171
Invalid free of 0xffff8c3f2e2a4000 (in kfence-#81):
test_double_free+0xdc/0x171
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
kfence-#81: 0xffff8c3f2e2a4000-0xffff8c3f2e2a401f, size=32, cache=kmalloc-32
allocated by task 490 on cpu 1 at 34.175321s:
test_alloc+0xfe/0x738
test_double_free+0x76/0x171
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
freed by task 490 on cpu 1 at 34.175348s:
test_double_free+0xa8/0x171
kunit_try_run_case+0x61/0xa0
kunit_generic_run_threadfn_adapter+0x16/0x30
kthread+0x176/0x1b0
ret_from_fork+0x22/0x30
CPU: 1 PID: 490 Comm: kunit_try_catch Tainted: G B 5.13.0-rc3+ #7
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014
==================================================================
Kernel stack offset randomisation
「Kernel stack offset randomisation」はシステムコールごとにカーネルのスタックオフセットをランダム化し、カーネルの情報漏洩や悪用を緩和する仕組みです。- Per-system-call kernel-stack offset randomization
- Linux 5.13 Poised To Allow Randomizing Kernel Stack Offset At Each System Call
約1%程度パフォーマンスに影響を与えますが、その最小限の影響と引き換えにカーネルの安全性が向上します。
デフォルトで有効に
「Ubuntu 21.10」では「Kernel stack offset randomisation」がデフォルトで有効になってます。また対象アーキテクチャーは「amd64」及び「arm64」が対象です。
Landlock
「Landlock」はソフトウェアをサンドボックス化する仕組みです。いわゆるアクセス制御の一種です。
ユーザーがどんなに信用しているソフトウェアでもセキュリティー上の問題がないとは言い切れません。
例えば不具合により意図しない振る舞いをしてしまう可能性もあります。
強制アクセス制御
ソフトウェアをサンドボックス化し、ソフトウェアからアクセスできるリソースを必要最低限に制限する仕組み(MAC/Mandatory Access Control)はすでに存在しており、例えば「AppArmor」や「SELinux」は「MAC」の一例です。「Ubuntu」では「AppArmor」を採用しています。
これらは「LSM(Linux Security Modules)」として「Linux kernel」内に実装されており、システム管理者は「MAC」を利用してソフトウェアの振る舞いに制限をかけることができます。
非特権プロセスから制限をかける
「Landlock」はソフトウェアがアクセスできるファイルに制限をかけられるという点において「AppArmor」と似ています。しかし「AppArmor」はシステム管理者がその制限を設定するのに対し、「Landlock」は非特権プロセスで動作しているソフトウェア自身からその制限を設定できる点が異なります。
「Landlock」は既存の「MAC」と共存でき、「AppArmor」と「Landlock」を組み合わせてソフトウェアに制限を課すことができます。
ここ数年「Landlock」と「Seccomp BPF (SECure COMPuting with filters)」を組み合わせてアプリケーション自身が自分に制限を設けるケースが見られるようになってきました。
デフォルトで有効に
「Ubuntu 21.10」ではプレビュー機能として「Landlock」がデフォルトで有効になってます。ソフトウェアの開発者は「AppArmor」に加え「Landlock」を活用することでより高度なソフトウェアの隔離を実現できるようになります。
非特権ユーザーによるBPFの利用禁止
「BPF(Berkeley Packet Filter)」はカーネル内で動作している仮想マシンであり、元々カーネルのネットワークサブシステム内で利用されていた仕組みでした。現在はその利用方法が拡大され、デバイスへのアクセスのフィルタリングやトレース、パフォーマンスのプロファイリングなど、様々な仕組みで活用されています。
非特権ユーザーからも利用可能に
「Linux kernel 4.4」で非特権ユーザーがカーネル内にBPFプログラムをロードできるようになりました。この時カーネル内の「BPF verifier」によりロードされたBPFプログラムがチェックされ、不正な振る舞いがないかどうかを検証します。
BPF verifierの脆弱性
しかし残念ながら「BPF verifier」の脆弱性により、カーネル内に緊急度の高い脆弱性がいくつももたらされるようになってしまいました。例えば悪意あるBPFプログラムが「BPF verifier」による検証をすり抜け、非特権ユーザーがroot権限を得られてしまう脆弱性はこの一例です。
特権ユーザーのみBPFプログラムをロード可能に
そこで「Ubuntu 21.10」ではデフォルトで特権ユーザーのみBPFプログラムをロードできるように変更されました。言い換えれば非特権ユーザーはBPFプログラムをロードできません。
もしシステム管理者が非特権ユーザーでもBPFプログラムをロードできるようにしたいならば、「sysctl」の設定を変更することでこの制限を外すことも可能です。
GCC 11による静的分析の改善
「Ubuntu 21.10」では最新の「GCC」を採用しています。「GCC 10」では「-fanalyzer」コマンドラインオプションによる静的分析オプションが導入されました。
「GCC 11」ではこれに加え、リテラル文字列の変更処理やシフト演算によるオーバーフローといった問題の検出にも対応しました。
「Ubuntu 21.10」上でこれらのオプションを有効にしてソフトウェアをビルドすれば、開発者はソフトウェアの潜在的な問題の検出や品質向上に役立てることができるでしょう。