Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Linux Kernelの1文字のミスで 権限昇格ができた話
Search
rona
March 20, 2026
Programming
2.6k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Linux Kernelの1文字のミスで 権限昇格ができた話
rona
March 20, 2026
Other Decks in Programming
See All in Programming
【やさしく解説 設計編・中級 #4】ルールの寿命と、システムの年輪
panda728
PRO
2
140
作るコストが小さくなった時代 幸せに働くために改めて考えたいこと 〜エンジニアとして価値を出し続けるために注視している二分野〜
yuppeeng
0
100
ローカルLLMでどこまでコードが書けるか -拡張版 / How much code can be written on a local LLM Extended
kishida
12
4.8k
【やさしく解説 設計編 #1】「ドメイン駆動」と「実装駆動」ってなに? 〜設計の考え方を、たとえ話で学ぼう〜
panda728
PRO
1
120
act2-costs.pdf
sumedhbala
0
110
ビデオ通話が繋がる0.2秒で何が起きているのか
supurazako
2
150
【SRE NEXT 2026 Lunch Session】一人目専任SREの立ち上げを加速する ― AIと進めたオンボーディングで2分を0.04秒にした話
pkshadeck
PRO
0
2.7k
PHP に部分適用が来るぞ!……ところで何それ?おいしいの? #phpcon / phpcon-2026
shogogg
0
220
エンジニアにデザインハーネスを 〜デザインプロセスを規定するためのハーネス〜 / Design harness from an engineer's perspective
rkaga
2
1.5k
5分で問診!Composer セキュリティ健康診断
codmoninc
0
280
Even G2とAWSで推しのエージェントを召喚しよう!
har1101
1
170
AI がコードを書く時代における新卒エンジニアの仕事風景 (2026) / New Graduate Engineers in the Era of AI Coding (2026)
sushichan044
0
220
Featured
See All Featured
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
390
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.9k
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
220
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
380
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.3k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
550
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.5k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
190
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
530
Facilitating Awesome Meetings
lara
57
7k
Transcript
Linux Kernelの1文字のミスで 権限昇格ができた話 rona (@rqda_A) Kernel/VM探検隊@つくば No3 1/53
WHOAMI Rona - 筑波大学 WORD編集部 - 趣味: CTF (pwn) -
好き: kernel空間、猫 2/53
1. Intro - タイトルの「1文字」は 嘘 - ごめんなさい - 1<<5(32)文字に変更させてください 3/53
1. Intro - CVE-2025-37997の話 - パッチは1<<5文字の変更 https://lore.kernel.org/linux-cve-announce/2025052902-CVE-2025-37997-2c6c@gregkh/T/#u 4/53
1. Intro - 以下の環境で一般ユーザーがsudoなしでrootになれる - RedHad Enterprise Linuxのデフォルトインストール - rootless
Docker/podmanが入ったLinux 5/53
Linux Kernelの1<<5文字のミスで 権限昇格ができた話 rona (@rqda_A) Kernel/VM探検隊@つくば No3 6/53
2. Prerequisite - パッチは32文字 - % が / になっていることが大事 https://lore.kernel.org/linux-cve-announce/2025052902-CVE-2025-37997-2c6c@gregkh/T/#u
7/53
2. Prerequisite - IPSetとは? → netfilterサブシステムでIPをまとめて管理する方法 - 利点: 対象ipをiptablesなどのルールをいちいち変えずに編集できる ipset
create blocklist hash:ip ipset add blocklist 192.0.2.68 ipset add blocklist 192.0.2.70 iptables -A INPUT -m set --match-set blocklist src -j DROP ipsetの例 8/53
2. Prerequisite ipset create blocklist hash:ip ipset add blocklist 192.0.2.68
ipset add blocklist 192.0.2.70 iptables -A INPUT -m set --match-set blocklist src -j DROP - IPSetとは? → netfilterサブシステムでIPをまとめて管理する方法 - 利点: 対象ipをiptablesなどのルールをいちいち変えずに編集できる このサブシステムに脆弱性があった ipsetの例 9/53
htable 0 1 2 3 401 402 403 404 region
0 region 1 hbucket used size pos value [] - htableはhash table (入力データのhash を使って bucket を選ぶ table) - hbucketへのポインタを持つ - hbucketは実データを保管するbucket 2. Prerequisite | IPSetの構造 10/53
2. Prerequisite | hbucketの構造 rcu_head rcu u8 size, pos long
used (bitmap) u32 ip ulong timeout u32 skbmark, skbmarkmask hbucket u16 skbprio, skbqueue ... ヘッダー部 データ部 (何個も続く) 11/53
- hbucketに大きくなってほしくないのでhtableをregionに分割 - hashの衝突が多くなってきたらregionを増やして多くのhbucketに分散 - 1regionは0x400個 2. Prerequisite | IPSetの構造
htable 0 1 2 3 401 402 403 404 region 0 region 1 801 802 803 804 region 2 12/53
1. 入力値のjhashを取って、tableのサイズ分だけにtruncate 入力 value jhash & (tablesize -1) 例: 192.168.1.1
例: 0x12318e42 例: 0x242 (region数 == 1) 例: 0xe42 (region数== 4) 2. Prerequisite | IPSet addの実装 13/53
2. htableのうち、先程計算したindex番目のhbucketを編集 hbucket used pos/size 192.168.1.68 192.168.1.1 0 1 2
... 0xe41 0xe42 htable 2. Prerequisite | IPSet addの実装 14/53
3. add時にtimeout (==有効期限)を設定できる hbucket used pos/size 192.168.100.98 192.168.1.1 / 1m
0 1 2 ... 0xe41 0xe42 htable 2. Prerequisite | IPSet addの実装 15/53
1. region毎にtimeoutしたエントリの存在を確認/存在したら削除 2. Prerequisite | IPSet GCの実装 hbucket used pos/size
192.168.100.98 192.168.1.1 / 1m 0 1 2 ... 0xe41 0xe42 htable 16/53
2. Prerequisite | IPSet GCの実装 hbucket used pos/size 192.168.100.98 削除
0 1 2 ... 0xe41 0xe42 htable 1. region毎にtimeoutしたエントリが存在確認/存在したら削除 17/53
3. Vulnerability | lockの取り方 - Kernelはマルチスレッドなので、適切なlockが必要 - region毎にhregion[n]をlockする方針 1region毎にlockを取ってGC bucket
index % region数でlockを取る 0 GC側 Add 側 htable htable 0x401 1 2 0x403 0x402 例: hregion[0]のlockを取ってGCするもの 例: hregion[0]のlockを取ってaddするもの (region数 == 2とする) 1 0x402 0x401 0x403 0 2 18/53
3. Vulnerability | lockの取り方 - Kernelはマルチスレッドなので、適切なlockが必要 - region毎にhregion[n]をlockする方針 → add側がlockの取り方をミスってる!!
1region毎にlockを取ってGC bucket index % region数でlockを取る 0 GC側 Add 側 htable htable 0x401 1 2 0x403 0x402 例: hregion[0]のlockを取ってGCするもの 例: hregion[0]のlockを取ってaddするもの (region数 == 2とする) 0x402 0x401 0x403 1 0 2 19/53
3. Vulnerability | パッチの意味 - % が / になっている →
add側のlockの計算マクロがこれ https://lore.kernel.org/linux-cve-announce/2025052902-CVE-2025-37997-2c6c@gregkh/T/#u 20/53
3. Vulnerability | lockの不整合・具体例 0 1 2 ... 0x401 0x402
htable 例: region数==2のとき GC Thread - region0のGCをしている - hregion[0]をlockする add Thread - index 1にエントリを追加し ようとしている - hregion[1]をlockする 21/53
0 1 2 ... 0x401 0x402 htable 例: region数==2のとき GC
Thread - region0のGCをしている - hregion[0]をlockする add Thread - index 1にエントリを追加し ようとしている - hregion[1]をlockする - (index % region数)をlock 3. Vulnerability | lockの不整合・具体例 22/53
0 1 2 ... 0x401 0x402 htable 例: region数==2のとき GC
Thread - region0のGCをしている - hregion[0]をlockする add Thread - index 1にエントリを追加し ようとしている - hregion[1]をlockする - (index % region数)をlock index==1に対して2スレ ッドが同時に操作 3. Vulnerability | lockの不整合・具体例 23/53
4. Exploit | bucketの構造 rcu_head rcu u8 size, pos long
used u32 ip ulong timeout u32 skbmark, skbmarkmask hbucket u16 skbprio, skbqueue ... ヘッダー部 データ部 (何個も続く) 24/53
1. regionのはじめから最後までを loop mtype_gc_doの実装 4. Exploit | GCの実装 25/53
1. regionのはじめから最後までを loop 2. 各regionにおいて、bucketのすべ てのエントリをloop mtype_gc_doの実装 4. Exploit |
GCの実装 26/53
1. regionのはじめから最後までを loop 2. 各regionにおいて、bucketのすべ てのエントリをloop 3. usedが立ってないエントリと mtype_gc_doの実装 4.
Exploit | GCの実装 27/53
1. regionのはじめから最後までを loop 2. 各regionにおいて、bucketのすべ てのエントリをloop 3. usedが立ってないエントリと expireしたエントリをd++で数える (expireしたものはusedのbitを落と
す) mtype_gc_doの実装 4. Exploit | GCの実装 28/53
1. regionのはじめから最後までをloop 2. 各regionにおいて、bucketのすべてのエントリ をloop 3. usedが立ってないエントリとexpireしたエント リをd++で数える (expireしたものはusedのbitを 落とす)
4. dがAHASH_INIT_SIZEが2を超えていたら mtype_gc_doの実装 4. Exploit | GCの実装 29/53
4. Exploit | GCの実装 1. regionのはじめから最後までをloop 2. 各regionにおいて、bucketのすべてのエントリ をloop 3.
usedが立ってないエントリとexpireしたエント リをd++で数える (expireしたものはusedのbitを 落とす) 4. dがAHASH_INIT_SIZE(2)を超えていたら 5. (最大エントリ数 - 2) * エントリサイズの領域を alloc mtype_gc_doの実装 30/53
4. Exploit | GCの実装 1. regionのはじめから最後までをloop 2. 各regionにおいて、bucketのすべてのエントリ をloop 3.
usedが立ってないエントリとexpireしたエント リをd++で数える (expireしたものはusedのbitを 落とす) 4. dがAHASH_INIT_SIZE(2)を超えていたら 5. (最大エントリ数 - 2) * エントリサイズの領域を alloc 6. 元の領域からusedのbitが立っているエントリ だけコピー mtype_gc_doの実装 31/53
4. Exploit | GCとaddのrace condition rcu_head rcu u8 size, pos
192.0.2.1 / 1h 192.0.2.68 / 1h id==1のhbucket 1 2 3 4 0 long used 192.0.2.194 / 0s 192.0.2.253 / 0s 1. GCがhregion[0]のlockを取ってregion0のGC を開始 具体例 32/53
4. Exploit | GCとaddのrace condition rcu_head rcu u8 size, pos
192.0.2.1 / 1h 192.0.2.68 / 1h id==1のhbucket 1 2 3 4 0 long used 192.0.2.194 / 0s 192.0.2.253 / 0s 1. GCがhregion[0]のlockを取ってregion0のGC を開始 2. GCがタイムアウトしたエントリのused bitを 落とす 具体例 33/53
4. Exploit | GCとaddのrace condition rcu_head rcu u8 size, pos
192.0.2.1 / 1h 192.0.2.68 / 1h id==1のhbucket 1 2 3 4 0 long used 203.0.113.1 / 1h 192.0.2.253 / 0s 1. GCがhregion[0]のlockを取ってregion0のGC を開始 2. GCがタイムアウトしたエントリのused bitを 落とす 3. 別スレッドでこのhbucketに対するaddが実行 され、エントリが挿入される (used bitが再度立 つ) 具体例 34/53
4. Exploit | GCとaddのrace condition rcu_head rcu u8 size, pos
192.0.2.1 / 1h 192.0.2.68 / 1h id==1のhbucket 1 2 3 4 0 long used 203.0.113.1 / 1h 192.0.2.253 / 0s rcu_head rcu u8 size, pos new hbucket 1 2 3 4 0 long used 4. GCは2要素分少なく した領域を新たにalloc 35/53
4. Exploit | GCとaddのrace condition rcu_head rcu u8 size, pos
192.0.2.1 / 1h 192.0.2.68 / 1h id==1のhbucket 1 2 3 4 0 long used 203.0.113.1 / 1h 192.0.2.253 / 0s rcu_head rcu u8 size, pos new hbucket 1 2 3 4 0 long used 4. GCは2要素分少なく した領域を新たにalloc 5. used bitが立ってい るエントリを1つずつ コピー 192.0.2.1 / 1h 0 36/53
4. Exploit | GCとaddのrace condition rcu_head rcu u8 size, pos
192.0.2.1 / 1h 192.0.2.68 / 1h id==1のhbucket 1 2 3 4 0 long used 203.0.113.1 / 1h 192.0.2.253 / 0s rcu_head rcu u8 size, pos new hbucket 1 2 3 4 0 long used 4. GCは2要素分少なく した領域を新たにalloc 5. used bitが立ってい るエントリを1つずつ コピー 192.0.2.1 / 1h 1 0 192.0.2.68 / 1h 37/53
4. Exploit | GCとaddのrace condition rcu_head rcu u8 size, pos
192.0.2.1 / 1h 192.0.2.68 / 1h id==1のhbucket 1 2 3 4 0 long used 203.0.113.1 / 1h 192.0.2.253 / 0s rcu_head rcu u8 size, pos new hbucket 1 2 3 4 0 long used 4. GCは2要素分少なく した領域を新たにalloc 5. used bitが立ってい るエントリを1つずつ コピー 192.0.2.1 / 1h 1 0 192.0.2.68 / 1h 2 203.0.113.1 / 1h 範囲外書き込み!! BoF (OOB write)!! 38/53
4. Exploit | bucketの構造 rcu_head rcu u8 size, pos u32
ip ulong timeout u32 skbmark, skbmarkmask long used u16 skbprio, skbqueue もし範囲外書き込みの先に別のhbucketがいた ら? 赤文字のところには任意のデータを入れられる → 別のhbucketを(自認)デカsizeに書き換えられ る 39/53
4. Exploit | bucketの構造 rcu_head rcu u8 size, pos u32
ip ulong timeout u32 skbmark, skbmarkmask long used u16 skbprio, skbqueue もし範囲外書き込みの先に別のhbucketがいたら? 赤文字のところには任意のデータを入れられる → 別のhbucketを(自認)デカsizeに書き換えられる → 巨大な範囲外書き込みができる 40/53
4. Exploit | dirty pagetable 範囲外書き込みを権限昇格につなげる手法 → dirty pagetable 41/53
4. Exploit | dirty pagetable 範囲外書き込みを権限昇格につなげる手法 → dirty pagetable pagetableとは?
→ 仮想アドレスと物理アドレスを対応付ける仕組み https://www.coins.tsukuba.ac.jp/~yas/coins/os2-2025/2026-01-15/index.html 42/53
4. Exploit | dirty pagetable 範囲外書き込みを権限昇格につなげる手法 → dirty pagetable pagetableとは?
→ 仮想アドレスと物理アドレスを対応付ける仕組み → pagetableを書き換えてある仮想アドレスを任意の物理アドレスに向けるのがdirty pagetable https://www.coins.tsukuba.ac.jp/~yas/coins/os2-2025/2026-01-15/index.html 43/53
4. Exploit | dirty pagetable 範囲外書き込みを権限昇格につなげる手法 → dirty pagetable pagetableとは?
→ 仮想アドレスと物理アドレスを対応付ける仕組み → pagetableを書き換えてある仮想アドレスを任意の物理アドレスに向けるのがdirty pagetable 任意の物理メモリをユーザーランドからいじれるようになる → カーネルも物理メモリに乗っていて物理メモリの世界にRWXなどという概念はない 44/53
4. Exploit | dirty pagetable 範囲外書き込みを権限昇格につなげる手法 → dirty pagetable pagetableとは?
→ 仮想アドレスと物理アドレスを対応付ける仕組み → pagetableを書き換えてある仮想アドレスを任意の物理アドレスに向けるのがdirty pagetable 任意の物理メモリをユーザーランドからいじれるようになる → カーネルも物理メモリに乗っていて物理メモリの世界にRWXなどという概念はない → 何でもできる (R-Xな領域の上書きも!) 45/53
4. Exploit | dirty pagetable 書き込み先: core_pattern - crashしたときにcoredumpを生成するためにroot権限でどんなことをすればいいか書かれ ている
- |から始まると、そのファイルを実行する 46/53
4. Exploit | dirty pagetable 書き込み先: core_pattern - crashしたときにコアダンプを生成するためにroot権限で何をすべきか書かれている -
|から始まると、そのファイルを実行する - 例えば |/home/rona/lpe に書き換えるとroot権限で何でも実行させられる (== 権限昇格) 47/53
4. Exploit | dirty pagetable 権限昇格手法 1. 範囲外書き込みで到達可能な範囲にpagetableが置かれるように調整 2. 範囲外書き込みでpagetable
entryをcore_patternが置かれている物理ページに向ける 48/53
4. Exploit | dirty pagetable 権限昇格手法 1. 範囲外書き込みで到達可能な範囲にpagetableが置かれるように調整 2. 範囲外書き込みでpagetable
entryをcore_patternが置かれている物理ページに向ける 3. core_patternを書き換える 49/53
4. Exploit | dirty pagetable 権限昇格手法 1. 範囲外書き込みで到達可能な範囲にpagetableが置かれるように調整 2. 範囲外書き込みでpagetable
entryをcore_patternが置かれている物理ページに向ける 3. core_patternを書き換える 4. win! 権限昇格! 50/53
4. Exploit | 影響を受けるプロダクト - 一般ユーザーがipsetをいじれる環境 → unprivileged_userns_cloneが有効なLinux - RedHad
Enterprise Linuxのデフォルトインストール - rootless Docker/podmanが入ったLinux 51/53
5. おわり - マルチスレッドアプリケーションを安全に書くのは難しい - Linux kernelのように良くauditされたOSSにもミスは存在する 52/53
6. 宣伝 dirty pagetableと同様の攻撃をやってみたい!という方はHungry Goatsを解いて みてください! 脆弱なLinuxカーネルモジュールを利用して権限昇格をする問題 https://alpacahack.com/challenges/hungry-goats 53/53