Commit Graph
951 Commits
Author SHA1 Message Date
Robbie Harwood dbc641ac92 efi: Make all grub_efi_guid_t variables static
This is believed to result in smaller code.

Signed-off-by: Robbie Harwood <rharwood@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-08-20 00:23:11 +02:00
Alec Brown ddb6c1bafb elf: Validate number of elf program header table entries
In bsdXX.c and multiboot_elfxx.c, e_phnum is used to obtain the number of
program header table entries, but it wasn't being checked if the value was
there.

According to the elf(5) manual page,
"If the number of entries in the program header table is larger than or equal to
PN_XNUM (0xffff), this member holds PN_XNUM (0xffff) and the real number of
entries in the program header table is held in the sh_info member of the
initial entry in section header table.  Otherwise, the sh_info member of the
initial entry contains the value zero."

Since this check wasn't being made, grub_elfXX_get_phnum() is being added to
elfXX.c to make this check and use e_phnum if it doesn't have PN_XNUM as a
value, else use sh_info. We also need to make sure e_phnum isn't greater than
PN_XNUM and sh_info isn't less than PN_XNUM.

Note that even though elf.c and elfXX.c are located in grub-core/kern, they are
compiled as modules and don't need the EXPORT_FUNC() macro to define the functions
in elf.h.

Also, changed casts of phnum to match variables being set as well as dropped
casts when unnecessary.

Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-08-19 22:27:51 +02:00
Alec Brown 385d906007 elf: Validate elf section header table index for section name string table
In multiboot_elfxx.c, e_shstrndx is used to obtain the section header table
index of the section name string table, but it wasn't being checked if the value
was there.

According to the elf(5) manual page,
"If the index of section name string table section is larger than or equal to
SHN_LORESERVE (0xff00), this member holds SHN_XINDEX (0xffff) and the real
index of the section name string table section is held in the sh_link member of
the initial entry in section header table. Otherwise, the sh_link member of the
initial entry in section header table contains the value zero."

Since this check wasn't being made, grub_elfXX_get_shstrndx() is being added to
elfXX.c to make this check and use e_shstrndx if it doesn't have SHN_XINDEX as a
value, else use sh_link. We also need to make sure e_shstrndx isn't greater than
or equal to SHN_LORESERVE and sh_link isn't less than SHN_LORESERVE.

Note that even though elf.c and elfXX.c are located in grub-core/kern, they are
compiled as modules and don't need the EXPORT_FUNC() macro to define the functions
in elf.h.

Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-08-19 22:26:53 +02:00
Alec Brown 27a14a8ae2 elf: Validate number of elf section header table entries
In bsdXX.c and multiboot_elfxx.c, e_shnum is used to obtain the number of
section header table entries, but it wasn't being checked if the value was
there.

According to the elf(5) manual page,
"If the number of entries in the section header table is larger than or equal to
SHN_LORESERVE (0xff00), e_shnum holds the value zero and the real number of
entries in the section header table is held in the sh_size member of the initial
entry in section header table. Otherwise, the sh_size member of the initial
entry in the section header table holds the value zero."

Since this check wasn't being made, grub_elfXX_get_shnum() is being added to
elfXX.c to make this check and use whichever member doesn't have a value of
zero. If both are zero, then we must return an error. We also need to make sure
that e_shnum doesn't have a value greater than or equal to SHN_LORESERVE and
sh_size isn't less than SHN_LORESERVE.

In order to get this function to work, the type ElfXX_Shnum is being added where
Elf32_Shnum defines Elf32_Word and Elf64_Shnum defines Elf64_Xword. This new
type is needed because if shnum obtains a value from sh_size, sh_size could be
of type El32_Word for Elf32_Shdr structures or Elf64_Xword for Elf64_Shdr
structures.

Note that even though elf.c and elfXX.c are located in grub-core/kern, they are
compiled as modules and don't need the EXPORT_FUNC() macro to define the functions
in elf.h.

For a few smaller changes, changed casts of shnum to match variables being set
as well as dropped casts when unnecessary and fixed spacing errors in bsdXX.c.
Also, shnum is an unsigned integer and is compared to int i in multiboot_elfxx.c,
it should be unsigned to match shnum.

Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-08-19 22:26:35 +02:00
Peter Jones 8812755d97 kern/i386/tsc_pmtimer: Make pmtimer tsc calibration not take 51 seconds to fail
On my laptop running at 2.4GHz, if I run a VM where tsc calibration
using pmtimer will fail presuming a broken pmtimer, it takes ~51 seconds
to do so (as measured with the stopwatch on my phone), with a tsc delta
of 0x1cd1c85300, or around 125 billion cycles.

