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>
Patch-Name: 2021-02-security/111-kern-misc-Add-function-to-check-printf-format-against-expected-format.patch
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>
Patch-Name: 2021-02-security/110-kern-misc-Add-STRING-type-for-internal-printf-format-handling.patch
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>
Patch-Name: 2021-02-security/109-kern-misc-Split-parse_printf_args-into-format-parsing-and-va_list-handling.patch
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>
Patch-Name: 2021-02-security/064-kern-misc-Always-set-end-in-grub_strtoull.patch
This modifies most of the places we do some form of:
X = malloc(Y * Z);
to use calloc(Y, Z) instead.
Among other issues, this fixes:
- allocation of integer overflow in grub_png_decode_image_header()
reported by Chris Coulson,
- allocation of integer overflow in luks_recover_key()
reported by Chris Coulson,
- allocation of integer overflow in grub_lvm_detect()
reported by Chris Coulson.
Fixes: CVE-2020-14308
Signed-off-by: Peter Jones <pjones@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Patch-Name: safe-alloc-3.patch
libgcc for boot environment isn't always present and compatible.
libgcc is often absent if endianness or bit-size at boot is different
from running OS.
libgcc may use optimised opcodes that aren't available on boot time.
So instead of relying on libgcc shipped with the compiler, supply
the functions in GRUB directly.
Tests are present to ensure that those replacement functions behave the
way compiler expects them to.
Previously we supplied only unsigned divisions on platforms that need software
division.
Yet compiler may itself use a signed division. A typical example would be a
difference between 2 pointers which involves division by object size.
A bit tricky because this function has to continue to work without
heap for short strings. Fixing prealloc to 32 arguments is reasonable
but make all stack references use 32-bit offset rather than 8-bit one.
So split va_args preparsing to separate function and put the prealloc
into the caller.
On upcoming arm64 port libgcc ctz* are not usable in standalone
environment. Since we need ctz* for this case and implementation is
in C we may as well use it on all concerned platforms.
* conf/Makefile.common (CFLAGS_PLATFORM): Don't add -mrtd -mregparm=3
unconditionally.
* configure.ac: Add -no-integrated-as when using clangfor asm files.
Add -mrtd -mregparm=3 on i386 when not using clang.
* grub-core/kern/misc.c (grub_memset): Add volatile when on clang.
strncpy.
* grub-core/fs/jfs.c (grub_jfs_lookup_symlink): Likewise.
* grub-core/kern/misc.c (grub_strncpy): Move from here ...
* include/grub/misc.h (grub_strncpy): ... to here. Make inline.
* grub-core/net/net.c (grub_net_addr_to_str): Use COMPILE_TIME_ASSERT
+ strcpy rather than strncpy.
per common usage and preffered in several parts of code.
(grub_memcmp): Likewise.
(grub_strncmp): Likewise.
* include/grub/misc.h (grub_strcasecmp): Likewise.
(grub_strncasecmp): Likewise.
* Makefile.util.def (cmp_test): New test.
(grub_script_strcmp): Likewise.
* tests/cmp_unit_test.c: New file.
* tests/grub_script_strcmp.in: Likewise.
* grub-core/fs/hfsplus.c (grub_hfsplus_cmp_catkey): Add a comment.
checks which are always false on some platforms.
(grub_cmd_lsacpi): Likewise.
* grub-core/kern/misc.c (grub_strtoul): Likewise.
* grub-core/loader/multiboot.c (grub_multiboot_set_video_mode):
Likewise.