LUKS: Reparatur verschlüsselter Partitionen

Im Artikel Verschlüsselung: LUKS und LVM wurde beschrieben, wie man (unter Linux) eine verschlüsselte Partition erstellt. Doch was, wenn sich diese nicht mehr einhängen, 'montieren' (engl. mount) lässt?

Dokumentation, Hintergründe: dm-crypt (Wikipedia/de), LUKS (Wikipedia/en)

Dateisystem korrupt

Es kann zum Beispiel vorkommen, dass sich die USB 3.0 PCIe-Karte (PCI-E) mitten beim Schreiben vom System verabschiedet und der eingesteckte USB-Stick (in diesem Fall mit 3 Partitionen, die verschlüsselte ist /dev/sdc3) nicht mehr lesbar ist. In /var/log/messages steht dann zum Beispiel:

Nov 12 16:21:16 ceres kernel: [2889125.501986] scsi26 : usb-storage 16-2:1.0
Nov 12 16:21:16 ceres mtp-probe: checking bus 16, device 3: "/sys/devices/pci0000:00/0000:00:07.0/0000:06:00.0/usb16/16-2"

Nov 12 16:22:17 ceres kernel: [2889185.771519] EXT4-fs (dm-3): mounted filesystem with ordered data mode. Opts: (null)

Nov 12 16:24:50 ceres kernel: [2889335.341982] xhci_hcd 0000:06:00.0: Timeout while waiting for address device command
Nov 12 16:24:50 ceres kernel: [2889335.539168] usb 16-2: device not accepting address 3, error -62

Nov 12 16:25:05 ceres kernel: [2889350.559728] xhci_hcd 0000:06:00.0: Timeout while waiting for reset device command
Nov 12 16:25:05 ceres kernel: [2889350.559734] usb 16-2: Cannot reset HCD device state
Nov 12 16:25:05 ceres kernel: [2889350.559755] usb 16-2: USB disconnect, device number 3
Nov 12 16:25:05 ceres kernel: [2889350.559807] sd 26:0:0:0: Device offlined - not ready after error recovery
Nov 12 16:25:05 ceres kernel: 9823491
Nov 12 16:25:05 ceres kernel: error o50.566136logical block 9823493
Nov 12 16:25:05 ceres kernel: [2889350.566138] Buffer I/O error on devic6666668888888888i

Nov 12 16:25:05 ceres kernel: [2889350.566439] Buffer I/O error on device dm-3, logical block 9823616

Nov 12 16:25:05 ceres kernel: [2889350.566452] EXT4-fs warning (device dm-3): ext4_end_bio:250: I/O error writing to inode 523300 (offset 3999334
40 size 126976 starting block 9823592)

Nov 12 16:26:25 ceres kernel: [2889429.168974] Buffer I/O error on device dm-3, logical block 0
Nov 12 16:26:25 ceres kernel: [2889429.168976] lost page write due to I/O error on dm-3
Nov 12 16:26:25 ceres kernel: [2889429.168978] EXT4-fs error (device dm-3): ext4_put_super:844: Couldn't clean up the journal

Das war es dann. Ein Aus- und erneutes Einstecken bringt lediglich die Meldung:

Nov 12 16:29:06 ceres kernel: [2889587.272956] EXT4-fs (dm-3): unable to read superblock
Nov 12 16:29:27 ceres dbus-daemon[1203]: ** Message: No devices in use, exit
Nov 12 16:29:34 ceres kernel: [2889613.917437] EXT4-fs (dm-3): unable to read superblock
Nov 12 16:29:52 ceres kernel: [2889632.341143] Buffer I/O error on device dm-3, logical block 0

Reparatur des verschlüsselten Dateisystems

Wer auf Nummer sicher gehen will, der kopiert sich erst die gesamte (fehlerhafte) Partition auf eine (weitere externe) Festplatte (mit genügend freiem Platz). Ein Beispiel (die fehlerhafte Partition ist /dev/sdb3):

dd if=/dev/sdb3 of=/media/USB-Disk/backup_sdb3.img bs=4096 conv=notrunc,noerror

Man könnte die Reparatur auch mit der Datei testen, aber es soll ja der Stick repariert werden. Geht die Reparatur aus irgendeinem Grund schief, lässt sich das Backup wieder zurück kopieren:

dd if=/media/USB-Disk/backup_sdb3.img of=/dev/sdb3 bs=4096

Wissen sollte man als erstes, um welches Device es sich handelt. Das könnte schon dies zeigen:

ls /dev/sd*

Wer unsicher ist, zieht den Stick ab (bitte sicher stellen, dass keine weitere Partition des Sticks 'mounted' ist) und kontrolliert sofort nach dem erneuten Einstecken mit

dmesg | tail -n 30

