Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 19 Aug 2022 09:07:25 -0600
From:      Warner Losh <imp@bsdimp.com>
To:        Guido van Rooij <guido@gvr.org>
Cc:        FreeBSD Hackers <freebsd-hackers@freebsd.org>
Subject:   Re: How to use serial console to enter GELI password to boot kernel on a GELI encrypted ZFS pool
Message-ID:  <CANCZdfqnDfSQvQi3Zkp4B411%2BTip1GDuGtH9iwHvs9BB_BiptQ@mail.gmail.com>
In-Reply-To: <Yv9Hxa6e%2BquafbQT@gvr.gvr.org>
References:  <CANCZdfoMjg2GmUjZAeQ_phZnn4tKSKEOcPq6-h==s==idzmjBg@mail.gmail.com> <1BFD8C02-370F-4E59-BC89-EEF970B44934@gvr.org> <CANCZdfrS%2BCmWAUF4EukrJ2qOH%2B0mCZjjq_3b=8t=oSwv_UcgUg@mail.gmail.com> <Yv9Hxa6e%2BquafbQT@gvr.gvr.org>

next in thread | previous in thread | raw e-mail | index | archive | help
--0000000000005b6f6205e699756c
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Fri, Aug 19, 2022 at 2:20 AM Guido van Rooij <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]guido@gvr.org>
> >    wrote:
> >
> >      On 16 Aug 2022, at 19:09, Warner Losh <[2]imp@bsdimp.com> wrote:
> >
> >    =C3=AF=C2=BB=C2=BF
> >    On Tue, Aug 16, 2022 at 3:44 AM Guido van Rooij <[3]guido@gvr.org>
> >    wrote:
> >
> >      On Mon, Aug 15, 2022 at 02:20:32PM -0600, Warner Losh wrote:
> >      >=C3=82  =C3=82  On Mon, Aug 15, 2022 at 8:23 AM Guido van Rooij
> >      <[1][4]guido@gvr.org>
> >      >=C3=82  =C3=82  wrote:
> >      >
> >      >=C3=82  =C3=82  =C3=82  Currently I have a system with ZFS on GEL=
I. I use the
> >      ability in
> >      >=C3=82  =C3=82  =C3=82  the EFI loader to enter the GELI password=
.
> >      >=C3=82  =C3=82  =C3=82  Is it possible somehow to use a serial co=
nsole to enter
> >      the
> >      >=C3=82  =C3=82  =C3=82  password?
> >      >=C3=82  =C3=82  =C3=82  My system does have a COM1 port but it is=
n't recognised at
> >      the early
> >      >=C3=82  =C3=82  =C3=82  bot stage. There I only see:
> >      >=C3=82  =C3=82  =C3=82  =C3=83=C3=82  =C3=83=C3=82  Consoles: EFI=
 console
