Wie verwende ich OverlayFS richtig, um mein Root-Dateisystem zu schützen?
Ich habe ein eingebettetes System, das von einer SD-Karte startet und ausgeführt wird. Da es zu einem plötzlichen Stromausfall kommt, möchte ich das Root-Dateisystem schützen. OverlayFS scheint die einfachste Lösung zu sein, aber die Beispiele, die ich finde, betreffen normalerweise nicht das Root-Dateisystem und / oder verwenden ein tmpfs, was für mich nicht gut ist, da ich sehr wenig Speicher habe.
Ich verwende Linux Kernel 4.4.0 mit CONFIG_OVERLAY_FS=y
aktiviert. Mein Dateisystem ist xenial-base-armhf.tar.gz
und ich habe getan apt install -y overlayroot
.
Meine SD-Karte sieht aus wie:
# 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
Vor dem Erstellen des OverlayFS wird alles wie folgt bereitgestellt:
# 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)
Mein Plan war es, /dev/mmcblk1p5
als Overlay-Dateisystem zu verwenden, das bei gemountet ist /overlay
.
# tree /overlay
/overlay
├── lost+found
├── root-fs
└── work
Entweder mache ich etwas falsch oder ich habe ein Konfigurationsproblem, weil:
# 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)
Sieht so aus, als hätte es funktioniert, aber wenn ich eine Datei erstelle, wie:
# touch /root/test_file_write
Dann ausschalten und auf die SD-Karte in meinem Desktop schauen, sehe ich /dev/mmcblk1p3/root/test_file_write
nicht, was ich erwartet hatte /dev/mmcblk1p5/root-fs/root/test_file_write
.
Sollte das funktionieren?
mount -o remount,ro /
kehrt zurückmount: / is busy
, und der Versuch, das System schreibgeschützt zu starten, führt zu vielen Fehlern. Es ist mir noch nicht gelungen, aber ich werde es weiter versuchen.touch /root/test_file_write
kehrt zurücktouch: cannot touch '/root/test_file_write': Read-only file system
, also funktioniert das Overlay eindeutig nicht ... aber warum?mkdir /tmp/{root,overlay,work}; touch /tmp/root/lowerfile; mount -t overlay overlay -o lowerdir=/tmp/root,upperdir=/tmp/overlay,workdir=/tmp/work /tmp/root/; touch /tmp/root/upperfile; umount /tmp/root
/tmp/overlay/upperfile
und/tmp/overlay/root/lowerfile
.Antworten:
Eine Lösung könnte darin bestehen, ein initramfs zu verwenden, um die rootfs mit Overlays zu mounten.
Sie können sehen, wie es auf dem Raspberry Pi gemacht wird
oder, falls nicht ein ARM - Gerät, bei dem
overlayroot
Ubuntu Paketquelle
Diese Antwort basiert auf meiner eigenen Erfahrung, jedoch nicht mit eingebetteten Geräten. Vielleicht ist es für andere nützlich, die über dieses Setup stolpern - Sie sollten es an Ihre spezifischen Umstände anpassen oder zumindest hoffentlich ein oder zwei Dinge daraus lernen.
Eine einfache Methode besteht darin, den Ort zu entführen, an dem das Root-Dateisystem bereitgestellt wird (in initramfs, andernfalls den
init
Prozess zu entführen ), das Overlay dort bereitzustellen und dann wie gewohnt fortzufahren. Wenn Sie es ohne initramfs bereitstellen, vergessen Sie nicht, alle virtuellen Dateisysteme (z. B./proc
und/sys
) in Ihrem Skript zu verschieben, bevor Sie die Steuerung an das normale übergebeninit
.Wenn Sie kein Initramfs möchten, sollte die verknüpfte Lösung von Mathieu Maret funktionieren, wie es in Himbeeren gemacht wird. Grundsätzlich überschreiben Sie den
init
Prozess / das Skript mit Ihrem eigenen über eine Befehlszeile zum Kernel. Angenommen, Sie erstellen das Skript im Root-Dateisystem unter/sbin/init-overlay
und fügen dann dieinit=/sbin/init-overlay
zu den Kernel-Boot-Parametern der Konfiguration Ihres Bootloaders hinzu.Das
init-overlay
Skript kann alles tun, bevor es die Kontrolle übergibtinit
. In diesem Fall wird das Overlay in einem anderen Verzeichnis und dannchroot
in diesem Verzeichnis bereitgestellt .Eine Möglichkeit, dies mit initramfs zu tun, besteht darin, das
/init
Skript innerhalb des initramfs nach dem Punkt, an dem es das Root-Dateisystem bereitstellt, einfach zu entführen . Angenommen, Sie möchten einen Overlay-Stamm, aber auch Zugriff auf die ursprünglichen Einhängepunkte an/run/rootfs/ro
und/run/rootfs/rw
(der erste ist der schreibgeschützte Stamm, der zweite sind die vorgenommenen Änderungenupperdir
), nachdem das System betriebsbereit ist . Ich gehe auch davon aus, dass das Laufwerk, das Ihr System startet, eineroot.squashfs
Datei enthält, die das schreibgeschützte Root-Dateisystem enthält, und dass Sie es bereitstellen möchten. Angenommen, Sie möchten auch/media/drive
nach der Inbetriebnahme des Systems auf dieses Laufwerk zugreifen .Der Grund, warum wir das initramfs-Skript entführen, ist, dass dies uns mehr Flexibilität im Prozess bietet als die Verwendung einiger vorgefertigter Parameter, die ohnehin Standard-Skriptbefehle ausführen. Sie müssen also die Boot-Konfiguration bearbeiten, um dem Kernel die Information zu übergeben, dass das "Root" -Dateisystem tatsächlich dasjenige
root.squashfs
ist, in dem es gefunden wird, da wir es später bereitstellen werden.Ein typischer Befehl
syslinux.cfg
auf einer VFAT-Partition wäre (ändern Sie die UUID, falls erforderlich):Dies setzt voraus, dass Sie das
root.squashfs
auf der VFAT-Partition platzieren, was möglicherweise nicht ideal ist (was Sie als root = oben angeben müssen, ist die Partition oder das Dateisystem, das dasroot.squashfs
oder ein ähnliches enthält , z. B. das echte Root-Dateisystem, wenn Sie dies nicht möchten es komprimiert). Ich erkläre es jedoch unter der Annahme, dass Sie es auf der Boot-Partition selbst platzieren. Ich weiß nicht, welche Art von eingebettetem System Sie verwenden, daher müssen Sie hier Ihr eigenes Urteilsvermögen verwenden.Zuerst müssen Sie die initramfs irgendwo in / tmp extrahieren, damit Sie das
/init
Skript ändern können . Vergessen Sie nicht, dies alsroot
(Superuser) zu tun , um das Eigentum ordnungsgemäß zu behalten, bevor wir es zurückpacken. Sie können das Ganze wahrscheinlich skripten, nachdem Sie verstanden haben, wie es gemacht werden kann. Zum Beispiel entpacken Sie es/tmp/initramfs
für Änderungen:Jetzt müssen wir herausfinden, wo das Standardskript das Stammverzeichnis bereitstellt. Suchen Sie nach so etwas in
/tmp/initramfs/init
(bearbeiten Sie es als root):Sie müssen nicht verstehen, wie das funktioniert. Alles, was Sie verstehen müssen, ist, dass dadurch das normale Dateisystem, das Sie enthält,
root.squashfs
an einem Mountpunkt bereitgestellt wird, der anscheinend über die${rootmnt}
Shell-Variable angegeben wird.Mit anderen Worten, was wir
${rootmnt}
an dieser Stelle haben, ist unsere VFAT-Partition (oder was auch immer wir über denroot=
Befehlszeilenparameter angegeben haben). Dieses Skript erledigt jetzt andere Aufgaben, z. B. das Verschieben aller virtuellen Dateisysteme an den${rootmnt}
Einhängepunkt. Daher müssen wir sicherstellen, dass alle benutzerdefinierten Aufgaben nach dem obigen Code ausgeführt werden.Alles was Sie tun müssen, ist einfach so etwas nach dem obigen Code in das initramfs einzufügen
/init
:Das ist es. Das Skript wird wie gewohnt fortgesetzt, wobei das Root-Dateisystem das Overlay ist und alle seine Teile anschließend leicht zugänglich sind. Beachten Sie , dass keine Fehlerprüfung durchgeführt wird. Es liegt in Ihrem eigenen Ermessen, die obigen Befehle hinzuzufügen oder sicherzustellen, dass das
overlay
Modul geladen ist.Packen Sie jetzt einfach die initramfs:
Und kopieren Sie /tmp/initrd.img auf Ihre SD-Karte oder wo auch immer. Vergessen Sie nicht, sich
root.squashfs
im Stammverzeichnis der VFAT-Partition zu befinden, obwohl dies offensichtlich leicht anpassbar ist und Sie dies nicht auf diese Weise tun müssen. Dies ist nur der "einfachste" Weg mit Syslinux (und sogar UEFI-Boot), keineswegs der beste.Tut mir leid, ich weiß, dass Sie nach einem eingebetteten Gerät gefragt haben, aber ich weiß nicht, wie der Startvorgang dort funktioniert. Ich verwende nur ein Beispiel für x86, aber dieser Teil ist weniger wichtig (nur der
syslinux.cfg
Teil).Bitte beachten Sie, dass dies den beschreibbaren Teil des machen
overlayfs
wietmpfs
, was nicht das, was Sie wollten. Es kann jedoch leicht geändert werden , wenn Sie oben schauen, mounten Sie einfach etwas anderes für/run/rootfs
anstelle von tmpfs, wohin auch immer Sie die Schreibvorgänge möchten.quelle