Linux – Wenn das Bios die NVMe-SSD nicht bootet

Von dem Problem habe ich nur durch Dritte erfahren, konnte es aber leicht lösen.  Stellt Euch mal vor Ihr kauft Euch eine NVMe SSD  und Euer Bios kann die nicht booten, was macht Ihr dann  ?

Das Problem

Es soll Motherboards geben, die zwar einen passenden Port für die NVMe SSD haben, aber leider vergessen haben, daß man ja auch davon booten können müßte. Wenn man jetzt nur so eine NVMe SSD hat, ist man sprichwörtlich gearscht. Falls man nicht vor hat, seinen Rechner per USB Stick zu booten und von der LiveDisk mit der SSD zu spielen, wird das eine sehr frustrierende Neuanschaffung.

Die Idee

Aber halt! Wenn man das System von einem USB Stick booten kann, könnte man dann nicht auch NUR davon booten ohne die Livedisk zu starten ?

Die Lösung

Na ja, vom Prinzip her schon, aber USB-Stick, das muß doch besser gehen. Ja geht es, aber ihr braucht dafür eine normale SSD oder HD, die kann aber ganz winzig sein, Hauptsache 512 MB passen drauf!

Bei der Installation Eures OSes wählt man für /, Swap und /home die neue NVMe SSD aus. Normal partitionieren und formatieren, soweit nichts besonderes.

Die /boot Partition kicken wir jetzt aber nicht auf die NVMe sondern die alte/kleine SSD. Dort wird auch der Bootloader installiert. Linux ist es nämlich völlig egal, wo die Partionen liegen, Hauptsache der Bootloader kann es finden und das kann er ja dann. Problem gelöst.

Sein System auf die neue NVMe umstellen, ohne neu zu installieren

Wie man eine defekte Bootpartition fixen kann, hatte ich schon mal thematisiert, daher setzte ich das Wissen jetzt bei Euch voraus. Wie man unschwer erkennen kann, habe ich hier den Booteintrag in Grub vor mir :

menuentry 'Fedora (4.14.4-200.fc26.x86_64) 26 (Twenty Six)' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-4.13.8-100.fc25.x86_64-advanced-e62edbbe-a1ae-4242-bca5-1249d6f2df67' {
 load_video
 set gfxpayload=keep
 insmod gzio
 insmod part_msdos
 insmod ext2
 set root='hd2,msdos1'
 if [ x$feature_platform_search_hint = xy ]; then
 search --no-floppy --fs-uuid --set=root --hint-bios=hd2,msdos1 --hint-efi=hd2,msdos1 --hint-baremetal=ahci2,msdos1 221608f2-5914-4619-9ef7-6dfddf233fd4
 else
 search --no-floppy --fs-uuid --set=root 221608f2-5914-4619-9ef7-6dfddf233fd4
 fi
 linux /vmlinuz-4.14.4-200.fc26.x86_64 root=/dev/mapper/luks-ffbd61f2-4c1e-4dc8-b12b-c89e9f69c9fa ro rd.driver.blacklist=nouveau modprobe.blacklist=nouveau vconsole.font=latarcyrheb-sun16 rd.luks.uuid=luks-ca1f019d-39ce-4cf8-b522-f6d3e63ebe2a rd.luks.uuid=luks-ffbd61f2-4c1e-4dc8-b12b-c89e9f69c9fa rhgb quiet splash audit=0 rd.driver.blacklist=nouveau nouveau.modeset=0 modprobe.blacklist=nouveau LANG=de_DE.UTF-8
 initrd /initramfs-4.14.4-200.fc26.x86_64.img
}

Ok, meine Systempartition ist vollverschlüsselt, daher habe ich da die LUKS-ID stehen. Auf einem „normalen“ System könnte das so aussehen :

menuentry 'Fedora (4.14.6-200.fc26.x86_64) 26 (Twenty Six)' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-4.7.10-100.fc23.x86_64-advanced-dca7eea1-687e-476a-a9a0-c41ef0329113' {
 load_video
 set gfxpayload=keep
 insmod gzio
 insmod part_msdos
 insmod ext2
 set root='hd0,msdos1'
 if [ x$feature_platform_search_hint = xy ]; then
 search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' dca7eea1-687e-476a-a9a0-c41ef0329113
 else
 search --no-floppy --fs-uuid --set=root dca7eea1-687e-476a-a9a0-c41ef0329113
 fi
 linux /boot/vmlinuz-4.14.6-200.fc26.x86_64 root=UUID=dca7eea1-687e-476a-a9a0-c41ef0329113 ro rhgb quiet audit=0 LANG=de_DE.UTF-8
 initrd /boot/initramfs-4.14.6-200.fc26.x86_64.img
}