um welche Partition es sich handelt. Der Output sieht ca. so aus:

[214.863601]  sdb: sdb1 sdb2 sdb3
[214.865706] sd 31:0:0:0: [sdb] Attached SCSI removable disk
[215.076448] SELinux: initialized (dev sdb1, type vfat), uses genfs_contexts
[215.079285] SELinux: initialized (dev sdb2, type vfat), uses genfs_contexts
[222.385871] EXT4-fs (dm-3): mounted filesystem with ordered data mode. Opts: (null)
[222.385880] SELinux: initialized (dev dm-3, type ext4), uses xattr

In diesem Fall hat der Stick 3 Partitionen, die erstens zwei sdb1 und sdb2 sind vom Typ vfat, die dritte ist die besagte Partition. Man merkt sich /dev/sdb3.

Dann muss nachgeschaut werden, ob das LUKS-Device noch vorhanden ist:

ls /dev/mapper 

udisks-luks-uuid-6917a7c2-6e5d-4d8d-bda3-1722c0fe7275-uid501

Ist das der Fall, muss es unter Umständen erst entfernt werden:

cryptsetup luksClose udisks-luks-uuid-6917a7c2-6e5d-4d8d-bda3-1722c0fe7275-uid501

Nun kann mit der Wiederherstellung begonnen werden (USB-Stick oder HD gesteckt lassen). Das Device öffnen und temporär zuordnen:

cryptsetup luksOpen /dev/sdb3 lukstemp

Es wird das Passwort verlangt. Nach dessen Eingabe findet man tempmount in /dev/mapper. Es kann nun repariert werden (Es reicht fsck.ext, wenn man den Partitionstyp nicht kennt):

fsck.ext4 /dev/mapper/lukstemp 

Nachdem es (hoffentlich) erfolgreich repariert wurde, muss man es wieder schliessen:

cryptsetup luksClose lukstemp

Nun kann der Stick aus- und wieder eingesteckt werden. Nach Eingabe des Passwortes ist die verschlüsselte Partition wieder zugänglich:

Nov 12 16:48:45 ceres kernel: [2890743.566971]  sdb: sdb1 sdb2 sdb3
Nov 12 16:48:45 ceres kernel: [2890743.569088] sd 30:0:0:0: [sdb] Attached SCSI removable disk
Nov 12 16:48:45 ceres hald[3121]: woohoo
Nov 12 16:49:03 ceres kernel: [2890761.195484] EXT4-fs (dm-3): mounted filesystem with ordered data mode. Opts: (null)

Rettung der Daten bei defekter Partitionstabelle

Ist die Partitionstabelle korrupt, ist das Einhängen ('mounten') unmöglich. Der LUKS-Header einer Partition muss gefunden werden. Denn die verschlüsselte "Partition" liegt nicht am Anfang der eigentlichen Partition, sondern in einem LUKS-Container. Der Datenbereich beginnt nach dem LUKS-Header 4c554b53babe. Man könnte das mit hexdump suchen (yum -y install hexdump). Doch das ist sehr langsam (viele Stunden, Tage).

hexdump -C /dev/sdb | grep <"4c 55 4b 53 ba be"

Man macht das besser mit bgrep. Das Programm muss kompiliert werden (Compiler: yum -y install gcc) und wird so auch gleich in das gewohnte Verzeichnis /usr/local/bin gelegt. Damit ist es im Suchpfad:

w.get https://github.com/tmbinc/bgrep/raw/master/bgrep.c 
// (bei 'w.get' den Punkt weglassen, konnte nicht geschrieben werden wegen: 
// ModSecurity msg "System Command Injection") )
gcc -O2 -o /usr/local/bin/bgrep bgrep.c

Nach dem LUKS-Header suchen:

bgrep 4c554b53babe /dev/sdb

/dev/sdb: 1c822404

In einen Dezimalwert wandeln:

echo $((0x1d532293))

491987603

Mit losetup ab der entsprechenden Stelle auf ein Loop-Device legen (mit Option -o, Korrektur vom 26.01.2019):

losetup -s 491987603 /dev/loop0 /dev/sdb
losetup -o 491987603 /dev/loop0 /dev/sdb

Das (verschlüsselte) loop-Device öffnen und das Passwort eingeben:

cryptsetup luksOpen /dev/loop0 lukstemp

Und schlussendlich irgendwo in das Dateisystem hängen (hier unter /mnt/sdc3_decrypted):

mount /dev/mapper/lukstemp /mnt/sdc3_decrypted

Nun kann man mit der Datenrettung beginnen. Aber wenn auch das Dateisystem beschädigt ist, befolgt man in analoger Weise die ersten Schritte dieses Artikels. Man führt die Reparatur auf /dev/mapper/lukstemp aus.