Re: [RFC PATCH v2 1/1] kern/dl: Add module version check

2022-12-23 Thread Zhang Boyang

Hi,

On 2022/12/22 14:31, Glenn Washburn wrote:

On Wed, 21 Dec 2022 20:11:57 +0800
Zhang Boyang  wrote:

+  grub_printf_ (N_("warning: module %.63s has incorrect version:
%.63s != %s\n"),
+   mod->name, modver, PACKAGE_VERSION);


I don't quite like this, but I could live with it. I mostly don't like
it because I don't want to get spammed with a lot of these warning
messages. But maybe this is the best of the bad set of options.



I sent a V3 patch at 
https://lists.gnu.org/archive/html/grub-devel/2022-12/msg00280.html , in 
which can disable this warning at build time, however I personally don't 
like it.


I think preloading modules is a good solution for you. e.g. run `insmod 
foobar` before switching $root/$prefix. This also eliminate the 
possibility of GRUB crashing because of mismatched modules. For a 
comprehensive list of modules, please see $GRUB_MODULES in 
https://salsa.debian.org/grub-team/grub/-/blob/master/debian/build-efi-images


If you think this solution is good to you, I want to drop V3 and submit 
a improved V2 as V4, because it's cleaner.



One thing to note is I believe that this will take GRUB out
of graphical mode and put it into text mode. This doesn't affect me
(right now) though.



I tested on i386-pc and x86_64-efi and there is no such behavior.


Another thing is that, for the use case of loading a grub.cfg from a
different GRUB installation, this message from version mismatched
modules loaded in the sourcing of the script will be displayed for a
fraction of a second until the menu from the sourced grub.cfg is
displayed. So it may not be helpful for the user.



What about adding a 100ms sleep when the warning is displayed? By the 
way, this can also be workaround by preloading modules.



This isn't likely an issue for loopback.cfg because usually the module
loading is done implicitly and all the commands are generally inside
the menu entries. In this case, printing to the screen seems like a
good idea because directly after the module loading the commands will
run, which might crash GRUB. So if the crash hangs the machine the user
will see this message and have a clue.



Best Regards,
Zhang Boyang


Glenn



___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [RFC PATCH v3 0/1] kern/dl: Add module version check

2022-12-23 Thread Pete Batard via Grub-devel

On 2022.12.23 07:18, Zhang Boyang wrote:
This feature is implemented in kern/dl.c in core.img, which is UNDER 
YOUR CONTROL.


Let me analyze the worst case from your perspective:

1) Every distro is enforcing version check, even in BIOS mode.

2) Because this check is in kern/dl.c, there is no such code in any 
module (.mod) files. However, this modules are little fatter because 
they have version information (.modver section), which is harmless.


3) You can still build your own copy of core.img with this check 
disabled (or just revert this patch completely), then ship that core.img 
with Rufus.


4) Since there is no check in your core.img, it will load any module 
happily, regardless whether it has mismatched version information.


Therefore, there is no problem at all. The only thing you need to do is 
build your core.img with this patch reverted in the future. Then things 
will "work" as usual.


I need to properly test this, but I think that should work, yes.

I should have looked a bit more closely at your proposal, because I 
agree that it should address my concerns, though I do have a small worry 
about the possibility of transitive checks in the future (i.e. modules 
that perform their own loading of submodules for whatever reason, with a 
version check being introduced there).


I'm not planning to try to hold your patch on that, but I sure hope that 
transitive version checks never become a thing.

Let me analyze why I want to add version check to BIOS mode:

1) Because you can always remove this patch from your build for Rufus, 
there is no harm in having this patch in vanilla GRUB.


As long as the version check remains localised inside core.img, yes.

2) This patch can provide benefits to BIOS users, because it can 
diagnose improper installations. For example, user runs `grub-install 
/dev/sdb` to update GRUB but machine boot from `/dev/sda`.


So there are benefits without any harm, why not have it in BIOS mode?

By the way, I highly recommend you to test latest git GRUB (as a preview 
of upcoming 2.12 release) with Rufus and it will almost certainly break 
your existing Rufus build. e.g. use Rufus (with GRUB2.06) to process 
ISOs (with GRUB2.12); and the reverse, use Rufus (with GRUB2.12) to 
process ISOs (with GRUB2.06). You probably need to ship another bunch of 
core.img with Rufus.


That's already been the case for previous releases, e.g. trying to use 
core.img from 2.0(x) with 2.0(x-1) is usually asking for trouble, and I 
do have a mechanism in place to address just that, where users don't 
even need to update Rufus as we can always download a new 'core.img' 
server from our repository. This is also the mechanism that helps us 
address the rare case where distro maintainers have applied breaking 
pacthes onto a dot release that affect core.img.


So, once distros start using GRUB 2.12 (because I need to be able to 
validate the core.img I build against an actual image), I'll have a 
core.img for GRUB 2.12 that users can automatically use in Rufus.


As I pointed out before, the main issue is that even when using the same 
base version, and because GRUB releases are far and in-between, distro 
maintainers cherry pick patches to apply on top of the dot release, and 
(usually, which is the proper thing to do) suffix their version id, 
which of course, would make a version check fail.


But we're still working with the same dot release base in Rufus always, 
which is why the core.img replacement (barring a few exceptions) always 
works.


Also, I'd also like to advice you to create a patchset/proposal, which 
make it easy to convert the bootcode in ISO to the bootcode in USB.


I considered it a long time ago, but the main issue is that it would 
only help with future GRUB based images, and not the many many current 
ones I needed to support.


Thus, all it would accomplish then, is force me to have two different 
methods of solving a problem, where one can most certainly do, and hope 
that, in 10 years time (at best, because you bet some people will still 
want to use 10-years old ISOs then, especially if they are booting old 
BIOS-based computers) I *might* be able to remove one of them.


I hope you can appreciate how this approach makes very little sense then 
when one method can accomplish all we need.


Plus, trying to reuse the files from El-Torito would be a major 
challenge, as, even if we were to somehow force include part_msdos, 
biosdisk, fat and ntfs always (which are completely unneeded for optical 
boot) and recover them, we'd still need to alter the prefix directory, 
and that resides in a part that is usually compressed.


So, the only viable alternative, would be to force optical media 
creators to generate a core.img that can work for USB boot (which means 
silent invocation of grub-mkimage behind the scenes), and have that 
somehow find its way on the resulting ISO media.


All in all, these are fairly heavy alterations to the GRUB optical boot 
generation proce

Re: [RFC PATCH v3 0/1] kern/dl: Add module version check

2022-12-23 Thread Zhang Boyang

Hi,

On 2022/12/23 21:07, Pete Batard wrote:

On 2022.12.23 07:18, Zhang Boyang wrote:
This feature is implemented in kern/dl.c in core.img, which is UNDER 
YOUR CONTROL.


Let me analyze the worst case from your perspective:

1) Every distro is enforcing version check, even in BIOS mode.

2) Because this check is in kern/dl.c, there is no such code in any 
module (.mod) files. However, this modules are little fatter because 
they have version information (.modver section), which is harmless.


3) You can still build your own copy of core.img with this check 
disabled (or just revert this patch completely), then ship that 
core.img with Rufus.


4) Since there is no check in your core.img, it will load any module 
happily, regardless whether it has mismatched version information.


Therefore, there is no problem at all. The only thing you need to do 
is build your core.img with this patch reverted in the future. Then 
things will "work" as usual.


I need to properly test this, but I think that should work, yes.



I think the result will be OK. If so, it's good news for both of us.

I should have looked a bit more closely at your proposal, because I 
agree that it should address my concerns, though I do have a small worry 
about the possibility of transitive checks in the future (i.e. modules 
that perform their own loading of submodules for whatever reason, with a 
version check being introduced there).


I'm not planning to try to hold your patch on that, but I sure hope that 
transitive version checks never become a thing.


By the way, I'm planning to drop V3 and reuse V2 as the base of V4 (if 
Glenn's concerns is solved). So there will be no "enforce" for BIOS at 
all in V4, thus the "small worry" is eliminated. However, I will 
probably add sleep(100ms) to warning message. But don't worry, you can 
patch your own build like this


