初めに
前回はrootfsをdm-verityで検証してから起動するように設定した。
ただし、そのままではrootfsがすべてread onlyになってしまうので、必要なディレクトリを書き込み可能にしたい。
そこで今回はOverlayFSを使用して書き込み可能領域の作成を試みる。
OverlayFSとは
複数のディレクトリを1つのマウントポイントに階層構造に重ねてマージする仕組み。
最上層がread/write可能で、下層はread onlyとしてマウントされる。Linuxのコンテナでも使用されているらしい。
詳しくは以下のドキュメントなどを参照。
Overlay Filesystem — The Linux Kernel documentation
作るもの
前回作成したdm-verityでrootfsを検証する流れにOverlayFSを組み込む。
起動の流れは以下を目指す。
- initramfsのinitスクリプトを起動
- initramfsに含めたroot hashと別のパーティションに格納したhash treeを用いてrootfsの入っているパーティションを検証
- device-mapperでread onlyのデバイスとしてrootfsの入っているパーティションが認識されるので、適当な場所にマウント
- 書き込み用ディレクトリのあるパーティションを適当な場所にマウント
- OverlayFSで書き込み用ディレクトリをマウント
- switch_rootでrootfsを切り替え
- ラズパイOSのrootfsで起動
手順
前回作成したsdカードイメージを編集していく。
書き込み用パーティションを作成
前回と同様にsdカードイメージにパーティションを追加する。
今回は2GBの書き込み用パーティションを追加で作成する。サイズは適当。
ここでの2024-03-15-raspios-bookworm-arm64-lite.img
は前回作成したdm-verity対応がされたsdカードイメージである。
truncate -s 8G 2024-03-15-raspios-bookworm-arm64-lite.img sudo fdisk 2024-03-15-raspios-bookworm-arm64-lite.img
書き込み用ディレクトリを作成
作成したパーティションをフォーマット、マウントして、書き込み用ディレクトリを作成する。
ディレクトリはデータ保存用にhome, var, etcと、作業用にoverlayfs-workを作成する。
コマンドは以下。losetup関連のコマンドはloop0が空いているものとして記載する。
sudo losetup -f sudo losetup -P /dev/loop0 2024-03-15-raspios-bookworm-arm64-lite.img mkfs.ext4 /dev/loop0p5 mkdir tmp sudo mount /dev/loop0p5 tmp/ sudo mkdir tmp/{home,var,etc,overlayfs-work} sudo mkdir tmp/overlayfs-work/{home,var,etc} sudo umount tmp sudo losetup -d /dev/loop0
initramfsのinitを修正
前回までと同様にinitを変更する。
以下の内容にする。前回のとの差分はOverlayFSの設定のみ。rootfsは変更していないので、VERITY_ROOTHASH
の値は変更なし。
#!/bin/sh VERITY_ROOTHASH=3d203e1917909149841a8465e71a50f23e27d8b5e191ebea04b90ba442fe6891 mount -v --bind /dev /dev mount -v --bind /dev/pts /dev/pts mount -vt proc proc /proc mount -vt sysfs sysfs /sys mount -vt tmpfs tmpfs /run mdev -s echo "start switch_root!" # parse cmdline cmdline=$(cat /proc/cmdline) for param in $cmdline; do echo $param case $param in root=*) ROOT=`echo $param | sed 's/.*=//'` ;; esac done # wait rootfs for i in {1..30} do /sbin/mdev -s TMP=`ls -l /dev/ | grep $ROOT` if [ -n "${TMP}" ];then break fi echo "waiting rootfs..." sleep 1 done # veritysetup veritysetup open $ROOT verity-root /dev/mmcblk0p3 $VERITY_ROOTHASH # mount rootfs. mkdir -p /dev/root mount -o noload /dev/mapper/verity-root /dev/root # mount rw partition mkdir -p /dev/rw-partition mount /dev/mmcblk0p5 /dev/rw-partition # mount overlayfs mount -t overlay overlay -olowerdir=/dev/root/home,upperdir=/dev/rw-partition/home,workdir=/dev/rw-partition/overlayfs-work/home /dev/root/home mount -t overlay overlay -olowerdir=/dev/root/var,upperdir=/dev/rw-partition/var,workdir=/dev/rw-partition/overlayfs-work/var /dev/root/var mount -t overlay overlay -olowerdir=/dev/root/etc,upperdir=/dev/rw-partition/etc,workdir=/dev/rw-partition/overlayfs-work/etc /dev/root/etc # switch root exec switch_root -c /dev/console /dev/root /sbin/init
前回までと同様に上記のinitスクリプトを含めたFITImageを作成する。
詳しい作り方は過去の記事を参照。
その後作成したFITImageをsdカードイメージの第一パーティションに格納する。
sdカードイメージのフラッシュ
イメージが完成したので、sdカードにフラッシュする。
windowsの場合はRapsberry Pi Imagerなどで書き込める。
前回の記事で言っていたログインできない問題について
どうやらラズパイの初期ユーザpiは廃止されたようなので、書き込みの際にRaspberry Pi Imagerで適当なユーザを作るように設定が必要かもしれない。
しかし、ユーザを設定したかと思ったら、pi:raspberryでログインできたりして、ここに関しては動きがよくわからない。ラズパイ特有の話だと思うので深くは追いかけないことにする。
「Raspberry Pi OS」、最新リリースでデフォルトユーザー「pi」削除--セキュリティ強化 - ZDNET Japan
以後の作業はラズパイ実機で行う。
u-bootの設定を変更する。
u-bootコンソールで以下の設定を行う。
setenv bootargs "coherent_pool=1M 8250.nr_uarts=1 root=/dev/mmcblk0p2 rw rootwait" setenv bootcmd "fatload mmc 0:1 0x1000000 FITImage;bootm 0x1000000;" saveenv
この設定をいちいち行うのも面倒なので、u-bootをビルドするときに設定を追加したほうがいい気がしてきた。
起動する
起動してファイルを書き込もうとすると、/var
, /home
, /etc
以外のディレクトリがread onlyになっていることを確認できる。
また、mountコマンドを実行すると、以下のようにoverlayfsが使用されていることも見れる。
overlay on /home type overlay (rw,relatime,lowerdir=/dev/root/home,upperdir=/dev/rw-partition/home,workdir=/dev/rw-partition/overlayfs-work/home) overlay on /var type overlay (rw,relatime,lowerdir=/dev/root/var,upperdir=/dev/rw-partition/var,workdir=/dev/rw-partition/overlayfs-work/var) overlay on /etc type overlay (rw,relatime,lowerdir=/dev/root/etc,upperdir=/dev/rw-partition/etc,workdir=/dev/rw-partition/overlayfs-work/etc)
終わりに
dm-verityで検証したread onlyなrootfsの一部を書き込み可能にするために、OverlayFSを使用した。
特定のディレクトリだけ書き込み可能な設定を行えた。そのため、書き込みが必要なディレクトリさえ決まって入れば、必要最低限のディレクトリだけを書き込み可能にすることで、想定外のファイルを編集されることや問題のあるソフトウェアのインストールを防いだりできそうだ。