Re: How to use serial console to enter GELI password to boot kernel on a GELI encrypted ZFS pool
Date: Sun, 21 Aug 2022 11:11:22 UTC
On Fri, Aug 19, 2022 at 09:07:25AM -0600, Warner Losh wrote: > On Fri, Aug 19, 2022 at 2:20 AM Guido van Rooij <[1]guido@gvr.org> > wrote: > > On Wed, Aug 17, 2022 at 09:19:42AM -0600, Warner Losh wrote: > >  On Wed, Aug 17, 2022 at 7:35 AM Guido van Rooij > <[1][2]guido@gvr.org> > >  wrote: > > > >   On 16 Aug 2022, at 19:09, Warner Losh > <[2][3]imp@bsdimp.com> wrote: > > > >  ï»¿ > >  On Tue, Aug 16, 2022 at 3:44 AM Guido van Rooij > <[3][4]guido@gvr.org> > >  wrote: > > > >   On Mon, Aug 15, 2022 at 02:20:32PM -0600, Warner Losh > wrote: > >   >ààOn Mon, Aug 15, 2022 at 8:23 AM Guido van Rooij > >   <[1][4][5]guido@gvr.org> > >   >ààwrote: > >   > > >   >àààCurrently I have a system with ZFS on GELI. I > use the > >   ability in > >   >àààthe EFI loader to enter the GELI password. > >   >àààIs it possible somehow to use a serial > console to enter > >   the > >   >àààpassword? > >   >àààMy system does have a COM1 port but it isn't > recognised at > >   the early > >   >àààbot stage. There I only see: > >   >àààÃàÃàConsoles: EFI console > >   >àààÃàÃàGELI Passphrase for disk0p4: > >   >ààà(Note: this is early in the boot process so > there is no > >   access to > >   >àààboot.config (or any other file in the ZFS > pool) as it > >   still on > >   >àààencrypted storage at that time). > >   > > >   >ààThe boot loader.efi will read > ESP:/efi/freebsd/loader.env for > >   >ààenvironment > >   >ààvariables. You can use that to set the COM1 port > since it > >   appears your > >   >ààEFI system doesn't do console redirection. > >   >ààIf you want it to only prompt COM1 for the > password, but > >   everything > >   >ààelse is > >   >ààon the efi console, that's a lot harder. > >   Hi Warner, > >   Thanks, but somehow I still cannot get it to work > properly. > >   Content of /efi/freebsd/loader.env: > >   boot_multicons="YES" > >   console="efi comconsole" > >   The boot prompt still only shows "Consoles: EFI console". > > > >  Yes. That's printed before we process the ESP file and switch > to the > >  new console... > >  à > > > >   When I boot I get the GELI passphrase prompt at the EFI > console > >   only. But when the kernel starts > >   to run I do get output to the serial console, staring > with: > >   ---<<BOOT>>--- > >   Copyright (c) 1992-2021 The FreeBSD Project. > >   So it seems the loader.env file is read correctly (it > didn't output > >   anything to the serial > >   console before I created efi/freebsd/loader.env). But > looking at the > >   source I see in > >   efi/loader/main.c:read_loader_env(): > >   Ã Ã Ã Ã if (fn) { > >   Ã Ã Ã Ã Ã Ã Ã Ã printf("ààReading > loader env vars from > >   %s\n", fn); > >   Ã Ã Ã Ã Ã Ã Ã à > >   parse_loader_efi_config(boot_img->DeviceHandle, fn); > >   Ã Ã Ã Ã } > >   I never saw the printf appearing. I do not understand > this. > > > >  It should have appeared on the video console of the EFI > console > >  (assuming no serial > >  redirect is going on in that BIOS). > > > >  It surely did not. > > > >  I'd have to delve more deeply into the prompts for the GELI > password > >  than I have > >  time to do this morning. What if you type the password blind > into the > >  serial port? > > > >  Tried that but nothing happened. When I > >  enter the passphrase after typing it in via > >  the serial port, it worked immediately so > >  we can conclude that no single keystrokeà > >  got through. > > > >  OK. I'll have to delve a little more deeply then... > I Think I know why it does not work. The "Consoles:" line is printed > in cons_probe() > which is called in main(): >     setenv("console", "efi", 1); >     cons_probe(); > So that explains why we see Consoles: EFI console > Then we see in main(): >     for (i = 0; devsw[i] != NULL; i++) >         if (devsw[i]->dv_init != NULL) >             (devsw[i]->dv_init)(); > The way I understand it, is this the place where the GELI passphrase > prompt originates > from. > > Well, not quite. We prompt for the GELI password when we first open a > device in devopen > (at least that's where we call geli_probe_and_attach())[*]. This should > be a bit later, though. > I'll have to put some debug prints in to see when it's called... But it > looks like we probe for > geli, according to the debug, at this point, so something needs to be > done to sort out this > chicken and egg problem. >  > > But only after that, we see the call to load /efi/freebsd/loader.env > Shouldn't the dv_init() calls be moved to after the call to > boot_howto_to_env(howto)? > > You have discovered a wonderful chicken and egg. If we don't call > dv_init we can't do I/O > to the devices, so we can't change the console. > But, the boot_hwoto_to_env() call only sets env variables that will be > used to either set > boot args to the kernel or other env variables that are used to > communicate the console. > It doesn't actually change the console, so is the wrong thing to > locate. > The likely best way to approach this is to fix loader.efi to initialize > enough of the devices > so that we can read files off the ESP early enough to set a good > console for further > interaction. > Warner > [*] this leads to a bit of a layering violation that causes a circular > dependency, but I digress... > Hi Warner, We know for sure that the filesystem the EFI loader is read from is not encrypted and thus we should be able to read the /efi/freebsd/loader.env. So how about doing the dv_init() loop twice: The first time without trying to unlock encrypted geom's. We can then safely read /efi/freebsd/loader.env. The second dv_init() loop, we only trying to unlock the encrypted ones. -Guido