-  || grub_dl_check_version (mod, e)
+  || (1||grub_dl_check_version (mod, e))

to completely disable the check.


Let me analyze why I want to add version check to BIOS mode:

1) Because you can always remove this patch from your build for Rufus, 
there is no harm in having this patch in vanilla GRUB.


As long as the version check remains localised inside core.img, yes.

2) This patch can provide benefits to BIOS users, because it can 
diagnose improper installations. For example, user runs `grub-install 
/dev/sdb` to update GRUB but machine boot from `/dev/sda`.


So there are benefits without any harm, why not have it in BIOS mode?

By the way, I highly recommend you to test latest git GRUB (as a 
preview of upcoming 2.12 release) with Rufus and it will almost 
certainly break your existing Rufus build. e.g. use Rufus (with 
GRUB2.06) to process ISOs (with GRUB2.12); and the reverse, use Rufus 
(with GRUB2.12) to process ISOs (with GRUB2.06). You probably need to 
ship another bunch of core.img with Rufus.




OK, That's great news.

That's already been the case for previous releases, e.g. trying to use 
core.img from 2.0(x) with 2.0(x-1) is usually asking for trouble, and I 
do have a mechanism in place to address just that, where users don't 
even need to update Rufus as we can always download a new 'core.img' 
server from our repository. This is also the mechanism that helps us 
address the rare case where distro maintainers have applied breaking 
pacthes onto a dot release that affect core.img.


So, once distros start using GRUB 2.12 (because I need to be able to 
validate the core.img I build against an actual image), I'll have a 
core.img for GRUB 2.12 that users can automatically use in Rufus.


As I pointed out before, the main issue is that even when using the same 
base version, and because GRUB releases are far and in-between, distro 
maintainers cherry pick patches to apply on top of the dot release, and 
(usually, which is the proper thing to do) suffix their version id, 
which of course, would make a version check fail.


But we're still working with the same dot release base in Rufus always, 
which is why the core.img replacement (barring a few exceptions) always 
works.




FYI, Ubuntu, Debian, and some other distros are likely to update their 
GRUB version (dot release) during life cycle, mostly because of secure 
boot related fixes. For example, 
https://tracker.debian.org/news/1352218/accepted-grub2-206-3deb10u1-source-into-oldstable-proposed-updates-oldstable-new-oldstable-proposed-updates/


Personally speaking, I guess the number of exceptions might be 
underestimated. Because most ISOs were using ISOLINUX instead of GRUB2 
in the past, and there seems a trend of replacing ISOLINUX with GRUB2. 
For example, Ubuntu 20.04 uses ISOLINUX and Ubuntu 20.10 uses GRUB2, so 
there is only 2 years of experience of using mismatched GRUB2 for 
Ubuntu. So I guess problem might arise when more and more distros switch 
to GRUB2. However, this is only a guess, and we both hope it's not true.


Also, I'd also like to advice you to create a patchset/propo

Re: [RFC PATCH v3 0/1] kern/dl: Add module version check

2022-12-23 Thread Zhang Boyang

On 2022/12/24 00:44, Zhang Boyang wrote:

-  || grub_dl_check_version (mod, e)
+  || (1||grub_dl_check_version (mod, e))


Oh, there is a small error, it should be:

-  || grub_dl_check_version (mod, e)
+  || (0 && grub_dl_check_version (mod, e))

Best Regards,
Zhang Boyang

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH v4 08/15] gdb: If enabled, print line used to load EFI kernel symbols when using gdb_grub script

2022-12-23 Thread Glenn Washburn
On Thu, 22 Dec 2022 19:17:31 +0100
Daniel Kiper  wrote:

> On Wed, Dec 21, 2022 at 11:57:33AM -0600, Glenn Washburn wrote:
> > On Wed, 21 Dec 2022 16:20:17 +0100
> > Daniel Kiper  wrote:
> >
> > > Adding Robbie...
> > >
> > > Please CC him next time when you post these patches. I would want
> > > to hear his opinion too. Or at least he is aware what is happening
> > > here...
> >
> > Sure, I CC'd him and Peter on the first couple of ones. But there
> > was
> 
> Thank you!
> 
> > never had a response in the 4 months since then, so I figured they
> > didn't care.
> 
> Until somebody ask you to not include themselves in the thread please
> CC them. AFAICT many people read emails often, like me, but jump into
> discussion when something really important for them is happening.
> 
> > > On Thu, Dec 15, 2022 at 11:29:31PM -0600, Glenn Washburn wrote:
> > > > If the macro PRINT_GDB_SYM_LOAD_CMD is non-zero, compile code
> > > > which
> 
> Why is this not a flag, like e.g. --enable-mm-debug, for the
> configure?

I had thought about it, and honestly, I was hoping someone would have a
better idea on the user interface. It feels clunky to me, so I wasn't
really wanting to advertise it. I think I'll add it in the next version.

> 
> > > > will print the command needed to load symbols for the GRUB EFI
> > > > kernel. This is needed because EFI firmware determines where to
> > > > load the GRUB EFI at runtime, and so the relevant addresses are
> > > > not known ahead of time.
> > > >
> > > > The command is a custom command defined in the gdb_grub GDB
> > > > script. So GDB should be started with the script as an argument
> > > > to the -x option or sourced into an active GDB session before
> > > > running the outputted command.
> > >
> > > I think this functionality should be disabled when lockdown is
> > > enforced, e.g. on UEFI platforms with Secure Boot enabled.
> >
> > Since this is off by default and must be enabled at build time,
> > then if the builder enabled it, they really did want it, regardless
> > of lockdown. What you're worried about seems highly improbable to
> > me (but then I don't know the inner workings of the distros). The
> > concern as I understand it, is that someone doing an official
> > release of a distro which will be secure boot ready will
> > accidentally have this build time macro enabled. That's almost
> > inconceivable to me, but I'm curious what the others have to say
> > (especially since Robbie posted a similar patch that always printed
> > this info as a debug message[1]). Or is it more about a regular
> > user signing with their own keys accidentally shooting themselves
> > in the foot by forgetting to disable this (after having already
> > enabled it) and then some physical attacker getting extra info to
> > do an evil maid attack?
> 
> I can imagine that a distro builds and signs GRUB with debug embedded
> and then somebody in the wild wants to enable this feature to debug a
> problem. Of course them cannot rebuild the GRUB image because it is
> signed. However, them can disable UEFI Secure Boot and enable
> debugging. Of course this probably will not work in all cases but
> should help solve most problems.

As I understand it then, the main downside is that debugging in lockdown
mode doesn't get any easier to debug. I guess I don't see that
affecting me terribly, so I'm not opposed to it.

Thinking about this more, I think I should add a command called
"gdbinfo" which also prints out this info on-demand by the user. I'll
have it disabled in lockdown mode too. I think this will make it nicer
for someone debugging issues with GRUB on real hardware and where the
issue is not in early boot. As it is now, I think the output would too
quickly disappear from the physical screen for it to be useful.

Glenn

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH v8 1/1] plainmount: Support plain encryption mode

2022-12-23 Thread Glenn Washburn
On Fri, 02 Dec 2022 17:11:23 +
Maxim Fomin  wrote:

> --- Original Message ---
> On Friday, December 2nd, 2022 at 0:00, Glenn Washburn
>  wrote:
> > I'm now compiling this patch and found a few compile issues below.
> > You're compile testing this right?
> 
> First versions of the patch were tested in pure grub src directory.
> Later I switched to directly making and installing GRUB package for
> my distro using its source script syntax. It seems this process was
> affected by environment options which hided these errors/warnings.
> 
> I test the patch on my two old laptops - one with UEFI BIOS
> (x86_64-efi) and one is pre-UEFI (i386-pc). I was compiling i386-pc
> target too, because otherwise the second laptop was unbootable.
> During i386-pc compilation I noticed some warnings related to
> 'PRIuGRUB_XXX' macros which were absent during efi target
> compilation. I noticed that there are similar warnings in other
> modules and decided that there are issues with 'PRIuGRUB_XXX' macros
> at i386-pc platform at global level. In any case, these issues didn't
> cause compilation fail in my working environment because I would not
> be able to compile and boot pre-UEFI lap. Do you use -Werror? 

