Remap read-only LUKS partition to read-write

cryptsetupdevice-mapperdisk-encryptiondm-crypt

cryptsetup can be invoked with --readonly or -r option, which will set up a read-only mapping:

cryptsetup --readonly luksOpen /dev/sdb1 sdb1

Once I have opened a device as read-only, can I later re-map it to read-write? Obviously, I mean mapping it read-write without closing it first, and then opening it again. Can I remap it without having to type my password again?

If this is not possible, is this just that cryptsetup does not support this, or is there some more fundamental level?

Best Answer

It doesn't seem to be possible with the cryptsetup command. Unfortunately cryptsetup has a few such immutable flags... --allow-discards is also one of them. If this wasn't set at the time you opened the container, you can't add it later.

At least, not with the cryptsetup command. However, since cryptsetup creates regular Device Mapper targets, you can resort to dmsetup to modify them. Of course, this isn't recommended for various reasons: it's like changing the partition table of partitions that are in use - mess it up and you might lose all your data.

The device mapper allows dynamic remapping of all devices at runtime and it doesn't care about the safety of your data at all; which is why this feature is usually wrapped behind the LVM layer which keeps the necessary metadata around to make it safe.

Create a read-only LUKS device:

# truncate -s 100M foobar.img
# cryptsetup luksFormat foobar.img
# cryptsetup luksOpen --read-only foobar.img foobar

The way dmsetup sees it:

# dmsetup info foobar
Name:              foobar
State:             ACTIVE (READ-ONLY)
Read Ahead:        256
Tables present:    LIVE
[...]
# dmsetup table --showkeys foobar
0 200704 crypt aes-xts-plain64 ef434503c1874d65d33b1c23a088bdbbf52cb76c7f7771a23ce475f8823f47df 0 7:0 4096

Note the master key which normally shouldn't be leaked, as it breaks whatever brute-force protection LUKS offers. Unfortunately I haven't found a way without using it, as dmsetup also lacks a direct --make-this-read-write option. However dmsetup reload allows replacing a mapping entirely, so we'll replace it with itself in read-write mode.

# dmsetup table --showkeys foobar | dmsetup reload foobar
# dmsetup info foobar
Name:              foobar
State:             ACTIVE (READ-ONLY)
Read Ahead:        256
Tables present:    LIVE & INACTIVE

It's still read-only after the reload, because reload goes into the inactive table.

To make the inactive table active, use dmsetup resume:

# dmsetup resume foobar
# dmsetup info foobar
Name:              foobar
State:             ACTIVE
Read Ahead:        256
Tables present:    LIVE

And thus we have a read-write LUKS device.

Does it work with a live filesystem?

# cryptsetup luksOpen --readonly foobar.img foobar
# mount /dev/mapper/foobar /mnt/foobar
mount: /mnt/foobar: WARNING: device write-protected, mounted read-only.
# mount -o remount,rw /mnt/foobar
mount: /mnt/foobar: cannot remount /dev/mapper/foobar read-write, is write-protected.

So it's read-only. Make it read-write and remount:

# dmsetup table --showkeys foobar | dmsetup reload foobar
# dmsetup resume foobar
# mount -o remount,rw /mnt/foobar
# echo hey it works > /mnt/foobar/amazing.txt

Can we go back to read-only?

# mount -o remount,ro /mnt/foobar
# dmsetup table --showkeys foobar | dmsetup reload foobar --readonly
# dmsetup resume foobar
# mount -o remount,rw /mnt/foobar
mount: /mnt/foobar: cannot remount /dev/mapper/foobar read-write, is write-protected.

So it probably works. The process to add allow_discards flag to an existing crypt mapping is similar - you have to reload with a table that contains this flag. However a filesystem that already detected the absence of discard support, might not be convinced to re-detect this on the fly. So it's unclear how practical it is.


Still, unless you have very good reason not to, you should stick to re-opening using regular cryptsetup commands, even if it means umounting and re-supplying the passphrase. It's safer all around and more importantly, doesn't circumvent the LUKS security concept.

Related Question