If instead of trying to wait for 5-200ms to show up on the pmtimer, we
try to wait for 5-200us, it decides it's broken in ~0x2626aa0 TSCs, aka
~2.4 million cycles, or more or less instantly.

Additionally, this reading the pmtimer was returning 0xffffffff anyway,
and that's obviously an invalid return. I've added a check for that and
0 so we don't bother waiting for the test if what we're seeing is dead
pins with no response at all.

If "debug" includes "pmtimer", you will see one of the following three
outcomes. If pmtimer gives all 0 or all 1 bits, you will see:

  pmtimer: 0xffffff bad_reads: 1
  pmtimer: 0xffffff bad_reads: 2
  pmtimer: 0xffffff bad_reads: 3
  pmtimer: 0xffffff bad_reads: 4
  pmtimer: 0xffffff bad_reads: 5
  pmtimer: 0xffffff bad_reads: 6
  pmtimer: 0xffffff bad_reads: 7
  pmtimer: 0xffffff bad_reads: 8
  pmtimer: 0xffffff bad_reads: 9
  pmtimer: 0xffffff bad_reads: 10
  timer is broken; giving up.

This outcome was tested using qemu+kvm with UEFI (OVMF) firmware and
these options: -machine pc-q35-2.10 -cpu Broadwell-noTSX

If pmtimer gives any other bit patterns but is not actually marching
forward fast enough to use for clock calibration, you will see:

  pmtimer delta is 0x0 (1904 iterations)
  tsc delta is implausible: 0x2626aa0

This outcome was tested using GRUB patched to not ignore bad reads using
qemu+kvm with UEFI (OVMF) firmware, and these options:
-machine pc-q35-2.10 -cpu Broadwell-noTSX

If pmtimer actually works, you'll see something like:

  pmtimer delta is 0xdff
  tsc delta is 0x278756

This outcome was tested using qemu+kvm with UEFI (OVMF) firmware, and
these options: -machine pc-i440fx-2.4 -cpu Broadwell-noTSX

I've also tested this outcome on a real Intel Xeon E3-1275v3 on an Intel
Server Board S1200V3RPS using the SDV.RP.B8 "Release" build here:
https://www.intel.com/content/www/us/en/download/674448/firmware-update-for-the-intel-server-board-s1200rp-uefi-development-kit-release-vb8.html

Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-08-10 14:24:46 +02:00
Robbie Harwood 92005be6d8 kern/fs: The grub_fs_probe() should dprint errors from filesystems
When filesystem detection fails, all that's currently debug-logged is
a series of messages like:

    grub-core/kern/fs.c:56:fs: Detecting ntfs...
    grub-core/kern/fs.c:76:fs: ntfs detection failed.

repeated for each filesystem. Any messages provided to grub_error() by
the filesystem are lost, and one has to break out gdb to figure out what
went wrong.