I didn't see this until just now. In case you're still interested, no I
don't use -Werror or any special compiler flags. And I'm using gcc
version 10.2.1 from a Debian 11 container.

Glenn

> 
> P.S. Also thanks for suggested fixes.
> 
> Best regards,
> Maxim Fomin
> 
> > > diff --git a/docs/grub.texi b/docs/grub.texi
> > > index 377969984..34ca6b4f1 100644
> > > --- a/docs/grub.texi
> > > +++ b/docs/grub.texi
> > > @@ -5138,13 +5138,13 @@ to generate password hashes.
> > > @xref{Security}.
> > > 
> > > Setup access to the encrypted device in plain mode. Offset of the
> > > encrypted -data at the device is specified in terms of 512 byte
> > > sectors with the blocklist +data at the device is specified in
> > > terms of 512 byte sectors using the blocklist syntax and loopback
> > > device. The following example shows how to specify 1MiB offset:
> > > 
> > > @example
> > > loopback node (hd0,gpt1)2048+
> > > -plainmount node
> > > +plainmount node @var{...}
> > > @end example
> > > 
> > > The @command{plainmount} command can be used to open LUKS
> > > encrypted volume @@ -5155,13 +5155,14 @@ The keyfile path
> > > parameter has higher priority than the secret passphrase
> > > parameter and is specified with the option @option{-d}. Password
> > > data obtained from keyfiles is not hashed and is used directly as
> > > a cipher key. An optional offset of password data in the keyfile
> > > can be specified with the option -@option{-O} or directly with
> > > the option @option{-d} and GRUB blocklist syntax. +@option{-O} or
> > > directly with the option @option{-d} and GRUB blocklist syntax,
> > > +if the keyfile data can be accessed from a device and is 512
> > > byte aligned. The following example shows both methods to specify
> > > password data in the keyfile at offset 1MiB:
> > > 
> > > @example
> > > -plainmount -d (hd0,gpt1)2048+
> > > -plainmount -d (hd0,gpt1)+ -O 1048576
> > > +plainmount -d (hd0,gpt1)2048+ @var{...}
> > > +plainmount -d (hd0,gpt1)+ -O 1048576 @var{...}
> > > @end example
> > > 
> > > If no keyfile is specified then the password is set to the string
> > > specified diff --git a/grub-core/disk/plainmount.c
> > > b/grub-core/disk/plainmount.c index 656c5d09f..85ada25bc 100644
> > > --- a/grub-core/disk/plainmount.c
> > > +++ b/grub-core/disk/plainmount.c
> > > @@ -146,8 +146,12 @@ plainmount_configure_password
> > > (grub_cryptodisk_t dev, const char *hash, dev->hash =
> > > grub_crypto_lookup_md_by_name (hash); len = dev->hash->mdlen;
> > > 
> > > - alloc_size = password_size >= key_size ? password_size :
> > > key_size;
> > > - p = grub_zalloc (alloc_size + (alloc_size / len));
> > > + alloc_size = grub_max (password_size, key_size);
> > > + /*
> > > + * Allocate buffer for the password and for an added prefix
> > > character
> > > + * for each hash round ('alloc_size' may not be a multiple of
> > > 'len').
> > > + */
> > > + p = grub_zalloc (alloc_size + (alloc_size / len) + 1);
> > > derived_hash = grub_zalloc (GRUB_CRYPTODISK_MAX_KEYLEN * 2);
> > > if (p == NULL || derived_hash == NULL)
> > > {
> > > @@ -170,9 +174,10 @@ plainmount_configure_password
> > > (grub_cryptodisk_t dev, const char *hash, if (len > size)
> > > len = size;
> > > 
> > > - grub_crypto_hash (dev->hash, dh, p, password_size);
> > > + grub_crypto_hash (dev->hash, dh, p, password_size + round);
> > > }
> > > - grub_memcpy (key_data, derived_hash, GRUB_CRYPTODISK_MAX_KEYLEN
> > > * 2);
> > > + grub_memcpy (key_data, derived_hash, key_size);
> > > +
> > > exit:
> > > grub_free (p);
> > > grub_free (derived_hash);
> > > ---
> > > docs/grub.texi | 81 +++
> > > grub-core/Makefile.core.def | 5 +
> > > grub-core/disk/plainmount.c | 462
> > >  3 files changed, 548
> > > insertions(+) crea

Re: [PATCH v8 1/1] plainmount: Support plain encryption mode

2022-12-23 Thread Glenn Washburn
On Fri, 23 Dec 2022 19:54:47 -0600
Glenn Washburn  wrote:

> On Fri, 02 Dec 2022 17:11:23 +
> Maxim Fomin  wrote:
> 
> > --- Original Message ---
> > On Friday, December 2nd, 2022 at 0:00, Glenn Washburn
> >  wrote:
> > > I'm now compiling this patch and found a few compile issues below.
> > > You're compile testing this right?
> > 
> > First versions of the patch were tested in pure grub src directory.
> > Later I switched to directly making and installing GRUB package for
> > my distro using its source script syntax. It seems this process was
> > affected by environment options which hided these errors/warnings.
> > 
> > I test the patch on my two old laptops - one with UEFI BIOS
> > (x86_64-efi) and one is pre-UEFI (i386-pc). I was compiling i386-pc
> > target too, because otherwise the second laptop was unbootable.
> > During i386-pc compilation I noticed some warnings related to
> > 'PRIuGRUB_XXX' macros which were absent during efi target
> > compilation. I noticed that there are similar warnings in other
> > modules and decided that there are issues with 'PRIuGRUB_XXX' macros
> > at i386-pc platform at global level. In any case, these issues
> > didn't cause compilation fail in my working environment because I
> > would not be able to compile and boot pre-UEFI lap. Do you use
> > -Werror? 
> 
> I didn't see this until just now. In case you're still interested, no
> I don't use -Werror or any special compiler flags. And I'm using gcc
> version 10.2.1 from a Debian 11 container.

Correction, -Werror is being used. Perhaps that's a default compiler
flag on Debian systems.

Glenn

> > P.S. Also thanks for suggested fixes.
> > 
> > Best regards,
> > Maxim Fomin
> > 
> > > > diff --git a/docs/grub.texi b/docs/grub.texi
> > > > index 377969984..34ca6b4f1 100644
> > > > --- a/docs/grub.texi
> > > > +++ b/docs/grub.texi
> > > > @@ -5138,13 +5138,13 @@ to generate password hashes.
> > > > @xref{Security}.
> > > > 
> > > > Setup access to the encrypted device in plain mode. Offset of
> > > > the encrypted -data at the device is specified in terms of 512
> > > > byte sectors with the blocklist +data at the device is
> > > > specified in terms of 512 byte sectors using the blocklist
> > > > syntax and loopback device. The following example shows how to
> > > > specify 1MiB offset:
> > > > 
> > > > @example
> > > > loopback node (hd0,gpt1)2048+
> > > > -plainmount node
> > > > +plainmount node @var{...}
> > > > @end example
> > > > 
> > > > The @command{plainmount} command can be used to open LUKS
> > > > encrypted volume @@ -5155,13 +5155,14 @@ The keyfile path
> > > > parameter has higher priority than the secret passphrase
> > > > parameter and is specified with the option @option{-d}. Password
> > > > data obtained from keyfiles is not hashed and is used directly
> > > > as a cipher key. An optional offset of password data in the
> > > > keyfile can be specified with the option -@option{-O} or
> > > > directly with the option @option{-d} and GRUB blocklist syntax.
> > > > +@option{-O} or directly with the option @option{-d} and GRUB
> > > > blocklist syntax, +if the keyfile data can be accessed from a
> > > > device and is 512 byte aligned. The following example shows
> > > > both methods to specify password data in the keyfile at offset
> > > > 1MiB:
> > > > 
> > > > @example
> > > > -plainmount -d (hd0,gpt1)2048+
> > > > -plainmount -d (hd0,gpt1)+ -O 1048576
> > > > +plainmount -d (hd0,gpt1)2048+ @var{...}
> > > > +plainmount -d (hd0,gpt1)+ -O 1048576 @var{...}
> > > > @end example
> > > > 
> > > > If no keyfile is specified then the password is set to the
> > > > string specified diff --git a/grub-core/disk/plainmount.c
> > > > b/grub-core/disk/plainmount.c index 656c5d09f..85ada25bc 100644
> > > > --- a/grub-core/disk/plainmount.c
> > > > +++ b/grub-core/disk/plainmount.c
> > > > @@ -146,8 +146,12 @@ plainmount_configure_password
> > > > (grub_cryptodisk_t dev, const char *hash, dev->hash =
> > > > grub_crypto_lookup_md_by_name (hash); len = dev->hash->mdlen;
> > > > 
> > > > - alloc_size = password_size >= key_size ? password_size :
> > > > key_size;
> > > > - p = grub_zalloc (alloc_size + (alloc_size / len));
> > > > + alloc_size = grub_max (password_size, key_size);
> > > > + /*
> > > > + * Allocate buffer for the password and for an added prefix
> > > > character
> > > > + * for each hash round ('alloc_size' may not be a multiple of
> > > > 'len').
> > > > + */
> > > > + p = grub_zalloc (alloc_size + (alloc_size / len) + 1);
> > > > derived_hash = grub_zalloc (GRUB_CRYPTODISK_MAX_KEYLEN * 2);
> > > > if (p == NULL || derived_hash == NULL)
> > > > {
> > > > @@ -170,9 +174,10 @@ plainmount_configure_password
> > > > (grub_cryptodisk_t dev, const char *hash, if (len > size)
> > > > len = size;
> > > > 
> > > > - grub_crypto_hash (dev->hash, dh, p, password_size);
> > > > + grub_crypto_hash (dev->hash, dh, p, password_size + round);
> > > > }
> > > > - grub_memcpy (key_data, derived_hash,
> > 

[PATCH v5 13/14] gdb: Modify gdb prompt when running gdb_grub script

2022-12-23 Thread Glenn Washburn
This will let users know that the GDB session is using the GRUB gdb scripts.

Signed-off-by: Glenn Washburn 
---
 grub-core/gdb_helper.py.in | 4 
 1 file changed, 4 insertions(+)

diff --git a/grub-core/gdb_helper.py.in b/grub-core/gdb_helper.py.in
index 8d5ee1d292..5ed9eab0f5 100644
--- a/grub-core/gdb_helper.py.in
+++ b/grub-core/gdb_helper.py.in
@@ -2,6 +2,10 @@ import os
 import re
 import subprocess
 
+def prompt_hook (current_prompt):
+  return "(grub gdb) "
+gdb.prompt_hook = prompt_hook
+
 # Convenience functions #
 
 class IsGrubLoaded (gdb.Function):
-- 
2.34.1


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v5 02/14] gdb: Prevent wrapping when writing to .segments.tmp

2022-12-23 Thread Glenn Washburn
GDB logging is redirected to write .segments.tmp, which means that GDB
will wrap lines longer than what it thinks is the screen width
(typically 80 characters). When wrapping does occur it causes gmodule.pl
to misbehave. So disable line wrapping by using GDB's "with" command so
that its guaranteed to return the width to the previous value upon
command completion.

Also disable command tracing when dumping the module sections because
that output will go to .segments.tmp and thus cause gmodule.pl to
misbehave.

Signed-off-by: Glenn Washburn 
---
 grub-core/gdb_grub.in | 4 
 1 file changed, 4 insertions(+)

diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index 4e45ad5622..edb5a8872c 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -22,6 +22,10 @@ define dump_module_sections_helper
 end
 
 define dump_module_sections
+   # Set unlimited width so that lines don't get wrapped writing
+   # to .segments.tmp
+   with width 0 -- \
+   with trace-commands off -- \
pipe dump_module_sections_helper $arg0 | sh -c 'cat >>.segments.tmp'
 end
 document dump_module_sections
-- 
2.34.1


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v5 10/14] gdb: Allow running user-defined commands at GRUB start

2022-12-23 Thread Glenn Washburn
A new command, run_on_start, for things to do when just before GRUB starts
executing. Currently, this is setting up the loading of module symbols as
they are loaded and allowing user-defined script to be run if a command
named "onstart" exists. A thbreak, temporary hardware breakpoint, is used
because a software breakpoint would be overwritten when the firmware loads
the GRUB image into memory. And it should be temporary in order to have as
many of the limited hardware breakpoints available to the user as possible.

Signed-off-by: Glenn Washburn 
---
 grub-core/gdb_grub.in | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index 18ce6b0eb2..281dfb5927 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -15,6 +15,8 @@ source gdb_helper.py
 define dynamic_load_symbols
dynamic_load_kernel_exec_symbols $arg0
 
+   run_on_start
+
# We may have been very late to loading the kernel.exec symbols and
# and modules may already be loaded. So load symbols for any already
# loaded.
@@ -54,6 +56,33 @@ document runtime_load_module
Load module symbols at runtime as they are loaded.
 end
 
+define run_on_start
+   # TODO: Add check to see if _start symbol is defined, if not, then
+   # the symbols have not yet been loaded and this command will not work.
+   thbreak _start
+   commands
+   silent
+
+   runtime_load_module
+
+   if $is_user_command("onstart")
+   onstart
+   end
+   continue
+   end
+end
+document run_on_start
+   On some targets, such as x86_64-efi, even if you know where the
+   firmware will load the GRUB image, you can not simply set a break
+   point before the image is loaded because loading the image
+   overwrites the break point in memory. So setup a hardware watch
+   point, which does not have that problem, and if that gets triggered,
+   then reset the break point. If a user-defined command named
+   "onstart" exists it will be run after the start is hit.
+   NOTE: This assumes symbols have already been correctly loaded for
+   the EFI application.
+end
+
 ###
 
 set confirm off
@@ -71,6 +100,7 @@ if ! $runonce
exec-file kernel.exec
else
file kernel.exec
+   run_on_start
runtime_load_module
end
 
-- 
2.34.1


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v5 06/14] gdb: Only connect to remote target once when first sourced

2022-12-23 Thread Glenn Washburn
The gdb_grub script was originally meant to be run once when GDB first
starts up via the -x argument. So it runs commands unconditionally
assuming that the script has not been run before. Its nice to be able
to source the script again when developing the script to modify/add
commands. So only run the commands not defined in user-defined commands,
if a variable $runonce has already been set and when those commands have
been run to set $runonce.

Signed-off-by: Glenn Washburn 
---
 grub-core/gdb_grub.in | 19 +++
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index 620d1def72..4ca939f69a 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -94,12 +94,15 @@ set confirm off
 
 set $platform_efi = $_streq("@platform@", "efi")
 
-if $platform_efi
-   # Only load the executable file, not the symbols
-   exec-file kernel.exec
-else
-   file kernel.exec
-   runtime_load_module
-end
+if ! $runonce
+   if $platform_efi
+   # Only load the executable file, not the symbols
+   exec-file kernel.exec
+   else
+   file kernel.exec
+   runtime_load_module
+   end
 
-target remote :1234
+   target remote :1234
+   set $runonce = 1
+end
-- 
2.34.1


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v5 04/14] gdb: Move runtime module loading into runtime_load_module

2022-12-23 Thread Glenn Washburn
By moving this code into a function, it can be run re-utilized while gdb is
running, not just when loading the script. This will also be useful in
some following changes which will make a separate script path for targets
which statically vs dynamically position GRUB code.

Signed-off-by: Glenn Washburn 
---
 grub-core/gdb_grub.in | 20 +---
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index fc17e3d899..d525a5a11f 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -71,16 +71,22 @@ document load_all_modules
Load debugging information for all loaded modules.
 end
 
+define runtime_load_module
+   break grub_dl_add
+   commands
+   silent
+   load_module mod
+   cont
+   end
+end
+document runtime_load_module
+   Load module symbols at runtime as they are loaded.
+end
+
 ###
 
 set confirm off
 file kernel.exec
 target remote :1234
 
-# inform when module is loaded
-break grub_dl_add
-commands
-   silent
-   load_module mod
-   cont
-end
+runtime_load_module
-- 
2.34.1


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v5 07/14] gdb: Replace module symbol loading implementation with Python one

