USBブートのLinuxの中身をアップデートしようと思い、中身を取り出したときのメモ。
暗号化されたファイルシステムをいじるのでdm-cryptカーネルモジュールを読み込む。(メモ:dm-cryptの名称は、Device-Mapper と CRYPTographic でできているらしい。)
# modprobe dm-crypt
鍵を探すため、initramfsの中身を取り出す。ここではlsinitrdコマンドを使うが、取り出せない場合もある。その場合、こちらを参照。
$ lsinitrd --unpack initrd.lz
おそらく、cryptsetupを使っていると思われるので、initramfsを展開した中にcryptsetupコマンドが使われているところがないかを検索する。
その他、ファイルが書き込まれないようにするためcasperを使っていることも考えられるので、cryptsetupでそれっぽいのが見つからなかったらcasperをキーワードに検索するのも良いかもしれない。
$ grep -r cryptsetup * grep: etc/ld.so.cache: binary file matches grep: sbin/cryptsetup: binary file matches scripts/casper: cryptsetup luksOpen -q -d ${fskey} -l ${fskey_size} ${fsimg} ${mapname} scripts/casper: cryptsetup luksClose ${mapname} grep: var/cache/ldconfig/aux-cache: binary file matches
ここでは、scripts/casperの中でcryptsetupをluksOpenで使っているところがあり、この中で-dオプション(暗号化鍵ファイルの指定)を使っているので$fskeyに含まれるファイル名のファイルが鍵であることが分かる。
cryptsetupは暗号化デバイスを作成・管理するdm-cryptを使うためのコマンドラインツール。LUKSはLinux Unified Key Setupの略。
scripts/casperのなかでfskeyを定義しているところを探す。見つからなければ、ファイルを開いて中身を見る。
# grep "fskey *=" scripts/casper local fskey="/conf/fs.key"
/conf/fs.keyが鍵ファイルのようであるので、このファイルを利用できるように取っておく。
一度ファイルを特定しておくと、あとからinitramfsで取り出すときはコマンド一発。
$ lsinitrd initrd64.lz -f conf/fs.key > fs.key
続いて、USBブートLinuxのメインとなるファイルシステムを開く。
# cryptsetup open --type luks main_fs.img usbfs --key-file fs.key
main_fs.imgはメインのファイルシステム、usbfsはブロックデバイスになったときの名前の指定。
cryptsetupでopenすると、指定したブロックデバイス名で/dev/mapperの下にデバイスが作成されるので、マウント。
# mkdir /mnt/fs # mount /dev/mapper/usbfs /mnt/fs # ls /mnt/fs ./ ../ filesystem.squashfs lost+found/
マウントしたディスクイメージの中にはSquashFSでディスクが作られている。
unsquashfsを使って中身を展開。ただし、/mnt/fsにマウントしたディスクイメージに空き容量があまりないと思うので、適当な場所にfilesystem.squashfsをコピーして作業を続ける。
# cp -a filesystem.squashfs /work/ # cd /work/ # unsquashfs filesystem.squashfs Parallel unsquashfs: Using 8 processors 118271 inodes (122926 blocks) to write [================================================================/] 122926/122926 100% created 87359 files created 13100 directories created 30811 symlinks created 79 devices created 0 fifos created 0 sockets # ls -l total 12 drwxr-xr-x. 3 root root 4096 Feb 13 13:07 ./ drwxr-xr-x. 5 root root 4096 Feb 13 13:06 ../ drwxr-xr-x. 21 root root 4096 Jan 18 00:10 squashfs-root/
squashfs-rootの中に中身が展開されている。
あとは好きに、中身を改修する。chrootしても良い。
# cd squashfs-root/ # mount --bind /dev/ dev/ # chroot squashfs-root [chrooted]/# mount -t proc none /proc [chrooted]/# mount -t sysfs none /sys [chrooted]/# mount -t devpts none /dev/pts
参考)initramfsの中にだけしか存在しないファイルもあるかもしれないので、必要に応じて、先に展開したinitrdの中身をメインのファイルシステムにコピーしてきても良いと思う。
今回利用したUSBはUbuntuベースだった(/etc/os-releaseにバージョンとともに書いてあった。)ので、まずはパッケージのアップデート。アップデートのリポジトリの設定がなかったので、以下のような感じで作成した。
[chrooted]/# cd /etc/apt/ [chrooted]/# mv sources.list sources.list.orig [chrooted]/# wget https://gist.githubusercontent.com/rohitrawat/60a04e6ebe4a9ec1203eac3a11d4afc1/raw/fcdfde2ab57e455ba9b37077abf85a81c504a4a9/sources.list [chrooted]/# sed -i.bak -e "s%http://us.archive.ubuntu.com/ubuntu/%http://ftp.iij.ad.jp/pub/linux/ubuntu/archive/%g" /etc/apt/sources.list [chrooted]/# mkdir -p /tmp/.private/root [chrooted]/# export LANG=C [chrooted]/# apt update [chrooted]/# apt list --upgradable [chrooted]/# apt full-upgrade
メモ:途中でGrubのインストールを促すメッセージが出た場合、どのパーティションにもインストールしないこと。Chrootしているので、書き込んだらchroot前のパーティションに書き込まれてしまう。
一通り作業が終わったら、更新したファイルシステムをSquashFSに戻していく作業を開始する。
一連の作業が終わり、起動させたときに以下のようなエラーが出た場合、SquashFSを展開するメモリサイズが十分に確保されていない可能性がある。
その場合、展開先のメモリサイズを指定している設定を変更する必要がある。その設定はinitramfsの中でされているので、initramfsを再構築する必要がある。(再構築前に展開先メモリサイズを更新すること)
cp: write error: No space left on device mount: mounting /dev/loop0 on //filesystem.squashfs failed: Invalid argument Can not mount /dev/loop0 (/cdrom/casper/filesystem.squashfs) on //filesystem.squashfs
どこで展開先メモリサイズが設定されているかを見つけるのは大変かもしれない。今回利用したUSBでは、initramfsの中の/scripts/casperの中にsize=として設定があった。
initramfsを作成する。
[chrooted]/# mkinitramfs -v -k -c lzma -o /initrd.lz 4.15.0-132-generic
最後の部分は、Kernelの最新バージョンを入れる。
ファイルシステムのサイズを小さくするために、不要なファイルは削除しておくことを推奨。例えばこんな感じ。
[chrooted]/# apt autoremove --purge [chrooted]/# apt autoclean [chrooted]/# apt clean [chrooted]/# rm /var/lib/apt/lists/ftp.iij.ad.jp_pub_linux_ubuntu_archive_dists_xenial* [chrooted]/# rm /var/lib/apt/lists/security.ubuntu.com_ubuntu_dists_xenial-security_* [chrooted]/# rm -fr /tmp/.private/* [chrooted]/# rm -fr /var/tmp/* [chrooted]/# rm -fr /tmp/* [chrooted]/# umount /proc || umount -lf /proc [chrooted]/# umount /sys [chrooted]/# umount /dev/pts [chrooted]/# umount /dev [chrooted]/# exit # rm squashfs-root/root/.bash_history
SquashFSを作成する。前にあったものは不要なので削除しつつ、作成したinitramfsを取り出しておく。
# rm filesystem.squashfs # mv squashfs-root/initrd64.lz ../usb_copy/ # mksquashfs squashfs-root filesystem.squashfs -comp xz
filesystem.squashfsが入っていたディスクイメージ(/mnt/fsにマウントされているもの)は、空き容量がなく改修したSquashFSは入り切らないため、新しくイメージを作成する。
# dd if=/dev/zero of=main_fs_new.img bs=4k count=200k # ls -l /dev/loop* crw-rw---- 1 root disk 10, 237 May 12 08:37 /dev/loop-control # mknod -m 0660 /dev/loop0 b 7 0 # ls -l /dev/loop* crw-rw---- 1 root disk 10, 237 May 12 08:37 /dev/loop-control brw-rw---- 1 root root 7, 0 May 16 16:42 /dev/loop0 # losetup /dev/loop0 main_fs_new.img
ddで作成したmain_fs_new.imgのサイズは800M(= 4k x 200k)。ここではmknodを使ってやってみたが、もっと楽なやり方もある。こちらを参照。
ディスクイメージがデバイス/dev/loop0でマウントされているので、ここにLUKSでフォーマットを作る。
# cryptsetup luksFormat /dev/loop0 --type luks1 --key-file fs.key WARNING! ======== This will overwrite data on /dev/loop0 irrevocably. Are you sure? (Type 'yes' in capital letters): YES
fs.keyは最初の方でinitramfsから取り出した鍵ファイル。
作成したファイルシステムを開く。
# cryptsetup open --type luks1 /dev/loop0 usbfs_new --key-file fs.key
更にその中にext4でファイルシステムを作る。
# ls /dev/mapper/ ./ ../ control usbfs@ usbfs_new@ # mkfs.ext4 /dev/mapper/usbfs_new mke2fs 1.45.5 (07-Jan-2020) Creating filesystem with 200704 4k blocks and 50176 inodes Filesystem UUID: d46c6069-aac5-4ec0-a525-f9ba94c44438 Superblock backups stored on blocks: 32768, 98304, 163840 Allocating group tables: done Writing inode tables: done Creating journal (4096 blocks): done Writing superblocks and filesystem accounting information: done
続いて、作成したSquashFSを書き込む。
# mkdir /mnt/usbfs_new # mount /dev/mapper/usbfs_new /mnt/usbfs_new # cp -a /work/filesystem.squashfs /mnt/usvfs_new
開いていたものを閉じていく。
# umount /mnt/usbfs_new # cryptsetup close usbfs_new # losetup -d /dev/loop0 # umount /mnt/usbfs # cryptsetup close usbfs
ちなみに、LUKS FSで作ったmain_fs_new.imgの拡張はsys-apps/coreutilsに入っているtruncateコマンドで簡単にできる。
# ls -lh main_fs_new.img -rw-r--r-- 1 root root 800M May 16 16:58 main_fs_new.img # truncate -s 890M main_fs_new.img # ls -lh main_fs_new.img -rw-r--r-- 1 root root 890M May 16 17:09 main_fs_new.img # losetup /dev/loop0 main_fs_new.img # cryptsetup open --type luks /dev/loop0 usbfs_new --key-file fs.key # resize2fs /dev/mapper/usbfs_new resize2fs 1.45.5 (07-Jan-2020) Please run 'e2fsck -f /dev/mapper/usbfs_new' first. # e2fsck -f /dev/mapper/usbfs_new e2fsck 1.45.5 (07-Jan-2020) Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information /dev/mapper/usbfs_new: 12/50176 files (0.0% non-contiguous), 196690/200704 blocks # resize2fs /dev/mapper/usbfs_new resize2fs 1.45.5 (07-Jan-2020) Resizing the filesystem on /dev/mapper/usbfs_new to 223744 (4k) blocks. Number of free blocks: 4014/27054, Needed: 0 The filesystem on /dev/mapper/usbfs_new is now 223744 (4k) blocks long.
更新したディスクイメージで起動できるかをテストしたい場合、ISOファイルを作りたければmkisofsで作成できる
mkisofs -D -r -cache-inodes -J -l -b isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -o ../hagiwara_new.iso . Size of boot image is 4 sectors -> No emulation 0.58% done, estimate finish Sat May 16 17:55:49 2020 1.15% done, estimate finish Sat May 16 17:55:49 2020 1.73% done, estimate finish Sat May 16 17:55:49 2020 ~中略~ 98.59% done, estimate finish Sat May 16 17:55:57 2020 99.17% done, estimate finish Sat May 16 17:55:57 2020 99.74% done, estimate finish Sat May 16 17:55:57 2020 Total translation table size: 2048 Total rockridge attributes bytes: 24943 Total directory bytes: 45056 Path table size(bytes): 90 Max brk space used 44000 867251 extents written (1693 MB)
0 件のコメント:
コメントを投稿