With this change, one instead sees:

    grub-core/kern/fs.c:56:fs: Detecting fat...
    grub-core/osdep/hostdisk.c:357:hostdisk: reusing open device
    `/path/to/device'
    grub-core/kern/fs.c:77:fs: error: invalid modification timestamp for /.
    grub-core/kern/fs.c:79:fs: fat detection failed.

in the debug prints.

Signed-off-by: Robbie Harwood <rharwood@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-07-27 19:20:53 +02:00
Glenn Washburn f5a92e6040 disk: Allow read hook callback to take read buffer to potentially modify it
It will be desirable in the future to allow having the read hook modify the
data passed back from a read function call on a disk or file. This adds that
infrastructure and has no impact on code flow for existing uses of the read
hook. Also changed is that now when the read hook callback is called it can
also indicate what error code should be sent back to the read caller.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-07-04 14:43:25 +02:00
Patrick Steinhardt 1df2934822 kern/efi/mm: Implement runtime addition of pages
Adjust the interface of grub_efi_mm_add_regions() to take a set of
GRUB_MM_ADD_REGION_* flags, which most notably is currently only the
GRUB_MM_ADD_REGION_CONSECUTIVE flag. This allows us to set the function
up as callback for the memory subsystem and have it call out to us in
case there's not enough pages available in the current heap.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Patrick Steinhardt <ps@pks.im>
2022-07-04 14:43:17 +02:00
Patrick Steinhardt 15a0156989 kern/efi/mm: Pass up errors from add_memory_regions()
The function add_memory_regions() is currently only called on system
initialization to allocate a fixed amount of pages. As such, it didn't
need to return any errors: in case it failed, we cannot proceed anyway.
This will change with the upcoming support for requesting more memory
from the firmware at runtime, where it doesn't make sense anymore to
fail hard.

Refactor the function to return an error to prepare for this. Note that
this does not change the behaviour when initializing the memory system
because grub_efi_mm_init() knows to call grub_fatal() in case
grub_efi_mm_add_regions() returns an error.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Patrick Steinhardt <ps@pks.im>
2022-07-04 14:38:57 +02:00
Patrick Steinhardt 96a7ea29e3 kern/efi/mm: Extract function to add memory regions
In preparation of support for runtime-allocating additional memory
region, this patch extracts the function to retrieve the EFI memory
map and add a subset of it to GRUB's own memory regions.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Patrick Steinhardt <ps@pks.im>
2022-07-04 14:36:15 +02:00
Patrick Steinhardt 938c3760b8 kern/efi/mm: Always request a fixed number of pages on init
When initializing the EFI memory subsystem, we will by default request
a quarter of the available memory, bounded by a minimum/maximum value.
Given that we're about to extend the EFI memory system to dynamically
request additional pages from the firmware as required, this scaling of
requested memory based on available memory will not make a lot of sense
anymore.

Remove this logic as a preparatory patch such that we'll instead defer
to the runtime memory allocator. Note that ideally, we'd want to change
this after dynamic requesting of pages has been implemented for the EFI
platform. But because we'll need to split up initialization of the
memory subsystem and the request of pages from the firmware, we'd have
to duplicate quite some logic at first only to remove it afterwards
again. This seems quite pointless, so we instead have patches slightly
out of order.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Patrick Steinhardt <ps@pks.im>
2022-07-04 14:25:41 +02:00
Patrick Steinhardt 887f98f0db mm: Allow dynamically requesting additional memory regions
Currently, all platforms will set up their heap on initialization of the
platform code. While this works mostly fine, it poses some limitations
on memory management on us. Most notably, allocating big chunks of
memory in the gigabyte range would require us to pre-request this many
bytes from the firmware and add it to the heap from the beginning on
some platforms like EFI. As this isn't needed for most configurations,
it is inefficient and may even negatively impact some usecases when,
e.g., chainloading. Nonetheless, allocating big chunks of memory is
required sometimes, where one example is the upcoming support for the
Argon2 key derival function in LUKS2.

In order to avoid pre-allocating big chunks of memory, this commit
implements a runtime mechanism to add more pages to the system. When
a given allocation cannot be currently satisfied, we'll call a given
callback set up by the platform's own memory management subsystem,
asking it to add a memory area with at least "n" bytes. If this
succeeds, we retry searching for a valid memory region, which should
now succeed.

If this fails, we try asking for "n" bytes, possibly spread across
multiple regions, in hopes that region merging means that we end up
with enough memory for things to work out.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Patrick Steinhardt <ps@pks.im>
2022-07-04 14:25:41 +02:00
Patrick Steinhardt 139fd9b134 mm: Drop unused unloading of modules on OOM
In grub_memalign(), there's a commented section which would allow for
unloading of unneeded modules in case where there is not enough free
memory available to satisfy a request. Given that this code is never
compiled in, let's remove it together with grub_dl_unload_unneeded().

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Patrick Steinhardt <ps@pks.im>
2022-07-04 14:25:41 +02:00
Daniel Axtens 8afa5ef45b mm: Debug support for region operations
This is handy for debugging. Enable with "set debug=regions".

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Patrick Steinhardt <ps@pks.im>
2022-07-04 14:25:29 +02:00
Daniel Axtens 052e6068be mm: When adding a region, merge with region after as well as before
On x86_64-efi (at least) regions seem to be added from top down. The mm
code will merge a new region with an existing region that comes
immediately before the new region. This allows larger allocations to be
satisfied that would otherwise be the case.

On powerpc-ieee1275, however, regions are added from bottom up. So if
we add 3x 32MB regions, we can still only satisfy a 32MB allocation,
rather than the 96MB allocation we might otherwise be able to satisfy.

  * Define 'post_size' as being bytes lost to the end of an allocation
    due to being given weird sizes from firmware that are not multiples
    of GRUB_MM_ALIGN.

  * Allow merging of regions immediately _after_ existing regions, not
    just before. As with the other approach, we create an allocated
    block to represent the new space and the pass it to grub_free() to
    get the metadata right.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Patrick Steinhardt <ps@pks.im>
2022-07-04 14:13:56 +02:00
Daniel Axtens f1ce0e15e7 kern/file: Do not leak device_name on error in grub_file_open()
If we have an error in grub_file_open() before we free device_name, we
will leak it.

Free device_name in the error path and null out the pointer in the good
path once we free it there.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-06-07 16:39:32 +02:00
Julian Andres Klode 6fe755c5c0 kern/efi/sb: Reject non-kernel files in the shim_lock verifier
We must not allow other verifiers to pass things like the GRUB modules.
Instead of maintaining a blocklist, maintain an allowlist of things
that we do not care about.

This allowlist really should be made reusable, and shared by the
lockdown verifier, but this is the minimal patch addressing
security concerns where the TPM verifier was able to mark modules
as verified (or the OpenPGP verifier for that matter), when it
should not do so on shim-powered secure boot systems.

Fixes: CVE-2022-28735

Signed-off-by: Julian Andres Klode <julian.klode@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-06-07 16:39:31 +02:00
Michael Chang acffb81485 build: Fix -Werror=array-bounds array subscript 0 is outside array bounds
The GRUB is failing to build with GCC-12 in many places like this:

  In function 'init_cbfsdisk',
      inlined from 'grub_mod_init' at ../../grub-core/fs/cbfs.c:391:3:
  ../../grub-core/fs/cbfs.c:345:7: error: array subscript 0 is outside array bounds of 'grub_uint32_t[0]' {aka 'unsigned int[]'} [-Werror=array-bounds]
    345 |   ptr = *(grub_uint32_t *) 0xfffffffc;
        |   ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This is caused by GCC regression in 11/12 [1]. In a nut shell, the
warning is about detected invalid accesses at non-zero offsets to NULL
pointers. Since hardwired constant address is treated as NULL plus an
offset in the same underlying code, the warning is therefore triggered.

Instead of inserting #pragma all over the places where literal pointers
are accessed to avoid diagnosing array-bounds, we can try to borrow the
idea from Linux kernel that the absolute_pointer() macro [2][3] is used
to disconnect a pointer using literal address from it's original object,
hence GCC won't be able to make assumptions on the boundary while doing
pointer arithmetic. With that we can greatly reduce the code we have to
cover up by making initial literal pointer assignment to use the new
wrapper but not having to track everywhere literal pointers are
accessed. This also makes code looks cleaner.

Please note the grub_absolute_pointer() macro requires to be invoked in
a function as long as it is compound expression. Some global variables
with literal pointers has been changed to local ones in order to use
grub_absolute_pointer() to initialize it. The shuffling is basically done
in a selective and careful way that the variable's scope doesn't matter
being local or global, for example, the global variable must not get
modified at run time throughout. For the record, here's the list of
global variables got shuffled in this patch:

  grub-core/commands/i386/pc/drivemap.c:int13slot
  grub-core/term/i386/pc/console.c:bios_data_area
  grub-core/term/ns8250.c:serial_hw_io_addr

[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578
[2] https://elixir.bootlin.com/linux/v5.16.14/source/include/linux/compiler.h#L180
[3] https://elixir.bootlin.com/linux/v5.16.14/source/include/linux/compiler-gcc.h#L31

Signed-off-by: Michael Chang <mchang@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-04-20 18:27:52 +02:00
Chad Kimes c143056a34 kern/efi/efi: Print VLAN info in EFI device path
Signed-off-by: Chad Kimes <chkimes@github.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-04-20 13:58:13 +02:00
Chris Coulson 37ddd9457f kern/efi/init: Log a console error during a stack check failure
The initial implementation of the stack protector just busy looped
in __stack_chk_fail in order to reduce the amount of code being
executed after the stack has been compromised because of a lack of
firmware memory protections. With future firmware implementations
incorporating memory protections such as W^X, call in to boot services
when an error occurs in order to log a message to the console before
automatically rebooting the machine.

Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-04-04 22:26:31 +02:00
Hans de Goede 3e4cbbeca0 kern/main: Suppress the "Welcome to GRUB!" message in EFI builds
GRUB EFI builds are now often used in combination with flicker-free
boot, but this breaks with upstream GRUB because the "Welcome to GRUB!"
message will kick the EFI fb into text mode and show the msg, breaking
the flicker-free experience.

EFI systems are so fast, that when the menu or the countdown are
enabled the message will be immediately overwritten, so in these cases
not printing the message does not matter.

And in case when the timeout_style is set to TIMEOUT_STYLE_HIDDEN,
the user has asked GRUB to be quiet (for example to allow flickfree
boot) and thus the message should not be printed.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Robbie Harwood <rharwood@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-04-04 17:23:16 +02:00
Darren Kenny 62f0489aff kern/rescue_parser: Ensure that parser allocated memory is not leaked
While it would appear unlikely that the memory allocated in *argv in
grub_parser_split_cmdline() would be leaked, we should try ensure that
it doesn't leak by calling grub_free() before we return from
grub_rescue_parse_line().

To avoid a possible double-free, grub_parser_split_cmdline() is being
changed to assign *argv = NULL when we've called grub_free() in the fail
section.

Fixes: CID 96680

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-03-21 19:41:37 +01:00
Robbie Harwood 2cd52835fc config: Where present, ensure config-util.h precedes config.h
gnulib defines go in config-util.h, and we need to know whether to
provide duplicates in config.h or not.

Signed-off-by: Robbie Harwood <rharwood@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-03-21 18:47:16 +01:00
Elyes Haouas edd9af9192 kern: Remove trailing whitespaces
Signed-off-by: Elyes Haouas <ehaouas@noos.fr>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-03-14 15:46:55 +01:00
Glenn Washburn a4430355a3 mm: Temporarily disable grub_mm_debug while calling grub_vprintf() in grub_printf()
To prevent infinite recursion when grub_mm_debug is on, disable it when
calling grub_vprintf(). One such call loop is:
  grub_vprintf() -> parse_printf_args() -> parse_printf_arg_fmt() ->
    grub_debug_calloc() -> grub_printf() -> grub_vprintf().

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-03-07 15:26:21 +01:00
Glenn Washburn fcf2594ca1 kern/misc: Allow selective disabling of debug facility names
Sometimes you only know which debug logging facility names you want to
turn off, not necessarily all the ones you want enabled. This patch allows
the debug string to contain facility names in the $debug variable which are
prefixed with a "-" to disable debug log messages for that conditional. Say
you want all debug logging on except for btrfs and scripting, then do:
"set debug=all,-btrfs,-scripting"

Note, that only the last occurrence of the facility name with or without a
leading "-" is considered. So simply appending ",-facilityname" to the
$debug variable will disable that conditional. To illustrate, the command
"set debug=all,-btrfs,-scripting,btrfs" will enable btrfs.

Also, add documentation explaining this new behavior.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2022-02-07 20:29:18 +01:00
Daniel Axtens 246d69b7ea mm: Document grub_mm_init_region()
The grub_mm_init_region() does some things that seem magical, especially
around region merging. Make it a bit clearer.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-12-23 03:14:25 +01:00
Daniel Axtens 1f8d0b0173 mm: Document grub_free()
The grub_free() possesses a surprising number of quirks, and also
uses single-letter variable names confusingly to iterate through
the free list.

Document what's going on.

Use prev and cur to iterate over the free list.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-12-23 03:08:27 +01:00
Daniel Axtens a847895a8d mm: grub_real_malloc(): Make small allocs comment match code
Small allocations move the region's *first pointer. The comment
says that this happens for allocations under 64K. The code says
it's for allocations under 32K. Commit 45bf8b3a75 changed the
code intentionally: make the comment match.

Fixes: 45bf8b3a75 (* grub-core/kern/mm.c (grub_real_malloc): Decrease cut-off of moving the)

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-12-23 03:02:20 +01:00
Daniel Axtens 246ad6a44c mm: Clarify grub_real_malloc()
When iterating through the singly linked list of free blocks,
grub_real_malloc() uses p and q for the current and previous blocks
respectively. This isn't super clear, so swap to using prev and cur.

This makes another quirk more obvious. The comment at the top of
grub_real_malloc() might lead you to believe that the function will
allocate from *first if there is space in that block.

It actually doesn't do that, and it can't do that with the current
data structures. If we used up all of *first, we would need to change
the ->next of the previous block to point to *first->next, but we
can't do that because it's a singly linked list and we don't have
access to *first's previous block.

What grub_real_malloc() actually does is set *first to the initial
previous block, and *first->next is the block we try to allocate
from. That allows us to keep all the data structures consistent.

Document that.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-12-23 02:59:14 +01:00
Heinrich Schuchardt d0219bffc7 efi: Create the grub_efi_close_protocol() library function
Create a library function for CloseProtocol() and use it for the SNP driver.

Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-12-23 01:33:13 +01:00
Robbie Harwood c3f323b3f5 kern/dl: Print module name on license check failure
Prior to this change, the GRUB would only indicate that the check had
been failed, but not by what module. This made it difficult to track
down either the problem module, or debug the false positive further.

Before performing the license check, resolve the module name so that
it can be printed if the license check fails.

Signed-off-by: Robbie Harwood <rharwood@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-11-02 16:13:34 +01:00
Glenn Washburn 50aace6bdb kern/misc: Add debug log condition to log output
Adding the conditional to debug log messages allows the GRUB user to
construct the $debug variable without needing to consult the source to
find the conditional (especially useful for situations where the source
is not readily available).

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-10-25 16:23:34 +02:00
Daniel Axtens 935bf8fa02 powerpc: Drop Open Hack'Ware - remove GRUB_IEEE1275_FLAG_CANNOT_INTERPRET
Open Hack'Ware was the only user.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-10-04 14:26:32 +02:00
Daniel Axtens 333e63b356 powerpc: Drop Open Hack'Ware - remove GRUB_IEEE1275_FLAG_FORCE_CLAIM
Open Hack'Ware was the only user. It added a lot of complexity.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-10-04 14:16:09 +02:00
Daniel Axtens f9ce538eec powerpc: Drop Open Hack'Ware
Open Hack'Ware was an alternative firmware of powerpc under QEMU.

The last commit to any Open Hack'Ware repo I can find is from 2014 [1].

Open Hack'Ware was used for the QEMU "prep" machine type, which was
deprecated in QEMU in commit 54c86f5a4844 (hw/ppc: deprecate the
machine type 'prep', replaced by '40p') in QEMU v3.1, and had reportedly
been broken for years before without anyone noticing. Support was removed
in February 2020 by commit b2ce76a0730e (hw/ppc/prep: Remove the
deprecated "prep" machine and the OpenHackware BIOS).

Open Hack'Ware's limitations require some messy code in GRUB. This
complexity is not worth carrying any more.

Remove detection of Open Hack'Ware. We will clean up the feature flags
in following commits.

[1]: https://github.com/qemu/openhackware and
     https://repo.or.cz/w/openhackware.git are QEMU submodules. They have
     only small changes on top of OHW v0.4.1, which was imported into
     QEMU SCM in 2010. I can't find anything resembling an official repo
     any more.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-10-04 14:04:04 +02:00
Michael Chang d307db1e75 emu: Fix executable stack marking
The gcc by default assumes executable stack is required if the source
object file doesn't have .note.GNU-stack section in place. If any of the
source objects doesn't incorporate the GNU-stack note, the resulting
program will have executable stack flag set in PT_GNU_STACK program
header to instruct program loader or kernel to set up the executable
stack when program loads to memory.

Usually the .note.GNU-stack section will be generated by gcc
automatically if it finds that executable stack is not required. However
it doesn't take care of generating .note.GNU-stack section for those
object files built from assembler sources. This leads to unnecessary
risk of security of exploiting the executable stack because those
assembler sources don't actually require stack to be executable to work.

The grub-emu and grub-emu-lite are found to flag stack as executable
revealed by execstack tool.

 $ mkdir -p build-emu && cd build-emu
 $ ../configure --with-platform=emu && make
 $ execstack -q grub-core/grub-emu grub-core/grub-emu-lite
 X grub-core/grub-emu
 X grub-core/grub-emu-lite

This patch will add the missing GNU-stack note to the assembler source
used by both utilities, therefore the result doesn't count on gcc
default behavior and the executable stack is disabled.

 $ execstack -q grub-core/grub-emu grub-core/grub-emu-lite
 - grub-core/grub-emu
 - grub-core/grub-emu-lite

Signed-off-by: Michael Chang <mchang@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-09-20 13:52:20 +02:00
Glenn Washburn 0c2aaec01d kern/fs: Allow number of blocks in block list to be optional, defaulting length to device length
This is primarily useful to do something like "loopback newdev (dev)8+" to
create a device that skips the first 4 KiB, which may contain a container
header, e.g. a non-standard RAID1 header, that GRUB does not recognize. This
would allow that container data to be potentially accessed up to the end of
container, which may be necessary for some layouts that store data at the
end. There is currently not a good way to programmatically get the number
of sectors on a disk to set the appropriate length of the blocklist.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-09-13 14:52:40 +02:00
Daniel Axtens 70ecee1e21 ieee1275: Drop HEAP_MAX_ADDR and HEAP_MIN_SIZE constants
The HEAP_MAX_ADDR is confusing. Currently it is set to 32MB, except on
ieee1275 on x86, where it is 64MB.

There is a comment which purports to explain it:

  /* If possible, we will avoid claiming heap above this address, because it
     seems to cause relocation problems with OSes that link at 4 MiB */

This doesn't make a lot of sense when the constants are well above 4MB
already. It was not always this way. Prior to commit 7b5d0fe444
(Increase heap limit) in 2010, HEAP_MAX_SIZE and HEAP_MAX_ADDR were
indeed 4MB. However, when the constants were increased the comment was
left unchanged.

It's been over a decade. It doesn't seem like we have problems with
claims over 4MB on powerpc or x86 ieee1275. The SPARC does things
completely differently and never used the constant.

Drop the constant and the check.

The only use of HEAP_MIN_SIZE was to potentially override the
HEAP_MAX_ADDR check. It is now unused. Remove it too.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-07-22 15:32:51 +02:00
Tianjia Zhang f17e8b9ed2 kern/efi/sb: Remove duplicate efi_shim_lock_guid variable
The efi_shim_lock_guid local variable and shim_lock_guid global variable
have the same GUID value. Only the latter is retained.

Signed-off-by: Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-05-28 12:49:56 +02:00
Daniel Kiper 66be067e61 i18n: Format large integers before the translation message - take 2
This is an additional fix which has been missing from the commit 837fe48de
(i18n: Format large integers before the translation message).

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
2021-05-10 15:06:33 +02:00
Miguel Ángel Arruga Vivas 837fe48deb i18n: Format large integers before the translation message
The GNU gettext only supports the ISO C99 macros for integral
types. If there is a need to use unsupported formatting macros,
e.g. PRIuGRUB_UINT64_T, according to [1] the number to a string
conversion should be separated from the code printing message
requiring the internationalization. So, the function grub_snprintf()
is used to print the numeric values to an intermediate buffer and
the internationalized message contains a string format directive.

[1] https://www.gnu.org/software/gettext/manual/html_node/Preparing-Strings.html#No-string-concatenation

Signed-off-by: Miguel Ángel Arruga Vivas <rosen644835@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-04-13 17:16:04 +02:00
Glenn Washburn d028b1a35e dl/elf: Use format code PRIxGRUB_UINT64_T for 64-bit arg in grub_error()
The macro ELF_R_TYPE does not change the underlying type. Here its argument
is a 64-bit Elf64_Xword. Make sure the format code matches.

For the RISC-V architecture, rel->r_info could be either Elf32_Xword or
Elf64_Xword depending on if 32 or 64-bit RISC-V is being built. So cast
to 64-bit value regardless.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-03-10 15:22:18 +01:00
Glenn Washburn e2ac93f09a kern/efi/mm: Format string error in grub_error()
The second format string argument, GRUB_EFI_MAX_USABLE_ADDRESS, is a macro
to a number literal. However, depending on what the target architecture, the
type can be 32 or 64 bits. Cast to a 64-bit integer. Also, change the
format string literals "%llx" to use PRIxGRUB_UINT64_T.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-03-10 14:56:06 +01:00
Glenn Washburn e96c7645f4 grub_error: Use format code PRIuGRUB_SIZE for variables of type grub_size_t
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-03-10 14:50:44 +01:00
Michael Chang 6d05264eec kern/efi/sb: Add chainloaded image as shim's verifiable object
While attempting to dual boot Microsoft Windows with UEFI chainloader,
it failed with below error when UEFI Secure Boot was enabled:

  error ../../grub-core/kern/verifiers.c:119:verification requested but
  nobody cares: /EFI/Microsoft/Boot/bootmgfw.efi.

It is a regression, as previously it worked without any problem.

It turns out chainloading PE image has been locked down by commit
578c95298 (kern: Add lockdown support). However, we should consider it
as verifiable object by shim to allow booting in UEFI Secure Boot mode.
The chainloaded PE image could also have trusted signature created by
vendor with their pubkey cert in db. For that matters it's usage should
not be locked down under UEFI Secure Boot, and instead shim should be
allowed to validate a PE binary signature before running it.

Fixes: 578c95298 (kern: Add lockdown support)

Signed-off-by: Michael Chang <mchang@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-03-10 13:49:42 +01:00
Marco A Benatto a9d8de9608 kern/mm: Fix grub_debug_calloc() compilation error
Fix compilation error due to missing parameter to
grub_printf() when MM_DEBUG is defined.

Fixes: 64e26162e (calloc: Make sure we always have an overflow-checking calloc() available)

Signed-off-by: Marco A Benatto <mbenatto@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-03-02 15:54:20 +01:00
Thomas Frauendorfer | Miray Software 83603bea6c kern/misc: Add function to check printf() format against expected format
The grub_printf_fmt_check() function parses the arguments of an untrusted
printf() format and an expected printf() format and then compares the
arguments counts and arguments types. The arguments count in the untrusted
format string must be less or equal to the arguments count in the expected
format string and both arguments types must match.

To do this the parse_printf_arg_fmt() helper function is extended in the
following way:

  1. Add a return value to report errors to the grub_printf_fmt_check().

  2. Add the fmt_check argument to enable stricter format verification:
     - the function expects that arguments definitions are always
       terminated by a supported conversion specifier.
     - positional parameters, "$", are not allowed, as they cannot be
       validated correctly with the current implementation. For example
       "%s%1$d" would assign the first args entry twice while leaving the
       second one unchanged.
     - Return an error if preallocated space in args is too small and
       allocation fails for the needed size. The grub_printf_fmt_check()
       should verify all arguments. So, if validation is not possible for
       any reason it should return an error.
     This also adds a case entry to handle "%%", which is the escape
     sequence to print "%" character.

  3. Add the max_args argument to check for the maximum allowed arguments
     count in a printf() string. This should be set to the arguments count
     of the expected format. Then the parse_printf_arg_fmt() function will
     return an error if the arguments count is exceeded.

The two additional arguments allow us to use parse_printf_arg_fmt() in
printf() and grub_printf_fmt_check() calls.

When parse_printf_arg_fmt() is used by grub_printf_fmt_check() the
function parse user provided untrusted format string too. So, in
that case it is better to be too strict than too lenient.

Signed-off-by: Thomas Frauendorfer | Miray Software <tf@miray.de>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-03-02 15:54:20 +01:00
Thomas Frauendorfer | Miray Software 1a2a5aff71 kern/misc: Add STRING type for internal printf() format handling
Set printf() argument type for "%s" to new type STRING. This is in
preparation for a follow up patch to compare a printf() format string
against an expected printf() format string.

For "%s" the corresponding printf() argument is dereferenced as pointer
while all other argument types are defined as integer value. However,
when validating a printf() format it is necessary to differentiate "%s"
from "%p" and other integers. So, let's do that.

Signed-off-by: Thomas Frauendorfer | Miray Software <tf@miray.de>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-03-02 15:54:20 +01:00
Thomas Frauendorfer | Miray Software 7f11bde314 kern/misc: Split parse_printf_args() into format parsing and va_list handling
This patch is preparing for a follow up patch which will use
the format parsing part to compare the arguments in a printf()
format from an external source against a printf() format with
expected arguments.

Signed-off-by: Thomas Frauendorfer | Miray Software <tf@miray.de>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-03-02 15:54:19 +01:00