OverlayFSを使用してルートファイルシステムを保護するには?

OverlayFSを使用してルートファイルシステムを保護するには?

OverlayFSを正しく使用してルートファイルシステムを保護するにはどうすればよいですか?

SDカードから起動して実行する組み込みシステムがあります。突然の停電が発生するので、ルートファイルシステムを保護したいと思います。ファイルシステムの上書き最も簡単な解決策のように見えますが、私が見つけた例には通常、ルートファイルシステムが含まれていないか、tmpfsを使用していません。

私はCONFIG_OVERLAY_FS=yLinuxカーネル4.4.0を使用しています。私のファイルシステムはxenial-base-armhf.tar.gz終わりましたapt install -y overlayroot

私のSDカードは次のとおりです

# fdisk -l /dev/mmcblk1
Disk /dev/mmcblk1: 29 GiB, 31104958464 bytes, 60751872 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: dos
Disk identifier: 0x7f56a0ab

Device         Boot    Start      End  Sectors  Size Id Type
/dev/mmcblk1p1 *        2048  1050623  1048576  512M  c W95 FAT32 (LBA)
/dev/mmcblk1p2       1050624  1052671     2048    1M da Non-FS data
/dev/mmcblk1p3       1052672  7344127  6291456    3G 83 Linux
/dev/mmcblk1p4       7344128 60751871 53407744 25.5G  5 Extended
/dev/mmcblk1p5       7346176 13637631  6291456    3G 83 Linux
/dev/mmcblk1p6      13639680 60751871 47112192 22.5G 83 Linux

OverlayFSを作成する前に、すべてが次のようにインストールされます。

# mount
/dev/mmcblk1p3 on / type ext4 (rw,noatime,data=ordered)
devtmpfs on /dev type devtmpfs (rw,relatime,size=170440k,nr_inodes=42610,mode=755)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/lib/systemd/systemd-    cgroups-agent,name=systemd)
configfs on /sys/kernel/config type configfs (rw,relatime)
tmpfs on /run/user/0 type tmpfs (rw,nosuid,nodev,relatime,size=35752k,mode=700)
/dev/mmcblk1p6 on /opt type ext4 (rw,noatime,data=ordered)
/dev/mmcblk1p5 on /overlay type ext4 (rw,noatime,data=ordered)

/dev/mmcblk1p5私の計画はこれをオーバーレイファイルシステムとして使用しています/overlay

# tree /overlay
/overlay
├── lost+found
├── root-fs
└── work

私が何か間違っているか、または次の理由で設定の問題があります。

# mount -t overlay overlay -o lowerdir=/,upperdir=/overlay/root-fs,workdir=/overlay/work /
# mount
/dev/mmcblk1p3 on / type ext4 (rw,noatime,data=ordered)
devtmpfs on /dev type devtmpfs (rw,relatime,size=170440k,nr_inodes=42610,mode=755)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd)
configfs on /sys/kernel/config type configfs (rw,relatime)
tmpfs on /run/user/0 type tmpfs (rw,nosuid,nodev,relatime,size=35752k,mode=700)
/dev/mmcblk1p6 on /opt type ext4 (rw,noatime,data=ordered)
/dev/mmcblk1p5 on /overlay type ext4 (rw,noatime,data=ordered)
overlay on / type overlay (rw,relatime,lowerdir=/,upperdir=/overlay/root-fs,workdir=/overlay/work)

うまくいくようですが、次のようなファイルを作成すると:

# touch /root/test_file_write

それから電源を切ってデスクトップにあるSDカードを見てみると、予想したものとは/dev/mmcblk1p3/root/test_file_write異なりました/dev/mmcblk1p5/root-fs/root/test_file_write

これはうまくいくべきですか?

ベストアンサー1

この答えは私の経験に基づいていますが、組み込みデバイスには適用されません。たぶん、この設定を誤って見つけた人に便利です。特定の状況に合わせて調整するか、少なくとも1つまたは2つを学ぶ必要があります。

簡単なアプローチは、ルートファイルシステムをマウントするとき(initramfsで、そうでなければプロセスをハイジャックinit)、その場所をハイジャックし、そこにオーバーレイをマウントして通常どおりに続行することです。 initramfsなしでマウントする場合は/proc一般的な。/sysinit

もしあなたならいいえinitramfsが必要な場合は、Mathieu MaretのRaspberry Piでこれを行う方法に関するリンクされたソリューションが機能するはずです。デフォルトでは、initカーネルコマンドラインを使用して独自のプロセス/スクリプトをオーバーライドできます。ルートファイルシステムからスクリプトを生成したとし、ブートローダ設定のカーネルブートパラメータに/sbin/init-overlayそれを追加する必要があります。init=/sbin/init-overlay

スクリプトinit-overlayは、制御権を渡す前に何でもできますinit。この場合、オーバーレイを別のディレクトリにインストールしてからchrootここにマウントします。


initramfsを使用してこれを行う1つの可能な方法は、/initルートファイルシステムをマウントしてからinitramfs内のスクリプトをハイジャックすることです。たとえば、オーバーレイルートを持ちたいのですが、システムを起動した後に元のマウントポイント/run/rootfs/roにアクセスしようとしているとします/run/rootfs/rw(前者は読み取り専用ルート、後者は変更されたルートです)upperdir。また、システムが起動しているドライブにroot.squashfs読み取り専用ルートファイルシステムを含むファイルがあり、それをマウントしようとしているとします。/media/drive便宜上、システムが稼働して実行されたら、このドライブに再度アクセスしたいとします。

