Samsung SSD resurrection

Yesterday, a discarded Samsung SD863 datacenter SSD found its way to my hands. Although a bit older – this one’s from 2016 – these are supposed to be quite reliable (except for a few rumoured firmware bugs), and 480GB of capacity are not to be disregarded even at today’s remarkable flash prices. Since it did not suffer from the usual drillholes of unreadability, I hooked it up to a linux machine – hopefully immune to virus-infected, supposedly “lost” thumbdrives – to give it a try. Unsurprisingly though, the drive announced 1GB of capacity, which does not fit its type MZ7KM480HAHP and explains its disposal. I had a hunch that the reason might lie with the microcode:

ata6.00: ATA-9: SAMSUNG MZ7KM480HAHP-00005, ERRORMOD, max UDMA/133
...
sd 5:0:0:0: [sdd] 1965352 512-byte logical blocks: (1.01 GB/960 MiB)

ERRORMOD as a version index looks rather like something went horribly wrong, causing some kind of corruption to the firmware. At least it still communicates through SATA, which indicates some backup capabilities.

Continue reading

LUKS meets badblocks

Most linux users know the famous badblocks tutorial because almost every harddrive starts to produce bad sectors at some point in its life. In some cases they correspond to real damages on the platter surfaces, but sometimes the drive logic has just made an error and blocked further reading of the sector. To give the drive a chance to reallocate the sector to unused space OR to rethink its decision (yes, some bad sectors just disappear after this) you will need to overwrite the sector, best with zeroes. Before this, it is always smart to probe the sector for its occupation, and which file it has been assigned to, if so. The tutorial describes a way to do this.

Things get more complicated if the drive in question is encrypted using LUKS, because the encryption system adds its own header to the start of the disk/partition and offsets all data towards the end, while the order of the sectors is left untouched. The workaround is pretty simple!

Let’s assume the device is /dev/sda, with at least one (encrypted) partition inside.

cryptsetup luksDump /dev/sda1

will dump the header information to the terminal, including the “payload offset” in LBA units. Now, if you want to determine the position of the bad sector inside the LUKS drive, you add the starting sector of the affected encrypted partition to its payload offset. Use that number for the “S”-parameter in the first example of the tutorial. From there, continue just as described.

Remember to use the mapped drive (e.g. /dev/mapper/sda1) for all filesystem related commands in the badblocks tutorial. If “fdisk” can’t show you the starting sector of the mapper device partitions, use “parted”:

select /dev/sda1

unit s

print

quit

I double-checked this method by dumping the sector data before and after the change (LUKS and physical) and comparing the contents with a hex editor – the calculation seems to be spot-on.

Another little piece of advice: After determining what damage will occur inside the encrypted partition, zero the sector ONLY on the physical drive and NEVER inside of the encrypted partition. LUKS will encrypt the zeroes to random gibberish, which will sometimes not trigger the sector remapping procedure of the drive. If you zero it on the physical drive instead, it will again be overwritten with valid data the next time you modify its encrypted version.

Also, if you are using a CBC encryption mode and zero the affected 512 byte block on the physical drive, a whole filesystem block (usually 4096 bytes) inside the LUKS partition will become corrupted, caused by CBC’s chained sector encryption scheme. To circumvent this from the start, use the newer LRW or XTS modes.

There IS one downside though. If a defective sector alters the encryption header and there is no header backup or duplicate of the contents – well, then that’s just that. With the header gone, there is no way to restore the contents of the drive! Same thing for your repair attempt – triple-check all dd-commands for typos before executing (especially if you are correctly using -skip or -seek)!