#initramfsとは#
前回でLUKSに必要なコマンド操作の基本を抑え、ユーザーパスワード操作を鍵ファイルの取り扱いに置き換える方法をまとめた。
今回は2、Linuxの起動プロセスの間へ復号処理を割り込ませる部分を検討していく。
initramfsがポイントになるようだが、これはどういう仕組みだろうか。
Ubuntu Weekly Recipe第384回 Initramfsのしくみにわかりやすく説明されていた。
「Initramfsの役割
Ubuntuはさまざまなディスクデバイスにルートファイルシステムをインストールし,起動するOSです。カーネルはブートローダーによって起動されたあと,ルートファイルシステムをマウントするために,サポートしているすべてのディスクデバイスのドライバを持っている必要があります。
しかしながらこのドライバをすべてカーネルに組み込んでしまうと,カーネルが肥大化してしまいます。しかもそのほとんどは,今使っているディスクデバイスでは不要なドライバです。必要なドライバを必要に応じてロードする仕組みとして「カーネルモジュール」がありますが,今度はその「カーネルモジュール」をどこに保存するのかという問題が発生します。当然のことながら,この時点でルートファイルシステムにはアクセスできません。
そこで出てくるのが「Initramfs」という仕組みです。
Ubuntuに限らずほとんどのLinuxディストリビューションでは,「ミニルート」とも呼ばれるメモリ上に展開可能な,小さなサイズのルートファイルシステムを持っています。このミニルートには,ルートファイルシステムをマウントするために必要なカーネルモジュールやスクリプトが保存されているのです。ブートローダーはカーネルと一緒にこのミニルートをメモリ上に展開し,カーネルにそのアドレスを伝えます。カーネルはそのアドレスを元にミニルートをマウントし,その中にあるスクリプトを実行することで本来のルートファイルシステムをマウントします。
「Initramfs」は,現在はデスクトップLinuxでもっとも使われているミニルートのファイルフォーマットの1つです(注1)。Ubnutuだと「/boot/initrd.img-3.19.0-23-generic」などのカーネルバージョンごとファイルになります。」
initramfsでLUKSパーティションを復号し、ルートファイルシステムとしてマウントさせられれば目的は達せられそうだ。
#Jetson Nanoでのinitramfs#
Jetson Nanoではどのようにinitramfsが使われているだろうか。
ルートファイルシステムを壊れやすいSDカードでなく、外付けUSBのSSDに保存したいという事例が見つかった。
Jetson Nanoの/をUSBドライブにしてSDカードを長生きさせる
この中で触れられているrootOnUSBが、
1、ルートファイルシステムをUSBに丸ごとコピーする
2、USBをマウントできるようにinitramfsを改変する
上記をやっている。
これを参考にすればinitramfsへの組み込みができそう。
Jetson Nano上で上記を行うスクリプトを考えてみる。
kmwebnet/makeinitramfs
このスクリプトではinitramfsに対して、
1、cryptsetupの組み込み
2、LUKSパーティションに事前に設定されているパスワードを使って、前回作成した
ATECC608Aの鍵を保存してあるスロットへアクセスし、IO保護キーで通信経路を暗号化しながら読み出してstdoutに出力するプログラム(keyout)と入れ替えるスクリプト
3、上記に必要な、事前設定パスワードとkeyoutプログラム
上記を組み込み、最後に
$ sudo mkinitramfs -o /boot/initrd.img-4.9.140-tegra
を実行する。
これで、cryptsetupが組み込まれたinitramfsが/boot/initrd.img-4.9.140-tegraとして出来上がった。
#デバイスツリーの準備他#
$ sudo /opt/nvidia/jetson-io/jetson-io.py
上記を実行して、i2s4を使えるように設定する。
詳細は、JetPack 4.3 (r32.3.1) で追加された Jetson-IO tool を使用して Pinmux テーブルを設定してみた。を参照。そうすると、
/boot/extlinux/extlinux.conf内が下記のようになる。
LABEL JetsonIO
MENU LABEL Custom 40-pin Header Config
LINUX /boot/Image
FDT /boot/tegra210-p3448-0000-p3449-0000-b00-user-custom.dtb
INITRD /boot/initrd
APPEND ${cbootargs}
上記にある
/boot/Image
/boot/tegra210-p3448-0000-p3449-0000-b00-user-custom.dtb
また、先ほど作成した
/boot/initrd.img-4.9.140-tegra
この3つが後ほど必要になるため、Jetson Nanoを停止して、SDカードを取りだしUSBで変換する。
Jetson Nano Dev Boardを使ってSDカード暗号化をテスト(Jetson Nano secureboot編)で用意したJetson Nanoファームウェア構築用UbuntuPCを使用し、上記SDカードをUSB変換を使い、マウントしUbuntuPCに3つを保存しておく。
理由としては、Jetson Nanoのパーティション定義が、/bootと/が1つのパーティションで、ルートファイルシステムの暗号化を行った場合、/bootごと暗号化され、起動ができないためだ。
また、これに対応するルートファイルシステムを準備する。
r32.4.2が新規に書き込まれたSDカードを作成する。
Jetson Nanoで使えるSDカードのイメージファイルまとめとイメージ書き込み方法
書き込み終わったら、Jetson Nano にSDカードを入れる前にルートファイルシステムを吸い出す。
Jetson Nano Dev Boardを使ってSDカード暗号化をテスト(Jetson Nano secureboot編)で用意したJetson Nanoファームウェア構築用UbuntuPCを使用し、上記SDカードをUSB変換を使い、マウントする。
”Linux_for_Tegra”ディレクトリ上から操作を開始する。
ddで13GBくらいのルートファイルシステムのイメージの入れ物を作り、ループバックでマウントし、luksFormatを行う。
その後、SDカードからルートファイルシステムをrsyncでコピーをかける流れ。
SDカードは/dev/sdaで認識した。
$ dd if=/dev/zero of=system.img.raw bs=1M count=0 seek=13312
$ sudo losetup -f system.img.raw
$ losetup -l //ループバックデバイス番号を確認する。
NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC
/dev/loop5
0 0 0 0
Linux_for_Tegra/system.img.raw
$ sudo apt install cryptsetup
$ sudo cryptsetup luksFormat /dev/loop5
WARNING!
========
This will overwrite data on /dev/loop1 irrevocably.
Are you sure? (Type uppercase yes): YES<大文字YES>
Enter passphrase for /dev/loop5: <”test”と入力>
Verify passphrase: <”test”と入力>
$ sudo cryptsetup luksOpen /dev/loop5 luks
Enter passphrase for /dev/loop5:<”test”と入力>
$ ls /dev/mapper/
control luks
$ sudo mkfs.ext4 /dev/mapper/luks
mke2fs 1.44.1 (24-Mar-2018)
Creating filesystem with 2096640 4k blocks and 524288 inodes
Filesystem UUID: b71b1ee2-993e-44b8-b5e5-5d6ab4346b6b
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632
Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done
$ sudo mkdir /media/luks
$ sudo mount /dev/mapper/luks /media/luks
$ sudo mkdir /media/usb
$ sudo fdisk -l /dev/sda
GPT PMBR size mismatch (26865663 != 249737215) will be corrected by w(rite).
Disk /dev/sda: 119.1 GiB, 127865454592 bytes, 249737216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 4C9B6CD1-8AEA-46F2-B51E-D99B485C0E4A
Device Start End Sectors Size Type
/dev/sda1 28672 26861567 26832896 12.8G Linux filesystem
/dev/sda2 2048 2303 256 128K Linux filesystem
/dev/sda3 4096 4991 896 448K Linux filesystem
/dev/sda4 6144 7295 1152 576K Linux filesystem
/dev/sda5 8192 8319 128 64K Linux filesystem
/dev/sda6 10240 10623 384 192K Linux filesystem
/dev/sda7 12288 13055 768 384K Linux filesystem
/dev/sda8 14336 14463 128 64K Linux filesystem
/dev/sda9 16384 17279 896 448K Linux filesystem
/dev/sda10 18432 19327 896 448K Linux filesystem
/dev/sda11 20480 22015 1536 768K Linux filesystem
/dev/sda12 22528 22655 128 64K Linux filesystem
/dev/sda13 24576 24735 160 80K Linux filesystem
/dev/sda14 26624 26879 256 128K Linux filesystem
Partition table entries are not in disk order.
$ sudo mount /dev/sda1 /media/usb
sudo apt-get install rsync -y
sudo rsync -axHAWX --numeric-ids --info=progress2 /media/usb/ /media/luks
コピー完了後、マウントした先が下記のようにルートファイルシステムになっていることを確認する。
$ ls -alr /media/luks/
合計 100
drwx------ 2 root root 4096 5月 29 15:07 var
drwxr-xr-x 12 root root 4096 4月 29 19:53 usr
drwxrwxrwt 2 root root 4096 4月 29 19:55 tmp
drwxr-xr-x 2 root root 4096 4月 24 2018 sys
drwxr-xr-x 2 root root 4096 4月 27 2018 srv
drwxr-xr-x 2 root root 4096 5月 11 2018 snap
drwxr-xr-x 2 root root 4096 2月 20 19:42 sbin
drwxr-xr-x 17 root root 4096 9月 11 2019 run
drwx------ 2 root root 4096 4月 27 2018 root
drwxr-xr-x 2 root root 4096 4月 24 2018 proc
drwxr-xr-x 4 root root 4096 4月 29 19:44 opt
drwxr-xr-x 2 root root 4096 4月 27 2018 mnt
drwxr-xr-x 2 root root 4096 8月 6 2018 media
drwx------ 2 root root 4096 4月 29 19:55 lost+found
drwxr-xr-x 21 root root 4096 4月 29 19:44 lib
drwxr-xr-x 2 root root 4096 4月 24 2018 home
drwxr-xr-x 136 root root 12288 4月 29 19:55 etc
drwxr-xr-x 2 root root 4096 4月 29 19:55 dev
drwxr-xr-x 4 root root 4096 4月 29 19:45 boot
drwxr-xr-x 2 root root 4096 2月 20 19:46 bin
-rw-rw-rw- 1 root root 62 4月 9 10:21 README.txt
drwxr-xr-x 5 root root 4096 5月 29 14:49 ..
drwxr-xr-x 22 root root 4096 4月 29 19:56 .
問題なければ、イメージファイルをUSBケーブル経由でJetson Nanoへ流しこめるように準備する。
$ sudo umount /media/luks
$ sudo cryptsetup luksClose /dev/mapper/luks
$ sudo losetup -d /dev/loop5
$ mv system.img.raw bootloader/
$ sudo bootloader/mksparse -v -fillpattern=0 bootloader/system.img.raw bootloader/system.img
mksparseというのは転送用にイメージファイルを圧縮するプログラム。
これで生成されるsystem.imgが実際に転送されるイメージ
これでbootloaderにルートファイルシステムのファイルを置くことができた。
ここまででinitramfs、および暗号化済みのルートファイルシステムの準備ができた。
次はJetson Nano Dev Boardを使ってSDカード暗号化をテスト(起動シーケンス作成編)
Jetson Nano Dev Boardを使ってSDカード暗号化をテスト 記事インデックス
概要編
Jetson Nano secureboot編
LUKS 調査編
initramfs 調査編 <いまここ
起動シーケンス作成編