adb remountがpixel 7aで失敗することがあったため、その覚書を書く。
どんなエラーが発生したか
次のように/dev/block/dm-0
についてPermission denied
といったエラーが発生した。
本来はRemounted / as RW
というようにRead Write modeで書き込めたとなるのが正しい。
$ ../platform-tools/adb remount
AVB verification is disabled, disabling verity state may have no effect
failed to remount partition dev:/dev/block/dm-0 mnt:/: Permission denied
Remounted /system_dlkm as RW
failed to remount partition dev:/dev/block/dm-2 mnt:/system_ext: Permission denied
failed to remount partition dev:/dev/block/dm-3 mnt:/product: Permission denied
Remounted /vendor as RW
Remounted /vendor_dlkm as RW
Remount failed
また、この状態で中に入っても手でmountしようとしてもエラーになる。
adb remountの時はPermission deined
となったブロックデバイスについてread-only
と出るようになった。
$ adb root
$ adb shell
# mount -o rw,remount /
'/dev/block/dm-0' is read-only
ネットに広がっているもの
そもそも最近のadb remount
ではAVB verification is disabled, disabling verity state may have no effect
とうメッセージが最初に出力される。
このメッセージはadb disable-verity
を実行したときと同じメッセージである。
mount
を実行し、mountテーブルを確認することで、/
は/dev/block/dm-0
というブロックデバイスに紐付いていることが分かる。そもそもmountされていない、またはfstabに記載のない/system
や他のフォルダに対してmountしようとするとnot in /proc/mounts
というメッセージが表示される。
/dev/block/dm-0 on / type ext4 (ro,seclabel,noatime)
/dev/block/dm-0とは何か?
いろいろ調べているうちにDevice Mapper
で作成されたパーティションあることが分かった。
Device Mapper
とはdmctl
により操作できるfdiskやpartedみたいなパーティション作成っぽいものである。
dmctlを調べてみる
grok3に聞いてみると、dmsetupみたいなツールの一部みたいな説明があったがhelp表示のサブコマンドからどうやらそれとはまた異なることが分かった。内容を見る限りパーティションを割り当てることをできそうなツールであることが分かった。
lynx:/ # dmctl
usage: dmctl <command> [command options]
dmctl -f file
commands:
create <dm-name> [-ro] <targets...>
delete <dm-name>
list <devices | targets> [-v]
message <dm-name> <sector> <message>
getpath <dm-name>
getuuid <dm-name>
ima <dm-name>
info <dm-name>
replace <dm-name> <targets...>
status <dm-name>
resume <dm-name>
suspend <dm-name>
table <dm-name>
help
-f file reads command and all parameters from named file
Target syntax:
<target_type> <start_sector> <num_sectors> [target_data]
dmsetupシリーズで言われているものとの違いはサブコマンドにreplace
があるか否か
このことからdmctl replace
を検索することでソースを見つけることができた。このソースをgrok3に食わせread-onlyを外す方法を確認してみた。最初はdmctl delete
とdmctl create
を使ってread-onlyで作成された領域を一度削除し、read-onlyなしに作成し直す方法が案内されたが、mountポイントに対して一時的にでも割当が外れることでmountポイントがおかしな状態になることを恐れdmctl replace
で作ってとgrok3に依頼した。すると、dmctl replaceを使ったソースを出力することができた。これを修正したのがこちらである。
ソースの構成
toggle_mount.sh ※利用は自己責任で
toggle_mount()
与えられたデバイスに対してro
またはrw
を指定してパーティションを読み取り専用・または読み書き可に変更する。読み取り専用で実際に戻せるかは試していないので少し怪しい。
手順は次の通り。
-
dmctl table
で現在のパーティション情報を取得する
lynx:/ # dmctl table system_a
Targets in the device-mapper table for system_a:
0-2410336: linear, 259:14 2048
-
dmctl table
で取得したパーティション情報を元にdmctl replace
コマンドを組み立てる
※ただし、「-ro」オプションの付与の有無で読み取り専用または読み書き可能かを、パーティションに対して定義し直す。
# dmctl replace system_a linear 0 2410336 259:14 2048
convert_all_to_rw()
「-all」を引数に指定して呼び出したときに実行される関数。
手順は次の通り。
- system・product・vendorを含むデバイス一覧を取得する
これはdmctl list devices
で得たデバイス一覧を元に行っており、adb remount
の対象のパーティションに合わせた。
lynx:/ # dmctl list devices | grep -E "system|product|vendor"
product_a : 254:3
system_a : 254:0
system_dlkm_a : 254:1
system_ext_a : 254:2
vendor_a : 254:4
vendor_dlkm_a : 254:5
- 上記で取得したデバイスを元に
toggle_mount()
を読み書き可で呼び出すようにした
実際に作成したシェルの実行結果
adb remountの対象デバイスに対し読み書き可でマウントすることができるようになった。
これらの設定は、Androidを再起動することでクリアされる。このため再起動後、システムファイルを書き込みたい場合は再度実行する必要がある。
$ adb root
$ adb shell
# bash toggle_mount.sh --all
shell-init: error retrieving current directory: getcwd: cannot access parent directories: Math result not representable
chdir: error retrieving current directory: getcwd: cannot access parent directories: Math result not representable
Converting all system, product, vendor devices to read-write
>>>Processing product_a (mode: rw)
Check: Table: Targets in the device-mapper table for product_a: 0-4120600: linear, 259:14 3425776
Running: dmctl replace product_a linear 0 4120600 259:14 3425776
/dev/block/dm-3 on /product type ext4 (ro,seclabel,noatime) -> dmctl replace product_a linear 0 4120600 259:14 3425776
Success: product_a is now rw
>>>Processing system_a (mode: rw)
Check: Table: Targets in the device-mapper table for system_a: 0-2410336: linear, 259:14 2048
Running: dmctl replace system_a linear 0 2410336 259:14 2048
/dev/block/dm-0 on / type ext4 (ro,seclabel,noatime) -> dmctl replace system_a linear 0 2410336 259:14 2048
Success: system_a is now rw
>>>Processing system_dlkm_a (mode: rw)
Check: Table: Targets in the device-mapper table for system_dlkm_a: 0-23032: linear, 259:14 2412384
Running: dmctl replace system_dlkm_a linear 0 23032 259:14 2412384
/dev/block/dm-1 on /system_dlkm type ext4 (ro,seclabel,noatime) -> dmctl replace system_dlkm_a linear 0 23032 259:14 2412384
Success: system_dlkm_a is now rw
>>>Processing system_ext_a (mode: rw)
Check: Table: Targets in the device-mapper table for system_ext_a: 0-990360: linear, 259:14 2435416
Running: dmctl replace system_ext_a linear 0 990360 259:14 2435416
/dev/block/dm-2 on /system_ext type ext4 (ro,seclabel,noatime) -> dmctl replace system_ext_a linear 0 990360 259:14 2435416
Success: system_ext_a is now rw
>>>Processing vendor_a (mode: rw)
Check: Table: Targets in the device-mapper table for vendor_a: 0-1513152: linear, 259:14 7546376
Running: dmctl replace vendor_a linear 0 1513152 259:14 7546376
/dev/block/dm-4 on /vendor type ext4 (ro,seclabel,noatime) -> dmctl replace vendor_a linear 0 1513152 259:14 7546376
Success: vendor_a is now rw
>>>Processing vendor_dlkm_a (mode: rw)
Check: Table: Targets in the device-mapper table for vendor_dlkm_a: 0-121984: linear, 259:14 9059528
Running: dmctl replace vendor_dlkm_a linear 0 121984 259:14 9059528
/dev/block/dm-5 on /vendor_dlkm type ext4 (ro,seclabel,noatime) -> dmctl replace vendor_dlkm_a linear 0 121984 259:14 9059528
Success: vendor_dlkm_a is now rw
Summary: 6 devices succeeded, 0 devices failed
感想
grok3が非常に役に立った。大まかな構成を伝えることで大まかに期待通りのソースを出力することができた。また、結構な人が同じようなメッセージで詰まっていそうなのでそんな方々の手助けになると嬉しい。
この記事がなんとなくいいなと思ったら、いいねお願いします🤗