initramfsスクリプトをハイジャックする理由は、最終的に基本スクリプトコマンドを実行するいくつかの事前作成されたパラメータを使用するよりも柔軟性が高いためです。したがって、root.squashfs後でマウントする予定であるため、「ルート」ファイルシステムが実際に見つかったファイルシステムであることをカーネルと通信するには、起動設定を編集する必要があります。

VFATパーティションの一般的なコマンドはsyslinux.cfg次のとおりです(必要に応じてUUIDを変更します)。

label linux
    linux vmlinuz
    append root=UUID=ABCD-1234 rootfstype=vfat rootflags=ro,umask=022,quiet ro quiet splash
    initrd initrd.img

これは理想的ではない可能性があるVFATパーティションを配置すると仮定しますroot.squashfs(上記でroot =として指定する必要があるのは、含めるか、類似したroot.squashfsパーティションまたはファイルシステム(たとえば、実際のルートファイルシステム)です。圧縮されます)。しかし、ブートパーティション自体に配置することを前提として説明しています。私はあなたがどのような組み込みシステムを実行しているのかわからないので、ここでは自分で判断する必要があります。

/initまず、スクリプトを変更できるように、initramfsを/ tmpの場所に抽出する必要があります。バックアップをパッケージ化する前にroot所有権を適切に維持したい場合は、(スーパーユーザー)でこれを行うことを忘れないでください。実行方法を理解したら、おそらく全体の内容をスクリプトで書くことができます。たとえば、/tmp/initramfs編集のために解凍します。

mkdir /tmp/initramfs 2>/dev/null; (cd /tmp/initramfs && zcat /initrd.img | sudo cpio -idmv)

これで、デフォルトのスクリプトマウントルートの場所を見つける必要があります。/tmp/initramfs/init(rootで編集)で同様のものを見つけます。

maybe_break mount
log_begin_msg "Mounting root file system"
. /scripts/${BOOT}
parse_numeric ${ROOT}
maybe_break mountroot
mountroot
log_end_msg

これがどのように機能するかを理解する必要はありません。あなたが理解する必要があるのは、これがシェル変数を通してroot.squashfs明らかに与えられたマウントポイントにあなたを含む一般的なファイルシステムをマウントすることです。${rootmnt}

つまり、現在私たちが持っているのは${rootmnt}VFATパーティション(またはroot=コマンドライン引数で指定したパーティション)です。スクリプトは、すべての仮想ファイルシステムを${rootmnt}マウントポイントに移動するなどの他のタスクを実行するため、すべてのカスタムタスクを実行する必要があります。後ろに上記のコード。

あなたがしなければならないのは、initramfsで上記のコードの後に​​次のようなものを挿入することだけです/init

# create some temporary directories under the initramfs's /run
# they will be our mountpoints and such, which will get moved
# by the default script to the actual root filesystem...
mkdir -m 755 /run/rootfs
mount -t tmpfs -o size=90%,mode=755,suid,exec tmpfs /run/rootfs
mkdir -m 755 /run/rootfs/drive /run/rootfs/ro /run/rootfs/rw /run/rootfs/.workdir

# move the original root that was mounted, temporarily
mount -n -o move "${rootmnt}" /run/rootfs/drive

# mount the squashfs and then the overlay to our designated locations
mount -t squashfs -o defaults,ro /run/rootfs/drive/root.squashfs /run/rootfs/ro
mount -t overlay -o lowerdir=/run/rootfs/ro,upperdir=/run/rootfs/rw,workdir=/run/rootfs/.workdir root "${rootmnt}"

# at this point we have our overlay root at ${rootmnt}!
# however, move the drive's filesystem mount to the new root
# this allows it to be accessed afterwards from /media/drive
# NOTE: this assumes you have the /media/drive dir in the root squashfs
mount -n -o move /run/rootfs/drive "${rootmnt}/media/drive"
rm -d /run/rootfs/drive

それはすべてです。スクリプトは通常どおり続行されますが、ルートファイルシステムはオーバーレイなので、すべての部分に簡単にアクセスできます。そういう点を参考にしてくださいエラーチェックなしoverlay、上記のコマンドを追加したり、モジュールがロードされていることを確認することはユーザーの役割です。

今、initramfsをパッケージ化しましょう。

sudo sh -c 'cd /tmp/initramfs && find . -print0 | cpio --null -ov --format=newc' | gzip -9 > /tmp/initrd.img

そして/tmp/initrd.imgをSDカードなどにコピーしてください。 VFATパーティションのルートディレクトリに配置することを忘れないでくださいroot.squashfs。もちろん、簡単にカスタマイズでき、必要はありません。これはsyslinux(またはUEFIブート)を実行する「最も簡単な」方法に過ぎず、決して最善の方法ではありません。

申し訳ありません。組み込みデバイスを要求していることはわかっていますが、起動プロセスがどのように機能するのかわかりません。私はx86の例を使用しましたが、その部分はそれほど重要ではありません(一部のみsyslinux.cfg)。

参考にしてくださいoverlayfsこれにより、書き込み可能な部分がtmpfs必要に応じて作成されます。しかしそれは変更しやすい、上記の内容を見れば、/run/rootfs書きたい場所にtmpfsの代わりに他のものをインストールすればいいです。

おすすめ記事