Quantcast
Channel: aimdevel’s blog
Viewing all articles
Browse latest Browse all 35

Linuxセキュリティ機能を盛り込んだラズパイのアップデート手順:解説編

$
0
0

前回の記事で行ったラズパイのアップデートについて、内容を説明する。

aimdevel.hatenablog.com

対象の資材

以下のリポジトリのmeta-my-securityディレクトリが対象。
https://github.com/aimdevel/meta-my-raspberrypi

各設定の説明

Linuxのアップデートを行うために作成した箇所について説明する。

partitionの設定

sdカードのパーティション設定は、meta-my-security/wic/my-security-dual.wks.inに記載してある。
meta-raspberrypiのwksファイルをベースに作成した。
以下のパーティション構成と同じになるように設定してある。

namesizeformatdescription
mmcblk0p1128MBvfatブートパーティション。u-bootを格納
mmcblk0p2128MBvfatlinuxを格納。アップデートA面
mmcblk0p3128MBvfatlinuxを格納。アップデートB面
mmcblk0p4nonenone拡張パーティション
mmcblk0p5512MBnonerootfs。この領域をdm-verityで検証する。アップデートA面
mmcblk0p6512MBnonerootfs。この領域をdm-verityで検証する。アップデートB面
mmcblk0p7500MBext4書き込み用暗号化領域。初回起動時にdm-cryptで暗号化する。アップデート後もデータが保持される領域として使用する。
mmcblk0p820MBext4dm-crypt用ファイル置場。キーファイルや初回起動フラグなど。
part /boot --source bootimg-partition --ondisk mmcblk0 --fstype=vfat --label boot --active --align 4096 --size 20
part / --source bootimg-partition --ondisk mmcblk0 --fstype=vfat --label boot --active --align 4096 --size 20
part / --source rawcopy --ondisk mmcblk0 --sourceparams="file=${IMGDEPLOYDIR}/${DM_VERITY_IMAGE}-${MACHINE}.${DM_VERITY_IMAGE_TYPE}.verity"
part / --ondisk mmcblk0 --size 100M
part / --ondisk mmcblk0 --size 500M
part / --ondisk mmcblk0 --fstype=ext4 --size 20M

このファイルの書き方は以下のページを参考にした。
https://docs.yoctoproject.org/ref-manual/kickstart.html

また、この設定を使用するためにlocal.confに以下の設定を追加。

WKS_FILE = "my-security-dual.wks.in"

u-boot用の設定

u-boot scriptをraucに対応させる。
raucでu-bootを使う場合には起動時の面管理をu-boot環境変数BOOT_ORDERで行っている。そのため、以下のファイルをベースにBOOT_ORDERの値で起動面を切り替えるスクリプトを追加する。
https://github.com/rauc/meta-rauc-community/blob/master/meta-rauc-raspberrypi/recipes-bsp/rpi-u-boot-scr/files/boot.cmd.in

作成したものは以下。
BOOT_ORDERがAの場合はkernelをmmc 0:2から取り出しmmcblk0p5をrootfsとして使用する。
BOOT_ORDERがBの場合はkernelをmmc 0:3から取り出しmmcblk0p6をrootfsとして使用する。

test -n "${BOOT_ORDER}" || setenv BOOT_ORDER "A B"
test -n "${BOOT_A_LEFT}" || setenv BOOT_A_LEFT 3
test -n "${BOOT_B_LEFT}" || setenv BOOT_B_LEFT 3
test -n "${BOOT_DEV}" || setenv BOOT_DEV "mmc 0:1"

setenv bootpart
setenv raucslot
setenv kernel_addr_r 0x4000000