Alles was man machen muß, ist die UUID der Partition zu ändern und schon bootet das System als System von der anderen SSD. Wie bekommt man die jetzt, nachdem man die NVMe SSD partitioniert und formatiert hat ?

UUID ermitteln

# blkid
/dev/xvda1: UUID=“dca7eea1-687e-476a-a9a0-c41ef0329113″ TYPE=“ext4″ PARTUUID=“000af34a-01″
/dev/xvda2: UUID=“262b5659-4c18-4d8b-89e9-d9ba932e77c0″ TYPE=“swap“ PARTUUID=“000af34a-02″
/dev/xvdb: UUID=“65d31ff9-53c9-4e0b-8a52-0a16622c82d9″ TYPE=“ext4″

Mit dem gleichen Befehl bekommt man auch die LUKS ID mitgeteilt, so man denn eine verschlüsselte Luks-Partition hat:

/dev/mapper/luks-ca1f019d-39ce-4cf8-b522-f6d3e63ebe2a: UUID=“46da0d80-21fb-45b7-8567-ba047de66cb6″ TYPE=“swap“
/dev/mapper/luks-ffbd61f2-4c1e-4dc8-b12b-c89e9f69c9fa: UUID=“e62edbbe-a1ae-4242-bca5-1249d6f2df67″ TYPE=“ext4″

(Zwischenfrage aus dem Publikum: Wieso verschlüsselst Du auch SWAP ?  Antwort: Weil in dem ausgelagerten Speicher Klartext steht und man sich andernfalls eine Sicherheitslücke ins Haus holt. )

Natürlich muß man sein System noch ein bisschen pimpen, damit es später nicht wieder von der alten Systempartition auf der „alten SSD“ booten, nur weil der Kernel neu erstellt wurde 😀 Folgende Punkte sind zu manipulieren:

/etc/fstab
/etc/mtab
/etc/default/grup

Also alle alten UUID/LUKS-IDs durch die neuen ersetzen. Das ist ein ganz schöner Schock, wenn man seine neue SSD im Betrieb hat und dann ein paar Tage später der Rechner wieder auf einem alten Stand ist 😀

 

 

Mitten im DBUS Update poweroff

Es fing wie immer harmlos an, obwohl, tut es das nicht immer ?  Hmm.. also.. es fing harmlos an :

Berlin: „0:10 Ping…Bist Du da ?“
Ich: „0:12 Ja, klar. Was gibt es denn?“
Berlin: „0:12 Mein Rechner bootet nicht mehr..Ich schick Dir mal ein Foto“

Womit das Unheil seinen Lauf nahm …Fehlermeldung von system-logind und anderen DienstenIch: „Also logind geht nicht ? Starten wir doch mal mit einem anderen Kernel… “
Berlin: „Mist, gleiches Ergebnis.“

Das ist natürlich eine Kaskade, wenn ein wichtiger Dienst nicht startet und andere auf den angewiesen sind, dann starten die auch nicht. Es wird daher nur eine Sache nicht gehen, das stand zu dem Zeitpunkt eigentlich schon fest.

Nun startet man den Rechner im Debugmodus…

Dazu im Kernelauswahlmenü auf die Taste „e“ drücken und in der Zeile mit „linux /vmlinuz….“ am ENDE “ 1″ anfügen. Dann mit STRG+X booten.

Was nun passiert ist, daß sobald ein Minimalsystem von der Platte startet, der Admin sein Passwort eingeben kann und in der Shell den Fehler beheben kann, wenn man ihn denn findet.

Ich: „schauen wir mal in die Logs vom letzten Boot..  journalctl –boot=-1“

Fehler von systemd im letzten BootlogIch: „Connection timed out… also hat er versucht einen Systemdienst zu kontaktieren, der nicht geantwortet hat. Wir starten den mal so, vielleicht gibt es noch mehr Ausgabe“

Ich: „systemctl start systemd-logind“
Berlin: „Nichts..“
Ich:  „Also der logind will nicht…  suchen wir mal die Service Datei“

[root /]# locate logind.service
/usr/lib/systemd/system/systemd-logind.service
/usr/lib/systemd/system/multi-user.target.wants/systemd-logind.service
/usr/share/man/man8/systemd-logind.service.8.gz

[root /]# cat /usr/lib/systemd/system/systemd-logind.service | grep Exec
ExecStart=/usr/lib/systemd/systemd-logind
MemoryDenyWriteExecute=yes

