Comment 15 for bug 474258

Revision history for this message
Cezary Baginski (cezary0) wrote :

I have a patch and a workaround.

PATCH
======
I refactored the code to expose the bug and make it easier to test edge cases:

    https://code.launchpad.net/~cezary0/cryptsetup/bugfix474258_refactored

If anyone can think of other/related issues, edge cases or useful test cases - let me know and I'll try to add the tests, so we can nail this once and for all. One I'm still thinking about is when an encrypted partition takes the same device name as the crypttab tmp entry - you might loose that encrypted partition even with the patch (workaround below).

I did consider some weird cases where a new partition contains 2 filesystem headers (reported by wipefs), that can confuse blkid, but this is probably too obscure and statistically improbable or not dangerous.

WORKAROUND (identify by partition size instead of label or UUID)
=====================================================
If you want to protect yourself from possibly loosing data, you can do the following:

1. Add "precheck" option to every swap entry in crypttab
2. set CRYPTDISKS_PRECHECK in /etc/default/cryptdisks to a script returning a nonzero value for any device that has data on it.
3. patch cryptdisks.functions, because the condition is just wrong

Example:

1. add "precheck" in /etc/crypttab:
cryptswap2 /dev/sda28 /dev/urandom swap,precheck,cipher=aes-cbc-essiv:sha256

2. set variable in /etc/default/cryptdisks:
CRYPTDISKS_PRECHECK=/usr/local/lib/chk_size

3. sudo mkdir -p /usr/local/lib/chk_size

4. sudo chmod 0755 /usr/local/lib/chk_size

5. discover the size of the partition you want to use:

  sudo sfdisk -s /dev/sda28 # gives partition size

6. create and edit /usr/local/lib/chk_size:

    #!/bin/sh
    EXPECTED_SIZE=2097152 # set to above size
    [ "$(sfdisk -s "$1")" -eq "$EXPECTED_SIZE" ]

7. patch /lib/cryptsetup/cryptdisks.functions:

# Fix it like this (changes: "" -> "!("; "!=" -> "="; "! /lib" -> "/lib"; "null;" -> "null);" ):

 if ! pre_out=$("$PRECHECK" "$src" 2> /dev/null) && \
    ! ( [ "$MAKESWAP" = "yes" ] && \
    /lib/cryptsetup/checks/blkid "$src" swap >/dev/null); then
  log_warning_msg "$dst: the precheck for '$src' failed: $pre_out"
  return 1

# NOTE: paste to replace the whole section, because it's too easy to make a mistake

P.S. Use backups / RAID / etc anyway - it ultimately costs less money and time.