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>
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>
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>
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>
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>
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>
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 45bf8b3a7549 changed the
code intentionally: make the comment match.
Fixes: 45bf8b3a7549 (* 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>
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>
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>
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>
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>
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>
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>
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>
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>
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 7b5d0fe4440c
(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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
Commit 32ddc42c (efi: Only register shim_lock verifier if shim_lock
protocol is found and SB enabled) reintroduced CVE-2020-15705 which
previously only existed in the out-of-tree linuxefi patches and was
fixed as part of the BootHole patch series.
Under Secure Boot enforce loading shim_lock verifier. Allow skipping
shim_lock verifier if SecureBoot/MokSBState EFI variables indicate
skipping validations, or if GRUB image is built with --disable-shim-lock.
Fixes: 132ddc42c (efi: Only register shim_lock verifier if shim_lock
protocol is found and SB enabled)
Fixes: CVE-2020-15705
Fixes: CVE-2021-3418
Reported-by: Dimitri John Ledkov <xnox@ubuntu.com>
Signed-off-by: Dimitri John Ledkov <xnox@ubuntu.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
It works only on UEFI platforms but can be quite easily extended to
others architectures and platforms if needed.
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Marco A Benatto <mbenatto@redhat.com>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
grub_parser_split_cmdline() expands variable names present in the supplied
command line in to their corresponding variable contents and uses a 1 kiB
stack buffer for temporary storage without sufficient bounds checking. If
the function is called with a command line that references a variable with
a sufficiently large payload, it is possible to overflow the stack
buffer via tab completion, corrupt the stack frame and potentially
control execution.
Fixes: CVE-2020-27749
Reported-by: Chris Coulson <chris.coulson@canonical.com>
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Add a new variable sized heap buffer type (grub_buffer_t) with simple
operations for appending data, accessing the data and maintaining
a read cursor.
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Introduce a common function epilogue used for cleaning up on all
return paths, which will simplify additional error handling to be
introduced in a subsequent commit.
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
process_char() and grub_parser_split_cmdline() use similar code for
terminating the most recent argument. Add a helper function for this.
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
grub_parser_split_cmdline() iterates over each command line character.
In order to add error checking and to simplify the subsequent error
handling, split the character processing in to a separate function.
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
The getline() function supplied to grub_parser_split_cmdline() returns
a newly allocated buffer and can be called multiple times, but the
returned buffer is never freed.
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Currently, if there is an error in grub_strtoull(), *end is not set.
This differs from the usual behavior of strtoull(), and also means that
some callers may use an uninitialized value for *end.
Set *end unconditionally.
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
There is the possibility that the value of str comes from an external
source and continuing to use it before ever checking its validity is
wrong. So, needs fixing.
Additionally, drop unneeded part initialization.
Fixes: CID 292444
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
The model of grub_efi_get_memory_map() is that if memory_map is NULL,
then the purpose is to discover how much memory should be allocated to
it for the subsequent call.
The problem here is that with grub_efi_is_finished set to 1, there is no
check at all that the function is being called with a non-NULL memory_map.
While this MAY be true, we shouldn't assume it.
The solution to this is to behave as expected, and if memory_map is NULL,
then don't try to use it and allow memory_map_size to be filled in, and
return 0 as is done later in the code if the buffer is too small (or NULL).
Additionally, drop unneeded ret = 1.
Fixes: CID 96632
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Free the memory allocated to name before returning on failure.
Fixes: CID 296222
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
After processing the command-line yet arriving at the point where we are
setting argv, we are allocating memory, even if argc == 0, which makes
no sense since we never put anything into the allocated argv.
The solution is to simply return that we've successfully processed the
arguments but that argc == 0, and also ensure that argv is NULL when
we're not allocating anything in it.
There are only 2 callers of this function, and both are handling a zero
value in argc assuming nothing is allocated in argv.
Fixes: CID 96680
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
When a module is attempted to be removed its reference counter is always
decremented. This means that repeated rmmod invocations will cause the
module to be unloaded even if another module depends on it.
This may lead to a use-after-free scenario allowing an attacker to execute
arbitrary code and by-pass the UEFI Secure Boot protection.
While being there, add the extern keyword to some function declarations in
that header file.
Fixes: CVE-2020-25632
Reported-by: Chris Coulson <chris.coulson@canonical.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Now the GRUB can check if it has been locked down and this can be used to
prevent executing commands that can be utilized to circumvent the UEFI
Secure Boot mechanisms. So, instead of hardcoding a list of modules that
have to be disabled, prevent the usage of commands that can be dangerous.
This not only allows the commands to be disabled on other platforms, but
also properly separate the concerns. Since the shim_lock verifier logic
should be only about preventing to run untrusted binaries and not about
defining these kind of policies.
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
If the UEFI Secure Boot is enabled then the GRUB must be locked down
to prevent executing code that can potentially be used to subvert its
verification mechanisms.
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
It may be useful for scripts to determine whether the GRUB is locked
down or not. Add the lockdown variable which is set to "y" when the GRUB
is locked down.
Suggested-by: Dimitri John Ledkov <xnox@ubuntu.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
When the GRUB starts on a secure boot platform, some commands can be
used to subvert the protections provided by the verification mechanism and
could lead to booting untrusted system.
To prevent that situation, allow GRUB to be locked down. That way the code
may check if GRUB has been locked down and further restrict the commands
that are registered or what subset of their functionality could be used.
The lockdown support adds the following components:
* The grub_lockdown() function which can be used to lockdown GRUB if,
e.g., UEFI Secure Boot is enabled.
* The grub_is_lockdown() function which can be used to check if the GRUB
was locked down.
* A verifier that flags OS kernels, the GRUB modules, Device Trees and ACPI
tables as GRUB_VERIFY_FLAGS_DEFER_AUTH to defer verification to other
verifiers. These files are only successfully verified if another registered
verifier returns success. Otherwise, the whole verification process fails.
For example, PE/COFF binaries verification can be done by the shim_lock
verifier which validates the signatures using the shim_lock protocol.
However, the verification is not deferred directly to the shim_lock verifier.
The shim_lock verifier is hooked into the verification process instead.
* A set of grub_{command,extcmd}_lockdown functions that can be used by
code registering command handlers, to only register unsafe commands if
the GRUB has not been locked down.
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Move the shim_lock verifier from its own module into the core image. The
Secure Boot lockdown mechanism has the intent to prevent the load of any
unsigned code or binary when Secure Boot is enabled.
The reason is that GRUB must be able to prevent executing untrusted code
if UEFI Secure Boot is enabled, without depending on external modules.
Signed-off-by: Marco A Benatto <mbenatto@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Move verifiers API from a module to the kernel image, so it can be
used there as well. There are no functional changes in this patch.
Signed-off-by: Marco A Benatto <mbenatto@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This patch is similar to commit 9dab2f51e (sparc: Enable __clzsi2() and
__clzdi2()) but for MIPS target and __clzdi2() only, __clzsi2() was
already enabled.
Suggested-by: Daniel Kiper <dkiper@net-space.pl>
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>