for BOOT_SLOT in "${BOOT_ORDER}"; do
  if test "x${bootpart}" != "x"; then
    # skip remaining slots
  elif test "x${BOOT_SLOT}" = "xA"; then
    if itest ${BOOT_A_LEFT} -gt 0; then
      setexpr BOOT_A_LEFT ${BOOT_A_LEFT} - 1
      echo "Found valid RAUC slot A"
      setenv bootpart "/dev/mmcblk0p5"
      setenv raucslot "A"
      setenv BOOT_DEV "mmc 0:2"
    fi
  elif test "x${BOOT_SLOT}" = "xB"; then
    if itest ${BOOT_B_LEFT} -gt 0; then
      setexpr BOOT_B_LEFT ${BOOT_B_LEFT} - 1
      echo "Found valid RAUC slot B"
      setenv bootpart "/dev/mmcblk0p6"
      setenv raucslot "B"
      setenv BOOT_DEV "mmc 0:3"
    fi
  fi
done

if test -n "${bootpart}"; then
  setenv bootargs "${bootargs} root=${bootpart} rauc.slot=${raucslot}"
  saveenv
else
  echo "No valid RAUC slot found. Resetting tries to 3"
  setenv BOOT_A_LEFT 3
  setenv BOOT_B_LEFT 3
  saveenv
  reset
fi

setenv bootargs "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1  smsc95xx.macaddr=DC:A6:32:6D:32:59 vc_mem.mem_base=0x3ec00000 vc_mem.mem_size=0x40000000  dwc_otg.lpm_enable=0 console=ttyS0,115200 root=${bootpart} rauc.slot=${raucslot} rootfstype=ext4 rootwait debug verbose"
fatload ${BOOT_DEV} ${kernel_addr_r} @@KERNEL_IMAGETYPE@@
saveenv
@@KERNEL_BOOTCMD@@

Linux kernelの設定

linux kernelをデプロイ用のディレクトリに格納する設定を行う。
local.confに以下の設定を加える。

IMAGE_BOOT_FILES:append = " fitImage-my-initramfs-raspberrypi4-64-raspberrypi4-64"

マウント設定

fstabを以下のように編集してbase-filesレシピで取り込む。

# stock fstab - you probably want to override this with a machine specific one

/dev/root            /                    auto       defaults              1  1
proc                 /proc                proc       defaults              0  0
devpts               /dev/pts             devpts     mode=0620,ptmxmode=0666,gid=5      0  0
tmpfs                /run                 tmpfs      mode=0755,nodev,nosuid,strictatime 0  0
tmpfs                /var/volatile        tmpfs      defaults              0  0

# uncomment this if your device has a SD/MMC/Transflash slot
#/dev/mmcblk0p1       /media/card          auto       defaults,sync,noauto  0  0

/dev/mmcblk0p1       /boot                auto       defaults              1  1
tmpfs                /mnt                 tmpfs      defaults              0  0

デフォルトの設定に加えて以下の設定をしている。 - /dev/mmcblk0p1を/bootにマウント
raucがuboot.env書き換えるため、uboot.envの入っているこのパーティションlinuxから見えるようにしておく必要がある。
- /mntにtmpfsをマウント
raucが/mnt下を使用するためwriteできるようにしておく必要がある。

rauc用鍵の作成

meta-raucに用意されているツールを使用する。
以下のreadmeの通りに作業して鍵を作成し、自身のレイヤに取り込んだ。
https://github.com/rauc/meta-rauc/blob/kirkstone/scripts/README

$ ./openssl-ca.sh
$ cp openssl-ca/dev/ca.cert.pem ../../../meta-my-raspberrypi/meta-my-security/recipes-core/rauc/files/
$ cp openssl-ca/dev/development-1.cert.pem ../../../meta-my-raspberrypi/meta-my-security/recipes-core/bundles/files/
$ cp openssl-ca/dev/private/development-1.key.pem ../../..
/meta-my-raspberrypi/meta-my-security/recipes-core/bundles/files/

アップデート設定

バイスのどの領域をアップデートするかの設定は以下に記述してある。
https://github.com/aimdevel/meta-my-raspberrypi/blob/main/meta-my-security/recipes-core/rauc/files/system.conf
ここで指定したスロット名やtypeはupdate-bundleを作成する際に使用する。

[system]
compatible=raspberrypi4-64
bootloader=uboot                    <== u-bootを使うことを指定。
data-directory=/var/data

