OverlayFSを正しく使用してルートファイルシステムを保護するにはどうすればよいですか?
SDカードから起動して実行する組み込みシステムがあります。突然の停電が発生するので、ルートファイルシステムを保護したいと思います。ファイルシステムの上書き最も簡単な解決策のように見えますが、私が見つけた例には通常、ルートファイルシステムが含まれていないか、tmpfsを使用していません。
私はCONFIG_OVERLAY_FS=y
Linuxカーネル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
一般的な。/sys
init
もしあなたならいいえ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の代わりに他のものをインストールすればいいです。
答え2
1つの解決策は、initramfsを使用してrootfsとoverlayfsをマウントすることです。
あなたは見ることができますRaspberry Piで行う方法
またはARMデバイスを使用しない場合Ubuntuoverlayroot
パッケージ
答え3
ディレクトリの読み取り専用「保護」のオーバーライド
完全なルートファイルシステムで動作させることができないか、/boot/inird
ソリューションを使用できません。ただし、特定のフォルダで動作するようにすることはできます。
ボード/システムが「生産」準備ができたら、以下のコードを実行する必要があります。ニーズに合わせて調整できます。私の出来事はSOCボードを運営していますネットワークビデオレコーダー(ネットワークビデオレコーダー)。
このコードは '保護する'システムのすべてのディレクトリ。ディレクトリに多くのI / Oがあることを知っています。そして、あなたはログなどのようにそこに書かれた内容に興味がありません。
「保護」/var
フォルダの例
私は/dev/shm
ramdiskフォルダを使用します。ディストリビューションにない場合は、RAMディスクを直接マウントする必要があります(tmpfsなど)。
# create folders needed by overlay filesystem on /dev/shm (RAM)
mkdir -p /dev/shm/var_upper /dev/shm/var_workdir /dev/shm/var_overlay
mkdir -p /var_
# since /var will be 'hidden' by overlay mouting 'over' it
# we need it 'visible' somewhere to be usable as lowerdir
# mount --bind does that to /var_
mount --bind /var /var_
sudo mount -t overlay overlay -o lowerdir=/var_,upperdir=/dev/shm/var_upper,workdir=/dev/shm/var_workdir /var
少し説明
オーバーレイは、親ディレクトリが保護されている連合ファイルシステム(またはディレクトリツリー)をインストールします。この例では/var
読み取り専用にします。書き込みはRAMでのみ行われるため、/dev/shm
再起動時にログなどが失われます。バインド解除は自動的に行われ、すべてがデフォルトの場所に戻りますので、再起動しても安全です。読み取り専用の「保護」が必要な別のフォルダにコピーできます。
私の最初の検索は、SOCボードの電源が切れたときのSDカードの損傷を防ぐソリューションを見つけることでした。