Ich: „Na dann starten wir mal systemd-logind von Hand. Gib ein was in der ExecStart hinter dem = steht“
Berlin: „Passiert nichts“
Ich: „Also jetzt müßte man strace benutzen, das traue ich Dir zu, aber die Ausgabe zu interpretieren ist eine Sache für sich. Ich muß auf Deinen Rechner.“

Zu dem Zeitpunkt liefen außer dem PID=1 Prozess noch genau 3 andere auf dem Rechner 😀

Ich: „start mal das Netzwerk … systemctl start network“
Berlin: „Geht nicht. Hängt.“
Ich: „Mist.. aber kein Beinbruch.. STRG+C und dann brauche ich mal die IP der Portfreigabe für SSH aus Deinem Fritz-Router.“

Jetzt muß man dazu wissen, daß man in der Fritzbox eine Portfreigabe für den SSHD machen kann und die leitet man auf die feste LAN IP des Pcs, den man von außen kontaktieren will. Das hat den Vorteil, daß der befreundete Admin, jederzeit helfen kann. Es setzt aber auch voraus, daß das Netzwerk da ist, was es nicht war…

Nachhilfe – Wie konfiguriert man eine Netzwerkkarte von Hand

Nachdem die IP kennt, gibt man ein:

ifconfig enp1s5  192.168.178.22 network 255.255.255.0 up
route add default gw 192.168.178.1
/usr/sbin/sshd

Wobei man hier natürlich die ermittelte IP einträgt und das richtige Netzwerkkarteninterface wählen muß. Wer seins nicht kennt, kann das mit „ip l“ auflisten:

# ip l
1: lo: <loopback,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000</loopback,
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 link/ether 50:13:3e:47:35:31 brd ff:ff:ff:ff:ff:ff

Ab der Stelle kann man dann per SSH auf dem Rechner einloggen, was sehr praktisch ist. Es stellte sich jetzt recht schnell raus, daß die ganzen Programm dem Init Prozess eine Message schicken wollen, aber keine Antwort mehr bekommen. Was daran lag, daß der DBUS-Daemon nicht lief. Jetzt konnte man endlich suchen, was dafür die Ursache war und das geht z.b. so :

[root /]# locate dbus.service
/usr/lib/systemd/system/dbus.service
/usr/lib/systemd/system/multi-user.target.wants/dbus.service
/usr/lib/systemd/user/dbus.service
/usr/lib/systemd/user/dbus.service.d
/usr/lib/systemd/user/dbus.service.d/flatpak.conf
[root /]# cat /usr/lib/systemd/system/dbus.service | grep Exec
ExecStart=/usr/bin/dbus-daemon –system –address=systemd: –nofork –nopidfile –systemd-activation –syslog-only
ExecReload=/usr/bin/dbus-send –print-reply –system –type=method_call –dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig

Also starten wir den dbus-daemon von Hand und stellen fest, daß er nicht startet. In dem Fall, weil seine libdbus.so.3 ein Target nicht enthielt, was nur sein kann, wenn die Version des Daemons und der lib nicht zusammen passen.

Ein „rpm -qa | grep dbus | sort “ brachte dann auch gleich den Fehler zutage. Statt 1.11.18 war der dbus-daemon nur als 1.11.16 installiert. Offensichtlich war der Rechner beim Update unsanft gestört worden oder der Updateprozess hing aus irgendeinem anderen Grund. Das kann man ja leicht mit einem Update beheben, oder ? 😉

Wie sich rausstellte, konnte man das nicht, weil für das Update durch RPM der DBUS-Daemon laufen müßte. Nun Starten Sie mal einen Update um den DBUS Daemon zu updaten, weil der nicht startet, weil er die falsche Version hat.

Das Ende naht ?

Hier hätte das Ende der Geschichte sein können, weil zu dem Zeitpunkt auch keine Livedisk vorhanden war, um den Rechner mal sauber zu starten und in einer Chroot dann das ausstehende Update zu applien.

Hey… wir haben doch einen SSH Zugang .. da geht doch auch … SCP 😀 Und wie der Zufall das so wollte, hatten beide Rechner das gleiche OS drauf.

Lösung:

scp /usr/bin/dbus-daemon root@externeipdeszielrechners:/usr/bin/

Dann den dbus von Hand starten und die dbus pakete installieren die noch im DNF-Cache  auf der Platte lagen. Das findet man unter /var/cache/dnf/updates…./  Da müßt Ihr ggf. mit find mal nach“.rpm“ suchen. Das Cache kann ziemlich unaufgeräumt sein.

