[[Vorlage(Archiviert, )]]
[[Vorlage(Fortgeschritten)]]
{{{#!vorlage Wissen
[:Terminal: Ein Terminal öffnen]
[:Editor: Einen Editor öffnen]
[:sudo: Root-Rechte]
[:Rechte: Rechte für Dateien und Ordner ändern]
}}}
[[Inhaltsverzeichnis()]]
Dieser Artikel beschreibt, wie Schreibzugriffe auf das Root-[:Dateisystem:] auf eine [wikipedia: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 [:Update:Aktualisierungen] möglichen sind - z.B. als Media-Server, Automotive Computer etc. Denn das Nur-Lesen Dateisystem kann bei Bedarf beschreibbar [:mount: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 [wikipedia: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 [wikipedia:SquashFS:SquashFS] für das Root-Dateisystem. Für jede permanente Änderung muss dann explizit ein neues Dateisystem-Abbild erzeugt werden.
= Überblick =
Prinzipiell existieren mit [wikipedia:aufs:] und OverlayFS zwei Möglichkeiten, wie ein Nur-Lesen Root-Dateisystem erzeugt werden kann. Langfristig soll [wikipedia: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:
{{{#!vorlage Befehl
sudo modprobe aufs
}}}
bzw.
{{{#!vorlage Befehl
sudo modprobe overlayfs
}}}
In den regulären von Ubuntu verwendeten Kerneln ist das `aufs`-Modul ab [:Lucid:Ubuntu 10.04] bis einschließlich [:Precise:Ubuntu 12.04] verfügbar, das `overlayfs`-Modul ist ab Version [:Oneiric:11.10] im Standardkernel enthalten. Es gibt allerdings spezielle Kernel für Portierungen, in denen diese Module fehlen, wie z.B. der [https://launchpad.net/~tiomap-dev/+archive/release: neuste Kernel von TI] für die ARM OMAP Platformen.
= Umsetzung =
Im Artikel [:Archiv/Nur-Lesen Root-Dateisystem mit aufs:Nur-Lesen Root-Dateisystem mit aufs] ist eine Anleitung enthalten, die auch für OverlayFs geeignet ist. Es sind lediglich folgende Anpassungen nötig:
1. Das Modul `overlayfs` muss in die Datei '''/etc/initramfs-tools/modules''' eingefügt werden, damit es im [wikipedia:initramfs:] verfügbar ist: {{{#!vorlage Befehl
echo overlayfs >>/etc/initramfs-tools/modules
}}}
1. Es wird ein anderes Skript benutzt, nämlich '''root-ro'''.
* Das [#Das-Skript-root-ro root-ro Skript] muss unter '''/etc/initramfs-tools/scripts/init-bottom/root-ro''' gespeichert werden.
* Es muss ausführbar gemacht werden [4].
1. Zuletzt muss das neue initramfs erstellt werden: {{{#!vorlage Befehl
sudo update-initramfs -u
}}}
Dann kann das System neu gestartet werden. Ob alles geklappt hat, lässt sich dann mit folgendem Kommando überprüfen:
{{{#!vorlage Befehl
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` und `aufs` unterstützt, dies wird über den Kernel [:Booten#Bootoptionen:Bootparameter] `root-ro-driver=[overlayfs|aufs]` definiert. Dabei ist `overlayfs` 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
{{{#!vorlage Befehl
sudo mount -o remount,rw /mnt/root-ro
}}}
Dann können Änderungen einfach kopiert werden:
{{{#!vorlage Befehl
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:
1. Den Kernel mit dem Parameter `disable-root-ro=true` starten
1. Oder die „magische“ Datei '''disable-root-ro''' benutzen {{{#!vorlage Befehl
sudo mount -o remount,rw /mnt/root-ro
sudo touch /mnt/root-ro/disable-root-ro
}}} neu starten {{{#!vorlage Befehl
sudo reboot
}}} und nach dem Neustart die Datei wieder löschen: {{{#!vorlage Befehl
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:
{{{#!vorlage Befehl
sudo rm /etc/initramfs-tools/scripts/init-bottom/root-ro
sudo update-initramfs -u
}}}
= Das Skript root-ro=
{{{#!code bash
#!/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
# .
#
#
# 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 <${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 =
## * [:Nur-Lesen Root-Dateisystem mit aufs:]
* [:chroot/persistente-Installation:]
* [ubuntu_doc:community/aufsRootFileSystemOnUsbFlash:aufsRootFileSystemOnUsbFlash] - Hier gibt es evtl eine aktuellere Version des Skripts root-ro.
#tag: System, Sicherheit, Installation