2022-12-23 Thread Glenn Washburn
Remove gmodule.pl and rewrite as a python in gdb_helper.py. This removes
PERL dependency for the GRUB GDB script, but adds Python as a dependency.
This is more desirable because Python is tightly integrated with GDB and
can do things not even available to GDB native scripting language. GDB must
be built with Python, however this is not a major limitation because every
major distro non-end-of-life versions build GDB with Python support. And GDB
has had support for Python since around 7.1-ish, which is about a decade.

This re-implementation has an added feature. If there is a user defined
command named "onload_", then that command will be executed
after the symbols for the specified module are loaded. When debugging a
module it can be desirable to set break points on code in the module.
This is difficult in GRUB because, at GDB start, the module is not loaded
and on EFI platforms its not known ahead of time where the module will
be loaded. So allow users to create an "onload_" command which
will be run when the module with name "modname" is loaded.

Another addition is a new convenience function is defined
$is_user_command(), which returns true if its string argument is
the name of a user-defined command.

A secondary benefit of these changes is that the script does not write
temporary files and has better error handling capabilities.

Signed-off-by: Glenn Washburn 
---
 grub-core/Makefile.core.def |  4 +-
 grub-core/gdb_grub.in   | 54 ++--
 grub-core/gdb_helper.py.in  | 82 +
 grub-core/gmodule.pl.in | 30 --
 4 files changed, 87 insertions(+), 83 deletions(-)
 create mode 100644 grub-core/gdb_helper.py.in
 delete mode 100644 grub-core/gmodule.pl.in

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 95942fc8c9..4951b049ec 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -20,8 +20,8 @@ transform_data = {
 
 transform_data = {
   installdir = platform;
-  name = gmodule.pl;
-  common = gmodule.pl.in;
+  name = gdb_helper.py;
+  common = gdb_helper.py.in;
 };
 
 transform_data = {
diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index 4ca939f69a..fc201204de 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -1,6 +1,6 @@
 ###
 ### Load debuging information about GNU GRUB 2 modules into GDB
-### automatically. Needs readelf, Perl and gmodule.pl script
+### automatically. Needs readelf, Python and gdb_helper.py script
 ###
 ### Has to be launched from the writable and trusted
 ### directory containing *.image and *.module
@@ -9,63 +9,15 @@
 ### Lubomir Kundrak 
 ###
 
-# Add section numbers and addresses to .segments.tmp
-define dump_module_sections_helper
-   set $mod = $arg0
-   printf "%s", $mod->name
-   set $segment = $mod->segment
-   while ($segment)
-   printf " %i 0x%lx", $segment->section, $segment->addr
-   set $segment = $segment->next
-   end
-   printf "\n"
-end
+source gdb_helper.py
 
-define dump_module_sections
-   # Set unlimited width so that lines don't get wrapped writing
-   # to .segments.tmp
-   with width 0 -- \
-   with trace-commands off -- \
-   pipe dump_module_sections_helper $arg0 | sh -c 'cat >>.segments.tmp'
-end
-document dump_module_sections
-   Gather information about module whose mod structure was
-   given for use with match_and_load_symbols
-end
-
-# Generate and execute GDB commands and delete temporary files
-# afterwards
-define match_and_load_symbols
-   shell perl gmodule.pl <.segments.tmp >.loadsym.gdb
-   source .loadsym.gdb
-   shell rm -f .segments.tmp .loadsym.gdb
-end
-document match_and_load_symbols
-   Launch script, that matches section names with information
-   generated by dump_module_sections and load debugging info
-   apropriately
-end
-
-###
-
-define load_module
-   dump_module_sections $arg0
-   match_and_load_symbols
-end
-document load_module
-   Load debugging information for module given as argument.
-end
 
 define load_all_modules
-   shell rm -f .segments.tmp
set $this = grub_dl_head
while ($this != 0)
-   dump_module_sections $this
+   load_module $this
set $this = $this->next
end
-   if (grub_dl_head != 0)
-   match_and_load_symbols
-   end
 end
 document load_all_modules
Load debugging information for all loaded modules.
diff --git a/grub-core/gdb_helper.py.in b/grub-core/gdb_helper.py.in
new file mode 100644
index 00..4306ef448a
--- /dev/null
+++ b/grub-core/gdb_helper.py.in
@@ -0,0 +1,82 @@
+import os
+import re
+import subprocess
+
+# Convenience functions #
+
+class IsUserCommand (gdb.Function):
+  """Set the second argument to true value if first argument is the name
+of a user-defined command.
+"""
+
+  def __init__ (self):
+super (IsUserCommand, self).__init_

[PATCH v5 12/14] gdb: Add extra early initialization symbols for i386-pc

2022-12-23 Thread Glenn Washburn
Add symbols for boot.image, disk.image, and lzma_decompress.image if the
target is i386-pc. This is only done for i386-pc because that is the only
target that uses the images. By loading the symbols for these images,
these images can be more easily debugged by allowing the setting of break-
points in that code and to see easily get the value of data symbols.

Signed-off-by: Glenn Washburn 
---
 grub-core/gdb_grub.in | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index 8e89bbf368..f188a842ab 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -114,12 +114,18 @@ set confirm off
 # fail.
 
 set $platform_efi = $_streq("@platform@", "efi")
+set $target = "@target_cpu@-@platform@"
 
 if ! $runonce
if $platform_efi
# Only load the executable file, not the symbols
exec-file kernel.exec
else
+   if $_streq($target, "i386-pc")
+   add-symbol-file boot.image
+   add-symbol-file diskboot.image
+   add-symbol-file lzma_decompress.image
+   end
file kernel.exec
run_on_start
runtime_load_module
-- 
2.34.1


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v5 00/14] GDB script fixes and improvements

2022-12-23 Thread Glenn Washburn
This series has been substantially rewritten since v4, although a large
minority of the patches haven't changed much. The biggest change is
that the implementation has been converted to Python instead of what was
done in shell script. I have always felt it should be done in Python, but
it seemed daunting to learn the Python-GDB API, so the shell script seemed
the path of least resistance. I decided to give it a second look and was
surprised it wasn't as bad as I thought it would be. Because the python API
is so tightly integrated into GDB, there are things you can do with it that
either aren't possible or which look like ugly hacks when attempting with
the native script.

The other big change is that there is a new --enable-efi-debug option to
configure which enables the printing of the gdb command for loading the
GRUB kernel symbols. This is disallowed when booting with Secure Boot on.
There are two ways the GDB command is printed: (1) in early EFI setup and
(2) on-demand by a user using the gdbinfo command.

There are a couple new features to the GDB script, like a trivial one that
changes the gdb prompt and another that allows for software breakpoints to
be set before the GRUB image is loaded.

This series also incorporates suggestions given for v4 and adds more to the
documentation.

Glenn

Glenn Washburn (14):
  gdb: Fix redirection issue in dump_module_sections
  gdb: Prevent wrapping when writing to .segments.tmp
  gdb: If no modules have been loaded, do not try to load module symbols
  gdb: Move runtime module loading into runtime_load_module
  gdb: Conditionally run GDB script logic for dynamically or statically
positioned GRUB
  gdb: Only connect to remote target once when first sourced
  gdb: Replace module symbol loading implementation with Python one
  gdb: Add functions to make loading from dynamically positioned targets
easier
  gdb: Add more support for debugging on EFI platforms
  gdb: Allow running user-defined commands at GRUB start
  gdb: Fix issue with breakpoints defined before the GRUB image is
loaded
  gdb: Add extra early initialization symbols for i386-pc
  gdb: Modify gdb prompt when running gdb_grub script
  docs: Add debugging chapter to development documentation

 config.h.in |   3 +
 configure.ac|  11 ++
 docs/grub-dev.texi  | 233 
 grub-core/Makefile.core.def |   5 +-
 grub-core/gdb_grub.in   | 159 +++-
 grub-core/gdb_helper.py.in  | 173 ++
 grub-core/gmodule.pl.in |  30 -
 grub-core/kern/efi/debug.c  |  40 +++
 grub-core/kern/efi/efi.c|   4 +-
 grub-core/kern/efi/init.c   |   7 +-
 include/grub/efi/debug.h|  43 +++
 include/grub/efi/efi.h  |   2 +-
 12 files changed, 620 insertions(+), 90 deletions(-)
 create mode 100644 grub-core/gdb_helper.py.in
 delete mode 100644 grub-core/gmodule.pl.in
 create mode 100644 grub-core/kern/efi/debug.c
 create mode 100644 include/grub/efi/debug.h

Range-diff against v4:
 1:  9f273b8fa5 =  1:  9f273b8fa5 gdb: Fix redirection issue in 
dump_module_sections
 2:  85f68a8369 =  2:  85f68a8369 gdb: Prevent wrapping when writing to 
.segments.tmp
 3:  88b3973cdb =  3:  88b3973cdb gdb: If no modules have been loaded, do not 
try to load module symbols
 4:  c0d7da87a8 !  4:  3037c1da91 gdb: Move runtime module loading into 
runtime_load_module
@@ Metadata
  ## Commit message ##
 gdb: Move runtime module loading into runtime_load_module
 
+By moving this code into a function, it can be run re-utilized while 
gdb is
+running, not just when loading the script. This will also be useful in
+some following changes which will make a separate script path for 
targets
+which statically vs dynamically position GRUB code.
+
  ## grub-core/gdb_grub.in ##
 @@ grub-core/gdb_grub.in: document load_all_modules
Load debugging information for all loaded modules.
 5:  4712465374 <  -:  -- gdb: Reliably load modules in 
runtime_load_module
 6:  283021b7b9 <  -:  -- gdb: Add functions to make loading from 
dynamically positioned targets easier
 7:  8f4b7c3bbd <  -:  -- gdb: Remove Perl dependency for GRUB GDB 
script
 8:  055e968779 <  -:  -- gdb: If enabled, print line used to load EFI 
kernel symbols when using gdb_grub script
 9:  64eccfc37e =  5:  f6288016f6 gdb: Conditionally run GDB script logic for 
dynamically or statically positioned GRUB
10:  5064458dfd =  6:  da13fbe653 gdb: Only connect to remote target once when 
first sourced
11:  c33e8f57b4 <  -:  -- gdb: Allow user defined "onload_" 
command to be run when module is loaded
 -:  -- >  7:  8e6059955a gdb: Replace module symbol loading 
implementation with Python one
 -:  -- >  8:  878900d69b gdb: Add functions to make loading from 
dynamically positioned targets easier
 -:  -- >  9:  036549604d gdb: Add more su

[PATCH v5 14/14] docs: Add debugging chapter to development documentation

2022-12-23 Thread Glenn Washburn
Debugging GRUB can be tricky and require arcane knowledge. This will
help those unfamiliar with the process to get started debugging GRUB
with less effort.

Signed-off-by: Glenn Washburn 
---
 docs/grub-dev.texi | 233 +
 1 file changed, 233 insertions(+)

diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi
index f76fc658bf..18f09a48e7 100644
--- a/docs/grub-dev.texi
+++ b/docs/grub-dev.texi
@@ -79,6 +79,7 @@ This edition documents version @value{VERSION}.
 * Contributing Changes::
 * Setting up and running test suite::
 * Updating External Code::
+* Debugging::
 * Porting::
 * Error Handling::
 * Stack and heap size::
@@ -595,6 +596,238 @@ cp minilzo-2.10/*.[hc] grub-core/lib/minilzo
 rm -r minilzo-2.10*
 @end example
 
+@node Debugging
+@chapter Debugging
+
+GRUB2 can be difficult to debug because it runs on the bare-metal and thus
+does not have the debugging facilities normally provided by an operating
+system. This chapter aims to provide useful information on some ways to
+debug GRUB2 for some architectures. It by no means intends to be exhaustive.
+The focus will be one x86_64 and i386 architectures. Luckily for some issues
+virtual machines have made the ability to debug GRUB2 much easier, and this
+chapter will focus debugging via the QEMU virtual machine. We will not be
+going over debugging of the userland tools (eg. grub-install), there are
+many tutorials on debugging programs in userland.
+
+You will need GDB and the QEMU binaries for your system, on Debian these
+can be installed with the @samp{gdb} and @samp{qemu-system-x86} packages.
+Also it is assumed that you have already successfully compiled GRUB2 from
+source for the target specified in the section below and have some
+familiarity with GDB. When GRUB2 is built it will create many different
+binaries. The ones of concern will be in the @file{grub-core}
+directory of the GRUB2 build dir. To aide in debugging we will want the
+debugging symbols generated during the build because these symbols are not
+kept in the binaries which get installed to the boot location. The build
+process outputs two sets of binaries, one without symbols which gets executed
+at boot, and another set of ELF images with debugging symbols. The built
+images with debugging symbols will have a @file{.image} suffix, and the ones
+without a @file{.img} suffix. Similarly, loadable modules with debugging
+symbols will have a @file{.module} suffix, and ones without a @file{.mod}
+suffix. In the case of the kernel the binary with symbols is named
+@file{kernel.exec}.
+
+In the following sections, information will be provided on debugging on
+various targets using @command{gdb} and the @samp{gdb_grub} GDB script.
+
+@menu
+* i386-pc::
+* x86_64-efi::
+@end menu
+
+@node i386-pc
+@section i386-pc
+
+The i386-pc target is a good place to start when first debugging GRUB2
+because in some respects its easier than EFI platforms. The reason being
+that the initial load address is always known in advance. To start
+debugging GRUB2 first QEMU must be started in GDB stub mode. The following
+command is a simple illustration:
+
+@example
+qemu-system-i386 -drive file=disk.img,format=raw \
+-device virtio-scsi-pci,id=scsi0 -S -s
+@end example
+
+This will start a QEMU instance booting from @file{disk.img}. It will pause
+at start waiting for a GDB instance to attach to it. You should change
+@file{disk.img} to something more appropriate. A block device can be used,
+but you may need to run QEMU as a privileged user.
+
+To connect to this QEMU instance with GDB, the @code{target remote} GDB
+command must be used. We also need to load a binary image, preferably with
+symbols. This can be done using the GDB command @code{file kernel.exec}, if
+GDB is started from the @file{grub-core} directory in the GRUB2 build
+directory. GRUB2 developers have made this more simple by including a GDB
+script which does much of the setup. This file at @file{grub-core/gdb_grub}
+of the build directory and is also installed via @command{make install}.
+If not building GRUB, the distribution may have a package which installs
+this GDB script along with debug symbol binaries, such as Debian's
+@samp{grub-pc-dbg} package. The GDB scripts is intended to by used
+like so, assuming:
+
+@example
+cd $(dirname /path/to/script/gdb_grub)
+gdb -x gdb_grub
+@end example
+
+Once GDB has been started with the @file{gdb_grub} script it will
+automatically connect to the QEMU instance. You can then do things you
+normally would in GDB like set a break point on @var{grub_main}.
+
+Setting breakpoints in modules is trickier since they haven't been loaded
+yet and are loaded at addresses determined at runtime. The module could be
+loaded to different addresses in different QEMU instances. The debug symbols
+in the modules @file{.module} binary, thus are always wrong, and GDB needs
+to be told where to load the symbols to. But this must happen at runtime
+after GRUB2 has dete

[PATCH v5 09/14] gdb: Add more support for debugging on EFI platforms

2022-12-23 Thread Glenn Washburn
If the configure option --enable-efi-debug is given, then enable the
printing early in EFI startup of the command needed to load symbols for
the GRUB EFI kernel. This is needed because EFI firmware determines where
to load the GRUB EFI at runtime, and so the relevant addresses are not
known ahead of time. This is not printed when secure boot is enabled.

The command is a custom command defined in the gdb_grub GDB script. So
GDB should be started with the script as an argument to the -x option or
sourced into an active GDB session before running the outputted command.

Also a command named "gdbinfo" is enabled which allows the user to print
the gdb command string on-demand, which can be valuable as the printing
early in EFI startup is quickly replaced by other text. So if using a
physical screen it may appear too briefly to be registered.

Co-developed-by: Peter Jones 
Signed-off-by: Glenn Washburn 
---
 config.h.in |  3 +++
 configure.ac| 11 ++
 grub-core/Makefile.core.def |  1 +
 grub-core/kern/efi/debug.c  | 40 ++
 grub-core/kern/efi/efi.c|  4 ++--
 grub-core/kern/efi/init.c   |  7 +-
 include/grub/efi/debug.h| 43 +
 include/grub/efi/efi.h  |  2 +-
 8 files changed, 107 insertions(+), 4 deletions(-)
 create mode 100644 grub-core/kern/efi/debug.c
 create mode 100644 include/grub/efi/debug.h

diff --git a/config.h.in b/config.h.in
index 4d1e50eba7..9f88be1593 100644
--- a/config.h.in
+++ b/config.h.in
@@ -13,6 +13,9 @@
 #define MM_DEBUG @MM_DEBUG@
 #endif
 
+/* Define to 1 to enable printing of gdb command to load module symbols.  */
+#define PRINT_GDB_SYM_LOAD_CMD @EFI_DEBUG@
+
 /* Define to 1 to enable disk cache statistics.  */
 #define DISK_CACHE_STATS @DISK_CACHE_STATS@
 #define BOOT_TIME_STATS @BOOT_TIME_STATS@
diff --git a/configure.ac b/configure.ac
index 93626b7982..4bf477b072 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1521,6 +1521,17 @@ else
 fi
 AC_SUBST([MM_DEBUG])
 
+# EFI debugging.
+AC_ARG_ENABLE([efi-debug],
+ AS_HELP_STRING([--enable-efi-debug],
+ [include aides for debugging the EFI binary]))
+if test x$enable_efi_debug = xyes; then
+  EFI_DEBUG=1
+else
+  EFI_DEBUG=0
+fi
+AC_SUBST([EFI_DEBUG])
+
 AC_ARG_ENABLE([cache-stats],
  AS_HELP_STRING([--enable-cache-stats],
  [enable disk cache statistics collection]))
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 4951b049ec..9891253aac 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -206,6 +206,7 @@ kernel = {
 
   efi = disk/efi/efidisk.c;
   efi = kern/efi/efi.c;
+  efi = kern/efi/debug.c;
   efi = kern/efi/init.c;
   efi = kern/efi/mm.c;
   efi = term/efi/console.c;
diff --git a/grub-core/kern/efi/debug.c b/grub-core/kern/efi/debug.c
new file mode 100644
index 00..c4f5561587
--- /dev/null
+++ b/grub-core/kern/efi/debug.c
@@ -0,0 +1,40 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2022  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see .
+ */
+/* debug.c - aides for debugging the EFI application */
+
+#include 
+#include 
+#include 
+
+__attribute__ ((unused)) static grub_err_t
+grub_cmd_gdbinfo (struct grub_command *cmd __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+  grub_efi_print_gdb_info ();
+  return 0;
+}
+
+void
+grub_efi_register_debug_commands (void)
+{
+#if PRINT_GDB_SYM_LOAD_CMD
+  grub_register_command_lockdown ("gdbinfo", grub_cmd_gdbinfo, 0,
+ N_("Print infomation useful for GDB 
debugging"));
+#endif
+}
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index cf49d6357e..17bd06f7e6 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -299,7 +299,7 @@ grub_efi_get_variable (const char *var, const 
grub_efi_guid_t *guid,
 /* Search the mods section from the PE32/PE32+ image. This code uses
a PE32 header, but should work with PE32+ as well.  */
 grub_addr_t
-grub_efi_modules_addr (void)
+grub_efi_section_addr (const char *section_name)
 {
   grub_efi_loaded_image_t *image;
   struct grub_msdos_image_header *header;
@@ -328,7 +328,7 @@ grub_efi_modules_addr (void)
 

[PATCH v5 03/14] gdb: If no modules have been loaded, do not try to load module symbols

2022-12-23 Thread Glenn Washburn
This prevents load_all_modules from failing when called before any
modules have been loaded. Failures in GDB user-defined functions cause
any function which called them to also fail.

Signed-off-by: Glenn Washburn 
---
 grub-core/gdb_grub.in | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index edb5a8872c..fc17e3d899 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -63,7 +63,9 @@ define load_all_modules
dump_module_sections $this
set $this = $this->next
end
-   match_and_load_symbols
+   if (grub_dl_head != 0)
+   match_and_load_symbols
+   end
 end
 document load_all_modules
Load debugging information for all loaded modules.
-- 
2.34.1


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v5 01/14] gdb: Fix redirection issue in dump_module_sections

2022-12-23 Thread Glenn Washburn
An error in any GDB command causes it to immediately abort with an error,
this includes any command that calls that command. This leads to an issue
in dump_module_sections where an error causes the command to exit without
turning off file redirection. The user then ends up with a GDB command
line where commands output nothing to the console.

Instead do the work of dump_module_sections in the command
dump_module_sections_helper and run the command using GDB's pipe command
which does the redirection and undoes the redirection when it finishes
regardless of any errors in the command.

Also, remove .segments.tmp file prior to loading modules in case one was
left from a previous run.

Signed-off-by: Glenn Washburn 
---
 grub-core/gdb_grub.in | 15 +--
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index e322d3dc10..4e45ad5622 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -10,15 +10,8 @@
 ###
 
 # Add section numbers and addresses to .segments.tmp
-define dump_module_sections
+define dump_module_sections_helper
set $mod = $arg0
-
-   # FIXME: save logging status
-   set logging file .segments.tmp
-   set logging redirect on
-   set logging overwrite off
-   set logging on
-
printf "%s", $mod->name
set $segment = $mod->segment
while ($segment)
@@ -26,9 +19,10 @@ define dump_module_sections
set $segment = $segment->next
end
printf "\n"
+end
 
-   set logging off
-   # FIXME: restore logging status
+define dump_module_sections
+   pipe dump_module_sections_helper $arg0 | sh -c 'cat >>.segments.tmp'
 end
 document dump_module_sections
Gather information about module whose mod structure was
@@ -59,6 +53,7 @@ document load_module
 end
 
 define load_all_modules
+   shell rm -f .segments.tmp
set $this = grub_dl_head
while ($this != 0)
dump_module_sections $this
-- 
2.34.1


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v5 11/14] gdb: Fix issue with breakpoints defined before the GRUB image is loaded

2022-12-23 Thread Glenn Washburn
On some platforms, notably x86, software breakpoints set in GDB before
the GRUB image is loaded will be cleared when the image is loaded. This
is because the breakpoints work by overwriting the memory of the break-
point location with a special instruction which when hit will cause the
debugger to stop execution. Just before execution is resumed by the
debugger, the original instruction bytes are put back. When a breakpoint
is set before the GRUB image is loaded, the special debugger instruction
will be written to memory and when the GRUB image is loaded by the
firmware, which has no knowledge of the debugger, the debugger instruction
is overwritten. To the GDB user, GDB will show the breakpoint as set, but
it will never be hit. Furthermore, GDB now becomes confused, such that
even deleting and re-setting the breakpoint after the GRUB image is loaded
will not allow for a working breakpoint.

To work around this, in run_on_start, first a watchpoint is set on _start,
which will be triggered when the firmware starts loading the GRUB image.
When the _start watchpoint is hit, the current breakpoints are saved to a
file and then deleted by GDB before they can be overwritten by the firmware
and confuse GDB. Then a temporary software breakpoint is set on _start,
which will get triggered when the firmware hands off to GRUB to execute. In
that breakpoint load the previously saved and deleted breakpoints now that
there is no worry of them getting overwritten by the firmware.

Note that watchpoints are generally types of hardware breakpoints on x86, so
its deleted as soon as it gets triggered so that a minimal set of hardware
breakpoints are used, allowing more for the user.

Signed-off-by: Glenn Washburn 
---
 grub-core/gdb_grub.in | 33 +++--
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index 281dfb5927..8e89bbf368 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -59,14 +59,35 @@ end
 define run_on_start
# TODO: Add check to see if _start symbol is defined, if not, then
# the symbols have not yet been loaded and this command will not work.
-   thbreak _start
+   watch *_start
+   set $break_efi_start_bpnum = $bpnum
commands
silent
-
-   runtime_load_module
-
-   if $is_user_command("onstart")
-   onstart
+   delete $break_efi_start_bpnum
+
+   # Save the breakpoints here before the GRUB image is loaded
+   # into memory, then delete them. Later they will be reloaded
+   # once the GRUB image has been loaded. This avoids the issue
+   # where the loading of the GRUB image overwrites the software
+   # breakpoints, thus confusing GDB and effectively clearing
+   # those breakpoints.
+   save breakpoints .early-breakpoints.gdb
+   delete breakpoints
+
+   tbreak _start
+   commands
+   silent
+
+   # Reload the breakpoints now that the GRUB image has
+   # finished being loaded into memory.
+   source .early-breakpoints.gdb
+
+   runtime_load_module
+
+   if $is_user_command("onstart")
+   onstart
+   end
+   continue
end
continue
end
-- 
2.34.1


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v5 05/14] gdb: Conditionally run GDB script logic for dynamically or statically positioned GRUB

2022-12-23 Thread Glenn Washburn
There are broadly two classes of targets to consider when loading symbols
for GRUB, targets that determine where to load GRUB at runtime
(dynamically positioned) and those that do not (statically positioned).
For statically poisitioned targets, symbol loading is determined at link
time, so nothing more needs to be known to load the symbols. For
dynamically positioned targets, such as EFI targets, at runtime symbols
should be offset by an amount that depends on where the runtime chose to
load GRUB.

It is important to not load symbols statically for dynamic targets
because then when subsequently loading the symbols correctly one must
take care to remove the existing static symbols, otherwise there will be
two sets of symbols and GDB seems to prefer the ones loaded first (ie the
static ones).

Use autoconf variables to generate a gdb_grub for a particular target,
which conditionally run startup code depending on if the target uses
static or dynamic loading.

Signed-off-by: Glenn Washburn 
---
 grub-core/gdb_grub.in | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index d525a5a11f..620d1def72 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -86,7 +86,20 @@ end
 ###
 
 set confirm off
-file kernel.exec
-target remote :1234
 
-runtime_load_module
+# Note: On EFI and other platforms that load GRUB to an address that is
+# determined at runtime, the symbols in kernel.exec will be wrong.
+# However, we must start by loading some executable file or GDB will
+# fail.
+
+set $platform_efi = $_streq("@platform@", "efi")
+
+if $platform_efi
+   # Only load the executable file, not the symbols
+   exec-file kernel.exec
+else
+   file kernel.exec
+   runtime_load_module
+end
+
+target remote :1234
-- 
2.34.1


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v5 08/14] gdb: Add functions to make loading from dynamically positioned targets easier

2022-12-23 Thread Glenn Washburn
Many targets, such as EFI, load GRUB at addresses that are determined at
runtime. So the load addresses in kernel.exec will almost certainly be
wrong. Given the address of the start of the text segment, these
functions will tell GDB to load the symbols at the proper locations. It
is left up to the user to determine how to get the text address of the
loaded GRUB image.

Signed-off-by: Glenn Washburn 
---
 grub-core/gdb_grub.in  | 21 -
 grub-core/gdb_helper.py.in | 87 ++
 2 files changed, 107 insertions(+), 1 deletion(-)

diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index fc201204de..18ce6b0eb2 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -1,6 +1,6 @@
 ###
 ### Load debuging information about GNU GRUB 2 modules into GDB
-### automatically. Needs readelf, Python and gdb_helper.py script
+### automatically. Needs readelf, objdump, Python and gdb_helper.py script
 ###
 ### Has to be launched from the writable and trusted
 ### directory containing *.image and *.module
@@ -12,6 +12,25 @@
 source gdb_helper.py
 
 
+define dynamic_load_symbols
+   dynamic_load_kernel_exec_symbols $arg0
+
+   # We may have been very late to loading the kernel.exec symbols and
+   # and modules may already be loaded. So load symbols for any already
+   # loaded.
+   load_all_modules
+
+   if $is_grub_loaded()
+   runtime_load_module
+   end
+end
+document dynamic_load_symbols
+   Load debugging symbols from kernel.exec and any loaded modules given
+   the address of the .text segment of the UEFI binary in memory. Also
+   setup session to automatically load module symbols for modules loaded
+   in the future.
+end
+
 define load_all_modules
set $this = grub_dl_head
while ($this != 0)
diff --git a/grub-core/gdb_helper.py.in b/grub-core/gdb_helper.py.in
index 4306ef448a..8d5ee1d292 100644
--- a/grub-core/gdb_helper.py.in
+++ b/grub-core/gdb_helper.py.in
@@ -4,6 +4,23 @@ import subprocess
 
 # Convenience functions #
 
+class IsGrubLoaded (gdb.Function):
+  """Return 1 if GRUB has been loaded in memory, otherwise 0.
+The hueristic used is checking if the first 4 bytes of the memory pointed
+to by the _start symbol are not 0. This is true for QEMU on the first run
+of GRUB. This may not be true on physical hardware, where memory is not
+necessarily cleared on soft reset. This may not also be true in QEMU on
+soft resets. Also this many not be true when chainloading GRUB.
+"""
+
+  def __init__ (self):
+super (IsGrubLoaded, self).__init__ ("is_grub_loaded")
+
+  def invoke (self):
+return int (gdb.parse_and_eval ("*(int *) _start")) != 0
+
+is_grub_loaded = IsGrubLoaded ()
+
 class IsUserCommand (gdb.Function):
   """Set the second argument to true value if first argument is the name
 of a user-defined command.
@@ -24,6 +41,76 @@ is_user_command = IsUserCommand ()
 
 # Commands #
 
+# Loading symbols is complicated by the fact that kernel.exec is an ELF
+# ELF binary, but the UEFI runtime is PE32+. All the data sections of
+# the ELF binary are concatenated (accounting for ELF section alignment)
+# and put into one .data section of the PE32+ runtime image. So given
+# the load address of the .data PE32+ section we can determine the
+# addresses each ELF data section maps to. The UEFI application is
+# loaded into memory just as it is laid out in the file. It is not
+# assumed that the binary is available, but it is known that the .text
+# section directly precedes the .data section and that .data is EFI
+# page aligned. Using this, the .data offset can be found from the .text
+# address.
+class GrubLoadKernelExecSymbols (gdb.Command):
+  """Load debugging symbols from kernel.exec given the address of the
+.text segment of the UEFI binary in memory."""
+
+  PE_SECTION_ALIGN = 12
+
+  def __init__ (self):
+super (GrubLoadKernelExecSymbols, self).__init__ 
("dynamic_load_kernel_exec_symbols",
+ gdb.COMMAND_USER,
+ gdb.COMPLETE_EXPRESSION)
+
+  def invoke (self, arg, from_tty):
+self.dont_repeat ()
+args = gdb.string_to_argv (arg)
+
+if len (args) != 1:
+  raise RuntimeError ("dynamic_load_kernel_exec_symbols expects exactly 
one argument")
+
+sections = self.parse_objdump_sections ("kernel.exec")
+pe_text = args[0]
+text_size = [s['size'] for s in sections if s['name'] == '.text'][0]
+pe_data_offset = self.alignup (text_size, self.PE_SECTION_ALIGN)
+
+sym_load_cmd_parts = ["add-symbol-file", "kernel.exec", pe_text]
+offset = 0
+for section in sections:
+  if 'DATA' in section["flags"] or section["name"] == ".bss":
+offset = self.alignup (offset, section["align"])
+sym_load_cmd_parts.extend (["-s", section["name"], "(%s+0x%x+0x%x)" % 
(pe_text, pe_data_offset, offset)])
+offset += section["