Nun noch sauber den dbus über systemd neugestartet und „dnf update -y“  benutzen um alle ausstehenden Updates einzuspielen. Das wärs dann.

Kleiner Tip: Zwei Shells benutzen, weil der Updateprozess wird gemäß den Anweisungen in den RPMS die Dienste neustarten wollen, was wegen des nicht vorhandenen Systemstarts nicht klappt. d.h. die Hängen alle beim „systemctl start blahblah.service„, was man mit ps auxf leicht sehen kann.

Einfach die Pids von den Starts mit kill abschiessen, wir rebooten danach eh frisch.

Berlin: „2:12 Hey, da passiert was“
Ich: „2:12 Ja, ich hab den Reboot ausgelöst, sollte jetzt starten“

Jetzt sind wir fertig. Der Rechner bootet wieder und mehr als 2 Stunden hat es gedauert, denn natürlich haben wir noch einige andere Dinge probiert 😉 Da die aber nicht zur Lösung geführt haben, war ich mal so frei die Euch zu ersparen 🙂

Genauso wenig hilfreich waren :

Microsoft – Skype Zwangstrennung nach 1 Stunde reden .. args!
DTAG – DSL Zwangstrennung  mitten im Debug ! Das kann man sowas von gebrauchen wenn man einen Notfall hat!
SystemD – mangels Fehlermeldung, daß DBUS nicht gestartet werden konnte ! Das hätte die Suche ja nur um knapp 90 Minuten verkürzt! Dafür wird noch jemand bezahlen … muharharhar …

 

 

Gelöst : Chroot mit OpenSSH 7.2p2-6

Erste Hinweise zu den Ursachen des Problems

Wie im Bugtracker von RedHat einsehbar ist, kristallisieren sich grade (während des Schreibens dieses Artikels) Probleme mit der Chroot-Funktion vom SSHD heraus. Ist die Chroot aktiviert, was man tun sollte, um Benutzer den Zugang zum eigentlichen System zu verweigern, so daß diese keine lokalen Angriffe fahren können, sondern in einer eigenen Umgebung arbeiten müssen, werden die für Root nötigen Capabilities nicht mehr gesetzt.

Capabilities sind die Eigenschaften eines Users, die erweiterte Rechte im Linuxsystem beinhalten, wie z.b. das Recht sich mit PTRACE in Prozessen einzuklinken, um diese zu belauschen oder zu verändern. Diese Capabilities machen Root erst aus und fehlen in der aktuellen sshd version:

# capsh --print
Current: =
Bounding set =
Securebits: 00/0x0/1'b0
 secure-noroot: no (unlocked)
 secure-no-suid-fixup: no (unlocked)
 secure-keep-caps: no (unlocked)
uid=0(root)
gid=0(root)
groups=

Ursache ist eine Änderung am SSHD aus 2015 : https://bugzilla.mindrot.org/show_bug.cgi?id=2486

Bis zu dieser Änderung konnte man keine intelligente Ausnahme für den Rootuser konfigurieren, wenn es darum ging den Benutzer in eine Chroot einzusperren, OHNE das man alle Benutzernamen des Systems in die Config einträgt. Das wäre kompletter Quatsch gewesen 😉 Deswegen mußte man sich folgendes Konstrukts bedienen:

ChrootDirectory /opt/root/
Match user root
     ChrootDirectory /

Übersetzt heißt das obige:

Für *ALLE* Benutzer, wechsle in eine CHROOT Umgebung im Pfad „/opt/root/“
Wenn Du ROOT bist, dann wechsle nach „/“

Und genau das führt nun zum Problem, da  ChrootDirectory „/“ für die Entwickler nie als Option in Betracht kam, obwohl es ein valides Argument war.  In der 7.2p2-6 wurde „ChrootDirectory“ überarbeitet und offensichtlich beschlossen, daß bei einer Chroot nie Capabilities nötig sein werden würden, was so vermutlich auch nicht für alle Server auf der Welt funktionieren wird. Das kann noch spannend werden.

Der Lösung auf der Spur

Die Lösung liegt in dem neu eingeführten Wert „none“ als Argument für ChrootDirectory. Dies hebt die ChrootBeschränkungen für den User Root wieder auf:

ChrootDirectory /opt/root/
Match user root
     ChrootDirectory none

Wo mit es wieder so funktioniert, wie ursprünglich gedacht.

Thank you for the help with investigation. Do not close this bug, because it is obviously a bug that we drop root capabilities. We should not certainly do that for a UID=0 regardless the chroot option.

Once I will test the patch, I will issue the updates.
Jakub Jelen / RedHat.com“