[keyring]
path=/etc/rauc/ca.cert.pem          <== 鍵の場所を指定
 
[slot.kerneldir.0]                  <== A面のkerneldirスロットの設定
device=/dev/mmcblk0p2
type=vfat
parent=rootfs.0

[slot.kerneldir.1]                  <== B面のkerneldirスロットの設定 
device=/dev/mmcblk0p3
type=vfat
parent=rootfs.1

[slot.rootfs.0]                     <== A面のrootfsスロットの設定
device=/dev/mmcblk0p5
type=raw
bootname=A

[slot.rootfs.1]                     <== B面のrootfsスロットの設定
device=/dev/mmcblk0p6
type=raw
bootname=B

update-bundleの作成

raucのアップデートに使用する資材をまとめたものである.raucbファイルの設定は以下のディレクトリにあるファイルに書かれている。
https://github.com/aimdevel/meta-my-raspberrypi/tree/main/meta-my-security/recipes-core/bundles

  • kernel-dir.bb
    このファイルはlinux kernelをvfatのファイルに格納する処理を行っている。
    作成したvfatファイルはraucbを作成するとき使用する。

  • update-bundle.bb
    このファイルでアップデートの詳細を記載する。
    内容は以下である。

DESCRIPTION = "RAUC bundle generator"

FILESEXTRAPATHS:prepend := "${THISDIR}/files:"

DEPENDS = "linux-raspberrypi"

inherit bundle

RAUC_BUNDLE_COMPATIBLE = "${MACHINE}"
RAUC_BUNDLE_VERSION = "v20241104"
RAUC_BUNDLE_DESCRIPTION = "RAUC Demo Bundle"

RAUC_BUNDLE_FORMAT = "verity"

RAUC_BUNDLE_SLOTS = "rootfs kerneldir"

RAUC_SLOT_kerneldir = "kernel-dir"
RAUC_SLOT_kerneldir[file] = "kernel-dir.vfat"
RAUC_SLOT_kerneldir[type] = "file"
RAUC_SLOT_kerneldir[fstype] = "vfat"

RAUC_SLOT_rootfs = "core-image-base"
RAUC_SLOT_rootfs[file] = "core-image-base-raspberrypi4-64.ext4.verity"
RAUC_SLOT_rootfs[rename] = "rootfs.img"

RAUC_KEY_FILE ?= "${THISDIR}/files/development-1.key.pem"
RAUC_CERT_FILE ?= "${THISDIR}/files/development-1.cert.pem"

RAUC_SLOT_*でアップデートするスロットを指定する。このスロットとはデバイス内で定義されたどの領域をアップデートするかを表している。これはアップデート設定の内容と対応させる必要がある。
そしてスロットごとにどのような資材をインストールするかをRAUC_SLOT_*[file]RAUC_SLOT_*[type]RAUC_SLOT_*[fstype]で指定する。ここの設定はもっと良い書き方があるかもしれない。
先ほど説明したkernel-dirで作成したvfatファイルもここで指定することでraucbに取り込んでいる。

妥協した点

  • bootパーティションの内容
    ラズパイの起動に必要なファイルがどれなのか調べてないので、不要なファイルも含まれている。
  • kernelパーティションAの内容
    yoctoで格納するファイルを指定する方法がわからなかったので、bootパーティションと同じ内容。
    アップデートすればクリアされる。
  • dm-cryptの鍵置き場
    sdカード上に鍵をおいてあるが、本当はeFuseなどのsdカード以外の領域おかなければならない。
    このままだとsdカードを持ち去られたら普通に復号されてしまう。

終わりに

kernelも含めてラズパイのアップデートを試した際の設定を説明した。
アップデート時にデバイスに設定するべき大まかな項目はわかったので、さらに細かい設定を見ていくか、それかOTAを試すべくraucbを配信するサーバを立てるかなど次に何をやるか考えたい。


Viewing all articles
Browse latest Browse all 35

Trending Articles