import grub2-2.02-87.el8_2
This commit is contained in:
parent
11a606d215
commit
05b11d159c
@ -1,33 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Wed, 11 Jul 2018 13:48:48 -0400
|
||||
Subject: [PATCH] Disable multiboot, multiboot2, and linux16 modules on EFI
|
||||
builds.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
---
|
||||
grub-core/Makefile.core.def | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||
index aa44d66aca4..d3e3bfd4d7a 100644
|
||||
--- a/grub-core/Makefile.core.def
|
||||
+++ b/grub-core/Makefile.core.def
|
||||
@@ -1680,7 +1680,7 @@ module = {
|
||||
|
||||
common = loader/multiboot.c;
|
||||
common = loader/multiboot_mbi2.c;
|
||||
- enable = x86;
|
||||
+ enable = i386_pc;
|
||||
enable = mips;
|
||||
};
|
||||
|
||||
@@ -1689,7 +1689,7 @@ module = {
|
||||
common = loader/multiboot.c;
|
||||
x86 = loader/i386/multiboot_mbi.c;
|
||||
extra_dist = loader/multiboot_elfxx.c;
|
||||
- enable = x86;
|
||||
+ enable = i386_pc;
|
||||
};
|
||||
|
||||
module = {
|
@ -9,7 +9,7 @@ Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
1 file changed, 6 deletions(-)
|
||||
|
||||
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||
index d3e3bfd4d7a..715d3a3ec02 100644
|
||||
index aa44d66aca4..e35217b8668 100644
|
||||
--- a/grub-core/Makefile.core.def
|
||||
+++ b/grub-core/Makefile.core.def
|
||||
@@ -2186,12 +2186,6 @@ module = {
|
@ -22,7 +22,7 @@ Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
5 files changed, 9 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||
index 715d3a3ec02..203584fb00b 100644
|
||||
index e35217b8668..cf3d549d212 100644
|
||||
--- a/grub-core/Makefile.core.def
|
||||
+++ b/grub-core/Makefile.core.def
|
||||
@@ -166,7 +166,6 @@ kernel = {
|
@ -38,7 +38,7 @@ Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
|
||||
delete mode 100644 grub-core/kern/i386/pc/tpm.c
|
||||
|
||||
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||
index 203584fb00b..01c5f9ae351 100644
|
||||
index cf3d549d212..fb0a1e0babb 100644
|
||||
--- a/grub-core/Makefile.core.def
|
||||
+++ b/grub-core/Makefile.core.def
|
||||
@@ -246,7 +246,6 @@ kernel = {
|
@ -27,7 +27,7 @@ Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
|
||||
rename grub-core/{kern/qsort.c => commands/bls_qsort.h} (93%)
|
||||
|
||||
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||
index 01c5f9ae351..f99fc994f6b 100644
|
||||
index fb0a1e0babb..3346d1be658 100644
|
||||
--- a/grub-core/Makefile.core.def
|
||||
+++ b/grub-core/Makefile.core.def
|
||||
@@ -129,7 +129,6 @@ kernel = {
|
@ -14,7 +14,7 @@ Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||
index f99fc994f6b..5b4841e1f00 100644
|
||||
index 3346d1be658..6864e780fd4 100644
|
||||
--- a/grub-core/Makefile.core.def
|
||||
+++ b/grub-core/Makefile.core.def
|
||||
@@ -782,6 +782,7 @@ module = {
|
@ -0,0 +1,50 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Javier Martinez Canillas <javierm@redhat.com>
|
||||
Date: Thu, 5 Mar 2020 16:21:47 +0100
|
||||
Subject: [PATCH] efi/http: Export {fw,http}_path variables to make them global
|
||||
|
||||
The fw_path environment variable is used by http_configure() function to
|
||||
determine the HTTP path that should be used as prefix when using relative
|
||||
HTTP paths. And this is stored in the http_path environment variable.
|
||||
|
||||
Later, that variable is looked up by grub_efihttp_open() to generate the
|
||||
complete path to be used in the HTTP request.
|
||||
|
||||
But these variables are not exported, which means that are not global and
|
||||
so are only found in the initial context.
|
||||
|
||||
This can cause commands like configfile that create a new context to fail
|
||||
because the fw_path and http_path variables will not be found.
|
||||
|
||||
Resolves: rhbz#1811561
|
||||
|
||||
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
|
||||
---
|
||||
grub-core/kern/main.c | 1 +
|
||||
grub-core/net/efi/http.c | 1 +
|
||||
2 files changed, 2 insertions(+)
|
||||
|
||||
diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
|
||||
index dcf48726d54..9bf6a8b231a 100644
|
||||
--- a/grub-core/kern/main.c
|
||||
+++ b/grub-core/kern/main.c
|
||||
@@ -142,6 +142,7 @@ grub_set_prefix_and_root (void)
|
||||
if (fw_path)
|
||||
{
|
||||
grub_env_set ("fw_path", fw_path);
|
||||
+ grub_env_export ("fw_path");
|
||||
grub_dprintf ("fw_path", "fw_path:\"%s\"\n", fw_path);
|
||||
grub_free (fw_path);
|
||||
}
|
||||
diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c
|
||||
index de351b2cd03..755b7a6d054 100644
|
||||
--- a/grub-core/net/efi/http.c
|
||||
+++ b/grub-core/net/efi/http.c
|
||||
@@ -39,6 +39,7 @@ http_configure (struct grub_efi_net_device *dev, int prefer_ip6)
|
||||
http_path++;
|
||||
grub_env_unset ("http_path");
|
||||
grub_env_set ("http_path", http_path);
|
||||
+ grub_env_export ("http_path");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,114 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Javier Martinez Canillas <javierm@redhat.com>
|
||||
Date: Thu, 5 Mar 2020 16:21:58 +0100
|
||||
Subject: [PATCH] efi/http: Enclose literal IPv6 addresses in square brackets
|
||||
|
||||
According to RFC 2732 (https://www.ietf.org/rfc/rfc2732.txt), literal IPv6
|
||||
addresses must be enclosed in square brackets. But GRUB currently does not
|
||||
do this and is causing HTTP servers to send Bad Request (400) responses.
|
||||
|
||||
For example, the following is the HTTP stream when fetching a config file:
|
||||
|
||||
HEAD /EFI/BOOT/grub.cfg HTTP/1.1
|
||||
Host: 2000:dead:beef:a::1
|
||||
Accept: */*
|
||||
User-Agent: UefiHttpBoot/1.0
|
||||
|
||||
HTTP/1.1 400 Bad Request
|
||||
Date: Thu, 05 Mar 2020 14:46:02 GMT
|
||||
Server: Apache/2.4.41 (Fedora) OpenSSL/1.1.1d
|
||||
Connection: close
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
|
||||
and after enclosing the IPv6 address the HTTP request is successful:
|
||||
|
||||
HEAD /EFI/BOOT/grub.cfg HTTP/1.1
|
||||
Host: [2000:dead:beef:a::1]
|
||||
Accept: */*
|
||||
User-Agent: UefiHttpBoot/1.0
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Date: Thu, 05 Mar 2020 14:48:04 GMT
|
||||
Server: Apache/2.4.41 (Fedora) OpenSSL/1.1.1d
|
||||
Last-Modified: Thu, 27 Feb 2020 17:45:58 GMT
|
||||
ETag: "206-59f924b24b1da"
|
||||
Accept-Ranges: bytes
|
||||
Content-Length: 518
|
||||
|
||||
Resolves: rhbz#1811560
|
||||
|
||||
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
|
||||
---
|
||||
grub-core/net/efi/http.c | 37 ++++++++++++++++++++++++++++---------
|
||||
1 file changed, 28 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c
|
||||
index 755b7a6d054..fc8cb25ae0a 100644
|
||||
--- a/grub-core/net/efi/http.c
|
||||
+++ b/grub-core/net/efi/http.c
|
||||
@@ -158,13 +158,7 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https,
|
||||
grub_efi_status_t status;
|
||||
grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
|
||||
char *url = NULL;
|
||||
-
|
||||
- request_headers[0].field_name = (grub_efi_char8_t *)"Host";
|
||||
- request_headers[0].field_value = (grub_efi_char8_t *)server;
|
||||
- request_headers[1].field_name = (grub_efi_char8_t *)"Accept";
|
||||
- request_headers[1].field_value = (grub_efi_char8_t *)"*/*";
|
||||
- request_headers[2].field_name = (grub_efi_char8_t *)"User-Agent";
|
||||
- request_headers[2].field_value = (grub_efi_char8_t *)"UefiHttpBoot/1.0";
|
||||
+ char *hostname = NULL;
|
||||
|
||||
{
|
||||
grub_efi_ipv6_address_t address;
|
||||
@@ -174,9 +168,24 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https,
|
||||
const char *protocol = (use_https == 1) ? "https" : "http";
|
||||
|
||||
if (grub_efi_string_to_ip6_address (server, &address, &rest) && *rest == 0)
|
||||
- url = grub_xasprintf ("%s://[%s]%s", protocol, server, name);
|
||||
+ {
|
||||
+ hostname = grub_xasprintf ("[%s]", server);
|
||||
+ if (!hostname)
|
||||
+ return GRUB_ERR_OUT_OF_MEMORY;
|
||||
+
|
||||
+ server = hostname;
|
||||
+
|
||||
+ url = grub_xasprintf ("%s://%s%s", protocol, server, name);
|
||||
+ if (!url)
|
||||
+ {
|
||||
+ grub_free (hostname);
|
||||
+ return GRUB_ERR_OUT_OF_MEMORY;
|
||||
+ }
|
||||
+ }
|
||||
else
|
||||
- url = grub_xasprintf ("%s://%s%s", protocol, server, name);
|
||||
+ {
|
||||
+ url = grub_xasprintf ("%s://%s%s", protocol, server, name);
|
||||
+ }
|
||||
|
||||
if (!url)
|
||||
{
|
||||
@@ -199,6 +208,13 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https,
|
||||
request_data.url = ucs2_url;
|
||||
}
|
||||
|
||||
+ request_headers[0].field_name = (grub_efi_char8_t *)"Host";
|
||||
+ request_headers[0].field_value = (grub_efi_char8_t *)server;
|
||||
+ request_headers[1].field_name = (grub_efi_char8_t *)"Accept";
|
||||
+ request_headers[1].field_value = (grub_efi_char8_t *)"*/*";
|
||||
+ request_headers[2].field_name = (grub_efi_char8_t *)"User-Agent";
|
||||
+ request_headers[2].field_value = (grub_efi_char8_t *)"UefiHttpBoot/1.0";
|
||||
+
|
||||
request_data.method = (headeronly > 0) ? GRUB_EFI_HTTPMETHODHEAD : GRUB_EFI_HTTPMETHODGET;
|
||||
|
||||
request_message.data.request = &request_data;
|
||||
@@ -228,6 +244,9 @@ efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https,
|
||||
|
||||
status = efi_call_2 (http->request, http, &request_token);
|
||||
|
||||
+ if (hostname)
|
||||
+ grub_free (hostname);
|
||||
+
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
{
|
||||
efi_call_1 (b->close_event, request_token.event);
|
@ -0,0 +1,48 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Javier Martinez Canillas <javierm@redhat.com>
|
||||
Date: Mon, 9 Mar 2020 15:29:45 +0100
|
||||
Subject: [PATCH] efi/net: Allow to specify a port number in addresses
|
||||
|
||||
The grub_efi_net_parse_address() function is not covering the case where a
|
||||
port number is specified in an IPv4 or IPv6 address, so will fail to parse
|
||||
the network address.
|
||||
|
||||
For most cases the issue is harmless, because the function is only used to
|
||||
match an address with a network interface and if fails the default is used.
|
||||
|
||||
But still is a bug that has to be fixed and it causes error messages to be
|
||||
printed like the following:
|
||||
|
||||
error: net/efi/net.c:782:unrecognised network address '192.168.122.1:8080'
|
||||
|
||||
error: net/efi/net.c:781:unrecognised network address '[2000:dead:beef:a::1]:8080'
|
||||
|
||||
Resolves: rhbz#1811560
|
||||
|
||||
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
|
||||
---
|
||||
grub-core/net/efi/net.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c
|
||||
index 4c70fc4da2a..c74854a82b7 100644
|
||||
--- a/grub-core/net/efi/net.c
|
||||
+++ b/grub-core/net/efi/net.c
|
||||
@@ -742,7 +742,7 @@ grub_efi_net_parse_address (const char *address,
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
- else if (*rest == 0)
|
||||
+ else if (*rest == 0 || *rest == ':')
|
||||
{
|
||||
grub_uint32_t subnet_mask = 0xffffffffU;
|
||||
grub_memcpy (ip4->subnet_mask, &subnet_mask, sizeof (ip4->subnet_mask));
|
||||
@@ -768,7 +768,7 @@ grub_efi_net_parse_address (const char *address,
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
- else if (*rest == 0)
|
||||
+ else if (*rest == 0 || *rest == ':')
|
||||
{
|
||||
ip6->prefix_length = 128;
|
||||
ip6->is_anycast = 0;
|
@ -0,0 +1,48 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Javier Martinez Canillas <javierm@redhat.com>
|
||||
Date: Mon, 9 Mar 2020 15:30:05 +0100
|
||||
Subject: [PATCH] efi/ip4_config: Improve check to detect literal IPv6
|
||||
addresses
|
||||
|
||||
The grub_efi_string_to_ip4_address() function wrongly assumes that an IPv6
|
||||
address is an IPv4 address, because it doesn't take into account the case
|
||||
of a caller passing an IPv6 address as a string.
|
||||
|
||||
This leads to the grub_efi_net_parse_address() function to fail and print
|
||||
the following error message:
|
||||
|
||||
error: net/efi/net.c:785:unrecognised network address '2000:dead:beef:a::1'
|
||||
|
||||
Resolves: rhbz#1811560
|
||||
|
||||
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
|
||||
---
|
||||
grub-core/net/efi/ip4_config.c | 13 ++++++++++++-
|
||||
1 file changed, 12 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c
|
||||
index 38e2a04747a..6117e60ab12 100644
|
||||
--- a/grub-core/net/efi/ip4_config.c
|
||||
+++ b/grub-core/net/efi/ip4_config.c
|
||||
@@ -56,9 +56,20 @@ int
|
||||
grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest)
|
||||
{
|
||||
grub_uint32_t newip = 0;
|
||||
- int i;
|
||||
+ int i, ncolon = 0;
|
||||
const char *ptr = val;
|
||||
|
||||
+ /* Check that is not an IPv6 address */
|
||||
+ for (i = 0; i < grub_strlen(ptr); i++)
|
||||
+ {
|
||||
+ if (ptr[i] == '[' && i == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (ptr[i] == ':')
|
||||
+ if (i == 0 || ++ncolon == 2)
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
unsigned long t;
|
@ -0,0 +1,68 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Javier Martinez Canillas <javierm@redhat.com>
|
||||
Date: Tue, 10 Mar 2020 11:23:49 +0100
|
||||
Subject: [PATCH] efi/net: Print a debug message if parsing the address fails
|
||||
|
||||
Currently if parsing the address fails an error message is printed. But in
|
||||
most cases this isn't a fatal error since the grub_efi_net_parse_address()
|
||||
function is only used to match an address with a network interface to use.
|
||||
|
||||
And if this fails, the default interface is used which is good enough for
|
||||
most cases. So instead of printing an error that would pollute the console
|
||||
just print a debug message if the address is not parsed correctly.
|
||||
|
||||
A user can enable debug messages for the efinet driver to have information
|
||||
about the failure and the fact that the default interface is being used.
|
||||
|
||||
Related: rhbz#1811560
|
||||
|
||||
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
|
||||
---
|
||||
grub-core/net/efi/net.c | 18 +++++++++++-------
|
||||
1 file changed, 11 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c
|
||||
index c74854a82b7..3ae1fbbe3c8 100644
|
||||
--- a/grub-core/net/efi/net.c
|
||||
+++ b/grub-core/net/efi/net.c
|
||||
@@ -778,9 +778,9 @@ grub_efi_net_parse_address (const char *address,
|
||||
}
|
||||
}
|
||||
|
||||
- return grub_error (GRUB_ERR_NET_BAD_ADDRESS,
|
||||
- N_("unrecognised network address `%s'"),
|
||||
- address);
|
||||
+ grub_dprintf ("efinet", "unrecognised network address '%s'\n", address);
|
||||
+
|
||||
+ return GRUB_ERR_NET_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
static grub_efi_net_interface_t *
|
||||
@@ -795,10 +795,7 @@ match_route (const char *server)
|
||||
err = grub_efi_net_parse_address (server, &ip4, &ip6, &is_ip6, 0);
|
||||
|
||||
if (err)
|
||||
- {
|
||||
- grub_print_error ();
|
||||
return NULL;
|
||||
- }
|
||||
|
||||
if (is_ip6)
|
||||
{
|
||||
@@ -1233,8 +1230,15 @@ grub_net_open_real (const char *name __attribute__ ((unused)))
|
||||
/*FIXME: Use DNS translate name to address */
|
||||
net_interface = match_route (server);
|
||||
|
||||
+ if (!net_interface && net_default_interface)
|
||||
+ {
|
||||
+ net_interface = net_default_interface;
|
||||
+ grub_dprintf ("efinet", "interface lookup failed, using default '%s'\n",
|
||||
+ net_interface->name);
|
||||
+ }
|
||||
+
|
||||
/*XXX: should we check device with default gateway ? */
|
||||
- if (!net_interface && !(net_interface = net_default_interface))
|
||||
+ if (!net_interface)
|
||||
{
|
||||
grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' no route found"),
|
||||
name);
|
@ -0,0 +1,60 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Javier Martinez Canillas <javierm@redhat.com>
|
||||
Date: Thu, 23 Apr 2020 15:06:46 +0200
|
||||
Subject: [PATCH] efi: Set image base address before jumping to the PE/COFF
|
||||
entry point
|
||||
|
||||
Upstream GRUB uses the EFI LoadImage() and StartImage() to boot the Linux
|
||||
kernel. But our custom EFI loader that supports Secure Boot instead uses
|
||||
the EFI handover protocol (for x86) or jumping directly to the PE/COFF
|
||||
entry point (for aarch64).
|
||||
|
||||
This is done to allow the bootloader to verify the images using the shim
|
||||
lock protocol to avoid booting untrusted binaries.
|
||||
|
||||
Since the bootloader loads the kernel from the boot media instead of using
|
||||
LoadImage(), it is responsible to set the Loaded Image base address before
|
||||
booting the kernel.
|
||||
|
||||
Otherwise the kernel EFI stub will complain that it was not set correctly
|
||||
and print the following warning message:
|
||||
|
||||
EFI stub: ERROR: FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value
|
||||
|
||||
Resolves: rhbz#1819624
|
||||
|
||||
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
|
||||
---
|
||||
grub-core/loader/efi/linux.c | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
|
||||
index b56ea0bc041..e09f824862b 100644
|
||||
--- a/grub-core/loader/efi/linux.c
|
||||
+++ b/grub-core/loader/efi/linux.c
|
||||
@@ -72,6 +72,7 @@ grub_err_t
|
||||
grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
|
||||
void *kernel_params)
|
||||
{
|
||||
+ grub_efi_loaded_image_t *loaded_image = NULL;
|
||||
handover_func hf;
|
||||
int offset = 0;
|
||||
|
||||
@@ -79,6 +80,17 @@ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
|
||||
offset = 512;
|
||||
#endif
|
||||
|
||||
+ /*
|
||||
+ * Since the EFI loader is not calling the LoadImage() and StartImage()
|
||||
+ * services for loading the kernel and booting respectively, it has to
|
||||
+ * set the Loaded Image base address.
|
||||
+ */
|
||||
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
|
||||
+ if (loaded_image)
|
||||
+ loaded_image->image_base = kernel_addr;
|
||||
+ else
|
||||
+ grub_dprintf ("linux", "Loaded Image base address could not be set\n");
|
||||
+
|
||||
grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n",
|
||||
kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params);
|
||||
hf = (handover_func)((char *)kernel_addr + handover_offset + offset);
|
196
SOURCES/0278-Reimplement-boot_counter.patch
Normal file
196
SOURCES/0278-Reimplement-boot_counter.patch
Normal file
@ -0,0 +1,196 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Thu, 4 Oct 2018 14:22:09 -0400
|
||||
Subject: [PATCH] Reimplement boot_counter
|
||||
|
||||
This adds "increment" and "decrement" commands, and uses them to maintain our
|
||||
variables in 01_fallback_counter. It also simplifies the counter logic, so
|
||||
that there are no nested tests that conflict with each other.
|
||||
|
||||
Apparently, this *really* wasn't tested well enough.
|
||||
|
||||
Resolves: rhbz#1614637
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
[lorbus: add comments and revert logic changes in 01_fallback_counting]
|
||||
Signed-off-by: Christian Glombek <lorbus@fedoraproject.org>
|
||||
---
|
||||
Makefile.util.def | 6 +++
|
||||
grub-core/Makefile.core.def | 5 ++
|
||||
grub-core/commands/increment.c | 105 ++++++++++++++++++++++++++++++++++++
|
||||
util/grub.d/01_fallback_counting.in | 22 ++++++++
|
||||
4 files changed, 138 insertions(+)
|
||||
create mode 100644 grub-core/commands/increment.c
|
||||
create mode 100644 util/grub.d/01_fallback_counting.in
|
||||
|
||||
diff --git a/Makefile.util.def b/Makefile.util.def
|
||||
index 08cc98ddb8b..eca3dfa753f 100644
|
||||
--- a/Makefile.util.def
|
||||
+++ b/Makefile.util.def
|
||||
@@ -448,6 +448,12 @@ script = {
|
||||
installdir = grubconf;
|
||||
};
|
||||
|
||||
+script = {
|
||||
+ name = '01_fallback_counting';
|
||||
+ common = util/grub.d/01_fallback_counting.in;
|
||||
+ installdir = grubconf;
|
||||
+};
|
||||
+
|
||||
script = {
|
||||
name = '01_menu_auto_hide';
|
||||
common = util/grub.d/01_menu_auto_hide.in;
|
||||
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||
index 6864e780fd4..c8a50b4fcfa 100644
|
||||
--- a/grub-core/Makefile.core.def
|
||||
+++ b/grub-core/Makefile.core.def
|
||||
@@ -362,6 +362,11 @@ kernel = {
|
||||
extra_dist = kern/mips/cache_flush.S;
|
||||
};
|
||||
|
||||
+module = {
|
||||
+ name = increment;
|
||||
+ common = commands/increment.c;
|
||||
+};
|
||||
+
|
||||
program = {
|
||||
name = grub-emu;
|
||||
mansection = 1;
|
||||
diff --git a/grub-core/commands/increment.c b/grub-core/commands/increment.c
|
||||
new file mode 100644
|
||||
index 00000000000..79cf137656c
|
||||
--- /dev/null
|
||||
+++ b/grub-core/commands/increment.c
|
||||
@@ -0,0 +1,105 @@
|
||||
+/* increment.c - Commands to increment and decrement variables. */
|
||||
+/*
|
||||
+ * GRUB -- GRand Unified Bootloader
|
||||
+ * Copyright (C) 2006,2007,2008 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 <http://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+#include <grub/dl.h>
|
||||
+#include <grub/term.h>
|
||||
+#include <grub/time.h>
|
||||
+#include <grub/types.h>
|
||||
+#include <grub/misc.h>
|
||||
+#include <grub/extcmd.h>
|
||||
+#include <grub/i18n.h>
|
||||
+#include <grub/env.h>
|
||||
+
|
||||
+GRUB_MOD_LICENSE ("GPLv3+");
|
||||
+
|
||||
+typedef enum {
|
||||
+ INCREMENT,
|
||||
+ DECREMENT,
|
||||
+} operation;
|
||||
+
|
||||
+static grub_err_t
|
||||
+incr_decr(operation op, int argc, char **args)
|
||||
+{
|
||||
+ const char *old;
|
||||
+ char *new;
|
||||
+ long value;
|
||||
+
|
||||
+ if (argc < 1)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no variable specified"));
|
||||
+ if (argc > 1)
|
||||
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("too many arguments"));
|
||||
+
|
||||
+ old = grub_env_get (*args);
|
||||
+ if (!old)
|
||||
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("No such variable \"%s\""),
|
||||
+ *args);
|
||||
+
|
||||
+ value = grub_strtol (old, NULL, 0);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
+
|
||||
+ switch (op)
|
||||
+ {
|
||||
+ case INCREMENT:
|
||||
+ value += 1;
|
||||
+ break;
|
||||
+ case DECREMENT:
|
||||
+ value -= 1;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ new = grub_xasprintf ("%ld", value);
|
||||
+ if (!new)
|
||||
+ return grub_errno;
|
||||
+
|
||||
+ grub_env_set (*args, new);
|
||||
+ grub_free (new);
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+static grub_err_t
|
||||
+grub_cmd_incr(struct grub_command *cmd UNUSED,
|
||||
+ int argc, char **args)
|
||||
+{
|
||||
+ return incr_decr(INCREMENT, argc, args);
|
||||
+}
|
||||
+
|
||||
+static grub_err_t
|
||||
+grub_cmd_decr(struct grub_command *cmd UNUSED,
|
||||
+ int argc, char **args)
|
||||
+{
|
||||
+ return incr_decr(DECREMENT, argc, args);
|
||||
+}
|
||||
+
|
||||
+static grub_command_t cmd_incr, cmd_decr;
|
||||
+
|
||||
+GRUB_MOD_INIT(increment)
|
||||
+{
|
||||
+ cmd_incr = grub_register_command ("increment", grub_cmd_incr, N_("VARIABLE"),
|
||||
+ N_("increment VARIABLE"));
|
||||
+ cmd_decr = grub_register_command ("decrement", grub_cmd_decr, N_("VARIABLE"),
|
||||
+ N_("decrement VARIABLE"));
|
||||
+}
|
||||
+
|
||||
+GRUB_MOD_FINI(increment)
|
||||
+{
|
||||
+ grub_unregister_command (cmd_incr);
|
||||
+ grub_unregister_command (cmd_decr);
|
||||
+}
|
||||
diff --git a/util/grub.d/01_fallback_counting.in b/util/grub.d/01_fallback_counting.in
|
||||
new file mode 100644
|
||||
index 00000000000..be0e770ea82
|
||||
--- /dev/null
|
||||
+++ b/util/grub.d/01_fallback_counting.in
|
||||
@@ -0,0 +1,22 @@
|
||||
+#! /bin/sh -e
|
||||
+
|
||||
+# Boot Counting
|
||||
+# The boot_counter env var can be used to count down boot attempts after an
|
||||
+# OSTree upgrade and choose the rollback deployment when 0 is reached. Both
|
||||
+# boot_counter and boot_success need to be (re-)set from userspace.
|
||||
+cat << EOF
|
||||
+insmod increment
|
||||
+# Check if boot_counter exists and boot_success=0 to activate this behaviour.
|
||||
+if [ -n "\${boot_counter}" -a "\${boot_success}" = "0" ]; then
|
||||
+ # if countdown has ended, choose to boot rollback deployment (default=1 on
|
||||
+ # OSTree-based systems)
|
||||
+ if [ "\${boot_counter}" = "0" -o "\${boot_counter}" = "-1" ]; then
|
||||
+ set default=1
|
||||
+ set boot_counter=-1
|
||||
+ # otherwise decrement boot_counter
|
||||
+ else
|
||||
+ decrement boot_counter
|
||||
+ fi
|
||||
+ save_env boot_counter
|
||||
+fi
|
||||
+EOF
|
@ -0,0 +1,165 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Glombek <lorbus@fedoraproject.org>
|
||||
Date: Tue, 2 Apr 2019 16:22:21 +0200
|
||||
Subject: [PATCH] grub.d: Split out boot success reset from menu auto hide
|
||||
script
|
||||
|
||||
Also rename fallback and menu auto hide script to be executed
|
||||
before and after boot success reset script.
|
||||
In menu auto hide script, rename last_boot_ok var to menu_hide_ok
|
||||
---
|
||||
Makefile.util.def | 14 ++++++++----
|
||||
...allback_counting.in => 08_fallback_counting.in} | 14 ++++++------
|
||||
util/grub.d/10_reset_boot_success.in | 25 ++++++++++++++++++++++
|
||||
.../{01_menu_auto_hide.in => 12_menu_auto_hide.in} | 23 +++++---------------
|
||||
4 files changed, 48 insertions(+), 28 deletions(-)
|
||||
rename util/grub.d/{01_fallback_counting.in => 08_fallback_counting.in} (65%)
|
||||
create mode 100644 util/grub.d/10_reset_boot_success.in
|
||||
rename util/grub.d/{01_menu_auto_hide.in => 12_menu_auto_hide.in} (58%)
|
||||
|
||||
diff --git a/Makefile.util.def b/Makefile.util.def
|
||||
index eca3dfa753f..5062a0e50fa 100644
|
||||
--- a/Makefile.util.def
|
||||
+++ b/Makefile.util.def
|
||||
@@ -449,14 +449,14 @@ script = {
|
||||
};
|
||||
|
||||
script = {
|
||||
- name = '01_fallback_counting';
|
||||
- common = util/grub.d/01_fallback_counting.in;
|
||||
+ name = '08_fallback_counting';
|
||||
+ common = util/grub.d/08_fallback_counting.in;
|
||||
installdir = grubconf;
|
||||
};
|
||||
|
||||
script = {
|
||||
- name = '01_menu_auto_hide';
|
||||
- common = util/grub.d/01_menu_auto_hide.in;
|
||||
+ name = '12_menu_auto_hide';
|
||||
+ common = util/grub.d/12_menu_auto_hide.in;
|
||||
installdir = grubconf;
|
||||
};
|
||||
|
||||
@@ -515,6 +515,12 @@ script = {
|
||||
condition = COND_HOST_LINUX;
|
||||
};
|
||||
|
||||
+script = {
|
||||
+ name = '10_reset_boot_success';
|
||||
+ common = util/grub.d/10_reset_boot_success.in;
|
||||
+ installdir = grubconf;
|
||||
+};
|
||||
+
|
||||
script = {
|
||||
name = '10_xnu';
|
||||
common = util/grub.d/10_xnu.in;
|
||||
diff --git a/util/grub.d/01_fallback_counting.in b/util/grub.d/08_fallback_counting.in
|
||||
similarity index 65%
|
||||
rename from util/grub.d/01_fallback_counting.in
|
||||
rename to util/grub.d/08_fallback_counting.in
|
||||
index be0e770ea82..2e2c3ff7d31 100644
|
||||
--- a/util/grub.d/01_fallback_counting.in
|
||||
+++ b/util/grub.d/08_fallback_counting.in
|
||||
@@ -1,15 +1,17 @@
|
||||
#! /bin/sh -e
|
||||
-
|
||||
-# Boot Counting
|
||||
+# Fallback Countdown
|
||||
+#
|
||||
+# This snippet depends on 10_reset_boot_success and needs to be kept in sync.
|
||||
+#
|
||||
# The boot_counter env var can be used to count down boot attempts after an
|
||||
-# OSTree upgrade and choose the rollback deployment when 0 is reached. Both
|
||||
-# boot_counter and boot_success need to be (re-)set from userspace.
|
||||
+# OSTree upgrade and choose the rollback deployment when 0 is reached.
|
||||
+# Both boot_counter=X and boot_success=1 need to be set from userspace.
|
||||
cat << EOF
|
||||
insmod increment
|
||||
# Check if boot_counter exists and boot_success=0 to activate this behaviour.
|
||||
if [ -n "\${boot_counter}" -a "\${boot_success}" = "0" ]; then
|
||||
- # if countdown has ended, choose to boot rollback deployment (default=1 on
|
||||
- # OSTree-based systems)
|
||||
+ # if countdown has ended, choose to boot rollback deployment,
|
||||
+ # i.e. default=1 on OSTree-based systems.
|
||||
if [ "\${boot_counter}" = "0" -o "\${boot_counter}" = "-1" ]; then
|
||||
set default=1
|
||||
set boot_counter=-1
|
||||
diff --git a/util/grub.d/10_reset_boot_success.in b/util/grub.d/10_reset_boot_success.in
|
||||
new file mode 100644
|
||||
index 00000000000..6c88d933dde
|
||||
--- /dev/null
|
||||
+++ b/util/grub.d/10_reset_boot_success.in
|
||||
@@ -0,0 +1,25 @@
|
||||
+#! /bin/sh -e
|
||||
+# Reset Boot Success
|
||||
+#
|
||||
+# The 08_fallback_counting and 12_menu_auto_hide snippets rely on this one
|
||||
+# and need to be kept in sync.
|
||||
+#
|
||||
+# The boot_success var needs to be set to 1 from userspace to mark a boot successful.
|
||||
+cat << EOF
|
||||
+insmod increment
|
||||
+# Hiding the menu is ok if last boot was ok or if this is a first boot attempt to boot the entry
|
||||
+if [ "\${boot_success}" = "1" -o "\${boot_indeterminate}" = "1" ]; then
|
||||
+ set menu_hide_ok=1
|
||||
+else
|
||||
+ set menu_hide_ok=0
|
||||
+fi
|
||||
+# Reset boot_indeterminate after a successful boot, increment otherwise
|
||||
+if [ "\${boot_success}" = "1" ] ; then
|
||||
+ set boot_indeterminate=0
|
||||
+else
|
||||
+ increment boot_indeterminate
|
||||
+fi
|
||||
+# Reset boot_success for current boot
|
||||
+set boot_success=0
|
||||
+save_env boot_success boot_indeterminate
|
||||
+EOF
|
||||
diff --git a/util/grub.d/01_menu_auto_hide.in b/util/grub.d/12_menu_auto_hide.in
|
||||
similarity index 58%
|
||||
rename from util/grub.d/01_menu_auto_hide.in
|
||||
rename to util/grub.d/12_menu_auto_hide.in
|
||||
index ad175870a54..6a7c0fa0d43 100644
|
||||
--- a/util/grub.d/01_menu_auto_hide.in
|
||||
+++ b/util/grub.d/12_menu_auto_hide.in
|
||||
@@ -1,5 +1,8 @@
|
||||
#! /bin/sh
|
||||
-
|
||||
+# Menu Auto Hide
|
||||
+#
|
||||
+# This snippet depends on 10_reset_boot_success and needs to be kept in sync.
|
||||
+#
|
||||
# Disable / skip generating menu-auto-hide config parts on serial terminals
|
||||
for x in ${GRUB_TERMINAL_INPUT} ${GRUB_TERMINAL_OUTPUT}; do
|
||||
case "$x" in
|
||||
@@ -10,29 +13,13 @@ for x in ${GRUB_TERMINAL_INPUT} ${GRUB_TERMINAL_OUTPUT}; do
|
||||
done
|
||||
|
||||
cat << EOF
|
||||
-if [ "\${boot_success}" = "1" -o "\${boot_indeterminate}" = "1" ]; then
|
||||
- set last_boot_ok=1
|
||||
-else
|
||||
- set last_boot_ok=0
|
||||
-fi
|
||||
-
|
||||
-# Reset boot_indeterminate after a successful boot
|
||||
-if [ "\${boot_success}" = "1" ] ; then
|
||||
- set boot_indeterminate=0
|
||||
-# Avoid boot_indeterminate causing the menu to be hidden more then once
|
||||
-elif [ "\${boot_indeterminate}" = "1" ]; then
|
||||
- set boot_indeterminate=2
|
||||
-fi
|
||||
-set boot_success=0
|
||||
-save_env boot_success boot_indeterminate
|
||||
-
|
||||
if [ x\$feature_timeout_style = xy ] ; then
|
||||
if [ "\${menu_show_once}" ]; then
|
||||
unset menu_show_once
|
||||
save_env menu_show_once
|
||||
set timeout_style=menu
|
||||
set timeout=60
|
||||
- elif [ "\${menu_auto_hide}" -a "\${last_boot_ok}" = "1" ]; then
|
||||
+ elif [ "\${menu_auto_hide}" -a "\${menu_hide_ok}" = "1" ]; then
|
||||
set orig_timeout_style=\${timeout_style}
|
||||
set orig_timeout=\${timeout}
|
||||
if [ "\${fastboot}" = "1" ]; then
|
@ -0,0 +1,75 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Tue, 26 Nov 2019 09:51:41 +0100
|
||||
Subject: [PATCH] grub.d: Fix boot_indeterminate getting set on boot_success=0
|
||||
boot
|
||||
|
||||
The "grub.d: Split out boot success reset from menu auto hide script"
|
||||
not only moved the code to clear boot_success and boot_indeterminate
|
||||
but for some reason also mixed in some broken changes to the
|
||||
boot_indeterminate handling.
|
||||
|
||||
The boot_indeterminate var is meant to suppress the boot menu after
|
||||
a reboot from either a selinux-relabel or offline-updates. These
|
||||
2 special boot scenarios do not set boot_success since there is no
|
||||
successfull interaction with the user. Instead they increment
|
||||
boot_indeterminate, and if it is 1 and only when it is 1, so the
|
||||
first reboot after a "special" boot we suppress the menu.
|
||||
|
||||
To ensure that we do show the menu if we somehow get stuck in a
|
||||
"special" boot loop where we do special-boots without them
|
||||
incrementing boot_indeterminate, the code before the
|
||||
"grub.d: Split out boot success reset from menu auto hide script"
|
||||
commit would increment boot_indeterminate once when it is 1, so that
|
||||
even if the "special" boot reboot-loop immediately we would show the
|
||||
menu on the next boot.
|
||||
|
||||
That commit broke this however, because it not only moves the code,
|
||||
it also changes it from only "incrementing" boot_indeterminate once to
|
||||
always incrementing it, except when boot_success == 1 (and we reset it).
|
||||
|
||||
This broken behavior causes the following problem:
|
||||
|
||||
1. Boot a broken kernel, system hangs, power-cycle
|
||||
2. boot_success now != 1, so we increment boot_indeterminate from 0
|
||||
(unset!) to 1. User either simply tries again, or makes some changes
|
||||
but the end-result still is a system hang, power-cycle
|
||||
3. Now boot_indeterminate==1 so we do not show the menu even though the
|
||||
previous boot failed -> BAD
|
||||
|
||||
This commit fixes this by restoring the behavior of setting
|
||||
boot_indeterminate to 2 when it was 1 before.
|
||||
|
||||
Fixes: "grub.d: Split out boot success reset from menu auto hide script"
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
util/grub.d/10_reset_boot_success.in | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/util/grub.d/10_reset_boot_success.in b/util/grub.d/10_reset_boot_success.in
|
||||
index 6c88d933dde..737e1ae5b68 100644
|
||||
--- a/util/grub.d/10_reset_boot_success.in
|
||||
+++ b/util/grub.d/10_reset_boot_success.in
|
||||
@@ -6,18 +6,18 @@
|
||||
#
|
||||
# The boot_success var needs to be set to 1 from userspace to mark a boot successful.
|
||||
cat << EOF
|
||||
-insmod increment
|
||||
# Hiding the menu is ok if last boot was ok or if this is a first boot attempt to boot the entry
|
||||
if [ "\${boot_success}" = "1" -o "\${boot_indeterminate}" = "1" ]; then
|
||||
set menu_hide_ok=1
|
||||
else
|
||||
set menu_hide_ok=0
|
||||
fi
|
||||
-# Reset boot_indeterminate after a successful boot, increment otherwise
|
||||
+# Reset boot_indeterminate after a successful boot
|
||||
if [ "\${boot_success}" = "1" ] ; then
|
||||
set boot_indeterminate=0
|
||||
-else
|
||||
- increment boot_indeterminate
|
||||
+# Avoid boot_indeterminate causing the menu to be hidden more then once
|
||||
+elif [ "\${boot_indeterminate}" = "1" ]; then
|
||||
+ set boot_indeterminate=2
|
||||
fi
|
||||
# Reset boot_success for current boot
|
||||
set boot_success=0
|
@ -0,0 +1,70 @@
|
||||
From 0bde74dcdf9de128317a28796e2690f92214db0d Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Wed, 15 Apr 2020 15:45:02 -0400
|
||||
Subject: [PATCH 281/314] yylex: Make lexer fatal errors actually be fatal
|
||||
|
||||
When presented with a command that can't be tokenized to anything
|
||||
smaller than YYLMAX characters, the parser calls YY_FATAL_ERROR(errmsg),
|
||||
expecting that will stop further processing, as such:
|
||||
|
||||
#define YY_DO_BEFORE_ACTION \
|
||||
yyg->yytext_ptr = yy_bp; \
|
||||
yyleng = (int) (yy_cp - yy_bp); \
|
||||
yyg->yy_hold_char = *yy_cp; \
|
||||
*yy_cp = '\0'; \
|
||||
if ( yyleng >= YYLMAX ) \
|
||||
YY_FATAL_ERROR( "token too large, exceeds YYLMAX" ); \
|
||||
yy_flex_strncpy( yytext, yyg->yytext_ptr, yyleng + 1 , yyscanner); \
|
||||
yyg->yy_c_buf_p = yy_cp;
|
||||
|
||||
The code flex generates expects that YY_FATAL_ERROR() will either return
|
||||
for it or do some form of longjmp(), or handle the error in some way at
|
||||
least, and so the strncpy() call isn't in an "else" clause, and thus if
|
||||
YY_FATAL_ERROR() is *not* actually fatal, it does the call with the
|
||||
questionable limit, and predictable results ensue.
|
||||
|
||||
Unfortunately, our implementation of YY_FATAL_ERROR() is:
|
||||
|
||||
#define YY_FATAL_ERROR(msg) \
|
||||
do { \
|
||||
grub_printf (_("fatal error: %s\n"), _(msg)); \
|
||||
} while (0)
|
||||
|
||||
The same pattern exists in yyless(), and similar problems exist in users
|
||||
of YY_INPUT(), several places in the main parsing loop,
|
||||
yy_get_next_buffer(), yy_load_buffer_state(), yyensure_buffer_stack,
|
||||
yy_scan_buffer(), etc.
|
||||
|
||||
All of these callers expect YY_FATAL_ERROR() to actually be fatal, and
|
||||
the things they do if it returns after calling it are wildly unsafe.
|
||||
|
||||
Fixes: CVE-2020-10713
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Upstream-commit-id: 926df817dc8
|
||||
---
|
||||
grub-core/script/yylex.l | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/script/yylex.l b/grub-core/script/yylex.l
|
||||
index 7b44c37b76f..b7203c82309 100644
|
||||
--- a/grub-core/script/yylex.l
|
||||
+++ b/grub-core/script/yylex.l
|
||||
@@ -37,11 +37,11 @@
|
||||
|
||||
/*
|
||||
* As we don't have access to yyscanner, we cannot do much except to
|
||||
- * print the fatal error.
|
||||
+ * print the fatal error and exit.
|
||||
*/
|
||||
#define YY_FATAL_ERROR(msg) \
|
||||
do { \
|
||||
- grub_printf (_("fatal error: %s\n"), _(msg)); \
|
||||
+ grub_fatal (_("fatal error: %s\n"), _(msg));\
|
||||
} while (0)
|
||||
|
||||
#define COPY(str, hint) \
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,127 @@
|
||||
From 42b76ec749c30cb11cad7c070d0b03a7d4f1f7d6 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Mon, 15 Jun 2020 10:58:42 -0400
|
||||
Subject: [PATCH 282/314] safemath: Add some arithmetic primitives that check
|
||||
for overflow
|
||||
|
||||
This adds a new header, include/grub/safemath.h, that includes easy to
|
||||
use wrappers for __builtin_{add,sub,mul}_overflow() declared like:
|
||||
|
||||
bool OP(a, b, res)
|
||||
|
||||
where OP is grub_add, grub_sub or grub_mul. OP() returns true in the
|
||||
case where the operation would overflow and res is not modified.
|
||||
Otherwise, false is returned and the operation is executed.
|
||||
|
||||
These arithmetic primitives require newer compiler versions. So, bump
|
||||
these requirements in the INSTALL file too.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Upstream-commit-id: de1c315841a
|
||||
---
|
||||
include/grub/compiler.h | 8 ++++++++
|
||||
include/grub/safemath.h | 37 +++++++++++++++++++++++++++++++++++++
|
||||
INSTALL | 22 ++--------------------
|
||||
3 files changed, 47 insertions(+), 20 deletions(-)
|
||||
create mode 100644 include/grub/safemath.h
|
||||
|
||||
diff --git a/include/grub/compiler.h b/include/grub/compiler.h
|
||||
index 9859ff4cc79..ebafec68957 100644
|
||||
--- a/include/grub/compiler.h
|
||||
+++ b/include/grub/compiler.h
|
||||
@@ -48,6 +48,14 @@
|
||||
# define WARN_UNUSED_RESULT
|
||||
#endif
|
||||
|
||||
+#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__)
|
||||
+# define CLANG_PREREQ(maj,min) \
|
||||
+ ((__clang_major__ > (maj)) || \
|
||||
+ (__clang_major__ == (maj) && __clang_minor__ >= (min)))
|
||||
+#else
|
||||
+# define CLANG_PREREQ(maj,min) 0
|
||||
+#endif
|
||||
+
|
||||
#define UNUSED __attribute__((__unused__))
|
||||
|
||||
#endif /* ! GRUB_COMPILER_HEADER */
|
||||
diff --git a/include/grub/safemath.h b/include/grub/safemath.h
|
||||
new file mode 100644
|
||||
index 00000000000..c17b89bba17
|
||||
--- /dev/null
|
||||
+++ b/include/grub/safemath.h
|
||||
@@ -0,0 +1,37 @@
|
||||
+/*
|
||||
+ * GRUB -- GRand Unified Bootloader
|
||||
+ * Copyright (C) 2020 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 <http://www.gnu.org/licenses/>.
|
||||
+ *
|
||||
+ * Arithmetic operations that protect against overflow.
|
||||
+ */
|
||||
+
|
||||
+#ifndef GRUB_SAFEMATH_H
|
||||
+#define GRUB_SAFEMATH_H 1
|
||||
+
|
||||
+#include <grub/compiler.h>
|
||||
+
|
||||
+/* These appear in gcc 5.1 and clang 3.8. */
|
||||
+#if GNUC_PREREQ(5, 1) || CLANG_PREREQ(3, 8)
|
||||
+
|
||||
+#define grub_add(a, b, res) __builtin_add_overflow(a, b, res)
|
||||
+#define grub_sub(a, b, res) __builtin_sub_overflow(a, b, res)
|
||||
+#define grub_mul(a, b, res) __builtin_mul_overflow(a, b, res)
|
||||
+
|
||||
+#else
|
||||
+#error gcc 5.1 or newer or clang 3.8 or newer is required
|
||||
+#endif
|
||||
+
|
||||
+#endif /* GRUB_SAFEMATH_H */
|
||||
diff --git a/INSTALL b/INSTALL
|
||||
index f3c20edc844..f8bd9116480 100644
|
||||
--- a/INSTALL
|
||||
+++ b/INSTALL
|
||||
@@ -11,27 +11,9 @@ GRUB depends on some software packages installed into your system. If
|
||||
you don't have any of them, please obtain and install them before
|
||||
configuring the GRUB.
|
||||
|
||||
-* GCC 4.1.3 or later
|
||||
- Note: older versions may work but support is limited
|
||||
-
|
||||
- Experimental support for clang 3.3 or later (results in much bigger binaries)
|
||||
+* GCC 5.1.0 or later
|
||||
+ Experimental support for clang 3.8.0 or later (results in much bigger binaries)
|
||||
for i386, x86_64, arm (including thumb), arm64, mips(el), powerpc, sparc64
|
||||
- Note: clang 3.2 or later works for i386 and x86_64 targets but results in
|
||||
- much bigger binaries.
|
||||
- earlier versions not tested
|
||||
- Note: clang 3.2 or later works for arm
|
||||
- earlier versions not tested
|
||||
- Note: clang on arm64 is not supported due to
|
||||
- https://llvm.org/bugs/show_bug.cgi?id=26030
|
||||
- Note: clang 3.3 or later works for mips(el)
|
||||
- earlier versions fail to generate .reginfo and hence gprel relocations
|
||||
- fail.
|
||||
- Note: clang 3.2 or later works for powerpc
|
||||
- earlier versions not tested
|
||||
- Note: clang 3.5 or later works for sparc64
|
||||
- earlier versions return "error: unable to interface with target machine"
|
||||
- Note: clang has no support for ia64 and hence you can't compile GRUB
|
||||
- for ia64 with clang
|
||||
* GNU Make
|
||||
* GNU Bison 2.3 or later
|
||||
* GNU gettext 0.17 or later
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,243 @@
|
||||
From 832189364ee0c85a94f670952c951252e54d3d1c Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Mon, 15 Jun 2020 12:15:29 -0400
|
||||
Subject: [PATCH 283/314] calloc: Make sure we always have an overflow-checking
|
||||
calloc() available
|
||||
|
||||
This tries to make sure that everywhere in this source tree, we always have
|
||||
an appropriate version of calloc() (i.e. grub_calloc(), xcalloc(), etc.)
|
||||
available, and that they all safely check for overflow and return NULL when
|
||||
it would occur.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Upstream-commit-id: 79e51ab7a9a
|
||||
---
|
||||
grub-core/kern/emu/misc.c | 12 +++++++++
|
||||
grub-core/kern/emu/mm.c | 10 ++++++++
|
||||
grub-core/kern/mm.c | 40 ++++++++++++++++++++++++++++++
|
||||
grub-core/lib/libgcrypt_wrap/mem.c | 11 ++++++--
|
||||
grub-core/lib/posix_wrap/stdlib.h | 8 +++++-
|
||||
include/grub/emu/misc.h | 1 +
|
||||
include/grub/mm.h | 6 +++++
|
||||
7 files changed, 85 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c
|
||||
index 3d3a4a4a975..b4072767391 100644
|
||||
--- a/grub-core/kern/emu/misc.c
|
||||
+++ b/grub-core/kern/emu/misc.c
|
||||
@@ -84,6 +84,18 @@ grub_util_error (const char *fmt, ...)
|
||||
grub_exit (1);
|
||||
}
|
||||
|
||||
+void *
|
||||
+xcalloc (grub_size_t nmemb, grub_size_t size)
|
||||
+{
|
||||
+ void *p;
|
||||
+
|
||||
+ p = calloc (nmemb, size);
|
||||
+ if (!p)
|
||||
+ grub_util_error ("%s", _("out of memory"));
|
||||
+
|
||||
+ return p;
|
||||
+}
|
||||
+
|
||||
void *
|
||||
xmalloc (grub_size_t size)
|
||||
{
|
||||
diff --git a/grub-core/kern/emu/mm.c b/grub-core/kern/emu/mm.c
|
||||
index f262e95e388..145b01d3719 100644
|
||||
--- a/grub-core/kern/emu/mm.c
|
||||
+++ b/grub-core/kern/emu/mm.c
|
||||
@@ -25,6 +25,16 @@
|
||||
#include <string.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
+void *
|
||||
+grub_calloc (grub_size_t nmemb, grub_size_t size)
|
||||
+{
|
||||
+ void *ret;
|
||||
+ ret = calloc (nmemb, size);
|
||||
+ if (!ret)
|
||||
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
void *
|
||||
grub_malloc (grub_size_t size)
|
||||
{
|
||||
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
|
||||
index 002cbfa4f3d..80d0720d005 100644
|
||||
--- a/grub-core/kern/mm.c
|
||||
+++ b/grub-core/kern/mm.c
|
||||
@@ -67,8 +67,10 @@
|
||||
#include <grub/dl.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/mm_private.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
#ifdef MM_DEBUG
|
||||
+# undef grub_calloc
|
||||
# undef grub_malloc
|
||||
# undef grub_zalloc
|
||||
# undef grub_realloc
|
||||
@@ -375,6 +377,30 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Allocate NMEMB instances of SIZE bytes and return the pointer, or error on
|
||||
+ * integer overflow.
|
||||
+ */
|
||||
+void *
|
||||
+grub_calloc (grub_size_t nmemb, grub_size_t size)
|
||||
+{
|
||||
+ void *ret;
|
||||
+ grub_size_t sz = 0;
|
||||
+
|
||||
+ if (grub_mul (nmemb, size, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ ret = grub_memalign (0, sz);
|
||||
+ if (!ret)
|
||||
+ return NULL;
|
||||
+
|
||||
+ grub_memset (ret, 0, sz);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/* Allocate SIZE bytes and return the pointer. */
|
||||
void *
|
||||
grub_malloc (grub_size_t size)
|
||||
@@ -561,6 +587,20 @@ grub_mm_dump (unsigned lineno)
|
||||
grub_printf ("\n");
|
||||
}
|
||||
|
||||
+void *
|
||||
+grub_debug_calloc (const char *file, int line, grub_size_t nmemb, grub_size_t size)
|
||||
+{
|
||||
+ void *ptr;
|
||||
+
|
||||
+ if (grub_mm_debug)
|
||||
+ grub_printf ("%s:%d: calloc (0x%" PRIxGRUB_SIZE ", 0x%" PRIxGRUB_SIZE ") = ",
|
||||
+ file, line, size);
|
||||
+ ptr = grub_calloc (nmemb, size);
|
||||
+ if (grub_mm_debug)
|
||||
+ grub_printf ("%p\n", ptr);
|
||||
+ return ptr;
|
||||
+}
|
||||
+
|
||||
void *
|
||||
grub_debug_malloc (const char *file, int line, grub_size_t size)
|
||||
{
|
||||
diff --git a/grub-core/lib/libgcrypt_wrap/mem.c b/grub-core/lib/libgcrypt_wrap/mem.c
|
||||
index beeb661a3c8..74c6eafe525 100644
|
||||
--- a/grub-core/lib/libgcrypt_wrap/mem.c
|
||||
+++ b/grub-core/lib/libgcrypt_wrap/mem.c
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/env.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -36,7 +37,10 @@ void *
|
||||
gcry_xcalloc (size_t n, size_t m)
|
||||
{
|
||||
void *ret;
|
||||
- ret = grub_zalloc (n * m);
|
||||
+ size_t sz;
|
||||
+ if (grub_mul (n, m, &sz))
|
||||
+ grub_fatal ("gcry_xcalloc would overflow");
|
||||
+ ret = grub_zalloc (sz);
|
||||
if (!ret)
|
||||
grub_fatal ("gcry_xcalloc failed");
|
||||
return ret;
|
||||
@@ -56,7 +60,10 @@ void *
|
||||
gcry_xcalloc_secure (size_t n, size_t m)
|
||||
{
|
||||
void *ret;
|
||||
- ret = grub_zalloc (n * m);
|
||||
+ size_t sz;
|
||||
+ if (grub_mul (n, m, &sz))
|
||||
+ grub_fatal ("gcry_xcalloc would overflow");
|
||||
+ ret = grub_zalloc (sz);
|
||||
if (!ret)
|
||||
grub_fatal ("gcry_xcalloc failed");
|
||||
return ret;
|
||||
diff --git a/grub-core/lib/posix_wrap/stdlib.h b/grub-core/lib/posix_wrap/stdlib.h
|
||||
index 3b46f47ff50..7a8d385e973 100644
|
||||
--- a/grub-core/lib/posix_wrap/stdlib.h
|
||||
+++ b/grub-core/lib/posix_wrap/stdlib.h
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
static inline void
|
||||
free (void *ptr)
|
||||
@@ -37,7 +38,12 @@ malloc (grub_size_t size)
|
||||
static inline void *
|
||||
calloc (grub_size_t size, grub_size_t nelem)
|
||||
{
|
||||
- return grub_zalloc (size * nelem);
|
||||
+ grub_size_t sz;
|
||||
+
|
||||
+ if (grub_mul (size, nelem, &sz))
|
||||
+ return NULL;
|
||||
+
|
||||
+ return grub_zalloc (sz);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h
|
||||
index a653132e36a..09e1f1065f6 100644
|
||||
--- a/include/grub/emu/misc.h
|
||||
+++ b/include/grub/emu/misc.h
|
||||
@@ -51,6 +51,7 @@ grub_util_device_is_mapped (const char *dev);
|
||||
#define GRUB_HOST_PRIxLONG_LONG "llx"
|
||||
#endif
|
||||
|
||||
+void * EXPORT_FUNC(xcalloc) (grub_size_t nmemb, grub_size_t size) WARN_UNUSED_RESULT;
|
||||
void * EXPORT_FUNC(xmalloc) (grub_size_t size) WARN_UNUSED_RESULT;
|
||||
void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) WARN_UNUSED_RESULT;
|
||||
char * EXPORT_FUNC(xstrdup) (const char *str) WARN_UNUSED_RESULT;
|
||||
diff --git a/include/grub/mm.h b/include/grub/mm.h
|
||||
index 28e2e53eb32..9c38dd3ca5d 100644
|
||||
--- a/include/grub/mm.h
|
||||
+++ b/include/grub/mm.h
|
||||
@@ -29,6 +29,7 @@
|
||||
#endif
|
||||
|
||||
void grub_mm_init_region (void *addr, grub_size_t size);
|
||||
+void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size);
|
||||
void *EXPORT_FUNC(grub_malloc) (grub_size_t size);
|
||||
void *EXPORT_FUNC(grub_zalloc) (grub_size_t size);
|
||||
void EXPORT_FUNC(grub_free) (void *ptr);
|
||||
@@ -48,6 +49,9 @@ extern int EXPORT_VAR(grub_mm_debug);
|
||||
void grub_mm_dump_free (void);
|
||||
void grub_mm_dump (unsigned lineno);
|
||||
|
||||
+#define grub_calloc(nmemb, size) \
|
||||
+ grub_debug_calloc (GRUB_FILE, __LINE__, nmemb, size)
|
||||
+
|
||||
#define grub_malloc(size) \
|
||||
grub_debug_malloc (GRUB_FILE, __LINE__, size)
|
||||
|
||||
@@ -63,6 +67,8 @@ void grub_mm_dump (unsigned lineno);
|
||||
#define grub_free(ptr) \
|
||||
grub_debug_free (GRUB_FILE, __LINE__, ptr)
|
||||
|
||||
+void *EXPORT_FUNC(grub_debug_calloc) (const char *file, int line,
|
||||
+ grub_size_t nmemb, grub_size_t size);
|
||||
void *EXPORT_FUNC(grub_debug_malloc) (const char *file, int line,
|
||||
grub_size_t size);
|
||||
void *EXPORT_FUNC(grub_debug_zalloc) (const char *file, int line,
|
||||
--
|
||||
2.26.2
|
||||
|
1945
SOURCES/0284-calloc-Use-calloc-at-most-places.patch
Normal file
1945
SOURCES/0284-calloc-Use-calloc-at-most-places.patch
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,69 @@
|
||||
From c37e76df9c58c3f170e838c42527ef8544bf4468 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Sat, 4 Jul 2020 12:25:09 -0400
|
||||
Subject: [PATCH 286/314] iso9660: Don't leak memory on realloc() failures
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Upstream-commit-id: f2bd30b2fe7
|
||||
---
|
||||
grub-core/fs/iso9660.c | 24 ++++++++++++++++++++----
|
||||
1 file changed, 20 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
|
||||
index f45841e2b47..6fc9302bce3 100644
|
||||
--- a/grub-core/fs/iso9660.c
|
||||
+++ b/grub-core/fs/iso9660.c
|
||||
@@ -533,14 +533,20 @@ add_part (struct iterate_dir_ctx *ctx,
|
||||
{
|
||||
int size = ctx->symlink ? grub_strlen (ctx->symlink) : 0;
|
||||
grub_size_t sz;
|
||||
+ char *new;
|
||||
|
||||
if (grub_add (size, len2, &sz) ||
|
||||
grub_add (sz, 1, &sz))
|
||||
return;
|
||||
|
||||
- ctx->symlink = grub_realloc (ctx->symlink, sz);
|
||||
- if (! ctx->symlink)
|
||||
- return;
|
||||
+ new = grub_realloc (ctx->symlink, sz);
|
||||
+ if (!new)
|
||||
+ {
|
||||
+ grub_free (ctx->symlink);
|
||||
+ ctx->symlink = NULL;
|
||||
+ return;
|
||||
+ }
|
||||
+ ctx->symlink = new;
|
||||
|
||||
grub_memcpy (ctx->symlink + size, part, len2);
|
||||
ctx->symlink[size + len2] = 0;
|
||||
@@ -634,7 +640,12 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
|
||||
is the length. Both are part of the `Component
|
||||
Record'. */
|
||||
if (ctx->symlink && !ctx->was_continue)
|
||||
- add_part (ctx, "/", 1);
|
||||
+ {
|
||||
+ add_part (ctx, "/", 1);
|
||||
+ if (grub_errno)
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
+
|
||||
add_part (ctx, (char *) &entry->data[pos + 2],
|
||||
entry->data[pos + 1]);
|
||||
ctx->was_continue = (entry->data[pos] & 1);
|
||||
@@ -653,6 +664,11 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
|
||||
add_part (ctx, "/", 1);
|
||||
break;
|
||||
}
|
||||
+
|
||||
+ /* Check if grub_realloc() failed in add_part(). */
|
||||
+ if (grub_errno)
|
||||
+ return grub_errno;
|
||||
+
|
||||
/* In pos + 1 the length of the `Component Record' is
|
||||
stored. */
|
||||
pos += entry->data[pos + 1] + 2;
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,38 @@
|
||||
From 0b3c4b90e1b928a2606f0801e6e872dd6cb85c42 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Date: Tue, 7 Jul 2020 15:36:26 +0200
|
||||
Subject: [PATCH 287/314] font: Do not load more than one NAME section
|
||||
|
||||
The GRUB font file can have one NAME section only. Though if somebody
|
||||
crafts a broken font file with many NAME sections and loads it then the
|
||||
GRUB leaks memory. So, prevent against that by loading first NAME
|
||||
section and failing in controlled way on following one.
|
||||
|
||||
Reported-by: Chris Coulson <chris.coulson@canonical.com>
|
||||
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Reviewed-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
|
||||
Upstream-commit-id: 482814113dc
|
||||
---
|
||||
grub-core/font/font.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
|
||||
index d63354fb51b..a7b955a1a74 100644
|
||||
--- a/grub-core/font/font.c
|
||||
+++ b/grub-core/font/font.c
|
||||
@@ -532,6 +532,12 @@ grub_font_load (const char *filename)
|
||||
if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FONT_NAME,
|
||||
sizeof (FONT_FORMAT_SECTION_NAMES_FONT_NAME) - 1) == 0)
|
||||
{
|
||||
+ if (font->name != NULL)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_FONT, "invalid font file: too many NAME sections");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
font->name = read_section_as_string (§ion);
|
||||
if (!font->name)
|
||||
goto fail;
|
||||
--
|
||||
2.26.2
|
||||
|
36
SOURCES/0288-gfxmenu-Fix-double-free-in-load_image.patch
Normal file
36
SOURCES/0288-gfxmenu-Fix-double-free-in-load_image.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From 583a48bca23f7c4e0d691f0e6d065dac61bbfca1 Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Date: Wed, 8 Jul 2020 20:41:56 +0000
|
||||
Subject: [PATCH 288/314] gfxmenu: Fix double free in load_image()
|
||||
|
||||
self->bitmap should be zeroed after free. Otherwise, there is a chance
|
||||
to double free (USE_AFTER_FREE) it later in rescale_image().
|
||||
|
||||
Fixes: CID 292472
|
||||
|
||||
Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Upstream-commit-id: 5d3e84b15a4
|
||||
---
|
||||
grub-core/gfxmenu/gui_image.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/gfxmenu/gui_image.c b/grub-core/gfxmenu/gui_image.c
|
||||
index 29784ed2d9a..6b2e976f16e 100644
|
||||
--- a/grub-core/gfxmenu/gui_image.c
|
||||
+++ b/grub-core/gfxmenu/gui_image.c
|
||||
@@ -195,7 +195,10 @@ load_image (grub_gui_image_t self, const char *path)
|
||||
return grub_errno;
|
||||
|
||||
if (self->bitmap && (self->bitmap != self->raw_bitmap))
|
||||
- grub_video_bitmap_destroy (self->bitmap);
|
||||
+ {
|
||||
+ grub_video_bitmap_destroy (self->bitmap);
|
||||
+ self->bitmap = 0;
|
||||
+ }
|
||||
if (self->raw_bitmap)
|
||||
grub_video_bitmap_destroy (self->raw_bitmap);
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,57 @@
|
||||
From 301523f584d9aa624424c68ab3f085a9b7eca417 Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Date: Wed, 8 Jul 2020 21:30:43 +0000
|
||||
Subject: [PATCH 289/314] xnu: Fix double free in
|
||||
grub_xnu_devprop_add_property()
|
||||
|
||||
grub_xnu_devprop_add_property() should not free utf8 and utf16 as it get
|
||||
allocated and freed in the caller.
|
||||
|
||||
Minor improvement: do prop fields initialization after memory allocations.
|
||||
|
||||
Fixes: CID 292442, CID 292457, CID 292460, CID 292466
|
||||
|
||||
Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Upstream-commit-id: 4d5e2d13519
|
||||
---
|
||||
grub-core/loader/i386/xnu.c | 19 +++++++++----------
|
||||
1 file changed, 9 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c
|
||||
index ee0eaadc4ee..c760db30fc0 100644
|
||||
--- a/grub-core/loader/i386/xnu.c
|
||||
+++ b/grub-core/loader/i386/xnu.c
|
||||
@@ -262,20 +262,19 @@ grub_xnu_devprop_add_property (struct grub_xnu_devprop_device_descriptor *dev,
|
||||
if (!prop)
|
||||
return grub_errno;
|
||||
|
||||
+ prop->data = grub_malloc (datalen);
|
||||
+ if (!prop->data)
|
||||
+ {
|
||||
+ grub_free (prop);
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
+ grub_memcpy (prop->data, data, datalen);
|
||||
+
|
||||
prop->name = utf8;
|
||||
prop->name16 = utf16;
|
||||
prop->name16len = utf16len;
|
||||
-
|
||||
prop->length = datalen;
|
||||
- prop->data = grub_malloc (prop->length);
|
||||
- if (!prop->data)
|
||||
- {
|
||||
- grub_free (prop->name);
|
||||
- grub_free (prop->name16);
|
||||
- grub_free (prop);
|
||||
- return grub_errno;
|
||||
- }
|
||||
- grub_memcpy (prop->data, data, prop->length);
|
||||
+
|
||||
grub_list_push (GRUB_AS_LIST_P (&dev->properties),
|
||||
GRUB_AS_LIST (prop));
|
||||
return GRUB_ERR_NONE;
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,52 @@
|
||||
From 656e3376d52c7244edac9264454c0fadac835749 Mon Sep 17 00:00:00 2001
|
||||
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Date: Thu, 9 Jul 2020 03:05:23 +0000
|
||||
Subject: [PATCH 290/314] lzma: Make sure we don't dereference past array
|
||||
|
||||
The two dimensional array p->posSlotEncoder[4][64] is being dereferenced
|
||||
using the GetLenToPosState() macro which checks if len is less than 5,
|
||||
and if so subtracts 2 from it. If len = 0, that is 0 - 2 = 4294967294.
|
||||
Obviously we don't want to dereference that far out so we check if the
|
||||
position found is greater or equal kNumLenToPosStates (4) and bail out.
|
||||
|
||||
N.B.: Upstream LZMA 18.05 and later has this function completely rewritten
|
||||
without any history.
|
||||
|
||||
Fixes: CID 51526
|
||||
|
||||
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Upstream-commit-id: f91e043bda4
|
||||
---
|
||||
grub-core/lib/LzmaEnc.c | 10 ++++++++--
|
||||
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/lib/LzmaEnc.c b/grub-core/lib/LzmaEnc.c
|
||||
index f2ec04a8c28..753e56a95e3 100644
|
||||
--- a/grub-core/lib/LzmaEnc.c
|
||||
+++ b/grub-core/lib/LzmaEnc.c
|
||||
@@ -1877,13 +1877,19 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
|
||||
}
|
||||
else
|
||||
{
|
||||
- UInt32 posSlot;
|
||||
+ UInt32 posSlot, lenToPosState;
|
||||
RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
|
||||
p->state = kMatchNextStates[p->state];
|
||||
LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
|
||||
pos -= LZMA_NUM_REPS;
|
||||
GetPosSlot(pos, posSlot);
|
||||
- RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
|
||||
+ lenToPosState = GetLenToPosState(len);
|
||||
+ if (lenToPosState >= kNumLenToPosStates)
|
||||
+ {
|
||||
+ p->result = SZ_ERROR_DATA;
|
||||
+ return CheckErrors(p);
|
||||
+ }
|
||||
+ RcTree_Encode(&p->rc, p->posSlotEncoder[lenToPosState], kNumPosSlotBits, posSlot);
|
||||
|
||||
if (posSlot >= kStartPosModelIndex)
|
||||
{
|
||||
--
|
||||
2.26.2
|
||||
|
66
SOURCES/0291-term-Fix-overflow-on-user-inputs.patch
Normal file
66
SOURCES/0291-term-Fix-overflow-on-user-inputs.patch
Normal file
@ -0,0 +1,66 @@
|
||||
From 6df814d4f43a47ffe2b354b9fa683ed4022fa5f1 Mon Sep 17 00:00:00 2001
|
||||
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Date: Tue, 7 Jul 2020 15:12:25 -0400
|
||||
Subject: [PATCH 291/314] term: Fix overflow on user inputs
|
||||
|
||||
This requires a very weird input from the serial interface but can cause
|
||||
an overflow in input_buf (keys) overwriting the next variable (npending)
|
||||
with the user choice:
|
||||
|
||||
(pahole output)
|
||||
|
||||
struct grub_terminfo_input_state {
|
||||
int input_buf[6]; /* 0 24 */
|
||||
int npending; /* 24 4 */ <- CORRUPT
|
||||
...snip...
|
||||
|
||||
The magic string requires causing this is "ESC,O,],0,1,2,q" and we overflow
|
||||
npending with "q" (aka increase npending to 161). The simplest fix is to
|
||||
just to disallow overwrites input_buf, which exactly what this patch does.
|
||||
|
||||
Fixes: CID 292449
|
||||
|
||||
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Upstream-commit-id: 98dfa546777
|
||||
---
|
||||
grub-core/term/terminfo.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c
|
||||
index 537a5c0cb0b..44d0b3b19fb 100644
|
||||
--- a/grub-core/term/terminfo.c
|
||||
+++ b/grub-core/term/terminfo.c
|
||||
@@ -398,7 +398,7 @@ grub_terminfo_getwh (struct grub_term_output *term)
|
||||
}
|
||||
|
||||
static void
|
||||
-grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
|
||||
+grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len, int max_len,
|
||||
int (*readkey) (struct grub_term_input *term))
|
||||
{
|
||||
int c;
|
||||
@@ -414,6 +414,9 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
|
||||
if (c == -1) \
|
||||
return; \
|
||||
\
|
||||
+ if (*len >= max_len) \
|
||||
+ return; \
|
||||
+ \
|
||||
keys[*len] = c; \
|
||||
(*len)++; \
|
||||
}
|
||||
@@ -602,8 +605,8 @@ grub_terminfo_getkey (struct grub_term_input *termi)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- grub_terminfo_readkey (termi, data->input_buf,
|
||||
- &data->npending, data->readkey);
|
||||
+ grub_terminfo_readkey (termi, data->input_buf, &data->npending,
|
||||
+ GRUB_TERMINFO_READKEY_MAX_LEN, data->readkey);
|
||||
|
||||
#if defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275)
|
||||
if (data->npending == 1 && data->input_buf[0] == GRUB_TERM_ESC
|
||||
--
|
||||
2.26.2
|
||||
|
56
SOURCES/0292-udf-Fix-memory-leak.patch
Normal file
56
SOURCES/0292-udf-Fix-memory-leak.patch
Normal file
@ -0,0 +1,56 @@
|
||||
From 1864839f0e0eeb2b93a5b20e4e36f9b80abc3c23 Mon Sep 17 00:00:00 2001
|
||||
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Date: Tue, 7 Jul 2020 22:02:31 -0400
|
||||
Subject: [PATCH 292/314] udf: Fix memory leak
|
||||
|
||||
Fixes: CID 73796
|
||||
|
||||
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Reviewed-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
|
||||
Upstream-commit-id: 8da62d8183c
|
||||
---
|
||||
grub-core/fs/udf.c | 17 +++++++++++++----
|
||||
1 file changed, 13 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
|
||||
index be41b48f913..6670beb5665 100644
|
||||
--- a/grub-core/fs/udf.c
|
||||
+++ b/grub-core/fs/udf.c
|
||||
@@ -965,8 +965,10 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
||||
return 0;
|
||||
|
||||
if (grub_udf_read_icb (dir->data, &dirent.icb, child))
|
||||
- return 0;
|
||||
-
|
||||
+ {
|
||||
+ grub_free (child);
|
||||
+ return 0;
|
||||
+ }
|
||||
if (dirent.characteristics & GRUB_UDF_FID_CHAR_PARENT)
|
||||
{
|
||||
/* This is the parent directory. */
|
||||
@@ -988,11 +990,18 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
||||
dirent.file_ident_length,
|
||||
(char *) raw))
|
||||
!= dirent.file_ident_length)
|
||||
- return 0;
|
||||
+ {
|
||||
+ grub_free (child);
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
filename = read_string (raw, dirent.file_ident_length, 0);
|
||||
if (!filename)
|
||||
- grub_print_error ();
|
||||
+ {
|
||||
+ /* As the hook won't get called. */
|
||||
+ grub_free (child);
|
||||
+ grub_print_error ();
|
||||
+ }
|
||||
|
||||
if (filename && hook (filename, type, child, hook_data))
|
||||
{
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,47 @@
|
||||
From 9b970d31434e3fd6a8de36a6adef5cc721b265a8 Mon Sep 17 00:00:00 2001
|
||||
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Date: Fri, 26 Jun 2020 10:51:43 -0400
|
||||
Subject: [PATCH 293/314] multiboot2: Fix memory leak if
|
||||
grub_create_loader_cmdline() fails
|
||||
|
||||
Fixes: CID 292468
|
||||
|
||||
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Upstream-commit-id: cd6760b6289
|
||||
---
|
||||
grub-core/loader/multiboot_mbi2.c | 11 +++++++++--
|
||||
1 file changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
|
||||
index 54078455e2f..872dcd42e97 100644
|
||||
--- a/grub-core/loader/multiboot_mbi2.c
|
||||
+++ b/grub-core/loader/multiboot_mbi2.c
|
||||
@@ -1089,6 +1089,7 @@ grub_multiboot2_add_module (grub_addr_t start, grub_size_t size,
|
||||
{
|
||||
struct module *newmod;
|
||||
grub_size_t len = 0;
|
||||
+ grub_err_t err = 0;
|
||||
|
||||
newmod = grub_malloc (sizeof (*newmod));
|
||||
if (!newmod)
|
||||
@@ -1107,8 +1108,14 @@ grub_multiboot2_add_module (grub_addr_t start, grub_size_t size,
|
||||
newmod->cmdline_size = len;
|
||||
total_modcmd += ALIGN_UP (len, MULTIBOOT_TAG_ALIGN);
|
||||
|
||||
- grub_create_loader_cmdline (argc, argv, newmod->cmdline,
|
||||
- newmod->cmdline_size);
|
||||
+ err = grub_create_loader_cmdline (argc, argv, newmod->cmdline,
|
||||
+ newmod->cmdline_size);
|
||||
+ if (err)
|
||||
+ {
|
||||
+ grub_free (newmod->cmdline);
|
||||
+ grub_free (newmod);
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
if (modules_last)
|
||||
modules_last->next = newmod;
|
||||
--
|
||||
2.26.2
|
||||
|
289
SOURCES/0294-tftp-Do-not-use-priority-queue.patch
Normal file
289
SOURCES/0294-tftp-Do-not-use-priority-queue.patch
Normal file
@ -0,0 +1,289 @@
|
||||
From 0ecb57c7bc38cb5de4a1b23909203a3331f5c84b Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Date: Thu, 9 Jul 2020 08:10:40 +0000
|
||||
Subject: [PATCH 294/314] tftp: Do not use priority queue
|
||||
|
||||
There is not need to reassemble the order of blocks. Per RFC 1350,
|
||||
server must wait for the ACK, before sending next block. Data packets
|
||||
can be served immediately without putting them to priority queue.
|
||||
|
||||
Logic to handle incoming packet is this:
|
||||
- if packet block id equal to expected block id, then
|
||||
process the packet,
|
||||
- if packet block id is less than expected - this is retransmit
|
||||
of old packet, then ACK it and drop the packet,
|
||||
- if packet block id is more than expected - that shouldn't
|
||||
happen, just drop the packet.
|
||||
|
||||
It makes the tftp receive path code simpler, smaller and faster.
|
||||
As a benefit, this change fixes CID# 73624 and CID# 96690, caused
|
||||
by following while loop:
|
||||
|
||||
while (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) == 0)
|
||||
|
||||
where tftph pointer is not moving from one iteration to another, causing
|
||||
to serve same packet again. Luckily, double serving didn't happen due to
|
||||
data->block++ during the first iteration.
|
||||
|
||||
Fixes: CID 73624, CID 96690
|
||||
|
||||
Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Upstream-commit-id: 8316694c4f7
|
||||
---
|
||||
grub-core/net/tftp.c | 174 ++++++++++++++-----------------------------
|
||||
1 file changed, 54 insertions(+), 120 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
|
||||
index e267af354f4..79c16f9b041 100644
|
||||
--- a/grub-core/net/tftp.c
|
||||
+++ b/grub-core/net/tftp.c
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <grub/mm.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/file.h>
|
||||
-#include <grub/priority_queue.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
@@ -106,31 +105,8 @@ typedef struct tftp_data
|
||||
int have_oack;
|
||||
struct grub_error_saved save_err;
|
||||
grub_net_udp_socket_t sock;
|
||||
- grub_priority_queue_t pq;
|
||||
} *tftp_data_t;
|
||||
|
||||
-static int
|
||||
-cmp_block (grub_uint16_t a, grub_uint16_t b)
|
||||
-{
|
||||
- grub_int16_t i = (grub_int16_t) (a - b);
|
||||
- if (i > 0)
|
||||
- return +1;
|
||||
- if (i < 0)
|
||||
- return -1;
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int
|
||||
-cmp (const void *a__, const void *b__)
|
||||
-{
|
||||
- struct grub_net_buff *a_ = *(struct grub_net_buff **) a__;
|
||||
- struct grub_net_buff *b_ = *(struct grub_net_buff **) b__;
|
||||
- struct tftphdr *a = (struct tftphdr *) a_->data;
|
||||
- struct tftphdr *b = (struct tftphdr *) b_->data;
|
||||
- /* We want the first elements to be on top. */
|
||||
- return -cmp_block (grub_be_to_cpu16 (a->u.data.block), grub_be_to_cpu16 (b->u.data.block));
|
||||
-}
|
||||
-
|
||||
static grub_err_t
|
||||
ack (tftp_data_t data, grub_uint64_t block)
|
||||
{
|
||||
@@ -207,73 +183,60 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
- err = grub_priority_queue_push (data->pq, &nb);
|
||||
- if (err)
|
||||
- return err;
|
||||
+ /* Ack old/retransmitted block. */
|
||||
+ if (grub_be_to_cpu16 (tftph->u.data.block) < data->block + 1)
|
||||
+ ack (data, grub_be_to_cpu16 (tftph->u.data.block));
|
||||
+ /* Ignore unexpected block. */
|
||||
+ else if (grub_be_to_cpu16 (tftph->u.data.block) > data->block + 1)
|
||||
+ grub_dprintf ("tftp", "TFTP unexpected block # %d\n", tftph->u.data.block);
|
||||
+ else
|
||||
+ {
|
||||
+ unsigned size;
|
||||
|
||||
- {
|
||||
- struct grub_net_buff **nb_top_p, *nb_top;
|
||||
- while (1)
|
||||
- {
|
||||
- nb_top_p = grub_priority_queue_top (data->pq);
|
||||
- if (!nb_top_p)
|
||||
- return GRUB_ERR_NONE;
|
||||
- nb_top = *nb_top_p;
|
||||
- tftph = (struct tftphdr *) nb_top->data;
|
||||
- if (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) >= 0)
|
||||
- break;
|
||||
- ack (data, grub_be_to_cpu16 (tftph->u.data.block));
|
||||
- grub_netbuff_free (nb_top);
|
||||
- grub_priority_queue_pop (data->pq);
|
||||
- }
|
||||
- while (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) == 0)
|
||||
- {
|
||||
- unsigned size;
|
||||
-
|
||||
- grub_priority_queue_pop (data->pq);
|
||||
-
|
||||
- if (file->device->net->packs.count < 50)
|
||||
+ if (file->device->net->packs.count < 50)
|
||||
+ {
|
||||
err = ack (data, data->block + 1);
|
||||
- else
|
||||
- {
|
||||
- file->device->net->stall = 1;
|
||||
- err = 0;
|
||||
- }
|
||||
- if (err)
|
||||
- return err;
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+ else
|
||||
+ file->device->net->stall = 1;
|
||||
|
||||
- err = grub_netbuff_pull (nb_top, sizeof (tftph->opcode) +
|
||||
- sizeof (tftph->u.data.block));
|
||||
- if (err)
|
||||
- return err;
|
||||
- size = nb_top->tail - nb_top->data;
|
||||
+ err = grub_netbuff_pull (nb, sizeof (tftph->opcode) +
|
||||
+ sizeof (tftph->u.data.block));
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ size = nb->tail - nb->data;
|
||||
|
||||
- data->block++;
|
||||
- if (size < data->block_size)
|
||||
- {
|
||||
- if (data->ack_sent < data->block)
|
||||
- ack (data, data->block);
|
||||
- file->device->net->eof = 1;
|
||||
- file->device->net->stall = 1;
|
||||
- grub_net_udp_close (data->sock);
|
||||
- data->sock = NULL;
|
||||
- }
|
||||
- /* Prevent garbage in broken cards. Is it still necessary
|
||||
- given that IP implementation has been fixed?
|
||||
- */
|
||||
- if (size > data->block_size)
|
||||
- {
|
||||
- err = grub_netbuff_unput (nb_top, size - data->block_size);
|
||||
- if (err)
|
||||
- return err;
|
||||
- }
|
||||
- /* If there is data, puts packet in socket list. */
|
||||
- if ((nb_top->tail - nb_top->data) > 0)
|
||||
- grub_net_put_packet (&file->device->net->packs, nb_top);
|
||||
- else
|
||||
- grub_netbuff_free (nb_top);
|
||||
- }
|
||||
- }
|
||||
+ data->block++;
|
||||
+ if (size < data->block_size)
|
||||
+ {
|
||||
+ if (data->ack_sent < data->block)
|
||||
+ ack (data, data->block);
|
||||
+ file->device->net->eof = 1;
|
||||
+ file->device->net->stall = 1;
|
||||
+ grub_net_udp_close (data->sock);
|
||||
+ data->sock = NULL;
|
||||
+ }
|
||||
+ /*
|
||||
+ * Prevent garbage in broken cards. Is it still necessary
|
||||
+ * given that IP implementation has been fixed?
|
||||
+ */
|
||||
+ if (size > data->block_size)
|
||||
+ {
|
||||
+ err = grub_netbuff_unput (nb, size - data->block_size);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+ /* If there is data, puts packet in socket list. */
|
||||
+ if ((nb->tail - nb->data) > 0)
|
||||
+ {
|
||||
+ grub_net_put_packet (&file->device->net->packs, nb);
|
||||
+ /* Do not free nb. */
|
||||
+ return GRUB_ERR_NONE;
|
||||
+ }
|
||||
+ }
|
||||
+ grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
case TFTP_ERROR:
|
||||
data->have_oack = 1;
|
||||
@@ -287,22 +250,10 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
|
||||
}
|
||||
}
|
||||
|
||||
-static void
|
||||
-destroy_pq (tftp_data_t data)
|
||||
-{
|
||||
- struct grub_net_buff **nb_p;
|
||||
- while ((nb_p = grub_priority_queue_top (data->pq)))
|
||||
- {
|
||||
- grub_netbuff_free (*nb_p);
|
||||
- grub_priority_queue_pop (data->pq);
|
||||
- }
|
||||
-
|
||||
- grub_priority_queue_destroy (data->pq);
|
||||
-}
|
||||
-
|
||||
-/* Create a normalized copy of the filename.
|
||||
- Compress any string of consecutive forward slashes to a single forward
|
||||
- slash. */
|
||||
+/*
|
||||
+ * Create a normalized copy of the filename. Compress any string of consecutive
|
||||
+ * forward slashes to a single forward slash.
|
||||
+ */
|
||||
static void
|
||||
grub_normalize_filename (char *normalized, const char *filename)
|
||||
{
|
||||
@@ -395,22 +346,9 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
file->not_easily_seekable = 1;
|
||||
file->data = data;
|
||||
|
||||
- data->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp);
|
||||
- if (!data->pq)
|
||||
- {
|
||||
- grub_free (data);
|
||||
- return grub_errno;
|
||||
- }
|
||||
-
|
||||
- grub_dprintf("tftp", "resolving address for %s\n", file->device->net->server);
|
||||
err = grub_net_resolve_address (file->device->net->server, &addr);
|
||||
if (err)
|
||||
{
|
||||
- grub_dprintf ("tftp", "Address resolution failed: %d\n", err);
|
||||
- grub_dprintf ("tftp", "file_size is %llu, block_size is %llu\n",
|
||||
- (unsigned long long)data->file_size,
|
||||
- (unsigned long long)data->block_size);
|
||||
- destroy_pq (data);
|
||||
grub_free (data);
|
||||
return err;
|
||||
}
|
||||
@@ -422,7 +360,6 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
if (!data->sock)
|
||||
{
|
||||
grub_dprintf("tftp", "connection failed\n");
|
||||
- destroy_pq (data);
|
||||
grub_free (data);
|
||||
return grub_errno;
|
||||
}
|
||||
@@ -436,7 +373,6 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
if (err)
|
||||
{
|
||||
grub_net_udp_close (data->sock);
|
||||
- destroy_pq (data);
|
||||
grub_free (data);
|
||||
return err;
|
||||
}
|
||||
@@ -453,7 +389,6 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
if (grub_errno)
|
||||
{
|
||||
grub_net_udp_close (data->sock);
|
||||
- destroy_pq (data);
|
||||
grub_free (data);
|
||||
return grub_errno;
|
||||
}
|
||||
@@ -496,7 +431,6 @@ tftp_close (struct grub_file *file)
|
||||
grub_print_error ();
|
||||
grub_net_udp_close (data->sock);
|
||||
}
|
||||
- destroy_pq (data);
|
||||
grub_free (data);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,150 @@
|
||||
From 320fe69ffff39f90169f793402de4d4223a1a64c Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Date: Wed, 15 Jul 2020 06:42:37 +0000
|
||||
Subject: [PATCH 295/314] relocator: Protect grub_relocator_alloc_chunk_addr()
|
||||
input args against integer underflow/overflow
|
||||
|
||||
Use arithmetic macros from safemath.h to accomplish it. In this commit,
|
||||
I didn't want to be too paranoid to check every possible math equation
|
||||
for overflow/underflow. Only obvious places (with non zero chance of
|
||||
overflow/underflow) were refactored.
|
||||
|
||||
Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Upstream-commit-id: ebb15735f10
|
||||
---
|
||||
grub-core/loader/i386/linux.c | 9 +++++++--
|
||||
grub-core/loader/i386/pc/linux.c | 9 +++++++--
|
||||
grub-core/loader/i386/xen.c | 12 ++++++++++--
|
||||
grub-core/loader/xnu.c | 11 +++++++----
|
||||
4 files changed, 31 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
|
||||
index 76304f05700..b4a30f607fa 100644
|
||||
--- a/grub-core/loader/i386/linux.c
|
||||
+++ b/grub-core/loader/i386/linux.c
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <grub/linux.h>
|
||||
#include <grub/efi/sb.h>
|
||||
#include <grub/tpm.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -593,9 +594,13 @@ grub_linux_boot (void)
|
||||
|
||||
{
|
||||
grub_relocator_chunk_t ch;
|
||||
+ grub_size_t sz;
|
||||
+
|
||||
+ if (grub_add (ctx.real_size, efi_mmap_size, &sz))
|
||||
+ return GRUB_ERR_OUT_OF_RANGE;
|
||||
+
|
||||
err = grub_relocator_alloc_chunk_addr (relocator, &ch,
|
||||
- ctx.real_mode_target,
|
||||
- (ctx.real_size + efi_mmap_size));
|
||||
+ ctx.real_mode_target, sz);
|
||||
if (err)
|
||||
return err;
|
||||
real_mode_mem = get_virtual_current_address (ch);
|
||||
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
|
||||
index 783a3cd93bc..540891371f9 100644
|
||||
--- a/grub-core/loader/i386/pc/linux.c
|
||||
+++ b/grub-core/loader/i386/pc/linux.c
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <grub/lib/cmdline.h>
|
||||
#include <grub/linux.h>
|
||||
#include <grub/efi/sb.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -231,8 +232,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
||||
setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
|
||||
|
||||
real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
|
||||
- grub_linux16_prot_size = grub_file_size (file)
|
||||
- - real_size - GRUB_DISK_SECTOR_SIZE;
|
||||
+ if (grub_sub (grub_file_size (file), real_size, &grub_linux16_prot_size) ||
|
||||
+ grub_sub (grub_linux16_prot_size, GRUB_DISK_SECTOR_SIZE, &grub_linux16_prot_size))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||
+ goto fail;
|
||||
+ }
|
||||
|
||||
if (! grub_linux_is_bzimage
|
||||
&& GRUB_LINUX_ZIMAGE_ADDR + grub_linux16_prot_size
|
||||
diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
|
||||
index 3073f64d5e5..85b93347b25 100644
|
||||
--- a/grub-core/loader/i386/xen.c
|
||||
+++ b/grub-core/loader/i386/xen.c
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <grub/xen_file.h>
|
||||
#include <grub/linux.h>
|
||||
#include <grub/i386/memory.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -635,6 +636,7 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)),
|
||||
grub_relocator_chunk_t ch;
|
||||
grub_addr_t kern_start;
|
||||
grub_addr_t kern_end;
|
||||
+ grub_size_t sz;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
@@ -699,8 +701,14 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)),
|
||||
|
||||
xen_state.max_addr = ALIGN_UP (kern_end, PAGE_SIZE);
|
||||
|
||||
- err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, kern_start,
|
||||
- kern_end - kern_start);
|
||||
+
|
||||
+ if (grub_sub (kern_end, kern_start, &sz))
|
||||
+ {
|
||||
+ err = GRUB_ERR_OUT_OF_RANGE;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, kern_start, sz);
|
||||
if (err)
|
||||
goto fail;
|
||||
kern_chunk_src = get_virtual_current_address (ch);
|
||||
diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
|
||||
index dc7d5409e1e..2bf02489bad 100644
|
||||
--- a/grub-core/loader/xnu.c
|
||||
+++ b/grub-core/loader/xnu.c
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <grub/env.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/efi/sb.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -59,15 +60,17 @@ grub_xnu_heap_malloc (int size, void **src, grub_addr_t *target)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_relocator_chunk_t ch;
|
||||
+ grub_addr_t tgt;
|
||||
+
|
||||
+ if (grub_add (grub_xnu_heap_target_start, grub_xnu_heap_size, &tgt))
|
||||
+ return GRUB_ERR_OUT_OF_RANGE;
|
||||
|
||||
- err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, &ch,
|
||||
- grub_xnu_heap_target_start
|
||||
- + grub_xnu_heap_size, size);
|
||||
+ err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, &ch, tgt, size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*src = get_virtual_current_address (ch);
|
||||
- *target = grub_xnu_heap_target_start + grub_xnu_heap_size;
|
||||
+ *target = tgt;
|
||||
grub_xnu_heap_size += size;
|
||||
grub_dprintf ("xnu", "val=%p\n", *src);
|
||||
return GRUB_ERR_NONE;
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,338 @@
|
||||
From 93d697a46b43ee13e0343c79777af5ce23c313b7 Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Date: Wed, 8 Jul 2020 01:44:38 +0000
|
||||
Subject: [PATCH 296/314] relocator: Protect grub_relocator_alloc_chunk_align()
|
||||
max_addr against integer underflow
|
||||
|
||||
This commit introduces integer underflow mitigation in max_addr calculation
|
||||
in grub_relocator_alloc_chunk_align() invocation.
|
||||
|
||||
It consists of 2 fixes:
|
||||
1. Introduced grub_relocator_alloc_chunk_align_safe() wrapper function to perform
|
||||
sanity check for min/max and size values, and to make safe invocation of
|
||||
grub_relocator_alloc_chunk_align() with validated max_addr value. Replace all
|
||||
invocations such as grub_relocator_alloc_chunk_align(..., min_addr, max_addr - size, size, ...)
|
||||
by grub_relocator_alloc_chunk_align_safe(..., min_addr, max_addr, size, ...).
|
||||
2. Introduced UP_TO_TOP32(s) macro for the cases where max_addr is 32-bit top
|
||||
address (0xffffffff - size + 1) or similar.
|
||||
|
||||
Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Upstream-commit-id: 10498c8ba17
|
||||
---
|
||||
grub-core/lib/i386/relocator.c | 28 ++++++++++----------------
|
||||
grub-core/lib/mips/relocator.c | 6 ++----
|
||||
grub-core/lib/powerpc/relocator.c | 6 ++----
|
||||
grub-core/lib/x86_64/efi/relocator.c | 7 +++----
|
||||
grub-core/loader/i386/linux.c | 5 ++---
|
||||
grub-core/loader/i386/multiboot_mbi.c | 7 +++----
|
||||
grub-core/loader/i386/pc/linux.c | 6 ++----
|
||||
grub-core/loader/mips/linux.c | 9 +++------
|
||||
grub-core/loader/multiboot.c | 2 +-
|
||||
grub-core/loader/multiboot_elfxx.c | 10 ++++-----
|
||||
grub-core/loader/multiboot_mbi2.c | 10 ++++-----
|
||||
grub-core/loader/xnu_resume.c | 2 +-
|
||||
include/grub/relocator.h | 29 +++++++++++++++++++++++++++
|
||||
13 files changed, 69 insertions(+), 58 deletions(-)
|
||||
|
||||
diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c
|
||||
index 71dd4f0ab0c..34cbe834fa3 100644
|
||||
--- a/grub-core/lib/i386/relocator.c
|
||||
+++ b/grub-core/lib/i386/relocator.c
|
||||
@@ -83,11 +83,10 @@ grub_relocator32_boot (struct grub_relocator *rel,
|
||||
/* Specific memory range due to Global Descriptor Table for use by payload
|
||||
that we will store in returned chunk. The address range and preference
|
||||
are based on "THE LINUX/x86 BOOT PROTOCOL" specification. */
|
||||
- err = grub_relocator_alloc_chunk_align (rel, &ch, 0x1000,
|
||||
- 0x9a000 - RELOCATOR_SIZEOF (32),
|
||||
- RELOCATOR_SIZEOF (32), 16,
|
||||
- GRUB_RELOCATOR_PREFERENCE_LOW,
|
||||
- avoid_efi_bootservices);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0x1000, 0x9a000,
|
||||
+ RELOCATOR_SIZEOF (32), 16,
|
||||
+ GRUB_RELOCATOR_PREFERENCE_LOW,
|
||||
+ avoid_efi_bootservices);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -125,13 +124,10 @@ grub_relocator16_boot (struct grub_relocator *rel,
|
||||
grub_relocator_chunk_t ch;
|
||||
|
||||
/* Put it higher than the byte it checks for A20 check. */
|
||||
- err = grub_relocator_alloc_chunk_align (rel, &ch, 0x8010,
|
||||
- 0xa0000 - RELOCATOR_SIZEOF (16)
|
||||
- - GRUB_RELOCATOR16_STACK_SIZE,
|
||||
- RELOCATOR_SIZEOF (16)
|
||||
- + GRUB_RELOCATOR16_STACK_SIZE, 16,
|
||||
- GRUB_RELOCATOR_PREFERENCE_NONE,
|
||||
- 0);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0x8010, 0xa0000,
|
||||
+ RELOCATOR_SIZEOF (16) +
|
||||
+ GRUB_RELOCATOR16_STACK_SIZE, 16,
|
||||
+ GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -183,11 +179,9 @@ grub_relocator64_boot (struct grub_relocator *rel,
|
||||
void *relst;
|
||||
grub_relocator_chunk_t ch;
|
||||
|
||||
- err = grub_relocator_alloc_chunk_align (rel, &ch, min_addr,
|
||||
- max_addr - RELOCATOR_SIZEOF (64),
|
||||
- RELOCATOR_SIZEOF (64), 16,
|
||||
- GRUB_RELOCATOR_PREFERENCE_NONE,
|
||||
- 0);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (rel, &ch, min_addr, max_addr,
|
||||
+ RELOCATOR_SIZEOF (64), 16,
|
||||
+ GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
diff --git a/grub-core/lib/mips/relocator.c b/grub-core/lib/mips/relocator.c
|
||||
index 9d5f49cb93a..743b213e695 100644
|
||||
--- a/grub-core/lib/mips/relocator.c
|
||||
+++ b/grub-core/lib/mips/relocator.c
|
||||
@@ -120,10 +120,8 @@ grub_relocator32_boot (struct grub_relocator *rel,
|
||||
unsigned i;
|
||||
grub_addr_t vtarget;
|
||||
|
||||
- err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
|
||||
- (0xffffffff - stateset_size)
|
||||
- + 1, stateset_size,
|
||||
- sizeof (grub_uint32_t),
|
||||
+ err = grub_relocator_alloc_chunk_align (rel, &ch, 0, UP_TO_TOP32 (stateset_size),
|
||||
+ stateset_size, sizeof (grub_uint32_t),
|
||||
GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
if (err)
|
||||
return err;
|
||||
diff --git a/grub-core/lib/powerpc/relocator.c b/grub-core/lib/powerpc/relocator.c
|
||||
index bdf2b111be7..8ffb8b68683 100644
|
||||
--- a/grub-core/lib/powerpc/relocator.c
|
||||
+++ b/grub-core/lib/powerpc/relocator.c
|
||||
@@ -115,10 +115,8 @@ grub_relocator32_boot (struct grub_relocator *rel,
|
||||
unsigned i;
|
||||
grub_relocator_chunk_t ch;
|
||||
|
||||
- err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
|
||||
- (0xffffffff - stateset_size)
|
||||
- + 1, stateset_size,
|
||||
- sizeof (grub_uint32_t),
|
||||
+ err = grub_relocator_alloc_chunk_align (rel, &ch, 0, UP_TO_TOP32 (stateset_size),
|
||||
+ stateset_size, sizeof (grub_uint32_t),
|
||||
GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
if (err)
|
||||
return err;
|
||||
diff --git a/grub-core/lib/x86_64/efi/relocator.c b/grub-core/lib/x86_64/efi/relocator.c
|
||||
index 3caef7a4021..7d200a125ee 100644
|
||||
--- a/grub-core/lib/x86_64/efi/relocator.c
|
||||
+++ b/grub-core/lib/x86_64/efi/relocator.c
|
||||
@@ -50,10 +50,9 @@ grub_relocator64_efi_boot (struct grub_relocator *rel,
|
||||
* 64-bit relocator code may live above 4 GiB quite well.
|
||||
* However, I do not want ask for problems. Just in case.
|
||||
*/
|
||||
- err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
|
||||
- 0x100000000 - RELOCATOR_SIZEOF (64_efi),
|
||||
- RELOCATOR_SIZEOF (64_efi), 16,
|
||||
- GRUB_RELOCATOR_PREFERENCE_NONE, 1);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0, 0x100000000,
|
||||
+ RELOCATOR_SIZEOF (64_efi), 16,
|
||||
+ GRUB_RELOCATOR_PREFERENCE_NONE, 1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
|
||||
index b4a30f607fa..191f1631e88 100644
|
||||
--- a/grub-core/loader/i386/linux.c
|
||||
+++ b/grub-core/loader/i386/linux.c
|
||||
@@ -231,9 +231,8 @@ allocate_pages (grub_size_t prot_size, grub_size_t *align,
|
||||
for (; err && *align + 1 > min_align; (*align)--)
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
- err = grub_relocator_alloc_chunk_align (relocator, &ch,
|
||||
- 0x1000000,
|
||||
- 0xffffffff & ~prot_size,
|
||||
+ err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000000,
|
||||
+ UP_TO_TOP32 (prot_size),
|
||||
prot_size, 1 << *align,
|
||||
GRUB_RELOCATOR_PREFERENCE_LOW,
|
||||
1);
|
||||
diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c
|
||||
index ca85358f771..9d3466d6ace 100644
|
||||
--- a/grub-core/loader/i386/multiboot_mbi.c
|
||||
+++ b/grub-core/loader/i386/multiboot_mbi.c
|
||||
@@ -470,10 +470,9 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
|
||||
|
||||
bufsize = grub_multiboot_get_mbi_size ();
|
||||
|
||||
- err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
|
||||
- 0x10000, 0xa0000 - bufsize,
|
||||
- bufsize, 4,
|
||||
- GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (grub_multiboot_relocator, &ch,
|
||||
+ 0x10000, 0xa0000, bufsize, 4,
|
||||
+ GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
if (err)
|
||||
return err;
|
||||
ptrorig = get_virtual_current_address (ch);
|
||||
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
|
||||
index 540891371f9..63736fae950 100644
|
||||
--- a/grub-core/loader/i386/pc/linux.c
|
||||
+++ b/grub-core/loader/i386/pc/linux.c
|
||||
@@ -460,10 +460,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
||||
|
||||
{
|
||||
grub_relocator_chunk_t ch;
|
||||
- err = grub_relocator_alloc_chunk_align (relocator, &ch,
|
||||
- addr_min, addr_max - size,
|
||||
- size, 0x1000,
|
||||
- GRUB_RELOCATOR_PREFERENCE_HIGH, 0);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (relocator, &ch, addr_min, addr_max, size,
|
||||
+ 0x1000, GRUB_RELOCATOR_PREFERENCE_HIGH, 0);
|
||||
if (err)
|
||||
return err;
|
||||
initrd_chunk = get_virtual_current_address (ch);
|
||||
diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c
|
||||
index 5f383be3d07..27c1db84a44 100644
|
||||
--- a/grub-core/loader/mips/linux.c
|
||||
+++ b/grub-core/loader/mips/linux.c
|
||||
@@ -434,12 +434,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
||||
{
|
||||
grub_relocator_chunk_t ch;
|
||||
|
||||
- err = grub_relocator_alloc_chunk_align (relocator, &ch,
|
||||
- (target_addr & 0x1fffffff)
|
||||
- + linux_size + 0x10000,
|
||||
- (0x10000000 - size),
|
||||
- size, 0x10000,
|
||||
- GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (relocator, &ch, (target_addr & 0x1fffffff) +
|
||||
+ linux_size + 0x10000, 0x10000000, size,
|
||||
+ 0x10000, GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
|
||||
if (err)
|
||||
goto fail;
|
||||
diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
|
||||
index 9a8dae5565b..f455e803910 100644
|
||||
--- a/grub-core/loader/multiboot.c
|
||||
+++ b/grub-core/loader/multiboot.c
|
||||
@@ -407,7 +407,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
|
||||
{
|
||||
grub_relocator_chunk_t ch;
|
||||
err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch,
|
||||
- lowest_addr, (0xffffffff - size) + 1,
|
||||
+ lowest_addr, UP_TO_TOP32 (size),
|
||||
size, MULTIBOOT_MOD_ALIGN,
|
||||
GRUB_RELOCATOR_PREFERENCE_NONE, 1);
|
||||
if (err)
|
||||
diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c
|
||||
index cc6853692a8..f2318e0d165 100644
|
||||
--- a/grub-core/loader/multiboot_elfxx.c
|
||||
+++ b/grub-core/loader/multiboot_elfxx.c
|
||||
@@ -109,10 +109,10 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
|
||||
if (load_size > mld->max_addr || mld->min_addr > mld->max_addr - load_size)
|
||||
return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
|
||||
|
||||
- err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch,
|
||||
- mld->min_addr, mld->max_addr - load_size,
|
||||
- load_size, mld->align ? mld->align : 1,
|
||||
- mld->preference, mld->avoid_efi_boot_services);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (GRUB_MULTIBOOT (relocator), &ch,
|
||||
+ mld->min_addr, mld->max_addr,
|
||||
+ load_size, mld->align ? mld->align : 1,
|
||||
+ mld->preference, mld->avoid_efi_boot_services);
|
||||
|
||||
if (err)
|
||||
{
|
||||
@@ -256,7 +256,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
|
||||
continue;
|
||||
|
||||
err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch, 0,
|
||||
- (0xffffffff - sh->sh_size) + 1,
|
||||
+ UP_TO_TOP32 (sh->sh_size),
|
||||
sh->sh_size, sh->sh_addralign,
|
||||
GRUB_RELOCATOR_PREFERENCE_NONE,
|
||||
mld->avoid_efi_boot_services);
|
||||
diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
|
||||
index 872dcd42e97..3cfb47650a0 100644
|
||||
--- a/grub-core/loader/multiboot_mbi2.c
|
||||
+++ b/grub-core/loader/multiboot_mbi2.c
|
||||
@@ -298,10 +298,10 @@ grub_multiboot2_load (grub_file_t file, const char *filename)
|
||||
return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
|
||||
}
|
||||
|
||||
- err = grub_relocator_alloc_chunk_align (grub_multiboot2_relocator, &ch,
|
||||
- mld.min_addr, mld.max_addr - code_size,
|
||||
- code_size, mld.align ? mld.align : 1,
|
||||
- mld.preference, keep_bs);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (grub_multiboot2_relocator, &ch,
|
||||
+ mld.min_addr, mld.max_addr,
|
||||
+ code_size, mld.align ? mld.align : 1,
|
||||
+ mld.preference, keep_bs);
|
||||
}
|
||||
else
|
||||
err = grub_relocator_alloc_chunk_addr (grub_multiboot2_relocator,
|
||||
@@ -747,7 +747,7 @@ grub_multiboot2_make_mbi (grub_uint32_t *target)
|
||||
COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % sizeof (grub_properly_aligned_t) == 0);
|
||||
|
||||
err = grub_relocator_alloc_chunk_align (grub_multiboot2_relocator, &ch,
|
||||
- 0, 0xffffffff - bufsize,
|
||||
+ 0, UP_TO_TOP32 (bufsize),
|
||||
bufsize, MULTIBOOT_TAG_ALIGN,
|
||||
GRUB_RELOCATOR_PREFERENCE_NONE, 1);
|
||||
if (err)
|
||||
diff --git a/grub-core/loader/xnu_resume.c b/grub-core/loader/xnu_resume.c
|
||||
index 534a74438b2..99119558d21 100644
|
||||
--- a/grub-core/loader/xnu_resume.c
|
||||
+++ b/grub-core/loader/xnu_resume.c
|
||||
@@ -129,7 +129,7 @@ grub_xnu_resume (char *imagename)
|
||||
{
|
||||
grub_relocator_chunk_t ch;
|
||||
err = grub_relocator_alloc_chunk_align (grub_xnu_relocator, &ch, 0,
|
||||
- (0xffffffff - hibhead.image_size) + 1,
|
||||
+ UP_TO_TOP32 (hibhead.image_size),
|
||||
hibhead.image_size,
|
||||
GRUB_XNU_PAGESIZE,
|
||||
GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
diff --git a/include/grub/relocator.h b/include/grub/relocator.h
|
||||
index 24d8672d22c..1b3bdd92ac6 100644
|
||||
--- a/include/grub/relocator.h
|
||||
+++ b/include/grub/relocator.h
|
||||
@@ -49,6 +49,35 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel,
|
||||
int preference,
|
||||
int avoid_efi_boot_services);
|
||||
|
||||
+/*
|
||||
+ * Wrapper for grub_relocator_alloc_chunk_align() with purpose of
|
||||
+ * protecting against integer underflow.
|
||||
+ *
|
||||
+ * Compare to its callee, max_addr has different meaning here.
|
||||
+ * It covers entire chunk and not just start address of the chunk.
|
||||
+ */
|
||||
+static inline grub_err_t
|
||||
+grub_relocator_alloc_chunk_align_safe (struct grub_relocator *rel,
|
||||
+ grub_relocator_chunk_t *out,
|
||||
+ grub_phys_addr_t min_addr,
|
||||
+ grub_phys_addr_t max_addr,
|
||||
+ grub_size_t size, grub_size_t align,
|
||||
+ int preference,
|
||||
+ int avoid_efi_boot_services)
|
||||
+{
|
||||
+ /* Sanity check and ensure following equation (max_addr - size) is safe. */
|
||||
+ if (max_addr < size || (max_addr - size) < min_addr)
|
||||
+ return GRUB_ERR_OUT_OF_RANGE;
|
||||
+
|
||||
+ return grub_relocator_alloc_chunk_align (rel, out, min_addr,
|
||||
+ max_addr - size,
|
||||
+ size, align, preference,
|
||||
+ avoid_efi_boot_services);
|
||||
+}
|
||||
+
|
||||
+/* Top 32-bit address minus s bytes and plus 1 byte. */
|
||||
+#define UP_TO_TOP32(s) ((~(s) & 0xffffffff) + 1)
|
||||
+
|
||||
#define GRUB_RELOCATOR_PREFERENCE_NONE 0
|
||||
#define GRUB_RELOCATOR_PREFERENCE_LOW 1
|
||||
#define GRUB_RELOCATOR_PREFERENCE_HIGH 2
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,34 @@
|
||||
From 19d627a430f6917afeee167daa9190d1ec83d7b7 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Coulson <chris.coulson@canonical.com>
|
||||
Date: Fri, 10 Jul 2020 11:21:14 +0100
|
||||
Subject: [PATCH 297/314] script: Remove unused fields from
|
||||
grub_script_function struct
|
||||
|
||||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Upstream-commit-id: d04089c8e52
|
||||
---
|
||||
include/grub/script_sh.h | 5 -----
|
||||
1 file changed, 5 deletions(-)
|
||||
|
||||
diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h
|
||||
index 360c2be1f05..b382bcf09bc 100644
|
||||
--- a/include/grub/script_sh.h
|
||||
+++ b/include/grub/script_sh.h
|
||||
@@ -359,13 +359,8 @@ struct grub_script_function
|
||||
/* The script function. */
|
||||
struct grub_script *func;
|
||||
|
||||
- /* The flags. */
|
||||
- unsigned flags;
|
||||
-
|
||||
/* The next element. */
|
||||
struct grub_script_function *next;
|
||||
-
|
||||
- int references;
|
||||
};
|
||||
typedef struct grub_script_function *grub_script_function_t;
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,108 @@
|
||||
From c1de65c0e3d630f33160d34e1e85925f01966b0d Mon Sep 17 00:00:00 2001
|
||||
From: Chris Coulson <chris.coulson@canonical.com>
|
||||
Date: Fri, 10 Jul 2020 14:41:45 +0100
|
||||
Subject: [PATCH 298/314] script: Avoid a use-after-free when redefining a
|
||||
function during execution
|
||||
|
||||
Defining a new function with the same name as a previously defined
|
||||
function causes the grub_script and associated resources for the
|
||||
previous function to be freed. If the previous function is currently
|
||||
executing when a function with the same name is defined, this results
|
||||
in use-after-frees when processing subsequent commands in the original
|
||||
function.
|
||||
|
||||
Instead, reject a new function definition if it has the same name as
|
||||
a previously defined function, and that function is currently being
|
||||
executed. Although a behavioural change, this should be backwards
|
||||
compatible with existing configurations because they can't be
|
||||
dependent on the current behaviour without being broken.
|
||||
|
||||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Upstream-commit-id: f6253a1f540
|
||||
---
|
||||
grub-core/script/execute.c | 2 ++
|
||||
grub-core/script/function.c | 16 +++++++++++++---
|
||||
include/grub/script_sh.h | 2 ++
|
||||
grub-core/script/parser.y | 3 ++-
|
||||
4 files changed, 19 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
|
||||
index 528ddfd36f0..a1aadb9ee05 100644
|
||||
--- a/grub-core/script/execute.c
|
||||
+++ b/grub-core/script/execute.c
|
||||
@@ -872,7 +872,9 @@ grub_script_function_call (grub_script_function_t func, int argc, char **args)
|
||||
old_scope = scope;
|
||||
scope = &new_scope;
|
||||
|
||||
+ func->executing++;
|
||||
ret = grub_script_execute (func->func);
|
||||
+ func->executing--;
|
||||
|
||||
function_return = 0;
|
||||
active_loops = loops;
|
||||
diff --git a/grub-core/script/function.c b/grub-core/script/function.c
|
||||
index d36655e510f..3aad04bf9dd 100644
|
||||
--- a/grub-core/script/function.c
|
||||
+++ b/grub-core/script/function.c
|
||||
@@ -34,6 +34,7 @@ grub_script_function_create (struct grub_script_arg *functionname_arg,
|
||||
func = (grub_script_function_t) grub_malloc (sizeof (*func));
|
||||
if (! func)
|
||||
return 0;
|
||||
+ func->executing = 0;
|
||||
|
||||
func->name = grub_strdup (functionname_arg->str);
|
||||
if (! func->name)
|
||||
@@ -60,10 +61,19 @@ grub_script_function_create (struct grub_script_arg *functionname_arg,
|
||||
grub_script_function_t q;
|
||||
|
||||
q = *p;
|
||||
- grub_script_free (q->func);
|
||||
- q->func = cmd;
|
||||
grub_free (func);
|
||||
- func = q;
|
||||
+ if (q->executing > 0)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("attempt to redefine a function being executed"));
|
||||
+ func = NULL;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ grub_script_free (q->func);
|
||||
+ q->func = cmd;
|
||||
+ func = q;
|
||||
+ }
|
||||
}
|
||||
else
|
||||
{
|
||||
diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h
|
||||
index b382bcf09bc..6c48e075122 100644
|
||||
--- a/include/grub/script_sh.h
|
||||
+++ b/include/grub/script_sh.h
|
||||
@@ -361,6 +361,8 @@ struct grub_script_function
|
||||
|
||||
/* The next element. */
|
||||
struct grub_script_function *next;
|
||||
+
|
||||
+ unsigned executing;
|
||||
};
|
||||
typedef struct grub_script_function *grub_script_function_t;
|
||||
|
||||
diff --git a/grub-core/script/parser.y b/grub-core/script/parser.y
|
||||
index 4f0ab8319e3..f80b86b6f15 100644
|
||||
--- a/grub-core/script/parser.y
|
||||
+++ b/grub-core/script/parser.y
|
||||
@@ -289,7 +289,8 @@ function: "function" "name"
|
||||
grub_script_mem_free (state->func_mem);
|
||||
else {
|
||||
script->children = state->scripts;
|
||||
- grub_script_function_create ($2, script);
|
||||
+ if (!grub_script_function_create ($2, script))
|
||||
+ grub_script_free (script);
|
||||
}
|
||||
|
||||
state->scripts = $<scripts>3;
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,46 @@
|
||||
From 7de922a99acd0521b99cd0dd81fe62643ce734a5 Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Date: Fri, 17 Jul 2020 05:17:26 +0000
|
||||
Subject: [PATCH 299/314] relocator: Fix grub_relocator_alloc_chunk_align() top
|
||||
memory allocation
|
||||
|
||||
Current implementation of grub_relocator_alloc_chunk_align()
|
||||
does not allow allocation of the top byte.
|
||||
|
||||
Assuming input args are:
|
||||
max_addr = 0xfffff000;
|
||||
size = 0x1000;
|
||||
|
||||
And this is valid. But following overflow protection will
|
||||
unnecessarily move max_addr one byte down (to 0xffffefff):
|
||||
if (max_addr > ~size)
|
||||
max_addr = ~size;
|
||||
|
||||
~size + 1 will fix the situation. In addition, check size
|
||||
for non zero to do not zero max_addr.
|
||||
|
||||
Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Upstream-commit-id: ab80a97eb1f
|
||||
---
|
||||
grub-core/lib/relocator.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c
|
||||
index 5847aac3643..f2c1944c28d 100644
|
||||
--- a/grub-core/lib/relocator.c
|
||||
+++ b/grub-core/lib/relocator.c
|
||||
@@ -1386,8 +1386,8 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel,
|
||||
};
|
||||
grub_addr_t min_addr2 = 0, max_addr2;
|
||||
|
||||
- if (max_addr > ~size)
|
||||
- max_addr = ~size;
|
||||
+ if (size && (max_addr > ~size))
|
||||
+ max_addr = ~size + 1;
|
||||
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
if (min_addr < 0x1000)
|
||||
--
|
||||
2.26.2
|
||||
|
57
SOURCES/0300-hfsplus-fix-two-more-overflows.patch
Normal file
57
SOURCES/0300-hfsplus-fix-two-more-overflows.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From 3a60f2bfd8ab98484a7d8ba52748795f7b225ddc Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Sun, 19 Jul 2020 14:43:31 -0400
|
||||
Subject: [PATCH 300/314] hfsplus: fix two more overflows
|
||||
|
||||
Both node->size and node->namelen come from the supplied filesystem,
|
||||
which may be user-supplied. We can't trust them for the math unless we
|
||||
know they don't overflow; making sure they go through calloc() first
|
||||
will give us that.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
|
||||
Upstream-commit-id: b4915078903
|
||||
---
|
||||
grub-core/fs/hfsplus.c | 11 ++++++++---
|
||||
1 file changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
|
||||
index f1cd72398ec..8b17ebba296 100644
|
||||
--- a/grub-core/fs/hfsplus.c
|
||||
+++ b/grub-core/fs/hfsplus.c
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <grub/hfs.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/hfsplus.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -475,8 +476,12 @@ grub_hfsplus_read_symlink (grub_fshelp_node_t node)
|
||||
{
|
||||
char *symlink;
|
||||
grub_ssize_t numread;
|
||||
+ grub_size_t sz = node->size;
|
||||
|
||||
- symlink = grub_malloc (node->size + 1);
|
||||
+ if (grub_add (sz, 1, &sz))
|
||||
+ return NULL;
|
||||
+
|
||||
+ symlink = grub_malloc (sz);
|
||||
if (!symlink)
|
||||
return 0;
|
||||
|
||||
@@ -715,8 +720,8 @@ list_nodes (void *record, void *hook_arg)
|
||||
if (type == GRUB_FSHELP_UNKNOWN)
|
||||
return 0;
|
||||
|
||||
- filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen)
|
||||
- * GRUB_MAX_UTF8_PER_UTF16 + 1);
|
||||
+ filename = grub_calloc (grub_be_to_cpu16 (catkey->namelen),
|
||||
+ GRUB_MAX_UTF8_PER_UTF16 + 1);
|
||||
if (! filename)
|
||||
return 0;
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,113 @@
|
||||
From 5c219ca7ec3b481573309245e3b7399c2f19a99c Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Sun, 19 Jul 2020 15:48:20 -0400
|
||||
Subject: [PATCH 301/314] lvm: fix two more potential data-dependent alloc
|
||||
overflows
|
||||
|
||||
It appears to be possible to make a (possibly invalid) lvm PV with a
|
||||
metadata size field that overflows our type when adding it to the
|
||||
address we've allocated. Even if it doesn't, it may be possible to do
|
||||
so with the math using the outcome of that as an operand. Check them
|
||||
both.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
|
||||
Upstream-commit-id: 45ec6046ea0
|
||||
---
|
||||
grub-core/disk/lvm.c | 48 ++++++++++++++++++++++++++++++++++++--------
|
||||
1 file changed, 40 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
|
||||
index d1df640b311..ca09d469990 100644
|
||||
--- a/grub-core/disk/lvm.c
|
||||
+++ b/grub-core/disk/lvm.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <grub/lvm.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/i18n.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
#include <grub/emu/misc.h>
|
||||
@@ -102,10 +103,12 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_uint64_t mda_offset, mda_size;
|
||||
+ grub_size_t ptr;
|
||||
char buf[GRUB_LVM_LABEL_SIZE];
|
||||
char vg_id[GRUB_LVM_ID_STRLEN+1];
|
||||
char pv_id[GRUB_LVM_ID_STRLEN+1];
|
||||
- char *metadatabuf, *p, *q, *vgname;
|
||||
+ char *metadatabuf, *mda_end, *vgname;
|
||||
+ char *p, *q;
|
||||
struct grub_lvm_label_header *lh = (struct grub_lvm_label_header *) buf;
|
||||
struct grub_lvm_pv_header *pvh;
|
||||
struct grub_lvm_disk_locn *dlocn;
|
||||
@@ -205,19 +208,31 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
grub_le_to_cpu64 (rlocn->size) -
|
||||
grub_le_to_cpu64 (mdah->size));
|
||||
}
|
||||
- p = q = metadatabuf + grub_le_to_cpu64 (rlocn->offset);
|
||||
|
||||
- while (*q != ' ' && q < metadatabuf + mda_size)
|
||||
- q++;
|
||||
-
|
||||
- if (q == metadatabuf + mda_size)
|
||||
+ if (grub_add ((grub_size_t)metadatabuf,
|
||||
+ (grub_size_t)grub_le_to_cpu64 (rlocn->offset),
|
||||
+ &ptr))
|
||||
{
|
||||
+error_parsing_metadata:
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("error parsing metadata");
|
||||
#endif
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
+ p = q = (char *)ptr;
|
||||
+
|
||||
+ if (grub_add ((grub_size_t)metadatabuf, (grub_size_t)mda_size, &ptr))
|
||||
+ goto error_parsing_metadata;
|
||||
+
|
||||
+ mda_end = (char *)ptr;
|
||||
+
|
||||
+ while (*q != ' ' && q < mda_end)
|
||||
+ q++;
|
||||
+
|
||||
+ if (q == mda_end)
|
||||
+ goto error_parsing_metadata;
|
||||
+
|
||||
vgname_len = q - p;
|
||||
vgname = grub_malloc (vgname_len + 1);
|
||||
if (!vgname)
|
||||
@@ -367,8 +382,25 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
{
|
||||
const char *iptr;
|
||||
char *optr;
|
||||
- lv->fullname = grub_malloc (sizeof ("lvm/") - 1 + 2 * vgname_len
|
||||
- + 1 + 2 * s + 1);
|
||||
+
|
||||
+ /* this is kind of hard to read with our safe (but rather
|
||||
+ * baroque) math primatives, but it boils down to:
|
||||
+ *
|
||||
+ * sz0 = vgname_len * 2 + 1
|
||||
+ * + s * 2 + 1
|
||||
+ * + sizeof ("lvm/") - 1;
|
||||
+ */
|
||||
+ grub_size_t sz0 = vgname_len, sz1 = s;
|
||||
+
|
||||
+ if (grub_mul (sz0, 2, &sz0) ||
|
||||
+ grub_add (sz0, 1, &sz0) ||
|
||||
+ grub_mul (sz1, 2, &sz1) ||
|
||||
+ grub_add (sz1, 1, &sz1) ||
|
||||
+ grub_add (sz0, sz1, &sz0) ||
|
||||
+ grub_add (sz0, sizeof ("lvm/") - 1, &sz0))
|
||||
+ goto lvs_fail;
|
||||
+
|
||||
+ lv->fullname = grub_malloc (sz0);
|
||||
if (!lv->fullname)
|
||||
goto lvs_fail;
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
34
SOURCES/0302-emu-make-grub_free-NULL-safe.patch
Normal file
34
SOURCES/0302-emu-make-grub_free-NULL-safe.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From d38b6703c0668e5d99e6f00aeef5d1b1d7458f9a Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Sun, 19 Jul 2020 16:08:08 -0400
|
||||
Subject: [PATCH 302/314] emu: make grub_free(NULL) safe
|
||||
|
||||
The grub_free() implementation in kern/mm.c safely handles NULL
|
||||
pointers, and code at many places depends on this. We don't know that
|
||||
the same is true on all host OSes, so we need to handle the same
|
||||
behavior in grub-emu's implementation.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
|
||||
Upstream-commit-id: 96bb109e658
|
||||
---
|
||||
grub-core/kern/emu/mm.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/kern/emu/mm.c b/grub-core/kern/emu/mm.c
|
||||
index 145b01d3719..4d1046a219e 100644
|
||||
--- a/grub-core/kern/emu/mm.c
|
||||
+++ b/grub-core/kern/emu/mm.c
|
||||
@@ -60,7 +60,8 @@ grub_zalloc (grub_size_t size)
|
||||
void
|
||||
grub_free (void *ptr)
|
||||
{
|
||||
- free (ptr);
|
||||
+ if (ptr)
|
||||
+ free (ptr);
|
||||
}
|
||||
|
||||
void *
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,252 @@
|
||||
From 3ca105b5d77e292517091da4777484068848da6d Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Sun, 19 Jul 2020 16:53:27 -0400
|
||||
Subject: [PATCH 303/314] efi: fix some malformed device path arithmetic
|
||||
errors.
|
||||
|
||||
Several places we take the length of a device path and subtract 4 from
|
||||
it, without ever checking that it's >= 4. There are also cases where
|
||||
this kind of malformation will result in unpredictable iteration,
|
||||
including treating the length from one dp node as the type in the next
|
||||
node. These are all errors, no matter where the data comes from.
|
||||
|
||||
This patch adds a checking macro, GRUB_EFI_DEVICE_PATH_VALID(), which
|
||||
can be used in several places, and makes GRUB_EFI_NEXT_DEVICE_PATH()
|
||||
return NULL and GRUB_EFI_END_ENTIRE_DEVICE_PATH() evaluate as true when
|
||||
the length is too small. Additionally, it makes several places in the
|
||||
code check for and return errors in these cases.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Upstream-commit-id: 23e68a83990
|
||||
---
|
||||
grub-core/kern/efi/efi.c | 67 +++++++++++++++++++++++++-----
|
||||
grub-core/loader/efi/chainloader.c | 19 ++++++++-
|
||||
grub-core/loader/i386/xnu.c | 9 ++--
|
||||
include/grub/efi/api.h | 14 ++++---
|
||||
4 files changed, 88 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
|
||||
index b1379b92fb8..03de9cb14e7 100644
|
||||
--- a/grub-core/kern/efi/efi.c
|
||||
+++ b/grub-core/kern/efi/efi.c
|
||||
@@ -344,7 +344,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
|
||||
|
||||
dp = dp0;
|
||||
|
||||
- while (1)
|
||||
+ while (dp)
|
||||
{
|
||||
grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
|
||||
grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
|
||||
@@ -354,9 +354,15 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
|
||||
if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
|
||||
&& subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
|
||||
{
|
||||
- grub_efi_uint16_t len;
|
||||
- len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
|
||||
- / sizeof (grub_efi_char16_t));
|
||||
+ grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
|
||||
+
|
||||
+ if (len < 4)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
+ "malformed EFI Device Path node has length=%d", len);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ len = (len - 4) / sizeof (grub_efi_char16_t);
|
||||
filesize += GRUB_MAX_UTF8_PER_UTF16 * len + 2;
|
||||
}
|
||||
|
||||
@@ -372,7 +378,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
- while (1)
|
||||
+ while (dp)
|
||||
{
|
||||
grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
|
||||
grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
|
||||
@@ -388,8 +394,15 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
|
||||
|
||||
*p++ = '/';
|
||||
|
||||
- len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
|
||||
- / sizeof (grub_efi_char16_t));
|
||||
+ len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
|
||||
+ if (len < 4)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
+ "malformed EFI Device Path node has length=%d", len);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ len = (len - 4) / sizeof (grub_efi_char16_t);
|
||||
fp = (grub_efi_file_path_device_path_t *) dp;
|
||||
/* According to EFI spec Path Name is NULL terminated */
|
||||
while (len > 0 && fp->path_name[len - 1] == 0)
|
||||
@@ -464,7 +477,26 @@ grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp)
|
||||
;
|
||||
p = GRUB_EFI_NEXT_DEVICE_PATH (p))
|
||||
{
|
||||
- total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
|
||||
+ grub_size_t len = GRUB_EFI_DEVICE_PATH_LENGTH (p);
|
||||
+
|
||||
+ /*
|
||||
+ * In the event that we find a node that's completely garbage, for
|
||||
+ * example if we get to 0x7f 0x01 0x02 0x00 ... (EndInstance with a size
|
||||
+ * of 2), GRUB_EFI_END_ENTIRE_DEVICE_PATH() will be true and
|
||||
+ * GRUB_EFI_NEXT_DEVICE_PATH() will return NULL, so we won't continue,
|
||||
+ * and neither should our consumers, but there won't be any error raised
|
||||
+ * even though the device path is junk.
|
||||
+ *
|
||||
+ * This keeps us from passing junk down back to our caller.
|
||||
+ */
|
||||
+ if (len < 4)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
+ "malformed EFI Device Path node has length=%d", len);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ total_size += len;
|
||||
if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
|
||||
break;
|
||||
}
|
||||
@@ -509,7 +541,7 @@ dump_vendor_path (const char *type, grub_efi_vendor_device_path_t *vendor)
|
||||
void
|
||||
grub_efi_print_device_path (grub_efi_device_path_t *dp)
|
||||
{
|
||||
- while (1)
|
||||
+ while (GRUB_EFI_DEVICE_PATH_VALID (dp))
|
||||
{
|
||||
grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
|
||||
grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
|
||||
@@ -981,7 +1013,11 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
|
||||
/* Return non-zero. */
|
||||
return 1;
|
||||
|
||||
- while (1)
|
||||
+ if (dp1 == dp2)
|
||||
+ return 0;
|
||||
+
|
||||
+ while (GRUB_EFI_DEVICE_PATH_VALID (dp1)
|
||||
+ && GRUB_EFI_DEVICE_PATH_VALID (dp2))
|
||||
{
|
||||
grub_efi_uint8_t type1, type2;
|
||||
grub_efi_uint8_t subtype1, subtype2;
|
||||
@@ -1017,5 +1053,16 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
|
||||
dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * There's no "right" answer here, but we probably don't want to call a valid
|
||||
+ * dp and an invalid dp equal, so pick one way or the other.
|
||||
+ */
|
||||
+ if (GRUB_EFI_DEVICE_PATH_VALID (dp1) &&
|
||||
+ !GRUB_EFI_DEVICE_PATH_VALID (dp2))
|
||||
+ return 1;
|
||||
+ else if (!GRUB_EFI_DEVICE_PATH_VALID (dp1) &&
|
||||
+ GRUB_EFI_DEVICE_PATH_VALID (dp2))
|
||||
+ return -1;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||
index 2da119ad513..c2411b6dab2 100644
|
||||
--- a/grub-core/loader/efi/chainloader.c
|
||||
+++ b/grub-core/loader/efi/chainloader.c
|
||||
@@ -125,6 +125,12 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
|
||||
fp->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE;
|
||||
fp->header.subtype = GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE;
|
||||
|
||||
+ if (!GRUB_EFI_DEVICE_PATH_VALID ((grub_efi_device_path_t *)fp))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI Device Path is invalid");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
path_name = grub_calloc (len, GRUB_MAX_UTF16_PER_UTF8 * sizeof (*path_name));
|
||||
if (!path_name)
|
||||
return;
|
||||
@@ -164,9 +170,18 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
|
||||
|
||||
size = 0;
|
||||
d = dp;
|
||||
- while (1)
|
||||
+ while (d)
|
||||
{
|
||||
- size += GRUB_EFI_DEVICE_PATH_LENGTH (d);
|
||||
+ grub_size_t len = GRUB_EFI_DEVICE_PATH_LENGTH (d);
|
||||
+
|
||||
+ if (len < 4)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
+ "malformed EFI Device Path node has length=%d", len);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ size += len;
|
||||
if ((GRUB_EFI_END_ENTIRE_DEVICE_PATH (d)))
|
||||
break;
|
||||
d = GRUB_EFI_NEXT_DEVICE_PATH (d);
|
||||
diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c
|
||||
index c760db30fc0..44f7ebfa2b6 100644
|
||||
--- a/grub-core/loader/i386/xnu.c
|
||||
+++ b/grub-core/loader/i386/xnu.c
|
||||
@@ -515,14 +515,15 @@ grub_cmd_devprop_load (grub_command_t cmd __attribute__ ((unused)),
|
||||
|
||||
devhead = buf;
|
||||
buf = devhead + 1;
|
||||
- dpstart = buf;
|
||||
+ dp = dpstart = buf;
|
||||
|
||||
- do
|
||||
+ while (GRUB_EFI_DEVICE_PATH_VALID (dp) && buf < bufend)
|
||||
{
|
||||
- dp = buf;
|
||||
buf = (char *) buf + GRUB_EFI_DEVICE_PATH_LENGTH (dp);
|
||||
+ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
|
||||
+ break;
|
||||
+ dp = buf;
|
||||
}
|
||||
- while (!GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp) && buf < bufend);
|
||||
|
||||
dev = grub_xnu_devprop_add_device (dpstart, (char *) buf
|
||||
- (char *) dpstart);
|
||||
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
|
||||
index 6c440c61316..a092fddb629 100644
|
||||
--- a/include/grub/efi/api.h
|
||||
+++ b/include/grub/efi/api.h
|
||||
@@ -671,6 +671,7 @@ typedef struct grub_efi_device_path grub_efi_device_path_protocol_t;
|
||||
#define GRUB_EFI_DEVICE_PATH_TYPE(dp) ((dp)->type & 0x7f)
|
||||
#define GRUB_EFI_DEVICE_PATH_SUBTYPE(dp) ((dp)->subtype)
|
||||
#define GRUB_EFI_DEVICE_PATH_LENGTH(dp) ((dp)->length)
|
||||
+#define GRUB_EFI_DEVICE_PATH_VALID(dp) ((dp) != NULL && GRUB_EFI_DEVICE_PATH_LENGTH (dp) >= 4)
|
||||
|
||||
/* The End of Device Path nodes. */
|
||||
#define GRUB_EFI_END_DEVICE_PATH_TYPE (0xff & 0x7f)
|
||||
@@ -679,13 +680,16 @@ typedef struct grub_efi_device_path grub_efi_device_path_protocol_t;
|
||||
#define GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE 0x01
|
||||
|
||||
#define GRUB_EFI_END_ENTIRE_DEVICE_PATH(dp) \
|
||||
- (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_END_DEVICE_PATH_TYPE \
|
||||
- && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) \
|
||||
- == GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE))
|
||||
+ (!GRUB_EFI_DEVICE_PATH_VALID (dp) || \
|
||||
+ (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_END_DEVICE_PATH_TYPE \
|
||||
+ && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) \
|
||||
+ == GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE)))
|
||||
|
||||
#define GRUB_EFI_NEXT_DEVICE_PATH(dp) \
|
||||
- ((grub_efi_device_path_t *) ((char *) (dp) \
|
||||
- + GRUB_EFI_DEVICE_PATH_LENGTH (dp)))
|
||||
+ (GRUB_EFI_DEVICE_PATH_VALID (dp) \
|
||||
+ ? ((grub_efi_device_path_t *) \
|
||||
+ ((char *) (dp) + GRUB_EFI_DEVICE_PATH_LENGTH (dp))) \
|
||||
+ : NULL)
|
||||
|
||||
/* Hardware Device Path. */
|
||||
#define GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE 1
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,88 @@
|
||||
From cab9214c4caad2ad95ce8bd456c68bc08def0833 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Coulson <chris.coulson@canonical.com>
|
||||
Date: Wed, 22 Jul 2020 17:06:04 +0100
|
||||
Subject: [PATCH 304/314] Fix a regression caused by "efi: fix some malformed
|
||||
device path arithmetic errors"
|
||||
|
||||
This commit introduced a bogus check inside copy_file_path to
|
||||
determine whether the destination grub_efi_file_path_device_path_t
|
||||
was valid before anything was copied to it. Depending on the
|
||||
contents of the heap buffer, this check could fail which would
|
||||
result in copy_file_path returning early.
|
||||
|
||||
Without any error propagated to the caller, make_file_path would
|
||||
then try to advance the invalid device path node with
|
||||
GRUB_EFI_NEXT_DEVICE_PATH, which would also fail, returning a NULL
|
||||
pointer that would subsequently be dereferenced.
|
||||
|
||||
Remove the bogus check, and also propagate errors from copy_file_path.
|
||||
---
|
||||
grub-core/loader/efi/chainloader.c | 26 ++++++++++++++------------
|
||||
1 file changed, 14 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||
index c2411b6dab2..8b99cf23e9d 100644
|
||||
--- a/grub-core/loader/efi/chainloader.c
|
||||
+++ b/grub-core/loader/efi/chainloader.c
|
||||
@@ -115,7 +115,7 @@ grub_chainloader_boot (void)
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
-static void
|
||||
+static grub_err_t
|
||||
copy_file_path (grub_efi_file_path_device_path_t *fp,
|
||||
const char *str, grub_efi_uint16_t len)
|
||||
{
|
||||
@@ -125,15 +125,9 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
|
||||
fp->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE;
|
||||
fp->header.subtype = GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE;
|
||||
|
||||
- if (!GRUB_EFI_DEVICE_PATH_VALID ((grub_efi_device_path_t *)fp))
|
||||
- {
|
||||
- grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI Device Path is invalid");
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
path_name = grub_calloc (len, GRUB_MAX_UTF16_PER_UTF8 * sizeof (*path_name));
|
||||
if (!path_name)
|
||||
- return;
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "failed to allocate path buffer");
|
||||
|
||||
size = grub_utf8_to_utf16 (path_name, len * GRUB_MAX_UTF16_PER_UTF8,
|
||||
(const grub_uint8_t *) str, len, 0);
|
||||
@@ -145,6 +139,8 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
|
||||
/* File Path is NULL terminated */
|
||||
fp->path_name[size++] = '\0';
|
||||
fp->header.length = size * sizeof (grub_efi_char16_t) + sizeof (*fp);
|
||||
+ grub_free (path_name);
|
||||
+ return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_efi_device_path_t *
|
||||
@@ -202,13 +198,19 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
|
||||
/* Fill the file path for the directory. */
|
||||
d = (grub_efi_device_path_t *) ((char *) file_path
|
||||
+ ((char *) d - (char *) dp));
|
||||
- copy_file_path ((grub_efi_file_path_device_path_t *) d,
|
||||
- dir_start, dir_end - dir_start);
|
||||
+ if (copy_file_path ((grub_efi_file_path_device_path_t *) d,
|
||||
+ dir_start, dir_end - dir_start) != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ fail:
|
||||
+ grub_free (file_path);
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
/* Fill the file path for the file. */
|
||||
d = GRUB_EFI_NEXT_DEVICE_PATH (d);
|
||||
- copy_file_path ((grub_efi_file_path_device_path_t *) d,
|
||||
- dir_end + 1, grub_strlen (dir_end + 1));
|
||||
+ if (copy_file_path ((grub_efi_file_path_device_path_t *) d,
|
||||
+ dir_end + 1, grub_strlen (dir_end + 1)) != GRUB_ERR_NONE)
|
||||
+ goto fail;
|
||||
|
||||
/* Fill the end of device path nodes. */
|
||||
d = GRUB_EFI_NEXT_DEVICE_PATH (d);
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,151 @@
|
||||
From 0bfbb0c63ccc73d8508d1a402f53f9f6a64de903 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Burmashev <alexander.burmashev@oracle.com>
|
||||
Date: Wed, 22 Jul 2020 06:04:38 -0700
|
||||
Subject: [PATCH 305/314] update safemath with fallback code for gcc older than
|
||||
5.1
|
||||
|
||||
The code used in the header was taken from linux kernel commit
|
||||
f0907827a8a9152aedac2833ed1b674a7b2a44f2. Rasmus Villemoes
|
||||
<linux@rasmusvillemoes.dk>, the original author of the patch, was
|
||||
contacted directly, confirmed his authorship of the code, and gave his
|
||||
permission on treating that dual license as MIT and including into GRUB2
|
||||
sources
|
||||
|
||||
Signed-off-by: Alex Burmashev <alexander.burmashev@oracle.com>
|
||||
---
|
||||
include/grub/safemath.h | 119 +++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 118 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/grub/safemath.h b/include/grub/safemath.h
|
||||
index c17b89bba17..1ccac276b59 100644
|
||||
--- a/include/grub/safemath.h
|
||||
+++ b/include/grub/safemath.h
|
||||
@@ -31,7 +31,124 @@
|
||||
#define grub_mul(a, b, res) __builtin_mul_overflow(a, b, res)
|
||||
|
||||
#else
|
||||
-#error gcc 5.1 or newer or clang 3.8 or newer is required
|
||||
+/*
|
||||
+ * Copyright 2020 Rasmus Villemoes
|
||||
+ *
|
||||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
+ * of this software and associated documentation files (the "Software"), to
|
||||
+ * deal in the Software without restriction, including without limitation the
|
||||
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
+ * sell copies of the Software, and to permit persons to whom the Software is
|
||||
+ * furnished to do so, subject to the following conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be included in
|
||||
+ * all copies or substantial portions of the Software.
|
||||
+
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
+ * IN THE SOFTWARE.
|
||||
+ */
|
||||
+/*
|
||||
+ * The code used in this header was taken from linux kernel commit
|
||||
+ * f0907827a8a9152aedac2833ed1b674a7b2a44f2
|
||||
+ * Rasmus Villemoes <linux@rasmusvillemoes.dk>, the original author of the
|
||||
+ * patch, was contacted directly, confirmed his authorship of the code, and
|
||||
+ * gave his permission on treating that dual license as MIT and including into
|
||||
+ * GRUB2 sources
|
||||
+ */
|
||||
+
|
||||
+#include <grub/types.h>
|
||||
+#define is_signed_type(type) (((type)(-1)) < (type)1)
|
||||
+#define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
|
||||
+#define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
|
||||
+#define type_min(T) ((T)((T)-type_max(T)-(T)1))
|
||||
+
|
||||
+#define __unsigned_add_overflow(a, b, d) ({ \
|
||||
+ typeof(+(a)) __a = (a); \
|
||||
+ typeof(+(b)) __b = (b); \
|
||||
+ typeof(d) __d = (d); \
|
||||
+ (void) (&__a == &__b); \
|
||||
+ (void) (&__a == __d); \
|
||||
+ *__d = __a + __b; \
|
||||
+ *__d < __a; \
|
||||
+})
|
||||
+#define __unsigned_sub_overflow(a, b, d) ({ \
|
||||
+ typeof(+(a)) __a = (a); \
|
||||
+ typeof(+(b)) __b = (b); \
|
||||
+ typeof(d) __d = (d); \
|
||||
+ (void) (&__a == &__b); \
|
||||
+ (void) (&__a == __d); \
|
||||
+ *__d = __a - __b; \
|
||||
+ __a < __b; \
|
||||
+})
|
||||
+#define __unsigned_mul_overflow(a, b, d) ({ \
|
||||
+ typeof(+(a)) __a = (a); \
|
||||
+ typeof(+(b)) __b = (b); \
|
||||
+ typeof(d) __d = (d); \
|
||||
+ (void) (&__a == &__b); \
|
||||
+ (void) (&__a == __d); \
|
||||
+ *__d = __a * __b; \
|
||||
+ __builtin_constant_p(__b) ? \
|
||||
+ __b > 0 && __a > type_max(typeof(__a)) / __b :\
|
||||
+ __a > 0 && __b > type_max(typeof(__b)) / __a; \
|
||||
+})
|
||||
+
|
||||
+#define __signed_add_overflow(a, b, d) ({ \
|
||||
+ typeof(+(a)) __a = (a); \
|
||||
+ typeof(+(b)) __b = (b); \
|
||||
+ typeof(d) __d = (d); \
|
||||
+ (void) (&__a == &__b); \
|
||||
+ (void) (&__a == __d); \
|
||||
+ *__d = (grub_uint64_t)__a + (grub_uint64_t)__b; \
|
||||
+ (((~(__a ^ __b)) & (*__d ^ __a)) \
|
||||
+ & type_min(typeof(__a))) != 0; \
|
||||
+})
|
||||
+
|
||||
+#define __signed_sub_overflow(a, b, d) ({ \
|
||||
+ typeof(+(a)) __a = (a); \
|
||||
+ typeof(+(b)) __b = (b); \
|
||||
+ typeof(d) __d = (d); \
|
||||
+ (void) (&__a == &__b); \
|
||||
+ (void) (&__a == __d); \
|
||||
+ *__d = (grub_uint64_t)__a - (grub_uint64_t)__b; \
|
||||
+ ((((__a ^ __b)) & (*__d ^ __a)) \
|
||||
+ & type_min(typeof(__a))) != 0; \
|
||||
+})
|
||||
+
|
||||
+#define __signed_mul_overflow(a, b, d) ({ \
|
||||
+ typeof(+(a)) __a = (a); \
|
||||
+ typeof(+(b)) __b = (b); \
|
||||
+ typeof(d) __d = (d); \
|
||||
+ typeof(+(a)) __tmax = type_max(typeof(+(a))); \
|
||||
+ typeof(+(a)) __tmin = type_min(typeof(+(a))); \
|
||||
+ (void) (&__a == &__b); \
|
||||
+ (void) (&__a == __d); \
|
||||
+ *__d = (grub_uint64_t)__a * (grub_uint64_t)__b; \
|
||||
+ (__b > 0 && (__a > __tmax/__b || __a < __tmin/__b)) ||\
|
||||
+ (__b < (typeof(__b))-1 && \
|
||||
+ (__a > __tmin/__b || __a < __tmax/__b)) || \
|
||||
+ (__b == (typeof(__b))-1 && __a == __tmin); \
|
||||
+})
|
||||
+
|
||||
+#define grub_add(a, b, d) \
|
||||
+ __builtin_choose_expr(is_signed_type(typeof(+(a))), \
|
||||
+ __signed_add_overflow(a, b, d), \
|
||||
+ __unsigned_add_overflow(a, b, d))
|
||||
+
|
||||
+#define grub_sub(a, b, d) \
|
||||
+ __builtin_choose_expr(is_signed_type(typeof(+(a))), \
|
||||
+ __signed_sub_overflow(a, b, d), \
|
||||
+ __unsigned_sub_overflow(a, b, d))
|
||||
+
|
||||
+#define grub_mul(a, b, d) \
|
||||
+ __builtin_choose_expr(is_signed_type(typeof(+(a))), \
|
||||
+ __signed_mul_overflow(a, b, d), \
|
||||
+ __unsigned_mul_overflow(a, b, d))
|
||||
+
|
||||
#endif
|
||||
|
||||
#endif /* GRUB_SAFEMATH_H */
|
||||
--
|
||||
2.26.2
|
||||
|
165
SOURCES/0306-efi-Fix-use-after-free-in-halt-reboot-path.patch
Normal file
165
SOURCES/0306-efi-Fix-use-after-free-in-halt-reboot-path.patch
Normal file
@ -0,0 +1,165 @@
|
||||
From 7a7d0278212dde624229dd6da973ccfdf60a7982 Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Date: Mon, 20 Jul 2020 23:03:05 +0000
|
||||
Subject: [PATCH 306/314] efi: Fix use-after-free in halt/reboot path
|
||||
|
||||
commit 92bfc33db984 ("efi: Free malloc regions on exit")
|
||||
introduced memory freeing in grub_efi_fini(), which is
|
||||
used not only by exit path but by halt/reboot one as well.
|
||||
As result of memory freeing, code and data regions used by
|
||||
modules, such as halt, reboot, acpi (used by halt) also got
|
||||
freed. After return to module code, CPU executes, filled
|
||||
by UEFI firmware (tested with edk2), 0xAFAFAFAF pattern as
|
||||
a code. Which leads to #UD exception later.
|
||||
|
||||
grub> halt
|
||||
!!!! X64 Exception Type - 06(#UD - Invalid Opcode) CPU Apic ID - 00000000 !!!!
|
||||
RIP - 0000000003F4EC28, CS - 0000000000000038, RFLAGS - 0000000000200246
|
||||
RAX - 0000000000000000, RCX - 00000000061DA188, RDX - 0A74C0854DC35D41
|
||||
RBX - 0000000003E10E08, RSP - 0000000007F0F860, RBP - 0000000000000000
|
||||
RSI - 00000000064DB768, RDI - 000000000832C5C3
|
||||
R8 - 0000000000000002, R9 - 0000000000000000, R10 - 00000000061E2E52
|
||||
R11 - 0000000000000020, R12 - 0000000003EE5C1F, R13 - 00000000061E0FF4
|
||||
R14 - 0000000003E10D80, R15 - 00000000061E2F60
|
||||
DS - 0000000000000030, ES - 0000000000000030, FS - 0000000000000030
|
||||
GS - 0000000000000030, SS - 0000000000000030
|
||||
CR0 - 0000000080010033, CR2 - 0000000000000000, CR3 - 0000000007C01000
|
||||
CR4 - 0000000000000668, CR8 - 0000000000000000
|
||||
DR0 - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
|
||||
DR3 - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
|
||||
GDTR - 00000000079EEA98 0000000000000047, LDTR - 0000000000000000
|
||||
IDTR - 0000000007598018 0000000000000FFF, TR - 0000000000000000
|
||||
FXSAVE_STATE - 0000000007F0F4C0
|
||||
|
||||
Proposal here is to continue to free allocated memory for
|
||||
exit boot services path but keep it for halt/reboot path
|
||||
as it won't be much security concern here.
|
||||
Introduced GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY
|
||||
loader flag to be used by efi halt/reboot path.
|
||||
|
||||
Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
|
||||
---
|
||||
grub-core/kern/arm/efi/init.c | 3 +++
|
||||
grub-core/kern/arm64/efi/init.c | 3 +++
|
||||
grub-core/kern/efi/efi.c | 3 ++-
|
||||
grub-core/kern/efi/init.c | 1 -
|
||||
grub-core/kern/i386/efi/init.c | 9 +++++++--
|
||||
grub-core/kern/ia64/efi/init.c | 9 +++++++--
|
||||
grub-core/lib/efi/halt.c | 3 ++-
|
||||
include/grub/loader.h | 1 +
|
||||
8 files changed, 25 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/arm/efi/init.c b/grub-core/kern/arm/efi/init.c
|
||||
index 06df60e2f0e..40c3b467fc6 100644
|
||||
--- a/grub-core/kern/arm/efi/init.c
|
||||
+++ b/grub-core/kern/arm/efi/init.c
|
||||
@@ -71,4 +71,7 @@ grub_machine_fini (int flags)
|
||||
efi_call_1 (b->close_event, tmr_evt);
|
||||
|
||||
grub_efi_fini ();
|
||||
+
|
||||
+ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
|
||||
+ grub_efi_memory_fini ();
|
||||
}
|
||||
diff --git a/grub-core/kern/arm64/efi/init.c b/grub-core/kern/arm64/efi/init.c
|
||||
index 6224999ec9c..5010caefd66 100644
|
||||
--- a/grub-core/kern/arm64/efi/init.c
|
||||
+++ b/grub-core/kern/arm64/efi/init.c
|
||||
@@ -57,4 +57,7 @@ grub_machine_fini (int flags)
|
||||
return;
|
||||
|
||||
grub_efi_fini ();
|
||||
+
|
||||
+ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
|
||||
+ grub_efi_memory_fini ();
|
||||
}
|
||||
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
|
||||
index 03de9cb14e7..5dfcf943322 100644
|
||||
--- a/grub-core/kern/efi/efi.c
|
||||
+++ b/grub-core/kern/efi/efi.c
|
||||
@@ -157,7 +157,8 @@ grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
|
||||
void
|
||||
grub_reboot (void)
|
||||
{
|
||||
- grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
|
||||
+ grub_machine_fini (GRUB_LOADER_FLAG_NORETURN |
|
||||
+ GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY);
|
||||
efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
|
||||
GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
|
||||
for (;;) ;
|
||||
diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
|
||||
index e6183a4c44d..79243b364a1 100644
|
||||
--- a/grub-core/kern/efi/init.c
|
||||
+++ b/grub-core/kern/efi/init.c
|
||||
@@ -136,5 +136,4 @@ grub_efi_fini (void)
|
||||
{
|
||||
grub_efidisk_fini ();
|
||||
grub_console_fini ();
|
||||
- grub_efi_memory_fini ();
|
||||
}
|
||||
diff --git a/grub-core/kern/i386/efi/init.c b/grub-core/kern/i386/efi/init.c
|
||||
index a28316cc640..46476e27eae 100644
|
||||
--- a/grub-core/kern/i386/efi/init.c
|
||||
+++ b/grub-core/kern/i386/efi/init.c
|
||||
@@ -38,6 +38,11 @@ grub_machine_init (void)
|
||||
void
|
||||
grub_machine_fini (int flags)
|
||||
{
|
||||
- if (flags & GRUB_LOADER_FLAG_NORETURN)
|
||||
- grub_efi_fini ();
|
||||
+ if (!(flags & GRUB_LOADER_FLAG_NORETURN))
|
||||
+ return;
|
||||
+
|
||||
+ grub_efi_fini ();
|
||||
+
|
||||
+ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
|
||||
+ grub_efi_memory_fini ();
|
||||
}
|
||||
diff --git a/grub-core/kern/ia64/efi/init.c b/grub-core/kern/ia64/efi/init.c
|
||||
index b5ecbd09121..f1965571b1d 100644
|
||||
--- a/grub-core/kern/ia64/efi/init.c
|
||||
+++ b/grub-core/kern/ia64/efi/init.c
|
||||
@@ -70,6 +70,11 @@ grub_machine_init (void)
|
||||
void
|
||||
grub_machine_fini (int flags)
|
||||
{
|
||||
- if (flags & GRUB_LOADER_FLAG_NORETURN)
|
||||
- grub_efi_fini ();
|
||||
+ if (!(flags & GRUB_LOADER_FLAG_NORETURN))
|
||||
+ return;
|
||||
+
|
||||
+ grub_efi_fini ();
|
||||
+
|
||||
+ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
|
||||
+ grub_efi_memory_fini ();
|
||||
}
|
||||
diff --git a/grub-core/lib/efi/halt.c b/grub-core/lib/efi/halt.c
|
||||
index e9441c844ac..a69a77681e3 100644
|
||||
--- a/grub-core/lib/efi/halt.c
|
||||
+++ b/grub-core/lib/efi/halt.c
|
||||
@@ -28,7 +28,8 @@
|
||||
void
|
||||
grub_halt (void)
|
||||
{
|
||||
- grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
|
||||
+ grub_machine_fini (GRUB_LOADER_FLAG_NORETURN |
|
||||
+ GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY);
|
||||
#if !defined(__ia64__) && !defined(__arm__) && !defined(__aarch64__)
|
||||
grub_acpi_halt ();
|
||||
#endif
|
||||
diff --git a/include/grub/loader.h b/include/grub/loader.h
|
||||
index 7f82a499fd9..b208642821b 100644
|
||||
--- a/include/grub/loader.h
|
||||
+++ b/include/grub/loader.h
|
||||
@@ -33,6 +33,7 @@ enum
|
||||
{
|
||||
GRUB_LOADER_FLAG_NORETURN = 1,
|
||||
GRUB_LOADER_FLAG_PXE_NOT_UNLOAD = 2,
|
||||
+ GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY = 4,
|
||||
};
|
||||
|
||||
void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void),
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,40 @@
|
||||
From c62652ca26ed1c145d0e820e0f108ce4e61b1f17 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Sun, 19 Jul 2020 17:11:06 -0400
|
||||
Subject: [PATCH 307/314] efi+dhcp: fix some allocation error checking.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
---
|
||||
grub-core/net/efi/dhcp.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/efi/dhcp.c b/grub-core/net/efi/dhcp.c
|
||||
index dbef63d8c08..e5c79b748b0 100644
|
||||
--- a/grub-core/net/efi/dhcp.c
|
||||
+++ b/grub-core/net/efi/dhcp.c
|
||||
@@ -80,7 +80,7 @@ grub_efi_dhcp4_parse_dns (grub_efi_dhcp4_protocol_t *dhcp4, grub_efi_dhcp4_packe
|
||||
if (status != GRUB_EFI_BUFFER_TOO_SMALL)
|
||||
return NULL;
|
||||
|
||||
- option_list = grub_malloc (option_count * sizeof(*option_list));
|
||||
+ option_list = grub_calloc (option_count, sizeof(*option_list));
|
||||
if (!option_list)
|
||||
return NULL;
|
||||
|
||||
@@ -360,8 +360,11 @@ grub_cmd_efi_bootp6 (struct grub_command *cmd __attribute__ ((unused)),
|
||||
|
||||
if (status == GRUB_EFI_BUFFER_TOO_SMALL && count)
|
||||
{
|
||||
- options = grub_malloc (count * sizeof(*options));
|
||||
- status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, options);
|
||||
+ options = grub_calloc (count, sizeof(*options));
|
||||
+ if (options)
|
||||
+ status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, options);
|
||||
+ else
|
||||
+ status = GRUB_EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,42 @@
|
||||
From 4436316229bc5b46016d61215b709ec434f4e0d3 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Sun, 19 Jul 2020 17:14:15 -0400
|
||||
Subject: [PATCH 308/314] efi+http: fix some allocation error checking.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
---
|
||||
grub-core/net/efi/http.c | 11 +++++++----
|
||||
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c
|
||||
index fc8cb25ae0a..26647a50fa4 100644
|
||||
--- a/grub-core/net/efi/http.c
|
||||
+++ b/grub-core/net/efi/http.c
|
||||
@@ -412,8 +412,8 @@ grub_efihttp_open (struct grub_efi_net_device *dev,
|
||||
int type)
|
||||
{
|
||||
grub_err_t err;
|
||||
- grub_off_t size;
|
||||
- char *buf;
|
||||
+ grub_off_t size = 0;
|
||||
+ char *buf = NULL;
|
||||
char *file_name = NULL;
|
||||
const char *http_path;
|
||||
|
||||
@@ -441,8 +441,11 @@ grub_efihttp_open (struct grub_efi_net_device *dev,
|
||||
return err;
|
||||
}
|
||||
|
||||
- buf = grub_malloc (size);
|
||||
- efihttp_read (dev, buf, size);
|
||||
+ if (size)
|
||||
+ {
|
||||
+ buf = grub_malloc (size);
|
||||
+ efihttp_read (dev, buf, size);
|
||||
+ }
|
||||
|
||||
file->size = size;
|
||||
file->data = buf;
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,131 @@
|
||||
From 9f8ce6fac51e229a18ed2fa3321f7fc3d6d822a6 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Sun, 19 Jul 2020 17:27:00 -0400
|
||||
Subject: [PATCH 309/314] efi/ip[46]_config.c: fix some potential allocation
|
||||
overflows
|
||||
|
||||
In theory all of this data comes from the firmware stack and it should
|
||||
be safe, but it's better to be paranoid.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
---
|
||||
grub-core/net/efi/ip4_config.c | 25 ++++++++++++++++++-------
|
||||
grub-core/net/efi/ip6_config.c | 13 ++++++++++---
|
||||
2 files changed, 28 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c
|
||||
index 6117e60ab12..5ea5ed03925 100644
|
||||
--- a/grub-core/net/efi/ip4_config.c
|
||||
+++ b/grub-core/net/efi/ip4_config.c
|
||||
@@ -4,15 +4,20 @@
|
||||
#include <grub/misc.h>
|
||||
#include <grub/net/efi.h>
|
||||
#include <grub/charset.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
char *
|
||||
grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address)
|
||||
{
|
||||
char *hw_addr, *p;
|
||||
- int sz, s;
|
||||
- int i;
|
||||
+ grub_size_t sz, s, i;
|
||||
|
||||
- sz = (int)hw_address_size * (sizeof ("XX:") - 1) + 1;
|
||||
+ if (grub_mul (hw_address_size, sizeof ("XX:") - 1, &sz) ||
|
||||
+ grub_add (sz, 1, &sz))
|
||||
+ {
|
||||
+ grub_errno = GRUB_ERR_OUT_OF_RANGE;
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
hw_addr = grub_malloc (sz);
|
||||
if (!hw_addr)
|
||||
@@ -20,7 +25,7 @@ grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_a
|
||||
|
||||
p = hw_addr;
|
||||
s = sz;
|
||||
- for (i = 0; i < (int)hw_address_size; i++)
|
||||
+ for (i = 0; i < hw_address_size; i++)
|
||||
{
|
||||
grub_snprintf (p, sz, "%02x:", hw_address[i]);
|
||||
p += sizeof ("XX:") - 1;
|
||||
@@ -238,14 +243,20 @@ grub_efi_ip4_interface_route_table (struct grub_efi_net_device *dev)
|
||||
{
|
||||
grub_efi_ip4_config2_interface_info_t *interface_info;
|
||||
char **ret;
|
||||
- int i, id;
|
||||
+ int id;
|
||||
+ grub_size_t i, nmemb;
|
||||
|
||||
interface_info = efi_ip4_config_interface_info (dev->ip4_config);
|
||||
if (!interface_info)
|
||||
return NULL;
|
||||
|
||||
- ret = grub_malloc (sizeof (*ret) * (interface_info->route_table_size + 1));
|
||||
+ if (grub_add (interface_info->route_table_size, 1, &nmemb))
|
||||
+ {
|
||||
+ grub_errno = GRUB_ERR_OUT_OF_RANGE;
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
+ ret = grub_calloc (nmemb, sizeof (*ret));
|
||||
if (!ret)
|
||||
{
|
||||
grub_free (interface_info);
|
||||
@@ -253,7 +264,7 @@ grub_efi_ip4_interface_route_table (struct grub_efi_net_device *dev)
|
||||
}
|
||||
|
||||
id = 0;
|
||||
- for (i = 0; i < (int)interface_info->route_table_size; i++)
|
||||
+ for (i = 0; i < interface_info->route_table_size; i++)
|
||||
{
|
||||
char *subnet, *gateway, *mask;
|
||||
grub_uint32_t u32_subnet, u32_gateway;
|
||||
diff --git a/grub-core/net/efi/ip6_config.c b/grub-core/net/efi/ip6_config.c
|
||||
index e0e00c23d21..1c5415d7185 100644
|
||||
--- a/grub-core/net/efi/ip6_config.c
|
||||
+++ b/grub-core/net/efi/ip6_config.c
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <grub/misc.h>
|
||||
#include <grub/net/efi.h>
|
||||
#include <grub/charset.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
char *
|
||||
grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address)
|
||||
@@ -228,14 +229,20 @@ grub_efi_ip6_interface_route_table (struct grub_efi_net_device *dev)
|
||||
{
|
||||
grub_efi_ip6_config_interface_info_t *interface_info;
|
||||
char **ret;
|
||||
- int i, id;
|
||||
+ int id;
|
||||
+ grub_size_t i, nmemb;
|
||||
|
||||
interface_info = efi_ip6_config_interface_info (dev->ip6_config);
|
||||
if (!interface_info)
|
||||
return NULL;
|
||||
|
||||
- ret = grub_malloc (sizeof (*ret) * (interface_info->route_count + 1));
|
||||
+ if (grub_add (interface_info->route_count, 1, &nmemb))
|
||||
+ {
|
||||
+ grub_errno = GRUB_ERR_OUT_OF_RANGE;
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
+ ret = grub_calloc (nmemb, sizeof (*ret));
|
||||
if (!ret)
|
||||
{
|
||||
grub_free (interface_info);
|
||||
@@ -243,7 +250,7 @@ grub_efi_ip6_interface_route_table (struct grub_efi_net_device *dev)
|
||||
}
|
||||
|
||||
id = 0;
|
||||
- for (i = 0; i < (int)interface_info->route_count ; i++)
|
||||
+ for (i = 0; i < interface_info->route_count ; i++)
|
||||
{
|
||||
char *gateway, *destination;
|
||||
grub_uint64_t u64_gateway[2];
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,219 @@
|
||||
From e5ef076d3188c3389769a3bde72382db9b94dc97 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Thu, 23 Jul 2020 15:02:48 -0400
|
||||
Subject: [PATCH 310/314] Fix up some types for gcc 4.8 compat safemath.h
|
||||
|
||||
The compat macros aren't as forgiving as __builtin_*_overflow().
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
---
|
||||
grub-core/disk/lvm.c | 22 ++++++++++++----------
|
||||
grub-core/font/font.c | 4 ++--
|
||||
grub-core/fs/btrfs.c | 20 +++++++++++++++-----
|
||||
grub-core/fs/ext2.c | 3 ++-
|
||||
grub-core/fs/hfsplus.c | 2 +-
|
||||
grub-core/fs/iso9660.c | 8 ++++----
|
||||
grub-core/normal/charset.c | 5 +++--
|
||||
7 files changed, 39 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
|
||||
index ca09d469990..4fbb3eac0ea 100644
|
||||
--- a/grub-core/disk/lvm.c
|
||||
+++ b/grub-core/disk/lvm.c
|
||||
@@ -103,7 +103,7 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_uint64_t mda_offset, mda_size;
|
||||
- grub_size_t ptr;
|
||||
+ grub_uint64_t ptr;
|
||||
char buf[GRUB_LVM_LABEL_SIZE];
|
||||
char vg_id[GRUB_LVM_ID_STRLEN+1];
|
||||
char pv_id[GRUB_LVM_ID_STRLEN+1];
|
||||
@@ -209,9 +209,9 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
grub_le_to_cpu64 (mdah->size));
|
||||
}
|
||||
|
||||
- if (grub_add ((grub_size_t)metadatabuf,
|
||||
- (grub_size_t)grub_le_to_cpu64 (rlocn->offset),
|
||||
- &ptr))
|
||||
+ grub_uint64_t mdb = (grub_uint64_t)metadatabuf;
|
||||
+ grub_uint64_t addend = (grub_uint64_t)grub_le_to_cpu64 (rlocn->offset);
|
||||
+ if (grub_add (mdb, addend, &ptr))
|
||||
{
|
||||
error_parsing_metadata:
|
||||
#ifdef GRUB_UTIL
|
||||
@@ -222,7 +222,7 @@ error_parsing_metadata:
|
||||
|
||||
p = q = (char *)ptr;
|
||||
|
||||
- if (grub_add ((grub_size_t)metadatabuf, (grub_size_t)mda_size, &ptr))
|
||||
+ if (grub_add (mdb, mda_size, &ptr))
|
||||
goto error_parsing_metadata;
|
||||
|
||||
mda_end = (char *)ptr;
|
||||
@@ -391,13 +391,15 @@ error_parsing_metadata:
|
||||
* + sizeof ("lvm/") - 1;
|
||||
*/
|
||||
grub_size_t sz0 = vgname_len, sz1 = s;
|
||||
+ grub_size_t one = 1, two = 2;
|
||||
+ grub_size_t lvm_str_sz = sizeof ("lvm/") - 1;
|
||||
|
||||
- if (grub_mul (sz0, 2, &sz0) ||
|
||||
- grub_add (sz0, 1, &sz0) ||
|
||||
- grub_mul (sz1, 2, &sz1) ||
|
||||
- grub_add (sz1, 1, &sz1) ||
|
||||
+ if (grub_mul (sz0, two, &sz0) ||
|
||||
+ grub_add (sz0, one, &sz0) ||
|
||||
+ grub_mul (sz1, two, &sz1) ||
|
||||
+ grub_add (sz1, one, &sz1) ||
|
||||
grub_add (sz0, sz1, &sz0) ||
|
||||
- grub_add (sz0, sizeof ("lvm/") - 1, &sz0))
|
||||
+ grub_add (sz0, lvm_str_sz, &sz0))
|
||||
goto lvs_fail;
|
||||
|
||||
lv->fullname = grub_malloc (sz0);
|
||||
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
|
||||
index a7b955a1a74..b36a099b856 100644
|
||||
--- a/grub-core/font/font.c
|
||||
+++ b/grub-core/font/font.c
|
||||
@@ -361,10 +361,10 @@ static char *
|
||||
read_section_as_string (struct font_file_section *section)
|
||||
{
|
||||
char *str;
|
||||
- grub_size_t sz;
|
||||
+ grub_size_t sz = section->length, one = 1;
|
||||
grub_ssize_t ret;
|
||||
|
||||
- if (grub_add (section->length, 1, &sz))
|
||||
+ if (grub_add (sz, one, &sz))
|
||||
return NULL;
|
||||
|
||||
str = grub_malloc (sz);
|
||||
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
|
||||
index 1d801f6c9ee..3faf9056c72 100644
|
||||
--- a/grub-core/fs/btrfs.c
|
||||
+++ b/grub-core/fs/btrfs.c
|
||||
@@ -323,10 +323,15 @@ save_ref (struct grub_btrfs_leaf_descriptor *desc,
|
||||
{
|
||||
void *newdata;
|
||||
grub_size_t sz;
|
||||
+ grub_size_t alloced, datasz, two = 2;
|
||||
|
||||
- if (grub_mul (desc->allocated, 2, &desc->allocated) ||
|
||||
- grub_mul (desc->allocated, sizeof (desc->data[0]), &sz))
|
||||
+ alloced = desc->allocated;
|
||||
+ datasz = sizeof (desc->data[0]);
|
||||
+
|
||||
+ if (grub_mul (alloced, two, &alloced) ||
|
||||
+ grub_mul (alloced, datasz, &sz))
|
||||
return GRUB_ERR_OUT_OF_RANGE;
|
||||
+ desc->allocated = alloced;
|
||||
|
||||
newdata = grub_realloc (desc->data, sz);
|
||||
if (!newdata)
|
||||
@@ -624,12 +629,17 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan)
|
||||
{
|
||||
void *tmp;
|
||||
grub_size_t sz;
|
||||
+ grub_size_t alloced = data->n_devices_allocated;
|
||||
+ grub_size_t attached_sz = sizeof(data->devices_attached[0]);
|
||||
+ grub_size_t attached = data->n_devices_attached;
|
||||
+ const grub_size_t one = 1, two = 2;
|
||||
|
||||
- if (grub_mul (data->n_devices_attached, 2, &data->n_devices_allocated) ||
|
||||
- grub_add (data->n_devices_allocated, 1, &data->n_devices_allocated) ||
|
||||
- grub_mul (data->n_devices_allocated, sizeof (data->devices_attached[0]), &sz))
|
||||
+ if (grub_mul (attached, two, &alloced) ||
|
||||
+ grub_add (alloced, one, &alloced) ||
|
||||
+ grub_mul (alloced, attached_sz, &sz))
|
||||
goto fail;
|
||||
|
||||
+ data->n_devices_allocated = alloced;
|
||||
data->devices_attached = grub_realloc (tmp = data->devices_attached, sz);
|
||||
if (!data->devices_attached)
|
||||
{
|
||||
diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
|
||||
index b4bd019f49a..3d59cf13125 100644
|
||||
--- a/grub-core/fs/ext2.c
|
||||
+++ b/grub-core/fs/ext2.c
|
||||
@@ -719,7 +719,8 @@ grub_ext2_read_symlink (grub_fshelp_node_t node)
|
||||
}
|
||||
}
|
||||
|
||||
- if (grub_add (grub_le_to_cpu32 (diro->inode.size), 1, &sz))
|
||||
+ sz = grub_le_to_cpu32 (diro->inode.size);
|
||||
+ if (grub_add (sz, (grub_size_t)1, &sz))
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||
return NULL;
|
||||
diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
|
||||
index 8b17ebba296..e06bcbb9ba3 100644
|
||||
--- a/grub-core/fs/hfsplus.c
|
||||
+++ b/grub-core/fs/hfsplus.c
|
||||
@@ -478,7 +478,7 @@ grub_hfsplus_read_symlink (grub_fshelp_node_t node)
|
||||
grub_ssize_t numread;
|
||||
grub_size_t sz = node->size;
|
||||
|
||||
- if (grub_add (sz, 1, &sz))
|
||||
+ if (grub_add (sz, (grub_size_t)1, &sz))
|
||||
return NULL;
|
||||
|
||||
symlink = grub_malloc (sz);
|
||||
diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
|
||||
index 6fc9302bce3..a4403e29dee 100644
|
||||
--- a/grub-core/fs/iso9660.c
|
||||
+++ b/grub-core/fs/iso9660.c
|
||||
@@ -536,7 +536,7 @@ add_part (struct iterate_dir_ctx *ctx,
|
||||
char *new;
|
||||
|
||||
if (grub_add (size, len2, &sz) ||
|
||||
- grub_add (sz, 1, &sz))
|
||||
+ grub_add (sz, (grub_size_t)1, &sz))
|
||||
return;
|
||||
|
||||
new = grub_realloc (ctx->symlink, sz);
|
||||
@@ -580,14 +580,14 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
|
||||
{
|
||||
off = grub_strlen (ctx->filename);
|
||||
if (grub_add (csize, off, &sz) ||
|
||||
- grub_add (sz, 1, &sz))
|
||||
+ grub_add (sz, (grub_size_t)1, &sz))
|
||||
return GRUB_ERR_OUT_OF_RANGE;
|
||||
ctx->filename = grub_realloc (ctx->filename, sz);
|
||||
}
|
||||
else
|
||||
{
|
||||
off = 0;
|
||||
- if (grub_add (csize, 1, &sz))
|
||||
+ if (grub_add (csize, (grub_size_t)1, &sz))
|
||||
return GRUB_ERR_OUT_OF_RANGE;
|
||||
ctx->filename = grub_zalloc (sz);
|
||||
}
|
||||
@@ -807,7 +807,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
|
||||
struct grub_fshelp_node *new_node;
|
||||
grub_size_t sz;
|
||||
|
||||
- if (grub_mul (node->alloc_dirents, 2, &node->alloc_dirents) ||
|
||||
+ if (grub_mul (node->alloc_dirents, (grub_size_t)2, &node->alloc_dirents) ||
|
||||
grub_sub (node->alloc_dirents, ARRAY_SIZE (node->dirents), &sz) ||
|
||||
grub_mul (sz, sizeof (node->dirents[0]), &sz) ||
|
||||
grub_add (sz, sizeof (struct grub_fshelp_node), &sz))
|
||||
diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c
|
||||
index 4dfcc31078d..f902b13b44e 100644
|
||||
--- a/grub-core/normal/charset.c
|
||||
+++ b/grub-core/normal/charset.c
|
||||
@@ -479,8 +479,9 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen,
|
||||
n = out->combining_inline;
|
||||
else if (out->ncomb > (int) ARRAY_SIZE (out->combining_inline))
|
||||
{
|
||||
- if (grub_add (out->ncomb, 1, &sz) ||
|
||||
- grub_mul (sz, sizeof (n[0]), &sz))
|
||||
+ grub_size_t ncomb = out->ncomb, one = 1, nsz = sizeof (n[0]);
|
||||
+ if (grub_add (ncomb, one, &sz) ||
|
||||
+ grub_mul (sz, nsz, &sz))
|
||||
goto fail;
|
||||
|
||||
n = grub_realloc (out->combining_ptr, sz);
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,51 @@
|
||||
From 0a9a828e88a2e14be684761afe582e7bb286676b Mon Sep 17 00:00:00 2001
|
||||
From: Colin Watson <cjwatson@debian.org>
|
||||
Date: Fri, 24 Jul 2020 17:18:09 +0100
|
||||
Subject: [PATCH 311/314] efilinux: Fix integer overflows in grub_cmd_initrd
|
||||
|
||||
These could be triggered by an extremely large number of arguments to
|
||||
the initrd command on 32-bit architectures, or a crafted filesystem with
|
||||
very large files on any architecture.
|
||||
|
||||
Signed-off-by: Colin Watson <cjwatson@debian.org>
|
||||
---
|
||||
grub-core/loader/i386/efi/linux.c | 9 +++++++--
|
||||
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
|
||||
index ea9f5134e67..ade7ab8f573 100644
|
||||
--- a/grub-core/loader/i386/efi/linux.c
|
||||
+++ b/grub-core/loader/i386/efi/linux.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/efi/linux.h>
|
||||
#include <grub/tpm.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -94,7 +95,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- files = grub_zalloc (argc * sizeof (files[0]));
|
||||
+ files = grub_calloc (argc, sizeof (files[0]));
|
||||
if (!files)
|
||||
goto fail;
|
||||
|
||||
@@ -105,7 +106,11 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
||||
if (! files[i])
|
||||
goto fail;
|
||||
nfiles++;
|
||||
- size += ALIGN_UP (grub_file_size (files[i]), 4);
|
||||
+ if (grub_add (size, ALIGN_UP (grub_file_size (files[i]), 4), &size))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||
+ goto fail;
|
||||
+ }
|
||||
}
|
||||
|
||||
initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,29 @@
|
||||
From 9fa474528317c2311e2f2ac0fd626316ef7486d4 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Fri, 24 Jul 2020 13:57:27 -0400
|
||||
Subject: [PATCH 312/314] linux loader: avoid overflow on initrd size
|
||||
calculation
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
---
|
||||
grub-core/loader/linux.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
|
||||
index c2c7cfcd0fd..61a2e144db0 100644
|
||||
--- a/grub-core/loader/linux.c
|
||||
+++ b/grub-core/loader/linux.c
|
||||
@@ -152,8 +152,8 @@ grub_initrd_init (int argc, char *argv[],
|
||||
initrd_ctx->nfiles = 0;
|
||||
initrd_ctx->components = 0;
|
||||
|
||||
- initrd_ctx->components = grub_zalloc (argc
|
||||
- * sizeof (initrd_ctx->components[0]));
|
||||
+ initrd_ctx->components = grub_calloc (argc,
|
||||
+ sizeof (initrd_ctx->components[0]));
|
||||
if (!initrd_ctx->components)
|
||||
return grub_errno;
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,101 @@
|
||||
From 2ba58823b68d5fbf8d625ed6d7e18b09bc556860 Mon Sep 17 00:00:00 2001
|
||||
From: Dimitri John Ledkov <xnox@ubuntu.com>
|
||||
Date: Wed, 22 Jul 2020 11:31:43 +0100
|
||||
Subject: [PATCH 313/314] linuxefi: fail kernel validation without shim
|
||||
protocol.
|
||||
|
||||
If certificates that signed grub are installed into db, grub can be
|
||||
booted directly. It will then boot any kernel without signature
|
||||
validation. The booted kernel will think it was booted in secureboot
|
||||
mode and will implement lockdown, yet it could have been tampered.
|
||||
|
||||
This version of the patch skips calling verification, when booted
|
||||
without secureboot. And is indented with gnu ident.
|
||||
|
||||
CVE-2020-15705
|
||||
|
||||
Reported-by: Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>
|
||||
Signed-off-by: Dimitri John Ledkov <xnox@ubuntu.com>
|
||||
---
|
||||
grub-core/loader/arm64/linux.c | 12 ++++++++----
|
||||
grub-core/loader/efi/chainloader.c | 1 +
|
||||
grub-core/loader/efi/linux.c | 1 +
|
||||
grub-core/loader/i386/efi/linux.c | 13 ++++++++-----
|
||||
4 files changed, 18 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
|
||||
index e1110749eb9..7a076c13171 100644
|
||||
--- a/grub-core/loader/arm64/linux.c
|
||||
+++ b/grub-core/loader/arm64/linux.c
|
||||
@@ -381,11 +381,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
||||
|
||||
grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
|
||||
|
||||
- rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size);
|
||||
- if (rc < 0)
|
||||
+ if (grub_efi_secure_boot ())
|
||||
{
|
||||
- grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
|
||||
- goto fail;
|
||||
+ rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size);
|
||||
+ if (rc <= 0)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_INVALID_COMMAND,
|
||||
+ N_("%s has invalid signature"), argv[0]);
|
||||
+ goto fail;
|
||||
+ }
|
||||
}
|
||||
|
||||
pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
|
||||
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||
index 8b99cf23e9d..a93edc975cd 100644
|
||||
--- a/grub-core/loader/efi/chainloader.c
|
||||
+++ b/grub-core/loader/efi/chainloader.c
|
||||
@@ -1079,6 +1079,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
|
||||
return 0;
|
||||
}
|
||||
+ // -1 fall-through to fail
|
||||
|
||||
fail:
|
||||
if (dev)
|
||||
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
|
||||
index e09f824862b..927d89a90d7 100644
|
||||
--- a/grub-core/loader/efi/linux.c
|
||||
+++ b/grub-core/loader/efi/linux.c
|
||||
@@ -33,6 +33,7 @@ struct grub_efi_shim_lock
|
||||
};
|
||||
typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
|
||||
|
||||
+// Returns 1 on success, -1 on error, 0 when not available
|
||||
int
|
||||
grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
|
||||
{
|
||||
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
|
||||
index ade7ab8f573..361e503cb52 100644
|
||||
--- a/grub-core/loader/i386/efi/linux.c
|
||||
+++ b/grub-core/loader/i386/efi/linux.c
|
||||
@@ -206,12 +206,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
||||
grub_tpm_measure (kernel, filelen, GRUB_BINARY_PCR, "grub_linuxefi", "Kernel");
|
||||
grub_print_error();
|
||||
|
||||
- rc = grub_linuxefi_secure_validate (kernel, filelen);
|
||||
- if (rc < 0)
|
||||
+ if (grub_efi_secure_boot ())
|
||||
{
|
||||
- grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"),
|
||||
- argv[0]);
|
||||
- goto fail;
|
||||
+ rc = grub_linuxefi_secure_validate (kernel, filelen);
|
||||
+ if (rc <= 0)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_INVALID_COMMAND,
|
||||
+ N_("%s has invalid signature"), argv[0]);
|
||||
+ goto fail;
|
||||
+ }
|
||||
}
|
||||
|
||||
params = grub_efi_allocate_pages_max (0x3fffffff,
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,168 @@
|
||||
From 9715e08cf30ebd8a24ca27b7c4dda8e949e100df Mon Sep 17 00:00:00 2001
|
||||
From: Colin Watson <cjwatson@debian.org>
|
||||
Date: Sat, 25 Jul 2020 12:15:37 +0100
|
||||
Subject: [PATCH 314/314] linux: Fix integer overflows in initrd size handling
|
||||
|
||||
These could be triggered by a crafted filesystem with very large files.
|
||||
|
||||
Fixes: CVE-2020-15707
|
||||
|
||||
Signed-off-by: Colin Watson <cjwatson@debian.org>
|
||||
Reviewed-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
|
||||
---
|
||||
grub-core/loader/linux.c | 74 +++++++++++++++++++++++++++++-----------
|
||||
1 file changed, 54 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
|
||||
index 61a2e144db0..0953f6d3266 100644
|
||||
--- a/grub-core/loader/linux.c
|
||||
+++ b/grub-core/loader/linux.c
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <grub/file.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/tpm.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
struct newc_head
|
||||
{
|
||||
@@ -99,13 +100,13 @@ free_dir (struct dir *root)
|
||||
grub_free (root);
|
||||
}
|
||||
|
||||
-static grub_size_t
|
||||
+static grub_err_t
|
||||
insert_dir (const char *name, struct dir **root,
|
||||
- grub_uint8_t *ptr)
|
||||
+ grub_uint8_t *ptr, grub_size_t *size)
|
||||
{
|
||||
struct dir *cur, **head = root;
|
||||
const char *cb, *ce = name;
|
||||
- grub_size_t size = 0;
|
||||
+ *size = 0;
|
||||
while (1)
|
||||
{
|
||||
for (cb = ce; *cb == '/'; cb++);
|
||||
@@ -131,14 +132,22 @@ insert_dir (const char *name, struct dir **root,
|
||||
ptr = make_header (ptr, name, ce - name,
|
||||
040777, 0);
|
||||
}
|
||||
- size += ALIGN_UP ((ce - (char *) name)
|
||||
- + sizeof (struct newc_head), 4);
|
||||
+ if (grub_add (*size,
|
||||
+ ALIGN_UP ((ce - (char *) name)
|
||||
+ + sizeof (struct newc_head), 4),
|
||||
+ size))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||
+ grub_free (n->name);
|
||||
+ grub_free (n);
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
*head = n;
|
||||
cur = n;
|
||||
}
|
||||
root = &cur->next;
|
||||
}
|
||||
- return size;
|
||||
+ return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
@@ -175,26 +184,33 @@ grub_initrd_init (int argc, char *argv[],
|
||||
if (eptr)
|
||||
{
|
||||
grub_file_filter_disable_compression ();
|
||||
+ grub_size_t dir_size, name_len;
|
||||
+
|
||||
initrd_ctx->components[i].newc_name = grub_strndup (ptr, eptr - ptr);
|
||||
- if (!initrd_ctx->components[i].newc_name)
|
||||
+ if (!initrd_ctx->components[i].newc_name ||
|
||||
+ insert_dir (initrd_ctx->components[i].newc_name, &root, 0,
|
||||
+ &dir_size))
|
||||
{
|
||||
grub_initrd_close (initrd_ctx);
|
||||
return grub_errno;
|
||||
}
|
||||
- initrd_ctx->size
|
||||
- += ALIGN_UP (sizeof (struct newc_head)
|
||||
- + grub_strlen (initrd_ctx->components[i].newc_name),
|
||||
- 4);
|
||||
- initrd_ctx->size += insert_dir (initrd_ctx->components[i].newc_name,
|
||||
- &root, 0);
|
||||
+ name_len = grub_strlen (initrd_ctx->components[i].newc_name);
|
||||
+ if (grub_add (initrd_ctx->size,
|
||||
+ ALIGN_UP (sizeof (struct newc_head) + name_len, 4),
|
||||
+ &initrd_ctx->size) ||
|
||||
+ grub_add (initrd_ctx->size, dir_size, &initrd_ctx->size))
|
||||
+ goto overflow;
|
||||
newc = 1;
|
||||
fname = eptr + 1;
|
||||
}
|
||||
}
|
||||
else if (newc)
|
||||
{
|
||||
- initrd_ctx->size += ALIGN_UP (sizeof (struct newc_head)
|
||||
- + sizeof ("TRAILER!!!") - 1, 4);
|
||||
+ if (grub_add (initrd_ctx->size,
|
||||
+ ALIGN_UP (sizeof (struct newc_head)
|
||||
+ + sizeof ("TRAILER!!!") - 1, 4),
|
||||
+ &initrd_ctx->size))
|
||||
+ goto overflow;
|
||||
free_dir (root);
|
||||
root = 0;
|
||||
newc = 0;
|
||||
@@ -209,19 +225,29 @@ grub_initrd_init (int argc, char *argv[],
|
||||
initrd_ctx->nfiles++;
|
||||
initrd_ctx->components[i].size
|
||||
= grub_file_size (initrd_ctx->components[i].file);
|
||||
- initrd_ctx->size += initrd_ctx->components[i].size;
|
||||
+ if (grub_add (initrd_ctx->size, initrd_ctx->components[i].size,
|
||||
+ &initrd_ctx->size))
|
||||
+ goto overflow;
|
||||
}
|
||||
|
||||
if (newc)
|
||||
{
|
||||
initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4);
|
||||
- initrd_ctx->size += ALIGN_UP (sizeof (struct newc_head)
|
||||
- + sizeof ("TRAILER!!!") - 1, 4);
|
||||
+ if (grub_add (initrd_ctx->size,
|
||||
+ ALIGN_UP (sizeof (struct newc_head)
|
||||
+ + sizeof ("TRAILER!!!") - 1, 4),
|
||||
+ &initrd_ctx->size))
|
||||
+ goto overflow;
|
||||
free_dir (root);
|
||||
root = 0;
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
+
|
||||
+overflow:
|
||||
+ free_dir (root);
|
||||
+ grub_initrd_close (initrd_ctx);
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||
}
|
||||
|
||||
grub_size_t
|
||||
@@ -262,8 +288,16 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
|
||||
|
||||
if (initrd_ctx->components[i].newc_name)
|
||||
{
|
||||
- ptr += insert_dir (initrd_ctx->components[i].newc_name,
|
||||
- &root, ptr);
|
||||
+ grub_size_t dir_size;
|
||||
+
|
||||
+ if (insert_dir (initrd_ctx->components[i].newc_name, &root, ptr,
|
||||
+ &dir_size))
|
||||
+ {
|
||||
+ free_dir (root);
|
||||
+ grub_initrd_close (initrd_ctx);
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
+ ptr += dir_size;
|
||||
ptr = make_header (ptr, initrd_ctx->components[i].newc_name,
|
||||
grub_strlen (initrd_ctx->components[i].newc_name),
|
||||
0100777,
|
||||
--
|
||||
2.26.2
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user