[systemd-devel] systemd-repart HOWTO + demo code

Thayne Harbaugh thayne at mastodonlabs.com
Fri Nov 1 07:39:54 UTC 2024


Response in line:

On Sun, 2024-10-20 at 00:13 -0600, Thayne Harbaugh wrote:
> Response in line:
> 
> On Sat, 2024-10-19 at 21:57 -0400, Adrian Vovk wrote:
> > Responses inline
> > 
> > On Sat, Oct 19, 2024, 21:52 Thayne Harbaugh
> > <thayne at mastodonlabs.com>
> > wrote:
> > > Response in line:
> > > 
> > > On Sat, 2024-10-19 at 20:36 -0400, Adrian Vovk wrote:
> > > > Hello,
> > > > I might have spotted something 

> <SNIP>

> > > > You tell repart to encrypt with a keyfile, but it seems like
> > > > you don't pass in which keyfile to use.

> > > Maybe I'm confused about how Encrypt= and EncryptedVolume=
> > > interact.

> <SNIP>

> > Yeah I think you are. I'm pretty sure EncryptedVolume= is about
> > defining what goes into /etc/crypttab, and thus how the volume is
> > set up at runtime or at boot. Not how the volume is set up when
> > it's created. Basically each EncryptedVolume= entry is an entry in
> > /etc/crypttab and no more.

> > > > By default, repart will encrypt with a null key in that
> > > > case. IIRC, you have to pass in the keyfile (or maybe socket)
> > > > to use in your drop-in.

> > > I feel like I should know what my "drop-in" ... but I have no
> > > idea.  Is thet the repart.d/30-xdata.conf?  Is it the override I
> > > made to systemd-repart.service as
> > > systemd-repart.service.d/systemd-repart-gen_tabs.conf ?

> > I mean the override you made to systemd-repart.service

> I changed the systemd-repart drop-in to pass
> --key-file=/run/fscrypt.sock:

>   ExecStart=systemd-repart --dry-run=no --key-file=/run/fscrypt.sock
> --generate-fstab=/run/fstab --generate-crypttab=/run/crypttab

> (change pushed into repart_howto project)

> I can now see that it opens the socket defined by fscrypt.socket,
> activates fscrypt at .service and executes getkey.  Woot!

> Unfortunately systemd-repart still does not exit and udev events
> continue to repeat waiting for a lock (the new, encrypted partition
> is not created):

I can see where systemd-repart locks the block device for
partitioning.  Various functions are called and udev events fire that
attempt to lock the same device ... and they block waiting for the
device.

After picking at this for a while I built my own versions of the
systemd suite, cryptsetup and lvm2 (to get dmeventd).  As soon as I
added my dmeventd everything worked!  I have not been able to figure
out the difference between my dmeventd and the one supplied by Ubuntu
24.10 Oracular - but I suspect that there's something busted with the
Ubuntu build of lvm2.

I have examples of repart working with encrypted file systems - both
growing an encrypted root FS as well as creating new partitions.  I
have made some minor updates to the repart HOWTO.  More updates to
come.

One thing I discovered is that it's problematic to build encrypted
partitions on a host system and mount them on a small, embedded
system: the PBKDF runs the system out-of-memory and triggers the OOM
killer.  I noticed that while the TPM branch in
repart.c:partition_encrypt() calls cryptsetup_set_minimal_pbkdf() the
code branch for key file does not - it likely needs a patch like this:

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Ensure that an encrypted image will work on low-memory systems

Cryptsetup uses PBKDF (Password-Based Key Derivation Function) to increase
brute-force attack costs.  Unfortunately the trade-off is that it increases
memory requirements for unlocking a keyslot.  This can create a situation where
the host system that builds an image has significant memore and the target
system that will use the image may be an embedded system with minimal memory
and the target system will have insufficient memory to unlock the keyslot.

Use the already-available cryptsetup_set_minimal_pbkdf() function used in the
TPM2 code branch in the keyslot-exclusive code branch to minimize memory
necessary for keyslot unlocking.

Index: systemd.git/src/partition/repart.c
===================================================================
--- systemd.git.orig/src/partition/repart.c
+++ systemd.git/src/partition/repart.c
@@ -4044,6 +4044,10 @@ static int partition_encrypt(Context *co
                 return log_error_errno(r, "Failed to LUKS2 format future partition: %m");
 
         if (IN_SET(p->encrypt, ENCRYPT_KEY_FILE, ENCRYPT_KEY_FILE_TPM2)) {
+                r = cryptsetup_set_minimal_pbkdf(cd);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to set minimal PBKDF: %m");
+
                 r = sym_crypt_keyslot_add_by_volume_key(
                                 cd,
                                 CRYPT_ANY_SLOT,

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

There's likely a better way to do this.  I'll likely open a P.R. to
systemd in the future to address this.  I also have some changes for
mkosi.

Thanks for the hint about the "systemd-repart --key-file=" argument.


More information about the systemd-devel mailing list