Your Linux Data Center Experts

Encrypted root With LVM on Fedora 7

By  Sean Reifschneider Date August 26, 2007

Update

Note: I have updated this for F8 and have made it a lot easier to do. Please see my Fedora 8 Crypto Root article before deciding to go with this mechanism.

Introduction

For about the last year I've been running an encrypted file-system on my laptop. We have some amount of sensitive data on our machines, and with dm_crypt it's relatively easy to set up. Definitely worth it to keep from being the target of yet another news story about lost laptops with sensitive data.

Over the last year, I've basically never noticed the crypto impacting performance, even though my laptop isn't particularly fast. I've got a 1.7GHz Pentium M, but often it runs limited to 800MHz, the speed stepping doesn't step up if I boot when running from battery power. Even with the low speed CPU, I really haven't found disc performance is impacted by the encryption.

As I mentioned in a previous blog entry, I set up a normal root partition and just set up /home to be encrypted. This gets the vast majority of the data I'm interested in. But some data can leak out of the /home partition, including things like the "updatedb" database, and Postgres databases, not to mention temporary files.

The Debian installer now supports installing directly to an encrypted LVM, including swap and the root directory. However, Fedora and Ubuntu don't include this ability yet.

I've recently set up a system and I decided to try setting it up with a full root partition that was encrypted.

The below procedure involves installing to a small root partition, I used 20GB, but a partition as small as just a few GB could be used if you're really tight on space. This system has a 250GB drive, and I wasn't sure if I was going to do the /home crypto or the whole thing, so I just put a 20GB partition on there. I could always add that partition to the LVM pool now that I have crypto set up.

You could get clever and through that make use of a full crypto drive, but I won't go into any of that here.

Note that this requires hand modification of the initrd images whenever you install a new kernel, so it's a bit annoying. Unlike Debian, the Fedora mkinitrd does not include any way that I know of to add user-provided code into the initial init script or set up additional code to be added, so this manual step is required for the time being.

Preliminary System Setup

First, you will need to modify a few files to make the initrd happy with LVM.

#  set up new fstab
cp /etc/fstab /etc/fstab.lvm
#  edit the first column of the root entry to: /dev/mapper/vg00-sys_root

Edit /etc/lvm/lvm.conf and set the following values set in the "devices {" section. Note that the "types" line needs to have the "253" value set to the correct value from "/proc/devices".

#  set these values in /etc/lvm/lvm.conf "devices" section:
filter = [ "r|/dev/cdrom|", "r|/dev/hda*|", "r|/dev/sda*|" ]
types = [ "device-mapper", 253 ]

This sets LVM to recognize the mapper device and ignore the hard drives and CD.

Alternate Procedure for Setting Up initrd

Initially, I manually created the initrd. Those instructions are the next section. However, shortly after doing my second setup of this configuration, I had to do a new kernel install to get madwifi running. So I went through and found that adding the following lines to /sbin/mkinitrd will cause new initrds to set up the crypto. Here is a patch for /sbin/mkinitrd:

*** mkinitrd.orig       Sun Aug 26 20:17:54 2007
--- mkinitrd    Sun Aug 26 20:34:09 2007
***************
*** 1242,1247 ****
--- 1242,1248 ----
  
  inst /sbin/insmod "$MNTIMAGE" /bin/insmod
  inst /sbin/rmmod "$MNTIMAGE" /bin/rmmod
+ inst /sbin/cryptsetup "$MNTIMAGE" /bin/cryptsetup
  
  if [ -e /etc/fstab.sys ]; then
      inst /etc/fstab.sys "$MNTIMAGE"
***************
*** 1460,1465 ****
--- 1461,1469 ----
      done
  fi
  
+ emit "echo Decrypting root device"
+ emit "cryptsetup luksOpen /dev/sda3 lvm"
+ 
  if [ -n "$vg_list" ]; then
      emit "echo Scanning logical volumes"
      emit "lvm vgscan --ignorelockingfailure"

To get it to load the modules in the initrd, you need to add the following line to "/etc/sysconfig/mkinitrd":

MODULES="aes sha256 dm_crypt cbc"

Use "mkinitrd" to make a new initrd in the normal way. It should work with the encrypted root.

Create a Crypto initrd (Manual)

Note: This is the manual procedure, the previous section should probably be used instead.

You need to extract the existing initrd. I put it under /boot, and on my system I'm using kernel version "2.6.22.4-65.fc7". Note that this procedure has to be done any time a new kernel is installed on the system, so before doing this the first time you should definitely make sure you are running the latest kernel.

