Nur-Lesen Root-Dateisystem
Archivierte Anleitung
Dieser Artikel wurde archiviert. Das bedeutet, dass er nicht mehr auf Richtigkeit überprüft oder anderweitig gepflegt wird. Der Inhalt wurde für keine aktuell unterstützte Ubuntu-Version getestet. Wenn du Gründe für eine Wiederherstellung siehst, melde dich bitte in der Diskussion zum Artikel. Bis dahin bleibt die Seite für weitere Änderungen gesperrt.
Artikel für fortgeschrittene Anwender
Dieser Artikel erfordert mehr Erfahrung im Umgang mit Linux und ist daher nur für fortgeschrittene Benutzer gedacht.
Zum Verständnis dieses Artikels sind folgende Seiten hilfreich:
Dieser Artikel beschreibt, wie Schreibzugriffe auf das Root-Dateisystem auf eine RAM-Disk umgeleitet werden können. Dadurch ergeben sich die unter anderem folgende Vorteile:
Nach jedem Neustart ist immer ein „sauberes“ (und stabiles) System verfügbar.
Das Root-Dateisystem kann nicht beschädigt werden, wenn der Rechner einfach ausgeschaltet wird.
Änderungen am Dateisystem werden sichtbar
Dabei liegt der Fokus dieses Artikels darauf, ein System für den alltäglichen Einsatz zu haben, wobei trotzdem einfache permanente Änderungen und Aktualisierungen möglichen sind - z.B. als Media-Server, Automotive Computer etc. Denn das Nur-Lesen Dateisystem kann bei Bedarf beschreibbar eingebunden werden. Ist dies nicht gewünscht oder sollen noch weitere Anforderungen erfüllt werden, können evtl. die folgenden Ansätze weiterhelfen:
Der Wikipedia-Artikel Live-System beschreibt diverse Konfigurationen für verschieden Einsatzzwecke.
Das Aufsetzten eines einfachen Ubuntu Live-System auf einem USB-Stick ist im Artikel Live-USB beschrieben.
Einsatz von SquashFS für das Root-Dateisystem. Für jede permanente Änderung muss dann explizit ein neues Dateisystem-Abbild erzeugt werden.
Überblick¶
Prinzipiell existieren mit aufs und OverlayFS zwei Möglichkeiten, wie ein Nur-Lesen Root-Dateisystem erzeugt werden kann. Langfristig soll aufs aber durch OverlayFs ersetzt werden, da ersteres nur unter hohem Aufwand der Ubuntu-Kernel-Maintainer (Betreuer) geführt werden kann. Denn die aufs-Unterstützung wird nicht in den Upstream-Kernel aufgenommen.
Voraussetzungen¶
Die Kernelmodule aufs
bzw. overlayfs
müssen verfügbar sein. Dies lässt sich mit folgenden Kommandos feststellen:
sudo modprobe aufs
bzw.
sudo modprobe overlayfs
In den regulären von Ubuntu verwendeten Kerneln ist das aufs
-Modul ab Ubuntu 10.04 bis einschließlich Ubuntu 12.04 verfügbar, das overlayfs
-Modul ist ab Version 11.10 im Standardkernel enthalten. Es gibt allerdings spezielle Kernel für Portierungen, in denen diese Module fehlen, wie z.B. der neuste Kernel von TI für die ARM OMAP Platformen.
Umsetzung¶
Im Artikel Nur-Lesen Root-Dateisystem mit aufs ist eine Anleitung enthalten, die auch für OverlayFs geeignet ist. Es sind lediglich folgende Anpassungen nötig:
Das Modul
overlayfs
muss in die Datei /etc/initramfs-tools/modules eingefügt werden, damit es im initramfs verfügbar ist:echo overlayfs >>/etc/initramfs-tools/modules
Es wird ein anderes Skript benutzt, nämlich root-ro.
Das root-ro Skript muss unter /etc/initramfs-tools/scripts/init-bottom/root-ro gespeichert werden.
Es muss ausführbar gemacht werden [4].
Zuletzt muss das neue initramfs erstellt werden:
sudo update-initramfs -u
Dann kann das System neu gestartet werden. Ob alles geklappt hat, lässt sich dann mit folgendem Kommando überprüfen:
sudo mount
Falls die originale Rootpartition /dev/sdXY war, sollte die Ausgabe jetzt u.a. diese drei Einträge enthalten:
overlayfs-root on / type overlayfs (rw) /dev/sdXY on /mnt/root-ro type ext4 (rw,relatime,user_xattr,acl,barrier=1,data=ordered) tmpfs-root on /mnt/root-rw type tmpfs (rw,relatime)
Funktion des Skripts root-ro¶
Die echte Rootpartition ist unter /mnt/root-ro nur lesbar eingehängt.
Die RAM-Disk, welche die Änderungen aufnimmt, ist unter /mnt/root-rw eingehängt.
Es werden die Treiber
overlayfs
undaufs
unterstützt, dies wird über den Kernel Bootparameterroot-ro-driver=[overlayfs|aufs]
definiert. Dabei istoverlayfs
der Standardwert, falls nichts angegeben ist.
Zum Deaktivieren gibt es zwei Möglichkeiten:
Es wird der Kernel Bootparameter
disable-root-ro=true
übergeben.Im echten Root-Dateisystem kann eine (leere) Datei disable-root-ro in dessen Wurzelverzeichnis angelegt werden, also unter /mnt/root-ro/disable-root-ro. Nach einem Neustart sollte die Datei wieder entfernt werden.
Änderungen auf dem Nur-Lesen Dateisystem durchführen¶
Das original Root-Dateisystem ist unter /mnt/root-ro eingehängt und kann beschreibbar gemacht werden mit
sudo mount -o remount,rw /mnt/root-ro
Dann können Änderungen einfach kopiert werden:
cp -v DATEI /mnt/root-ro
Damit die Änderungen auch im „virtuellen“ Root-Dateisystem sichtbar werden, ist ggf. ein Neustart erforderlich. Denn wenn es sowohl auf der RAM-Disk (/mnt/root-rw) als auch im echten Root-Dateisystem (/mnt/root-ro) einen Eintrag gibt, hat derjenige auf der RAM-Disk Vorrang.
Deinstallation¶
Zur Deinstallation muss das Root-Dateinsystem zuerst wieder beschreibbar gemacht werden. Dafür gibt es die oben genannten Wege:
Den Kernel mit dem Parameter
disable-root-ro=true
startenOder die „magische“ Datei disable-root-ro benutzen
sudo mount -o remount,rw /mnt/root-ro sudo touch /mnt/root-ro/disable-root-ro
neu starten
sudo reboot
und nach dem Neustart die Datei wieder löschen:
sudo rm /disable-root-ro
Wurde das System mit einem „normalen“ beschreibaren Root-Dateisystem gestartet, kann das Skript einfach gelöscht und ein neues initramfs erzeugt werden:
sudo rm /etc/initramfs-tools/scripts/init-bottom/root-ro sudo update-initramfs -u
Das Skript root-ro¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 | #!/bin/sh # Copyright, 2012 Axel Heider # # Based on scrpts from # Sebastian P. # Nicholas A. Schembri State College PA USA # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see # <http://www.gnu.org/licenses/>. # # # Tested with Ubuntu 11.10 # # Notes: # * no changes to the root fs are made by this script. # * if /home/[user] is on the RO root fs, files are in ram and not saved. # # Install: # put this file in /etc/initramfs-tools/scripts/init-bottom/root-ro # chmod 0755 root-ro # optional: clean up menu.lst, update-grub # update-initramfs -u # # Disable read-only root fs # * option 1: kernel boot parameter "disable-root-ro=true" # * option 2: create file "/disable-root-ro" # # ROOT_RO_DRIVER variable controls which driver isused for the ro/rw layering # Supported drivers are: overlayfs, aufs # the kernel parameter "root-ro-driver=[driver]" can be used to initialize # the variable ROOT_RO_DRIVER. If nothing is given, overlayfs is used. # # no pre requirement PREREQ="" prereqs() { echo "${PREREQ}" } case "$1" in prereqs) prereqs exit 0 ;; esac . /scripts/functions MYTAG="root-ro" DISABLE_MAGIC_FILE="/disable-root-ro" # parse kernel boot command line ROOT_RO_DRIVER= DISABLE_ROOT_RO= for CMD_PARAM in $(cat /proc/cmdline); do case ${CMD_PARAM} in disable-root-ro=*) DISABLE_ROOT_RO=${CMD_PARAM#disable-root-ro=} ;; root-ro-driver=*) ROOT_RO_DRIVER=${CMD_PARAM#root-ro-driver=} ;; esac done # check if read-only root fs is disabled if [ ! -z "${DISABLE_ROOT_RO}" ]; then log_warning_msg "${MYTAG}: disabled, found boot parameter disable-root-ro=${DISABLE_ROOT_RO}" exit 0 fi if [ -e "${rootmnt}${DISABLE_MAGIC_FILE}" ]; then log_warning_msg "${MYTAG}: disabled, found file ${rootmnt}${DISABLE_MAGIC_FILE}" exit 0 fi # generic settings # ${ROOT} and ${rootmnt} are predefined by caller of this script. Note that # the root fs ${rootmnt} it mounted readonly on the initrams, which fits nicely # for our purposes. ROOT_RW=/mnt/root-rw ROOT_RO=/mnt/root-ro # check if ${ROOT_RO_DRIVER} is defined, otherwise set default if [ -z "${ROOT_RO_DRIVER}" ]; then ROOT_RO_DRIVER=overlayfs fi # settings based in ${ROOT_RO_DRIVER}, stop here if unsupported. case ${ROOT_RO_DRIVER} in overlayfs) MOUNT_PARMS="-t overlayfs -o lowerdir=${ROOT_RO},upperdir=${ROOT_RW} overlayfs-root ${rootmnt}" ;; aufs) MOUNT_PARMS="-t aufs -o dirs=${ROOT_RW}:${ROOT_RO}=ro aufs-root ${rootmnt}" ;; *) panic "${MYTAG} ERROR: invalide ROOT_RO_DRIVER ${ROOT_RO_DRIVER}" ;; esac # check if kernel module exists modprobe -qb ${ROOT_RO_DRIVER} if [ $? -ne 0 ]; then log_failure_msg "${MYTAG} ERROR: missing kernel module ${ROOT_RO_DRIVER}" exit 0 fi # make the mount point on the init root fs ${ROOT_RW} [ -d ${ROOT_RW} ] || mkdir -p ${ROOT_RW} if [ $? -ne 0 ]; then log_failure_msg "${MYTAG} ERROR: failed to create ${ROOT_RW}" exit 0 fi # make the mount point on the init root fs ${ROOT_RO} [ -d ${ROOT_RO} ] || mkdir -p ${ROOT_RO} if [ $? -ne 0 ]; then log_failure_msg "${MYTAG} ERROR: failed to create ${ROOT_RO}" exit 0 fi # mount a tempfs using the device name tmpfs-root at ${ROOT_RW} mount -t tmpfs tmpfs-root ${ROOT_RW} if [ $? -ne 0 ]; then log_failure_msg "${MYTAG} ERROR: failed to create tmpfs" exit 0 fi # root is mounted on ${rootmnt}, move it to ${ROOT_RO}. mount --move ${rootmnt} ${ROOT_RO} if [ $? -ne 0 ]; then log_failure_msg "${MYTAG} ERROR: failed to move root away from ${rootmnt} to ${ROOT_RO}" exit 0 fi # there is nothing left at ${rootmnt} now. So for any error we get we should # either do recovery to restore ${rootmnt} for drop to a initramfs shell using # "panic". Otherwise the boot process is very likely to fail with even more # errors and leave the system in a wired state. # mount virtual fs ${rootmnt} with rw-fs ${ROOT_RW} on top or ro-fs ${ROOT_RO}. mount ${MOUNT_PARMS} if [ $? -ne 0 ]; then log_failure_msg "${MYTAG} ERROR: failed to create new ro/rw layerd ${rootmnt}" # do recovery and try resoring the mount for ${rootmnt} mount --move ${ROOT_RO} ${rootmnt} if [ $? -ne 0 ]; then # thats badm, drpo to s shell to let the user try fixing this panic "${MYTAG} RECOVERY ERROR: failed to move ${ROOT_RO} back to ${rootmnt}" fi exit 0 fi # now the real root fs is on ${ROOT_RO} of the init file system, our layered # root fs is set up at ${rootmnt}. So we can write anywhere in {rootmnt} and the # changes will end up in ${ROOT_RW} while ${ROOT_RO} it not touched. However # ${ROOT_RO} and ${ROOT_RW} are on the initramfs root fs, which will be removed # an replaced by ${rootmnt}. Thus we must move ${ROOT_RO} and ${ROOT_RW} to the # rootfs visible later, ie. ${rootmnt}${ROOT_RO} and ${rootmnt}${ROOT_RO}. # Since the layered ro/rw is already up, these changes also end up on # ${ROOT_RW} while ${ROOT_RO} is not touched. # move mount from ${ROOT_RO} to ${rootmnt}${ROOT_RO} [ -d ${rootmnt}${ROOT_RO} ] || mkdir -p ${rootmnt}${ROOT_RO} mount --move ${ROOT_RO} ${rootmnt}${ROOT_RO} if [ $? -ne 0 ]; then log_failure_msg "${MYTAG} ERROR: failed to move ${ROOT_RO} to ${rootmnt}${ROOT_RO}" exit 0 fi # move mount from ${ROOT_RW} to ${rootmnt}${ROOT_RW} [ -d ${rootmnt}${ROOT_RW} ] || mkdir -p ${rootmnt}${ROOT_RW} mount --move ${ROOT_RW} ${rootmnt}${ROOT_RW} if [ $? -ne 0 ]; then s "${MYTAG}: ERROR: failed to move ${ROOT_RW} to ${rootmnt}${ROOT_RW}" exit 0 fi # technically, everything is set up nicely now. Since ${rootmnt} had beend # mounted read-only on the initfamfs already, ${rootmnt}${ROOT_RO} is it, too. # Now we init process could run - but unfortunately, we may have to prepare # some more things here. # Basically, there are two ways to deal with the read-only root fs. If the # system is made aware of this, things can be simplified a lot. # If it is not, things need to be done to our best knowledge. # # So we assume here, the system does not really know about our read-only root fs. # # Let's deal with /etc/fstab first. It usually contains an entry for the root # fs, which is no longer valid now. We have to remove it and add our new # ${ROOT_RO} entry. # Remember we are still on the initramfs root fs here, so we have to work on # ${rootmnt}/etc/fstab. The original fstab is ${rootmnt}${ROOT_RO}/etc/fstab. ROOT_TYPE=$(cat /proc/mounts | grep ${ROOT} | cut -d' ' -f3) ROOT_OPTIONS=$(cat /proc/mounts | grep ${ROOT} | cut -d' ' -f4) cat <<EOF >${rootmnt}/etc/fstab # # This fstab is in RAM, the real one can be found at ${ROOT_RO}/etc/fstab # The original entry for '/' and all swap files have been removed. The new # entry for the read-only the real root fs follows. Write access can be # enabled using: # sudo mount -o remount,rw ${ROOT_RO} # re-mounting it read-only is done using: # sudo mount -o remount,ro ${ROOT_RO} # ${ROOT} ${ROOT_RO} ${ROOT_TYPE} ${ROOT_OPTIONS} 0 0 # # remaining entries from the original ${ROOT_RO}/etc/fstab follow. # EOF if [ $? -ne 0 ]; then log_failure_msg "${MYTAG} ERROR: failed to modify /etc/fstab (step 1)" #exit 0 fi #remove root entry and swap from fstab cat ${rootmnt}${ROOT_RO}/etc/fstab | grep -v ' / ' | grep -v swap >>${rootmnt}/etc/fstab if [ $? -ne 0 ]; then log_failure_msg "${MYTAG} ERROR: failed to modify etc/fstab (step 2)" #exit 0 fi # now we are done. Additinal steps may be necessary depending on the actualy # distribution and/or its configuration. log_success_msg "${MYTAG} sucessfully set up ro/tmpfs-rw layered root fs using ${ROOT_RO_DRIVER}" exit 0 |
Links¶
aufsRootFileSystemOnUsbFlash - Hier gibt es evtl eine aktuellere Version des Skripts root-ro.