adb remountが失敗する(pixel 7a/lineageOS 22.2)

# adb remountがpixel 7aで失敗することがあったため、その覚書を書く。

## どんなエラーが発生したか
### 次のように`/dev/block/dm-0`について`Permission denied`といったエラーが発生した。
本来は`Remounted / as RW`というようにRead Write modeで書き込めたとなるのが正しい。
```bash
$ ../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`と出るようになった。
```shell
$ adb root
$ adb shell
# mount -o rw,remount /
'/dev/block/dm-0' is read-only
```

## ネットに広がっているもの
- ### `disable-verity`を使うと良い
そもそも最近の`adb remount`では`AVB verification is disabled, disabling verity state may have no effect`とうメッセージが最初に出力される。
このメッセージは`adb disable-verity`を実行したときと同じメッセージである。

- ### `mount: 'system' not in /proc/mounts`といったmountポイントが誤ったもの。
`mount`を実行し、mountテーブルを確認することで、`/`は`/dev/block/dm-0`というブロックデバイスに紐付いていることが分かる。そもそもmountされていない、またはfstabに記載のない`/system`や他のフォルダに対してmountしようとすると`not in /proc/mounts`というメッセージが表示される。
```bash
/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表示のサブコマンドからどうやらそれとはまた異なることが分かった。内容を見る限りパーティションを割り当てることをできそうなツールであることが分かった。
```bash
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`を検索することで[ソース](<https://android.googlesource.com/platform/system/core/+/master/fs_mgr/tools/dmctl.cpp>)を見つけることができた。このソースをgrok3に食わせread-onlyを外す方法を確認してみた。最初は`dmctl delete`と`dmctl create`を使ってread-onlyで作成された領域を一度削除し、read-onlyなしに作成し直す方法が案内されたが、mountポイントに対して一時的にでも割当が外れることでmountポイントがおかしな状態になることを恐れ`dmctl replace`で作ってとgrok3に依頼した。すると、dmctl replaceを使ったソースを出力することができた。これを修正したのが[こちら](<https://gist.github.com/doshiraki/3d3a89993d25b3a9122e1eca72841a53?permalink_comment_id=5547999>)である。

## ソースの構成
[toggle_mount.sh](<https://gist.github.com/doshiraki/3d3a89993d25b3a9122e1eca72841a53?permalink_comment_id=5547999>) ※利用は自己責任で
## toggle_mount()
与えられたデバイスに対して`ro`または`rw`を指定してパーティションを読み取り専用・または読み書き可に変更する。読み取り専用で実際に戻せるかは試していないので少し怪しい。

### 手順は次の通り。
- `dmctl table`で現在のパーティション情報を取得する
```bash
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」オプションの付与の有無で読み取り専用または読み書き可能かを、パーティションに対して定義し直す。
```bash
# dmctl replace system_a linear 0 2410336 259:14 2048
```

## convert_all_to_rw()
「-all」を引数に指定して呼び出したときに実行される関数。

### 手順は次の通り。
- system・product・vendorを含むデバイス一覧を取得する
これは`dmctl list devices`で得たデバイス一覧を元に行っており、`adb remount`の対象のパーティションに合わせた。
```bash
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を再起動することでクリアされる。このため再起動後、システムファイルを書き込みたい場合は再度実行する必要がある。
```bash
$ 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が非常に役に立った。大まかな構成を伝えることで大まかに期待通りのソースを出力することができた。また、結構な人が同じようなメッセージで詰まっていそうなのでそんな方々の手助けになると嬉しい。

:::note info
この記事がなんとなくいいなと思ったら、いいねお願いします🤗
:::