#  make new initrd that includes crypto modules
#  Remove "x86_64" if you are running 32-bit mode
mkinitrd --with=aes-x86_64 --with=sha256 --with=dm_crypt --with=cbc \
      --fstab=/etc/fstab.lvm initrd-2.6.22.4-65.fc7-crypt.img 2.6.22.4-65.fc7

#  Extract initrd
mkdir initrd-2.6.22.4-65.fc7-crypt.dir
cd initrd-2.6.22.4-65.fc7-crypt.dir
gunzip <initrd-2.6.22.4-65.fc7-crypt.img | cpio -ivd
cp /sbin/cryptsetup sbin

Now, you need to modify the "init" file by adding the following lines after the line which reads "mkblkdevs" and before "echo Creating root device.":

echo Decrypting root device
cryptsetup luksOpen /dev/sda3 lvm

echo Scanning logical volumes
lvm vgscan --ignorelockingfailure
echo Activating logical volumes
lvm vgchange -ay --ignorelockingfailure vg00

Finally, you now need to re-create the initrd:

find ./ | cpio -H newc -o | gzip -9 >/boot/initrd-2.6.22.4-65.fc7-crypto.img

Setting up the Encrypted LVM Root

This step creates the encrypted LVM volume.

#  write random data to the device for security
#  this assumes the partition you want to
#  overwrite for crypto LVM is /dev/sda3
#  WARNING: Overwrites /dev/sda3
dd if=/dev/urandom of=/dev/sda3
#  this will take a long time

#  create the encrypted partition
#  WARNING: Overwrites /dev/sda3
cryptsetup --key-size 128 --verbose --verify-passphrase --cipher \
      aes-cbc-essiv:sha256 luksFormat /dev/sda3
#  enter your passphrase twice

#  create LVM
cryptsetup luksOpen /dev/sda3 lvm
pvcreate /dev/mapper/lvm
vgcreate vg00 /dev/mapper/lvm
lvcreate -l <VOLUME_SIZE> -n sys_root vg00

Set up grub.conf

Modify "/etc/grub.conf" by copying the current boot section to a new one and that needs to reference the new initrd line and the kernel needs to reference the new root location. For example:

title Fedora Crypto (2.6.22.4-65.fc7)
   root (hd0,0)
   kernel /vmlinuz-2.6.22.4-65.fc7 ro root=/dev/mapper/vg00-sys_root rhgb
   initrd /initrd-2.6.22.4-65.fc7-crypto.img

METHOD 1: Dump root Partition to LVM: Safest

I rebooted from the old kernel after appending "init=/bin/sh" to the "kernel" line. This boots the old kernel without mounting the partition read-write.

You need to start the crypto device and LVM, and then copy the root partition over. I just used dd, and then resized the file-system.

#  load modules required for crypto
modprobe aes           #  for 32-bit
modprobe aes-x86_64    #  for 64-bit
modprobe dm-crypt
modprobe sha256

#  bring up crypto LVM and copy data
cryptsetup luksOpen /dev/sda3 lvm
vgchange -ay --ignorelockingfailure
dd if=/dev/sda2 of=/dev/mapper/vg00-sys_root

#  extend the file-system to full LVM partition size
fsck -fy /dev/mapper/vg00-sys_root
resize2fs -p /dev/mapper/vg00-sys_root

#  shut down the the crypto
vgchange -an --ignorelockingfailure
cryptsetup luksClose lvm

Now, reboot and select the crypto boot option. It should ask you for your passphrase and then boot.

METHOD 2: Dump root Partition to LVM: With System Up

The above method is safest but requires that you run it from the console and you can't do it over SSH. I read an article somewhere about shutting down services so that you could remount your root partition read-only, and while that doesn't seem possible on F7, it is possible to get it down enough that you can safely copy the mounted root to the LVM partition.

So first you need to shut down all services except networking and ssh:

telinit 3
chkconfig --list | awk '/3:on/ { printf "service %s stop\n", $1 }' | \
      grep -v -e sshd -e network | bash

This shuts down all services except for ssh and the network. Now, simply copy the file-system to the LVM partition:

dd if=/dev/sda3 of=/dev/vg00/sys_root
fsck -fy /dev/vg00/sys_root
resize2fs /dev/vg00/sys_root

The fsck should report few if any errors with the file-system. It WILL replay the journal, and may report a few errors. However, it it reports a lot you should probably do the other mechanism. I think one time I had it report 10 errors, another time it reported none.

Reboot

Once done, you will want to shut down the LVM and reboot:

vgchange -an
cryptsetup luksClose lvm
reboot
comments powered by Disqus