> >      >=C3=82  =C3=82  =C3=82  =C3=83=C3=82  =C3=83=C3=82  GELI Passphra=
se for disk0p4:
> >      >=C3=82  =C3=82  =C3=82  (Note: this is early in the boot process =
so there is no
> >      access to
> >      >=C3=82  =C3=82  =C3=82  boot.config (or any other file in the ZFS=
 pool) as it
> >      still on
> >      >=C3=82  =C3=82  =C3=82  encrypted storage at that time).
> >      >
> >      >=C3=82  =C3=82  The boot loader.efi will read ESP:/efi/freebsd/lo=
ader.env for
> >      >=C3=82  =C3=82  environment
> >      >=C3=82  =C3=82  variables. You can use that to set the COM1 port =
since it
> >      appears your
> >      >=C3=82  =C3=82  EFI system doesn't do console redirection.
> >      >=C3=82  =C3=82  If you want it to only prompt COM1 for the passwo=
rd, but
> >      everything
> >      >=C3=82  =C3=82  else is
> >      >=C3=82  =C3=82  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=3D"YES"
> >      console=3D"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...
> >    =C3=82
> >
> >      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 outpu=
t
> >      anything to the serial
> >      console before I created efi/freebsd/loader.env). But looking at t=
he
> >      source I see in
> >      efi/loader/main.c:read_loader_env():
> >      =C3=82  =C3=82  =C3=82  =C3=82  if (fn) {
> >      =C3=82  =C3=82  =C3=82  =C3=82  =C3=82  =C3=82  =C3=82  =C3=82  pr=
intf("=C3=82  =C3=82  Reading loader env vars from
> >      %s\n", fn);
> >      =C3=82  =C3=82  =C3=82  =C3=82  =C3=82  =C3=82  =C3=82  =C3=82
> >      parse_loader_efi_config(boot_img->DeviceHandle, fn);
> >      =C3=82  =C3=82  =C3=82  =C3=82  }
> >      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 th=
e
> >    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=C3=82
> >    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 =3D 0; devsw[i] !=3D NULL; i++)
>                 if (devsw[i]->dv_init !=3D 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...

--0000000000005b6f6205e699756c
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div dir=3D"ltr"><br></div><br><div class=3D"gmail_quote">=
<div dir=3D"ltr" class=3D"gmail_attr">On Fri, Aug 19, 2022 at 2:20 AM Guido=
 van Rooij &lt;<a href=3D"mailto:guido@gvr.org">guido@gvr.org</a>&gt; wrote=
:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.=
8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Wed, Aug 17=
, 2022 at 09:19:42AM -0600, Warner Losh wrote:<br>
&gt;=C2=A0 =C2=A0 On Wed, Aug 17, 2022 at 7:35 AM Guido van Rooij &lt;[1]<a=
 href=3D"mailto:guido@gvr.org" target=3D"_blank">guido@gvr.org</a>&gt;<br>
&gt;=C2=A0 =C2=A0 wrote:<br>
&gt; <br>
&gt;=C2=A0 =C2=A0 =C2=A0 On 16 Aug 2022, at 19:09, Warner Losh &lt;[2]<a hr=
ef=3D"mailto:imp@bsdimp.com" target=3D"_blank">imp@bsdimp.com</a>&gt; wrote=
:<br>
&gt; <br>
&gt;=C2=A0 =C2=A0 =C3=AF=C2=BB=C2=BF<br>
&gt;=C2=A0 =C2=A0 On Tue, Aug 16, 2022 at 3:44 AM Guido van Rooij &lt;[3]<a=
 href=3D"mailto:guido@gvr.org" target=3D"_blank">guido@gvr.org</a>&gt;<br>
&gt;=C2=A0 =C2=A0 wrote:<br>
&gt; <br>
&gt;=C2=A0 =C2=A0 =C2=A0 On Mon, Aug 15, 2022 at 02:20:32PM -0600, Warner L=
osh wrote:<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 On Mon, Aug 15, 2022=
 at 8:23 AM Guido van Rooij<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &lt;[1][4]<a href=3D"mailto:guido@gvr.org" target=
=3D"_blank">guido@gvr.org</a>&gt;<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 wrote:<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 Current=
ly I have a system with ZFS on GELI. I use the<br>
&gt;=C2=A0 =C2=A0 =C2=A0 ability in<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 the EFI=
 loader to enter the GELI password.<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 Is it p=
ossible somehow to use a serial console to enter<br>
&gt;=C2=A0 =C2=A0 =C2=A0 the<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 passwor=
d?<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 My syst=
em does have a COM1 port but it isn&#39;t recognised at<br>
&gt;=C2=A0 =C2=A0 =C2=A0 the early<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 bot sta=
ge. There I only see:<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 =C3=83=
=C3=82=C2=A0 =C3=83=C3=82=C2=A0 Consoles: EFI console<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 =C3=83=
=C3=82=C2=A0 =C3=83=C3=82=C2=A0 GELI Passphrase for disk0p4:<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 (Note: =
this is early in the boot process so there is no<br>
&gt;=C2=A0 =C2=A0 =C2=A0 access to<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 boot.co=
nfig (or any other file in the ZFS pool) as it<br>
&gt;=C2=A0 =C2=A0 =C2=A0 still on<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 encrypt=
ed storage at that time).<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 The boot loader.efi =
will read ESP:/efi/freebsd/loader.env for<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 environment<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 variables. You can u=
se that to set the COM1 port since it<br>
&gt;=C2=A0 =C2=A0 =C2=A0 appears your<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 EFI system doesn&#39=
;t do console redirection.<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 If you want it to on=
ly prompt COM1 for the password, but<br>
&gt;=C2=A0 =C2=A0 =C2=A0 everything<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 else is<br>
&gt;=C2=A0 =C2=A0 =C2=A0 &gt;=C3=82=C2=A0 =C3=82=C2=A0 on the efi console, =
that&#39;s a lot harder.<br>
&gt;=C2=A0 =C2=A0 =C2=A0 Hi Warner,<br>
&gt;=C2=A0 =C2=A0 =C2=A0 Thanks, but somehow I still cannot get it to work =
properly.<br>
&gt;=C2=A0 =C2=A0 =C2=A0 Content of /efi/freebsd/loader.env:<br>
&gt;=C2=A0 =C2=A0 =C2=A0 boot_multicons=3D&quot;YES&quot;<br>
&gt;=C2=A0 =C2=A0 =C2=A0 console=3D&quot;efi comconsole&quot;<br>
&gt;=C2=A0 =C2=A0 =C2=A0 The boot prompt still only shows &quot;Consoles: E=
FI console&quot;.<br>
&gt; <br>
&gt;=C2=A0 =C2=A0 Yes. That&#39;s printed before we process the ESP file an=
d switch to the<br>
&gt;=C2=A0 =C2=A0 new console...<br>
&gt;=C2=A0 =C2=A0 =C3=82<br>
&gt; <br>
&gt;=C2=A0 =C2=A0 =C2=A0 When I boot I get the GELI passphrase prompt at th=
e EFI console<br>
&gt;=C2=A0 =C2=A0 =C2=A0 only. But when the kernel starts<br>
&gt;=C2=A0 =C2=A0 =C2=A0 to run I do get output to the serial console, star=
ing with:<br>
&gt;=C2=A0 =C2=A0 =C2=A0 ---&lt;&lt;BOOT&gt;&gt;---<br>
&gt;=C2=A0 =C2=A0 =C2=A0 Copyright (c) 1992-2021 The FreeBSD Project.<br>
&gt;=C2=A0 =C2=A0 =C2=A0 So it seems the loader.env file is read correctly =
(it didn&#39;t output<br>
&gt;=C2=A0 =C2=A0 =C2=A0 anything to the serial<br>
&gt;=C2=A0 =C2=A0 =C2=A0 console before I created efi/freebsd/loader.env). =
But looking at the<br>
&gt;=C2=A0 =C2=A0 =C2=A0 source I see in<br>
&gt;=C2=A0 =C2=A0 =C2=A0 efi/loader/main.c:read_loader_env():<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=
=A0 if (fn) {<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=
=A0 =C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 printf(&quot;=C3=82=
=C2=A0 =C3=82=C2=A0 Reading loader env vars from<br>
&gt;=C2=A0 =C2=A0 =C2=A0 %s\n&quot;, fn);<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=
=A0 =C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 =C3=82<br>
&gt;=C2=A0 =C2=A0 =C2=A0 parse_loader_efi_config(boot_img-&gt;DeviceHandle,=
 fn);<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=A0 =C3=82=C2=
=A0 }<br>
&gt;=C2=A0 =C2=A0 =C2=A0 I never saw the printf appearing. I do not underst=
and this.<br>
&gt; <br>
&gt;=C2=A0 =C2=A0 It should have appeared on the video console of the EFI c=
onsole<br>
&gt;=C2=A0 =C2=A0 (assuming no serial<br>
&gt;=C2=A0 =C2=A0 redirect is going on in that BIOS).<br>
&gt; <br>
&gt;=C2=A0 =C2=A0 It surely did not.<br>
&gt; <br>
&gt;=C2=A0 =C2=A0 I&#39;d have to delve more deeply into the prompts for th=
e GELI password<br>
&gt;=C2=A0 =C2=A0 than I have<br>
&gt;=C2=A0 =C2=A0 time to do this morning. What if you type the password bl=
ind into the<br>
&gt;=C2=A0 =C2=A0 serial port?<br>
&gt; <br>
&gt;=C2=A0 =C2=A0 Tried that but nothing happened. When I<br>
&gt;=C2=A0 =C2=A0 enter the passphrase after typing it in via<br>
&gt;=C2=A0 =C2=A0 the serial port, it worked immediately so<br>
&gt;=C2=A0 =C2=A0 we can conclude that no single keystroke=C3=82<br>
&gt;=C2=A0 =C2=A0 got through.<br>
&gt; <br>
&gt;=C2=A0 =C2=A0 OK. I&#39;ll have to delve a little more deeply then...<b=
r>
<br>
I Think I know why it does not work. The &quot;Consoles:&quot; line is prin=
ted in cons_probe()<br>
which is called in main():<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 setenv(&quot;console&quot;, &quot;efi&quot;, 1)=
;<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 cons_probe();<br>
So that explains why we see Consoles: EFI console<br>
Then we see in main():<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 for (i =3D 0; devsw[i] !=3D NULL; i++)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (devsw[i]-&gt;dv=
_init !=3D NULL)<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 (devsw[i]-&gt;dv_init)();<br>
The way I understand it, is this the place where the GELI passphrase prompt=
 originates<br>
from.<br></blockquote><div><br></div><div>Well, not quite. We prompt for th=
e GELI password when we first open a device in devopen</div><div>(at least =
that&#39;s where we call geli_probe_and_attach())[*]. This should be a bit =
later, though.</div><div>I&#39;ll have to put some debug prints in to see w=
hen it&#39;s called... But it looks like we probe for</div><div>geli, accor=
ding to the debug, at this point, so something needs to be done to sort out=
 this</div><div>chicken and egg problem.</div><div>=C2=A0</div><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px sol=
id rgb(204,204,204);padding-left:1ex">
But only after that, we see the call to load /efi/freebsd/loader.env<br>
<br>
Shouldn&#39;t the dv_init() calls be moved to after the call to boot_howto_=
to_env(howto)?<br></blockquote><div><br></div><div>You have discovered a wo=
nderful chicken and egg. If we don&#39;t call dv_init we can&#39;t do I/O</=
div><div>to the devices, so we can&#39;t change the console.</div><div><br>=
</div><div>But, the boot_hwoto_to_env() call only sets env variables that w=
ill be used to either set</div><div>boot args to the kernel or other env va=
riables that are used to communicate the console.</div><div>It doesn&#39;t =
actually change the console, so is the wrong thing to locate.</div><div><br=
></div><div>The likely best way to approach this is to fix loader.efi to in=
itialize enough of the devices</div><div>so that we can read files off the =
ESP early enough to set a good console for further</div><div>interaction.</=
div><div><br></div><div>Warner</div><div><br></div><div>[*] this leads to a=
 bit of a layering violation that causes a circular dependency, but I digre=
ss...<br></div></div></div>

--0000000000005b6f6205e699756c--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CANCZdfqnDfSQvQi3Zkp4B411%2BTip1GDuGtH9iwHvs9BB_BiptQ>