From c4e3900971b87316e740318676ccad6edefaa488 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Jul 29 2020 18:46:33 +0000 Subject: import grub2-2.02-0.86.el7_8 --- diff --git a/.gitignore b/.gitignore index 1118eab..8173666 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ SOURCES/grub-2.02~beta2.tar.xz SOURCES/unifont-5.1.20080820.pcf.gz -SOURCES/centos.cer diff --git a/.grub2.metadata b/.grub2.metadata index c59c687..a7bf121 100644 --- a/.grub2.metadata +++ b/.grub2.metadata @@ -1,3 +1,2 @@ 1bf580f1e8bce4909a7ac7ca485cee02b00ed383 SOURCES/grub-2.02~beta2.tar.xz 87f8600ba24e521b5d20bdf6c4b71af8ae861e3a SOURCES/unifont-5.1.20080820.pcf.gz -6e9105eb51e55a46761838f289a917611cad8091 SOURCES/centos.cer diff --git a/SOURCES/0290-Prepend-prefix-when-HTTP-path-is-relative.patch b/SOURCES/0290-Prepend-prefix-when-HTTP-path-is-relative.patch new file mode 100644 index 0000000..41ddacb --- /dev/null +++ b/SOURCES/0290-Prepend-prefix-when-HTTP-path-is-relative.patch @@ -0,0 +1,153 @@ +From 2370f3f3db0f6887d6be36880be9dc6237cb4f3f Mon Sep 17 00:00:00 2001 +From: Stephen Benjamin +Date: Thu, 16 Aug 2018 16:58:51 -0400 +Subject: [PATCH 290/335] Prepend prefix when HTTP path is relative + +This sets a couple of variables. With the url http://www.example.com/foo/bar : +http_path: /foo/bar +http_url: http://www.example.com/foo/bar + +Signed-off-by: Peter Jones +--- + grub-core/kern/main.c | 10 ++++- + grub-core/net/efi/http.c | 82 ++++++++++++++++++++++++++++++---------- + 2 files changed, 71 insertions(+), 21 deletions(-) + +diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c +index da47b18b50e..dcf48726d54 100644 +--- a/grub-core/kern/main.c ++++ b/grub-core/kern/main.c +@@ -130,11 +130,19 @@ grub_set_prefix_and_root (void) + if (fwdevice && fwpath) + { + char *fw_path; ++ char separator[3] = ")"; + +- fw_path = grub_xasprintf ("(%s)/%s", fwdevice, fwpath); ++ grub_dprintf ("fw_path", "\n"); ++ grub_dprintf ("fw_path", "fwdevice:\"%s\" fwpath:\"%s\"\n", fwdevice, fwpath); ++ ++ if (!grub_strncmp(fwdevice, "http", 4) && fwpath[0] != '/') ++ grub_strcpy(separator, ")/"); ++ ++ fw_path = grub_xasprintf ("(%s%s%s", fwdevice, separator, fwpath); + if (fw_path) + { + grub_env_set ("fw_path", 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 243acbaa35b..de351b2cd03 100644 +--- a/grub-core/net/efi/http.c ++++ b/grub-core/net/efi/http.c +@@ -9,10 +9,52 @@ + static void + http_configure (struct grub_efi_net_device *dev, int prefer_ip6) + { ++ grub_efi_ipv6_address_t address; + grub_efi_http_config_data_t http_config; + grub_efi_httpv4_access_point_t httpv4_node; + grub_efi_httpv6_access_point_t httpv6_node; + grub_efi_status_t status; ++ int https; ++ char *http_url; ++ const char *rest, *http_server, *http_path = NULL; ++ ++ http_server = grub_env_get ("root"); ++ https = (grub_strncmp (http_server, "https", 5) == 0) ? 1 : 0; ++ ++ /* extract http server + port */ ++ if (http_server) ++ { ++ http_server = grub_strchr (http_server, ','); ++ if (http_server) ++ http_server++; ++ } ++ ++ /* fw_path is like (http,192.168.1.1:8000)/httpboot, extract path part */ ++ http_path = grub_env_get ("fw_path"); ++ if (http_path) ++ { ++ http_path = grub_strchr (http_path, ')'); ++ if (http_path) ++ { ++ http_path++; ++ grub_env_unset ("http_path"); ++ grub_env_set ("http_path", http_path); ++ } ++ } ++ ++ if (http_server && http_path) ++ { ++ if (grub_efi_string_to_ip6_address (http_server, &address, &rest) && *rest == 0) ++ http_url = grub_xasprintf ("%s://[%s]%s", https ? "https" : "http", http_server, http_path); ++ else ++ http_url = grub_xasprintf ("%s://%s%s", https ? "https" : "http", http_server, http_path); ++ if (http_url) ++ { ++ grub_env_unset ("http_url"); ++ grub_env_set ("http_url", http_url); ++ grub_free (http_url); ++ } ++ } + + grub_efi_http_t *http = dev->http; + +@@ -352,32 +394,32 @@ grub_efihttp_open (struct grub_efi_net_device *dev, + grub_err_t err; + grub_off_t size; + char *buf; +- char *root_url; +- grub_efi_ipv6_address_t address; +- const char *rest; ++ char *file_name = NULL; ++ const char *http_path; + +- if (grub_efi_string_to_ip6_address (file->device->net->server, &address, &rest) && *rest == 0) +- root_url = grub_xasprintf ("%s://[%s]", type ? "https" : "http", file->device->net->server); +- else +- root_url = grub_xasprintf ("%s://%s", type ? "https" : "http", file->device->net->server); +- if (root_url) +- { +- grub_env_unset ("root_url"); +- grub_env_set ("root_url", root_url); +- grub_free (root_url); +- } +- else +- { ++ /* If path is relative, prepend http_path */ ++ http_path = grub_env_get ("http_path"); ++ if (http_path && file->device->net->name[0] != '/') { ++ file_name = grub_xasprintf ("%s/%s", http_path, file->device->net->name); ++ if (!file_name) + return grub_errno; +- } ++ } + +- err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 1, 0); ++ err = efihttp_request (dev->http, file->device->net->server, ++ file_name ? file_name : file->device->net->name, type, 1, 0); + if (err != GRUB_ERR_NONE) +- return err; ++ { ++ grub_free (file_name); ++ return err; ++ } + +- err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 0, &size); ++ err = efihttp_request (dev->http, file->device->net->server, ++ file_name ? file_name : file->device->net->name, type, 0, &size); ++ grub_free (file_name); + if (err != GRUB_ERR_NONE) +- return err; ++ { ++ return err; ++ } + + buf = grub_malloc (size); + efihttp_read (dev, buf, size); +-- +2.26.2 + diff --git a/SOURCES/0291-efi-http-Export-fw-http-_path-variables-to-make-them.patch b/SOURCES/0291-efi-http-Export-fw-http-_path-variables-to-make-them.patch new file mode 100644 index 0000000..8095fd1 --- /dev/null +++ b/SOURCES/0291-efi-http-Export-fw-http-_path-variables-to-make-them.patch @@ -0,0 +1,52 @@ +From 4ff5717d7c45e53637ac5dedf8b37bc25268e2e7 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Thu, 5 Mar 2020 16:21:47 +0100 +Subject: [PATCH 291/335] 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. + +Signed-off-by: Javier Martinez Canillas +--- + 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"); + } + } + +-- +2.26.2 + diff --git a/SOURCES/0292-efi-http-Enclose-literal-IPv6-addresses-in-square-br.patch b/SOURCES/0292-efi-http-Enclose-literal-IPv6-addresses-in-square-br.patch new file mode 100644 index 0000000..b83d6e3 --- /dev/null +++ b/SOURCES/0292-efi-http-Enclose-literal-IPv6-addresses-in-square-br.patch @@ -0,0 +1,116 @@ +From 37bc0adedaba1c662125f9ece262c918155d69ac Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Thu, 5 Mar 2020 16:21:58 +0100 +Subject: [PATCH 292/335] 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 + +Signed-off-by: Javier Martinez Canillas +--- + 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); +-- +2.26.2 + diff --git a/SOURCES/0293-efi-net-Allow-to-specify-a-port-number-in-addresses.patch b/SOURCES/0293-efi-net-Allow-to-specify-a-port-number-in-addresses.patch new file mode 100644 index 0000000..28c54d5 --- /dev/null +++ b/SOURCES/0293-efi-net-Allow-to-specify-a-port-number-in-addresses.patch @@ -0,0 +1,49 @@ +From e38e81e73ca86b80d0a90be44d0bd257ad0148ff Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Mon, 9 Mar 2020 15:29:45 +0100 +Subject: [PATCH 293/335] 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' + +Signed-off-by: Javier Martinez Canillas +--- + 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 f208d1b180c..8981abcb83d 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; +-- +2.26.2 + diff --git a/SOURCES/0294-efi-ip4_config-Improve-check-to-detect-literal-IPv6-.patch b/SOURCES/0294-efi-ip4_config-Improve-check-to-detect-literal-IPv6-.patch new file mode 100644 index 0000000..1808a93 --- /dev/null +++ b/SOURCES/0294-efi-ip4_config-Improve-check-to-detect-literal-IPv6-.patch @@ -0,0 +1,49 @@ +From f865c027b51915e178945168b8f94c4148b43907 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Mon, 9 Mar 2020 15:30:05 +0100 +Subject: [PATCH 294/335] 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' + +Signed-off-by: Javier Martinez Canillas +--- + 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 b711a5d9457..313c818b184 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; +-- +2.26.2 + diff --git a/SOURCES/0295-efi-net-Print-a-debug-message-if-parsing-the-address.patch b/SOURCES/0295-efi-net-Print-a-debug-message-if-parsing-the-address.patch new file mode 100644 index 0000000..5893e7e --- /dev/null +++ b/SOURCES/0295-efi-net-Print-a-debug-message-if-parsing-the-address.patch @@ -0,0 +1,70 @@ +From d71587f7ed21e623e1c61855c127a13b7256e421 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Tue, 10 Mar 2020 11:23:49 +0100 +Subject: [PATCH 295/335] 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. + +Signed-off-by: Javier Martinez Canillas +--- + 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 8981abcb83d..86bcae281a7 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); +-- +2.26.2 + diff --git a/SOURCES/0296-btrfs-avoid-used-uninitialized-error-with-GCC7.patch b/SOURCES/0296-btrfs-avoid-used-uninitialized-error-with-GCC7.patch new file mode 100644 index 0000000..3b838ef --- /dev/null +++ b/SOURCES/0296-btrfs-avoid-used-uninitialized-error-with-GCC7.patch @@ -0,0 +1,33 @@ +From 32fb865bb398d1e310c1ecfe9fabd4dabd17c90d Mon Sep 17 00:00:00 2001 +From: Andrei Borzenkov +Date: Tue, 4 Apr 2017 19:22:32 +0300 +Subject: [PATCH 296/336] btrfs: avoid "used uninitialized" error with GCC7 + +sblock was local and so considered new variable on every loop +iteration. + +Upstream-commit-id: 6cef7f60795 +--- + grub-core/fs/btrfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 4a6efffeb46..24a71045025 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -227,11 +227,11 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, + static grub_err_t + read_sblock (grub_disk_t disk, struct grub_btrfs_superblock *sb) + { ++ struct grub_btrfs_superblock sblock; + unsigned i; + grub_err_t err = GRUB_ERR_NONE; + for (i = 0; i < ARRAY_SIZE (superblock_sectors); i++) + { +- struct grub_btrfs_superblock sblock; + /* Don't try additional superblocks beyond device size. */ + if (i && (grub_le_to_cpu64 (sblock.this_device.size) + >> GRUB_DISK_SECTOR_BITS) <= superblock_sectors[i]) +-- +2.26.2 + diff --git a/SOURCES/0297-build-Use-AC_HEADER_MAJOR-to-find-device-macros.patch b/SOURCES/0297-build-Use-AC_HEADER_MAJOR-to-find-device-macros.patch new file mode 100644 index 0000000..20bcac7 --- /dev/null +++ b/SOURCES/0297-build-Use-AC_HEADER_MAJOR-to-find-device-macros.patch @@ -0,0 +1,109 @@ +From 2ef912c5d484bbc5427dca6e1c22808f870cb66e Mon Sep 17 00:00:00 2001 +From: Mike Gilbert +Date: Tue, 19 Apr 2016 14:27:22 -0400 +Subject: [PATCH 297/336] build: Use AC_HEADER_MAJOR to find device macros + +Depending on the OS/libc, device macros are defined in different +headers. This change ensures we include the right one. + +sys/types.h - BSD +sys/mkdev.h - Sun +sys/sysmacros.h - glibc (Linux) + +glibc currently pulls sys/sysmacros.h into sys/types.h, but this may +change in a future release. + +https://sourceware.org/ml/libc-alpha/2015-11/msg00253.html + +Upstream-commit-id: 7a5b301e3ad +--- + configure.ac | 3 ++- + grub-core/osdep/devmapper/getroot.c | 6 ++++++ + grub-core/osdep/devmapper/hostdisk.c | 5 +++++ + grub-core/osdep/linux/getroot.c | 6 ++++++ + grub-core/osdep/unix/getroot.c | 5 +++++ + 5 files changed, 24 insertions(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 8b10a93cb56..936cfa0ce5a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -405,7 +405,8 @@ fi + + # Check for functions and headers. + AC_CHECK_FUNCS(posix_memalign memalign getextmntent) +-AC_CHECK_HEADERS(sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h limits.h) ++AC_CHECK_HEADERS(sys/param.h sys/mount.h sys/mnttab.h limits.h) ++AC_HEADER_MAJOR + + AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default + #include +diff --git a/grub-core/osdep/devmapper/getroot.c b/grub-core/osdep/devmapper/getroot.c +index de32102322b..227fa5058b6 100644 +--- a/grub-core/osdep/devmapper/getroot.c ++++ b/grub-core/osdep/devmapper/getroot.c +@@ -40,6 +40,12 @@ + #include + #endif + ++#if defined(MAJOR_IN_MKDEV) ++#include ++#elif defined(MAJOR_IN_SYSMACROS) ++#include ++#endif ++ + #include + + #include +diff --git a/grub-core/osdep/devmapper/hostdisk.c b/grub-core/osdep/devmapper/hostdisk.c +index 19c1101fdac..a697bcb4d8d 100644 +--- a/grub-core/osdep/devmapper/hostdisk.c ++++ b/grub-core/osdep/devmapper/hostdisk.c +@@ -24,6 +24,11 @@ + #include + #include + ++#if defined(MAJOR_IN_MKDEV) ++#include ++#elif defined(MAJOR_IN_SYSMACROS) ++#include ++#endif + + #ifdef HAVE_DEVICE_MAPPER + # include +diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c +index 5987d078a2f..6a7784a4ea2 100644 +--- a/grub-core/osdep/linux/getroot.c ++++ b/grub-core/osdep/linux/getroot.c +@@ -35,6 +35,12 @@ + #include + #endif + ++#if defined(MAJOR_IN_MKDEV) ++#include ++#elif defined(MAJOR_IN_SYSMACROS) ++#include ++#endif ++ + #include + #include /* ioctl */ + #include +diff --git a/grub-core/osdep/unix/getroot.c b/grub-core/osdep/unix/getroot.c +index e3887cbea68..026dd79b2d6 100644 +--- a/grub-core/osdep/unix/getroot.c ++++ b/grub-core/osdep/unix/getroot.c +@@ -57,6 +57,11 @@ + #endif + + #include ++#if defined(MAJOR_IN_MKDEV) ++#include ++#elif defined(MAJOR_IN_SYSMACROS) ++#include ++#endif + + #if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) + # include +-- +2.26.2 + diff --git a/SOURCES/0298-Fix-build-with-glibc-2.20.patch b/SOURCES/0298-Fix-build-with-glibc-2.20.patch new file mode 100644 index 0000000..a5b4ed6 --- /dev/null +++ b/SOURCES/0298-Fix-build-with-glibc-2.20.patch @@ -0,0 +1,47 @@ +From 4c926bc85d44fc11324f2e7e6337e156eb1c7e5e Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 3 Sep 2014 01:15:08 -0700 +Subject: [PATCH 298/336] Fix build with glibc 2.20 + +* grub-core/kern/emu/hostfs.c: squahes below warning + warning: #warning "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE" + +Signed-off-by: Khem Raj + +Upstream-commit-id: a276b840464 +--- + grub-core/kern/emu/hostfs.c | 4 ++++ + ChangeLog | 4 ++++ + 2 files changed, 8 insertions(+) + +diff --git a/grub-core/kern/emu/hostfs.c b/grub-core/kern/emu/hostfs.c +index 7e725f65f6a..823116da68e 100644 +--- a/grub-core/kern/emu/hostfs.c ++++ b/grub-core/kern/emu/hostfs.c +@@ -19,7 +19,11 @@ + + #include + ++/* Legacy feature macro.*/ + #define _BSD_SOURCE ++/* New feature macro that provides everything _BSD_SOURCE and ++ * _SVID_SOURCE provided and possibly more. */ ++#define _DEFAULT_SOURCE + #include + #include + #include +diff --git a/ChangeLog b/ChangeLog +index a2da9743231..d3f26cf2f0d 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,7 @@ ++2014-09-15 Khem Raj ++ * grub-core/kern/emu/hostfs.c: use _DEFAULT_SOURCE in addition to ++ _BSD_SOURCE to avoid warnings under glibc 2.20+. ++ + 2014-06-21 Роман Пехов + + * grub-core/commands/loadenv.c (check_blocklists): Fix overlap check. +-- +2.26.2 + diff --git a/SOURCES/0299-yylex-Make-lexer-fatal-errors-actually-be-fatal.patch b/SOURCES/0299-yylex-Make-lexer-fatal-errors-actually-be-fatal.patch new file mode 100644 index 0000000..8c8db58 --- /dev/null +++ b/SOURCES/0299-yylex-Make-lexer-fatal-errors-actually-be-fatal.patch @@ -0,0 +1,70 @@ +From 090453af07db09c4856fe8573436f10bb4b3f114 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 15 Apr 2020 15:45:02 -0400 +Subject: [PATCH 299/336] 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 +Reviewed-by: Daniel Kiper +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 9c2cfe11531..a3f15dfe571 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 + diff --git a/SOURCES/0300-safemath-Add-some-arithmetic-primitives-that-check-f.patch b/SOURCES/0300-safemath-Add-some-arithmetic-primitives-that-check-f.patch new file mode 100644 index 0000000..ebe8ece --- /dev/null +++ b/SOURCES/0300-safemath-Add-some-arithmetic-primitives-that-check-f.patch @@ -0,0 +1,125 @@ +From 5c0dc6965ffb6e6bb86b56a363c0f9a38a38be61 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 15 Jun 2020 10:58:42 -0400 +Subject: [PATCH 300/336] 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 +Reviewed-by: Daniel Kiper +Upstream-commit-id: de1c315841a +--- + include/grub/compiler.h | 8 ++++++++ + include/grub/safemath.h | 37 +++++++++++++++++++++++++++++++++++++ + INSTALL | 21 +++------------------ + 3 files changed, 48 insertions(+), 18 deletions(-) + create mode 100644 include/grub/safemath.h + +diff --git a/include/grub/compiler.h b/include/grub/compiler.h +index a9a684ccba6..60d9c7fae25 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 ++ + #include "types.h" + + union component64 +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 . ++ * ++ * Arithmetic operations that protect against overflow. ++ */ ++ ++#ifndef GRUB_SAFEMATH_H ++#define GRUB_SAFEMATH_H 1 ++ ++#include ++ ++/* 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 b67cd7f3476..8f46a3e999c 100644 +--- a/INSTALL ++++ b/INSTALL +@@ -11,24 +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 +- 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 +- None of tested clang versions generated usable thumb code +- earlier versions not tested +- Note: clang 3.3 or later works for arm64 +- earlier versions have no arm64 support +- 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 doesn't support -mno-app-regs and so can't be used for sparc64 +- Note: clang has no support for ia64 and hence you can't compile GRUB +- for ia64 with clang ++* 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 + * GNU Make + * GNU Bison 2.3 or later + * GNU gettext 0.17 or later +-- +2.26.2 + diff --git a/SOURCES/0301-calloc-Make-sure-we-always-have-an-overflow-checking.patch b/SOURCES/0301-calloc-Make-sure-we-always-have-an-overflow-checking.patch new file mode 100644 index 0000000..c83b4c4 --- /dev/null +++ b/SOURCES/0301-calloc-Make-sure-we-always-have-an-overflow-checking.patch @@ -0,0 +1,243 @@ +From 32e0b660ff1a49517eaf22a10ee93b3f9a689c91 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 15 Jun 2020 12:15:29 -0400 +Subject: [PATCH 301/336] 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 +Reviewed-by: Daniel Kiper +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 258a5649e2d..975e4a766da 100644 +--- a/grub-core/kern/emu/misc.c ++++ b/grub-core/kern/emu/misc.c +@@ -83,6 +83,18 @@ grub_util_error (const char *fmt, ...) + 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 + #include + ++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 1c3d02388f0..a424b7d0943 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -67,8 +67,10 @@ + #include + #include + #include ++#include + + #ifdef MM_DEBUG ++# undef grub_calloc + # undef grub_malloc + # undef grub_zalloc + # undef grub_realloc +@@ -366,6 +368,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) +@@ -552,6 +578,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 + #include + #include ++#include + + 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 + #include ++#include + + 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 a588ba21da2..9e0e793d3df 100644 +--- a/include/grub/emu/misc.h ++++ b/include/grub/emu/misc.h +@@ -50,6 +50,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 + diff --git a/SOURCES/0302-calloc-Use-calloc-at-most-places.patch b/SOURCES/0302-calloc-Use-calloc-at-most-places.patch new file mode 100644 index 0000000..062e462 --- /dev/null +++ b/SOURCES/0302-calloc-Use-calloc-at-most-places.patch @@ -0,0 +1,1948 @@ +From fc1c035be81a22f6d5dda205ea4f480a6725599f Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 15 Jun 2020 12:26:01 -0400 +Subject: [PATCH 302/336] calloc: Use calloc() at most places + +This modifies most of the places we do some form of: + + X = malloc(Y * Z); + +to use calloc(Y, Z) instead. + +Among other issues, this fixes: + - allocation of integer overflow in grub_png_decode_image_header() + reported by Chris Coulson, + - allocation of integer overflow in luks_recover_key() + reported by Chris Coulson, + - allocation of integer overflow in grub_lvm_detect() + reported by Chris Coulson. + +Fixes: CVE-2020-14308 + +Signed-off-by: Peter Jones +Reviewed-by: Daniel Kiper +Upstream-commit-id: 48eeedf1e4b +--- + grub-core/bus/usb/usbhub.c | 8 +-- + grub-core/commands/efi/lsefisystab.c | 3 +- + grub-core/commands/legacycfg.c | 25 +++++++-- + grub-core/commands/menuentry.c | 2 +- + grub-core/commands/nativedisk.c | 2 +- + grub-core/commands/parttool.c | 12 +++-- + grub-core/commands/regexp.c | 2 +- + grub-core/commands/search_wrap.c | 2 +- + grub-core/disk/diskfilter.c | 4 +- + grub-core/disk/ldm.c | 14 ++--- + grub-core/disk/luks.c | 2 +- + grub-core/disk/lvm.c | 8 +-- + grub-core/disk/xen/xendisk.c | 2 +- + grub-core/efiemu/loadcore.c | 2 +- + grub-core/efiemu/mm.c | 6 +-- + grub-core/font/font.c | 3 +- + grub-core/fs/affs.c | 6 +-- + grub-core/fs/btrfs.c | 4 +- + grub-core/fs/hfs.c | 2 +- + grub-core/fs/hfsplus.c | 63 ++++++++++++++++------- + grub-core/fs/iso9660.c | 2 +- + grub-core/fs/ntfs.c | 4 +- + grub-core/fs/sfs.c | 2 +- + grub-core/fs/tar.c | 2 +- + grub-core/fs/udf.c | 4 +- + grub-core/fs/zfs/zfs.c | 4 +- + grub-core/gfxmenu/gui_string_util.c | 2 +- + grub-core/gfxmenu/widget-box.c | 4 +- + grub-core/io/gzio.c | 2 +- + grub-core/kern/efi/efi.c | 31 +++++++++-- + grub-core/kern/emu/hostdisk.c | 2 +- + grub-core/kern/fs.c | 2 +- + grub-core/kern/misc.c | 2 +- + grub-core/kern/parser.c | 2 +- + grub-core/kern/uboot/uboot.c | 2 +- + grub-core/lib/libgcrypt/cipher/ac.c | 8 +-- + grub-core/lib/libgcrypt/cipher/primegen.c | 4 +- + grub-core/lib/libgcrypt/cipher/pubkey.c | 4 +- + grub-core/lib/priority_queue.c | 2 +- + grub-core/lib/reed_solomon.c | 7 ++- + grub-core/lib/relocator.c | 10 ++-- + grub-core/loader/arm/linux.c | 2 +- + grub-core/loader/efi/chainloader.c | 11 ++-- + grub-core/loader/i386/bsdXX.c | 2 +- + grub-core/loader/i386/xnu.c | 4 +- + grub-core/loader/macho.c | 2 +- + grub-core/loader/multiboot_elfxx.c | 2 +- + grub-core/loader/xnu.c | 2 +- + grub-core/mmap/mmap.c | 4 +- + grub-core/net/bootp.c | 2 +- + grub-core/net/dns.c | 10 ++-- + grub-core/net/net.c | 4 +- + grub-core/normal/charset.c | 10 ++-- + grub-core/normal/cmdline.c | 14 ++--- + grub-core/normal/menu_entry.c | 14 ++--- + grub-core/normal/menu_text.c | 4 +- + grub-core/normal/term.c | 4 +- + grub-core/osdep/linux/getroot.c | 6 +-- + grub-core/osdep/unix/config.c | 2 +- + grub-core/osdep/windows/getroot.c | 2 +- + grub-core/osdep/windows/hostdisk.c | 4 +- + grub-core/osdep/windows/init.c | 2 +- + grub-core/osdep/windows/platform.c | 4 +- + grub-core/osdep/windows/relpath.c | 2 +- + grub-core/partmap/gpt.c | 2 +- + grub-core/partmap/msdos.c | 2 +- + grub-core/script/execute.c | 2 +- + grub-core/tests/fake_input.c | 2 +- + grub-core/tests/video_checksum.c | 6 +-- + grub-core/video/capture.c | 2 +- + grub-core/video/emu/sdl.c | 2 +- + grub-core/video/i386/pc/vga.c | 2 +- + grub-core/video/readers/png.c | 2 +- + util/getroot.c | 2 +- + util/grub-file.c | 2 +- + util/grub-fstest.c | 2 +- + util/grub-install-common.c | 2 +- + util/grub-install.c | 4 +- + util/grub-mkimagexx.c | 4 +- + util/grub-mkstandalone.c | 2 +- + util/grub-pe2elf.c | 12 ++--- + util/grub-probe.c | 4 +- + include/grub/unicode.h | 4 +- + 83 files changed, 261 insertions(+), 186 deletions(-) + +diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c +index 34a7ff1b5f8..a06cce302d2 100644 +--- a/grub-core/bus/usb/usbhub.c ++++ b/grub-core/bus/usb/usbhub.c +@@ -149,8 +149,8 @@ grub_usb_add_hub (grub_usb_device_t dev) + grub_usb_set_configuration (dev, 1); + + dev->nports = hubdesc.portcnt; +- dev->children = grub_zalloc (hubdesc.portcnt * sizeof (dev->children[0])); +- dev->ports = grub_zalloc (dev->nports * sizeof (dev->ports[0])); ++ dev->children = grub_calloc (hubdesc.portcnt, sizeof (dev->children[0])); ++ dev->ports = grub_calloc (dev->nports, sizeof (dev->ports[0])); + if (!dev->children || !dev->ports) + { + grub_free (dev->children); +@@ -268,8 +268,8 @@ grub_usb_controller_dev_register_iter (grub_usb_controller_t controller, void *d + + /* Query the number of ports the root Hub has. */ + hub->nports = controller->dev->hubports (controller); +- hub->devices = grub_zalloc (sizeof (hub->devices[0]) * hub->nports); +- hub->ports = grub_zalloc (sizeof (hub->ports[0]) * hub->nports); ++ hub->devices = grub_calloc (hub->nports, sizeof (hub->devices[0])); ++ hub->ports = grub_calloc (hub->nports, sizeof (hub->ports[0])); + if (!hub->devices || !hub->ports) + { + grub_free (hub->devices); +diff --git a/grub-core/commands/efi/lsefisystab.c b/grub-core/commands/efi/lsefisystab.c +index 8717db91ea2..2a86bd53aeb 100644 +--- a/grub-core/commands/efi/lsefisystab.c ++++ b/grub-core/commands/efi/lsefisystab.c +@@ -61,7 +61,8 @@ grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)), + grub_printf ("Vendor: "); + + for (vendor_utf16 = st->firmware_vendor; *vendor_utf16; vendor_utf16++); +- vendor = grub_malloc (4 * (vendor_utf16 - st->firmware_vendor) + 1); ++ /* Allocate extra 3 bytes to simplify math. */ ++ vendor = grub_calloc (4, vendor_utf16 - st->firmware_vendor + 1); + if (!vendor) + return grub_errno; + *grub_utf16_to_utf8 ((grub_uint8_t *) vendor, st->firmware_vendor, +diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c +index 2c09fb7dd78..d1127fa8968 100644 +--- a/grub-core/commands/legacycfg.c ++++ b/grub-core/commands/legacycfg.c +@@ -244,6 +244,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), + struct grub_command *cmd; + char **cutargs; + int cutargc; ++ grub_err_t err = 0; + + for (i = 0; i < 2; i++) + { +@@ -304,7 +305,14 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), + if (argc < 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + +- cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1)); ++ cutargs = grub_calloc (argc - 1, sizeof (cutargs[0])); ++ err = grub_errno; ++ if (!cutargs) ++ { ++out: ++ grub_errno = err; ++ return grub_errno; ++ } + cutargc = argc - 1; + grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2)); + cutargs[0] = args[0]; +@@ -420,7 +428,12 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), + { + char rbuf[3] = "-r"; + bsdargc = cutargc + 2; +- bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc); ++ bsdargs = grub_calloc (bsdargc, sizeof (bsdargs[0])); ++ if (!bsdargs) ++ { ++ err = grub_errno; ++ goto out; ++ } + grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0])); + bsdargs[argc] = rbuf; + bsdargs[argc + 1] = bsddevname; +@@ -523,7 +536,13 @@ grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused + char **newargs; + grub_err_t err; + char nounzipbuf[10] = "--nounzip"; +- newargs = grub_malloc ((argc + 1) * sizeof (newargs[0])); ++ ++ cmd = grub_command_find ("module"); ++ if (!cmd) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"), ++ "module"); ++ ++ newargs = grub_calloc (argc + 1, sizeof (newargs[0])); + if (!newargs) + return grub_errno; + grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0])); +diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c +index 58d4dadf6ee..16c52ed00e8 100644 +--- a/grub-core/commands/menuentry.c ++++ b/grub-core/commands/menuentry.c +@@ -154,7 +154,7 @@ grub_normal_add_menu_entry (int argc, const char **args, + goto fail; + + /* Save argc, args to pass as parameters to block arg later. */ +- menu_args = grub_malloc (sizeof (char*) * (argc + 1)); ++ menu_args = grub_calloc (argc + 1, sizeof (char *)); + if (! menu_args) + goto fail; + +diff --git a/grub-core/commands/nativedisk.c b/grub-core/commands/nativedisk.c +index 33b6b99eaaf..36298cf2ed4 100644 +--- a/grub-core/commands/nativedisk.c ++++ b/grub-core/commands/nativedisk.c +@@ -191,7 +191,7 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)), + else + path_prefix = prefix; + +- mods = grub_malloc (argc * sizeof (mods[0])); ++ mods = grub_calloc (argc, sizeof (mods[0])); + if (!mods) + return grub_errno; + +diff --git a/grub-core/commands/parttool.c b/grub-core/commands/parttool.c +index a47ff0776c1..a79b84a565b 100644 +--- a/grub-core/commands/parttool.c ++++ b/grub-core/commands/parttool.c +@@ -59,7 +59,13 @@ grub_parttool_register(const char *part_name, + for (nargs = 0; args[nargs].name != 0; nargs++); + cur->nargs = nargs; + cur->args = (struct grub_parttool_argdesc *) +- grub_malloc ((nargs + 1) * sizeof (struct grub_parttool_argdesc)); ++ grub_calloc (nargs + 1, sizeof (struct grub_parttool_argdesc)); ++ if (!cur->args) ++ { ++ grub_free (cur); ++ curhandle--; ++ return -1; ++ } + grub_memcpy (cur->args, args, + (nargs + 1) * sizeof (struct grub_parttool_argdesc)); + +@@ -249,7 +255,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), + if (grub_strcmp (args[i], "help") == 0) + return show_help (dev); + +- parsed = (int *) grub_zalloc (argc * sizeof (int)); ++ parsed = (int *) grub_calloc (argc, sizeof (int)); + + for (i = 1; i < argc; i++) + if (! parsed[i]) +@@ -278,7 +284,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), + args[i]); + ptool = cur; + pargs = (struct grub_parttool_args *) +- grub_zalloc (ptool->nargs * sizeof (struct grub_parttool_args)); ++ grub_calloc (ptool->nargs, sizeof (struct grub_parttool_args)); + for (j = i; j < argc; j++) + if (! parsed[j]) + { +diff --git a/grub-core/commands/regexp.c b/grub-core/commands/regexp.c +index f00b184c81e..4019164f365 100644 +--- a/grub-core/commands/regexp.c ++++ b/grub-core/commands/regexp.c +@@ -116,7 +116,7 @@ grub_cmd_regexp (grub_extcmd_context_t ctxt, int argc, char **args) + if (ret) + goto fail; + +- matches = grub_zalloc (sizeof (*matches) * (regex.re_nsub + 1)); ++ matches = grub_calloc (regex.re_nsub + 1, sizeof (*matches)); + if (! matches) + goto fail; + +diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c +index 3f75fecdf1d..07ba57072df 100644 +--- a/grub-core/commands/search_wrap.c ++++ b/grub-core/commands/search_wrap.c +@@ -122,7 +122,7 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) + for (i = 0; state[SEARCH_HINT_BAREMETAL].args[i]; i++) + nhints++; + +- hints = grub_malloc (sizeof (hints[0]) * nhints); ++ hints = grub_calloc (nhints, sizeof (hints[0])); + if (!hints) + return grub_errno; + j = 0; +diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c +index e8a3bcbd138..509c0f353c7 100644 +--- a/grub-core/disk/diskfilter.c ++++ b/grub-core/disk/diskfilter.c +@@ -1013,7 +1013,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, + array->lvs->segments->node_count = nmemb; + array->lvs->segments->raid_member_size = disk_size; + array->lvs->segments->nodes +- = grub_zalloc (nmemb * sizeof (array->lvs->segments->nodes[0])); ++ = grub_calloc (nmemb, sizeof (array->lvs->segments->nodes[0])); + array->lvs->segments->stripe_size = stripe_size; + for (i = 0; i < nmemb; i++) + { +@@ -1092,7 +1092,7 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id, + grub_partition_t p; + for (p = disk->partition; p; p = p->parent) + s++; +- pv->partmaps = xmalloc (s * sizeof (pv->partmaps[0])); ++ pv->partmaps = xcalloc (s, sizeof (pv->partmaps[0])); + s = 0; + for (p = disk->partition; p; p = p->parent) + pv->partmaps[s++] = xstrdup (p->partmap->name); +diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c +index 8075f2a9eee..97a482705d0 100644 +--- a/grub-core/disk/ldm.c ++++ b/grub-core/disk/ldm.c +@@ -323,8 +323,8 @@ make_vg (grub_disk_t disk, + lv->segments->type = GRUB_DISKFILTER_MIRROR; + lv->segments->node_count = 0; + lv->segments->node_alloc = 8; +- lv->segments->nodes = grub_zalloc (sizeof (*lv->segments->nodes) +- * lv->segments->node_alloc); ++ lv->segments->nodes = grub_calloc (lv->segments->node_alloc, ++ sizeof (*lv->segments->nodes)); + if (!lv->segments->nodes) + goto fail2; + ptr = vblk[i].dynamic; +@@ -543,8 +543,8 @@ make_vg (grub_disk_t disk, + { + comp->segment_alloc = 8; + comp->segment_count = 0; +- comp->segments = grub_malloc (sizeof (*comp->segments) +- * comp->segment_alloc); ++ comp->segments = grub_calloc (comp->segment_alloc, ++ sizeof (*comp->segments)); + if (!comp->segments) + goto fail2; + } +@@ -590,8 +590,8 @@ make_vg (grub_disk_t disk, + } + comp->segments->node_count = read_int (ptr + 1, *ptr); + comp->segments->node_alloc = comp->segments->node_count; +- comp->segments->nodes = grub_zalloc (sizeof (*comp->segments->nodes) +- * comp->segments->node_alloc); ++ comp->segments->nodes = grub_calloc (comp->segments->node_alloc, ++ sizeof (*comp->segments->nodes)); + if (!lv->segments->nodes) + goto fail2; + } +@@ -1017,7 +1017,7 @@ grub_util_ldm_embed (struct grub_disk *disk, unsigned int *nsectors, + *nsectors = lv->size; + if (*nsectors > max_nsectors) + *nsectors = max_nsectors; +- *sectors = grub_malloc (*nsectors * sizeof (**sectors)); ++ *sectors = grub_calloc (*nsectors, sizeof (**sectors)); + if (!*sectors) + return grub_errno; + for (i = 0; i < *nsectors; i++) +diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c +index 25020294712..7e682b5207a 100644 +--- a/grub-core/disk/luks.c ++++ b/grub-core/disk/luks.c +@@ -324,7 +324,7 @@ luks_recover_key (grub_disk_t source, + && grub_be_to_cpu32 (header.keyblock[i].stripes) > max_stripes) + max_stripes = grub_be_to_cpu32 (header.keyblock[i].stripes); + +- split_key = grub_malloc (keysize * max_stripes); ++ split_key = grub_calloc (keysize, max_stripes); + if (!split_key) + return grub_errno; + +diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c +index 862a9664f2c..680a796cb48 100644 +--- a/grub-core/disk/lvm.c ++++ b/grub-core/disk/lvm.c +@@ -173,7 +173,7 @@ grub_lvm_detect (grub_disk_t disk, + first one. */ + + /* Allocate buffer space for the circular worst-case scenario. */ +- metadatabuf = grub_malloc (2 * mda_size); ++ metadatabuf = grub_calloc (2, mda_size); + if (! metadatabuf) + goto fail; + +@@ -426,7 +426,7 @@ grub_lvm_detect (grub_disk_t disk, + #endif + goto lvs_fail; + } +- lv->segments = grub_malloc (sizeof (*seg) * lv->segment_count); ++ lv->segments = grub_calloc (lv->segment_count, sizeof (*seg)); + seg = lv->segments; + + for (i = 0; i < lv->segment_count; i++) +@@ -483,8 +483,8 @@ grub_lvm_detect (grub_disk_t disk, + if (seg->node_count != 1) + seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = "); + +- seg->nodes = grub_zalloc (sizeof (*stripe) +- * seg->node_count); ++ seg->nodes = grub_calloc (seg->node_count, ++ sizeof (*stripe)); + stripe = seg->nodes; + + p = grub_strstr (p, "stripes = ["); +diff --git a/grub-core/disk/xen/xendisk.c b/grub-core/disk/xen/xendisk.c +index 2b11c2a2eaa..0c6778b0eed 100644 +--- a/grub-core/disk/xen/xendisk.c ++++ b/grub-core/disk/xen/xendisk.c +@@ -399,7 +399,7 @@ grub_xendisk_init (void) + if (!ctr) + return; + +- virtdisks = grub_malloc (ctr * sizeof (virtdisks[0])); ++ virtdisks = grub_calloc (ctr, sizeof (virtdisks[0])); + if (!virtdisks) + return; + if (grub_xenstore_dir ("device/vbd", fill, &ctr)) +diff --git a/grub-core/efiemu/loadcore.c b/grub-core/efiemu/loadcore.c +index 6968b3719ca..d6b30f6e99d 100644 +--- a/grub-core/efiemu/loadcore.c ++++ b/grub-core/efiemu/loadcore.c +@@ -198,7 +198,7 @@ grub_efiemu_count_symbols (const Elf_Ehdr *e) + + grub_efiemu_nelfsyms = (unsigned) s->sh_size / (unsigned) s->sh_entsize; + grub_efiemu_elfsyms = (struct grub_efiemu_elf_sym *) +- grub_malloc (sizeof (struct grub_efiemu_elf_sym) * grub_efiemu_nelfsyms); ++ grub_calloc (grub_efiemu_nelfsyms, sizeof (struct grub_efiemu_elf_sym)); + + /* Relocators */ + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); +diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c +index e606dbffc92..3a7cd28e98f 100644 +--- a/grub-core/efiemu/mm.c ++++ b/grub-core/efiemu/mm.c +@@ -553,11 +553,11 @@ grub_efiemu_mmap_sort_and_uniq (void) + /* Initialize variables*/ + grub_memset (present, 0, sizeof (int) * GRUB_EFI_MAX_MEMORY_TYPE); + scanline_events = (struct grub_efiemu_mmap_scan *) +- grub_malloc (sizeof (struct grub_efiemu_mmap_scan) * 2 * mmap_num); ++ grub_calloc (mmap_num, sizeof (struct grub_efiemu_mmap_scan) * 2); + + /* Number of chunks can't increase more than by factor of 2 */ + result = (grub_efi_memory_descriptor_t *) +- grub_malloc (sizeof (grub_efi_memory_descriptor_t) * 2 * mmap_num); ++ grub_calloc (mmap_num, sizeof (grub_efi_memory_descriptor_t) * 2); + if (!result || !scanline_events) + { + grub_free (result); +@@ -659,7 +659,7 @@ grub_efiemu_mm_do_alloc (void) + + /* Preallocate mmap */ + efiemu_mmap = (grub_efi_memory_descriptor_t *) +- grub_malloc (mmap_reserved_size * sizeof (grub_efi_memory_descriptor_t)); ++ grub_calloc (mmap_reserved_size, sizeof (grub_efi_memory_descriptor_t)); + if (!efiemu_mmap) + { + grub_efiemu_unload (); +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index 14b93e17251..b5f43d992a4 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -293,8 +293,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct + font->num_chars = sect_length / FONT_CHAR_INDEX_ENTRY_SIZE; + + /* Allocate the character index array. */ +- font->char_index = grub_malloc (font->num_chars +- * sizeof (struct char_index_entry)); ++ font->char_index = grub_calloc (font->num_chars, sizeof (struct char_index_entry)); + if (!font->char_index) + return 1; + font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t)); +diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c +index f673897e0fd..91073795f90 100644 +--- a/grub-core/fs/affs.c ++++ b/grub-core/fs/affs.c +@@ -301,7 +301,7 @@ grub_affs_read_symlink (grub_fshelp_node_t node) + return 0; + } + latin1[symlink_size] = 0; +- utf8 = grub_malloc (symlink_size * GRUB_MAX_UTF8_PER_LATIN1 + 1); ++ utf8 = grub_calloc (GRUB_MAX_UTF8_PER_LATIN1 + 1, symlink_size); + if (!utf8) + { + grub_free (latin1); +@@ -422,7 +422,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, + return 1; + } + +- hashtable = grub_zalloc (data->htsize * sizeof (*hashtable)); ++ hashtable = grub_calloc (data->htsize, sizeof (*hashtable)); + if (!hashtable) + return 1; + +@@ -628,7 +628,7 @@ grub_affs_label (grub_device_t device, char **label) + len = file.namelen; + if (len > sizeof (file.name)) + len = sizeof (file.name); +- *label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); ++ *label = grub_calloc (GRUB_MAX_UTF8_PER_LATIN1 + 1, len); + if (*label) + *grub_latin1_to_utf8 ((grub_uint8_t *) *label, file.name, len) = '\0'; + } +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index 24a71045025..db57875f490 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -375,7 +375,7 @@ lower_bound (struct grub_btrfs_data *data, + { + desc->allocated = 16; + desc->depth = 0; +- desc->data = grub_malloc (sizeof (desc->data[0]) * desc->allocated); ++ desc->data = grub_calloc (desc->allocated, sizeof (desc->data[0])); + if (!desc->data) + return grub_errno; + } +@@ -1732,7 +1732,7 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), + *nsectors = 64 * 2 - 1; + if (*nsectors > max_nsectors) + *nsectors = max_nsectors; +- *sectors = grub_malloc (*nsectors * sizeof (**sectors)); ++ *sectors = grub_calloc (*nsectors, sizeof (**sectors)); + if (!*sectors) + return grub_errno; + for (i = 0; i < *nsectors; i++) +diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c +index d1dc015455d..79f6845879a 100644 +--- a/grub-core/fs/hfs.c ++++ b/grub-core/fs/hfs.c +@@ -1360,7 +1360,7 @@ grub_hfs_label (grub_device_t device, char **label) + grub_size_t len = data->sblock.volname[0]; + if (len > sizeof (data->sblock.volname) - 1) + len = sizeof (data->sblock.volname) - 1; +- *label = grub_malloc (len * MAX_UTF8_PER_MAC_ROMAN + 1); ++ *label = grub_calloc (MAX_UTF8_PER_MAC_ROMAN + 1, len); + if (*label) + macroman_to_utf8 (*label, data->sblock.volname + 1, + len + 1, 0); +diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c +index 950d8a1e1c6..05016ee98a4 100644 +--- a/grub-core/fs/hfsplus.c ++++ b/grub-core/fs/hfsplus.c +@@ -655,6 +655,7 @@ list_nodes (void *record, void *hook_arg) + char *filename; + int i; + struct grub_fshelp_node *node; ++ grub_uint16_t *keyname; + struct grub_hfsplus_catfile *fileinfo; + enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN; + struct list_nodes_ctx *ctx = hook_arg; +@@ -713,29 +714,33 @@ list_nodes (void *record, void *hook_arg) + if (! filename) + return 0; + ++ keyname = grub_calloc (grub_be_to_cpu16 (catkey->namelen), sizeof (*keyname)); ++ if (!keyname) ++ { ++ grub_free (filename); ++ return 0; ++ } ++ + /* Make sure the byte order of the UTF16 string is correct. */ + for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++) + { +- catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]); ++ keyname[i] = grub_be_to_cpu16 (catkey->name[i]); + +- if (catkey->name[i] == '/') +- catkey->name[i] = ':'; ++ if (keyname[i] == '/') ++ keyname[i] = ':'; + + /* If the name is obviously invalid, skip this node. */ +- if (catkey->name[i] == 0) +- return 0; ++ if (keyname[i] == 0) ++ { ++ grub_free (keyname); ++ grub_free (filename); ++ return 0; ++ } + } + +- *grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name, ++ *grub_utf16_to_utf8 ((grub_uint8_t *) filename, keyname, + grub_be_to_cpu16 (catkey->namelen)) = '\0'; +- +- /* Restore the byte order to what it was previously. */ +- for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++) +- { +- if (catkey->name[i] == ':') +- catkey->name[i] = '/'; +- catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]); +- } ++ grub_free (keyname); + + /* hfs+ is case insensitive. */ + if (! ctx->dir->data->case_sensitive) +@@ -963,6 +968,7 @@ grub_hfsplus_label (grub_device_t device, char **label) + grub_disk_t disk = device->disk; + struct grub_hfsplus_catkey *catkey; + int i, label_len; ++ grub_uint16_t *label_name; + struct grub_hfsplus_key_internal intern; + struct grub_hfsplus_btnode *node; + grub_disk_addr_t ptr; +@@ -991,22 +997,41 @@ grub_hfsplus_label (grub_device_t device, char **label) + grub_hfsplus_btree_recptr (&data->catalog_tree, node, ptr); + + label_len = grub_be_to_cpu16 (catkey->namelen); ++ label_name = grub_calloc (label_len, sizeof (*label_name)); ++ if (!label_name) ++ { ++ grub_free (node); ++ grub_free (data); ++ return grub_errno; ++ } ++ + for (i = 0; i < label_len; i++) + { +- catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]); ++ label_name[i] = grub_be_to_cpu16 (catkey->name[i]); + + /* If the name is obviously invalid, skip this node. */ + if (catkey->name[i] == 0) +- return 0; ++ { ++ grub_free (label_name); ++ grub_free (node); ++ grub_free (data); ++ return 0; ++ } + } + +- *label = grub_malloc (label_len * GRUB_MAX_UTF8_PER_UTF16 + 1); ++ *label = grub_calloc (label_len, GRUB_MAX_UTF8_PER_UTF16 + 1); + if (! *label) +- return grub_errno; ++ { ++ grub_free (label_name); ++ grub_free (node); ++ grub_free (data); ++ return grub_errno; ++ } + +- *grub_utf16_to_utf8 ((grub_uint8_t *) (*label), catkey->name, ++ *grub_utf16_to_utf8 ((grub_uint8_t *) (*label), label_name, + label_len) = '\0'; + ++ grub_free (label_name); + grub_free (node); + grub_free (data); + +diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c +index 6a6677337d7..2fe433ceb54 100644 +--- a/grub-core/fs/iso9660.c ++++ b/grub-core/fs/iso9660.c +@@ -331,7 +331,7 @@ grub_iso9660_convert_string (grub_uint8_t *us, int len) + int i; + grub_uint16_t t[MAX_NAMELEN / 2 + 1]; + +- p = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1); ++ p = grub_calloc (len, GRUB_MAX_UTF8_PER_UTF16 + 1); + if (! p) + return NULL; + +diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c +index d3a91f5d791..7997fc2c323 100644 +--- a/grub-core/fs/ntfs.c ++++ b/grub-core/fs/ntfs.c +@@ -556,8 +556,8 @@ get_utf8 (grub_uint8_t *in, grub_size_t len) + grub_uint16_t *tmp; + grub_size_t i; + +- buf = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1); +- tmp = grub_malloc (len * sizeof (tmp[0])); ++ buf = grub_calloc (len, GRUB_MAX_UTF8_PER_UTF16 + 1); ++ tmp = grub_calloc (len, sizeof (tmp[0])); + if (!buf || !tmp) + { + grub_free (buf); +diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c +index 6c821504876..754cad880f5 100644 +--- a/grub-core/fs/sfs.c ++++ b/grub-core/fs/sfs.c +@@ -261,7 +261,7 @@ grub_sfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + node->next_extent = node->block; + node->cache_size = 0; + +- node->cache = grub_malloc (sizeof (node->cache[0]) * cache_size); ++ node->cache = grub_calloc (cache_size, sizeof (node->cache[0])); + if (!node->cache) + { + grub_errno = 0; +diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c +index 39bf197aabe..4864451e19b 100644 +--- a/grub-core/fs/tar.c ++++ b/grub-core/fs/tar.c +@@ -120,7 +120,7 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name, + if (data->linkname_alloc < linksize + 1) + { + char *n; +- n = grub_malloc (2 * (linksize + 1)); ++ n = grub_calloc (2, linksize + 1); + if (!n) + return grub_errno; + grub_free (data->linkname); +diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c +index fd412830c2b..488f35a3ee5 100644 +--- a/grub-core/fs/udf.c ++++ b/grub-core/fs/udf.c +@@ -836,7 +836,7 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf) + { + unsigned i; + utf16len = sz - 1; +- utf16 = grub_malloc (utf16len * sizeof (utf16[0])); ++ utf16 = grub_calloc (utf16len, sizeof (utf16[0])); + if (!utf16) + return NULL; + for (i = 0; i < utf16len; i++) +@@ -846,7 +846,7 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf) + { + unsigned i; + utf16len = (sz - 1) / 2; +- utf16 = grub_malloc (utf16len * sizeof (utf16[0])); ++ utf16 = grub_calloc (utf16len, sizeof (utf16[0])); + if (!utf16) + return NULL; + for (i = 0; i < utf16len; i++) +diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c +index cfb25c030de..3d7351de37c 100644 +--- a/grub-core/fs/zfs/zfs.c ++++ b/grub-core/fs/zfs/zfs.c +@@ -3253,7 +3253,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, + } + subvol->nkeys = 0; + zap_iterate (&keychain_dn, 8, count_zap_keys, &ctx, data); +- subvol->keyring = grub_zalloc (subvol->nkeys * sizeof (subvol->keyring[0])); ++ subvol->keyring = grub_calloc (subvol->nkeys, sizeof (subvol->keyring[0])); + if (!subvol->keyring) + { + grub_free (fsname); +@@ -4250,7 +4250,7 @@ grub_zfs_embed (grub_device_t device __attribute__ ((unused)), + *nsectors = (VDEV_BOOT_SIZE >> GRUB_DISK_SECTOR_BITS); + if (*nsectors > max_nsectors) + *nsectors = max_nsectors; +- *sectors = grub_malloc (*nsectors * sizeof (**sectors)); ++ *sectors = grub_calloc (*nsectors, sizeof (**sectors)); + if (!*sectors) + return grub_errno; + for (i = 0; i < *nsectors; i++) +diff --git a/grub-core/gfxmenu/gui_string_util.c b/grub-core/gfxmenu/gui_string_util.c +index a9a415e3129..ba1e1eab319 100644 +--- a/grub-core/gfxmenu/gui_string_util.c ++++ b/grub-core/gfxmenu/gui_string_util.c +@@ -55,7 +55,7 @@ canonicalize_path (const char *path) + if (*p == '/') + components++; + +- char **path_array = grub_malloc (components * sizeof (*path_array)); ++ char **path_array = grub_calloc (components, sizeof (*path_array)); + if (! path_array) + return 0; + +diff --git a/grub-core/gfxmenu/widget-box.c b/grub-core/gfxmenu/widget-box.c +index b6060288914..470597ded2b 100644 +--- a/grub-core/gfxmenu/widget-box.c ++++ b/grub-core/gfxmenu/widget-box.c +@@ -303,10 +303,10 @@ grub_gfxmenu_create_box (const char *pixmaps_prefix, + box->content_height = 0; + box->raw_pixmaps = + (struct grub_video_bitmap **) +- grub_malloc (BOX_NUM_PIXMAPS * sizeof (struct grub_video_bitmap *)); ++ grub_calloc (BOX_NUM_PIXMAPS, sizeof (struct grub_video_bitmap *)); + box->scaled_pixmaps = + (struct grub_video_bitmap **) +- grub_malloc (BOX_NUM_PIXMAPS * sizeof (struct grub_video_bitmap *)); ++ grub_calloc (BOX_NUM_PIXMAPS, sizeof (struct grub_video_bitmap *)); + + /* Initialize all pixmap pointers to NULL so that proper destruction can + be performed if an error is encountered partway through construction. */ +diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c +index 129209e37d0..daf514bc482 100644 +--- a/grub-core/io/gzio.c ++++ b/grub-core/io/gzio.c +@@ -542,7 +542,7 @@ huft_build (unsigned *b, /* code lengths in bits (all assumed <= BMAX) */ + z = 1 << j; /* table entries for j-bit table */ + + /* allocate and link in new table */ +- q = (struct huft *) grub_zalloc ((z + 1) * sizeof (struct huft)); ++ q = (struct huft *) grub_calloc (z + 1, sizeof (struct huft)); + if (! q) + { + if (h) +diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c +index 570535f78d0..4bd7ca210ad 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -198,7 +198,7 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid, + + len = grub_strlen (var); + len16 = len * GRUB_MAX_UTF16_PER_UTF8; +- var16 = grub_malloc ((len16 + 1) * sizeof (var16[0])); ++ var16 = grub_calloc (len16 + 1, sizeof (var16[0])); + if (!var16) + return grub_errno; + len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL); +@@ -233,7 +233,7 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, + + len = grub_strlen (var); + len16 = len * GRUB_MAX_UTF16_PER_UTF8; +- var16 = grub_malloc ((len16 + 1) * sizeof (var16[0])); ++ var16 = grub_calloc (len16 + 1, sizeof (var16[0])); + if (!var16) + return NULL; + len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL); +@@ -365,6 +365,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0) + { + grub_efi_file_path_device_path_t *fp; + grub_efi_uint16_t len; ++ grub_efi_char16_t *dup_name; + + *p++ = '/'; + +@@ -372,7 +373,16 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0) + / sizeof (grub_efi_char16_t)); + fp = (grub_efi_file_path_device_path_t *) dp; + +- p = (char *) grub_utf16_to_utf8 ((unsigned char *) p, fp->path_name, len); ++ dup_name = grub_calloc (len, sizeof (*dup_name)); ++ if (!dup_name) ++ { ++ grub_free (name); ++ return NULL; ++ } ++ p = (char *) grub_utf16_to_utf8 ((unsigned char *) p, ++ grub_memcpy (dup_name, fp->path_name, len * sizeof (*dup_name)), ++ len); ++ grub_free (dup_name); + } + + dp = GRUB_EFI_NEXT_DEVICE_PATH (dp); +@@ -862,9 +872,20 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) + fp = (grub_efi_file_path_device_path_t *) dp; + buf = grub_malloc ((len - 4) * 2 + 1); + if (buf) +- *grub_utf16_to_utf8 (buf, fp->path_name, ++ { ++ grub_efi_char16_t *dup_name = grub_malloc (len - 4); ++ if (!dup_name) ++ { ++ grub_errno = GRUB_ERR_NONE; ++ grub_printf ("/File((null))"); ++ grub_free (buf); ++ break; ++ } ++ *grub_utf16_to_utf8 (buf, grub_memcpy (dup_name, fp->path_name, len - 4), + (len - 4) / sizeof (grub_efi_char16_t)) +- = '\0'; ++ = '\0'; ++ grub_free (dup_name); ++ } + else + grub_errno = GRUB_ERR_NONE; + grub_printf ("/File(%s)", buf); +diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c +index 44b0fcbb1e5..419073a0391 100644 +--- a/grub-core/kern/emu/hostdisk.c ++++ b/grub-core/kern/emu/hostdisk.c +@@ -615,7 +615,7 @@ static char * + grub_util_path_concat_real (size_t n, int ext, va_list ap) + { + size_t totlen = 0; +- char **l = xmalloc ((n + ext) * sizeof (l[0])); ++ char **l = xcalloc (n + ext, sizeof (l[0])); + char *r, *p, *pi; + size_t i; + int first = 1; +diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c +index 9085895b6fe..23f4301c026 100644 +--- a/grub-core/kern/fs.c ++++ b/grub-core/kern/fs.c +@@ -151,7 +151,7 @@ grub_fs_blocklist_open (grub_file_t file, const char *name) + while (p); + + /* Allocate a block list. */ +- blocks = grub_zalloc (sizeof (struct grub_fs_block) * (num + 1)); ++ blocks = grub_calloc (num + 1, sizeof (struct grub_fs_block)); + if (! blocks) + return 0; + +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index d0ca2ee603b..8b4a78b35be 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -882,7 +882,7 @@ parse_printf_args (const char *fmt0, struct printf_args *args, + args->ptr = args->prealloc; + else + { +- args->ptr = grub_malloc (args->count * sizeof (args->ptr[0])); ++ args->ptr = grub_calloc (args->count, sizeof (args->ptr[0])); + if (!args->ptr) + { + grub_errno = GRUB_ERR_NONE; +diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c +index b9bd12352db..5de8559e777 100644 +--- a/grub-core/kern/parser.c ++++ b/grub-core/kern/parser.c +@@ -213,7 +213,7 @@ grub_parser_split_cmdline (const char *cmdline, + return grub_errno; + grub_memcpy (args, buffer, bp - buffer); + +- *argv = grub_malloc (sizeof (char *) * (*argc + 1)); ++ *argv = grub_calloc (*argc + 1, sizeof (char *)); + if (!*argv) + { + grub_free (args); +diff --git a/grub-core/kern/uboot/uboot.c b/grub-core/kern/uboot/uboot.c +index 6800a4beb1c..948b08b9579 100644 +--- a/grub-core/kern/uboot/uboot.c ++++ b/grub-core/kern/uboot/uboot.c +@@ -168,7 +168,7 @@ grub_uboot_dev_enum (void) + return num_devices; + + max_devices = 2; +- enum_devices = grub_malloc (sizeof(struct device_info) * max_devices); ++ enum_devices = grub_calloc (max_devices, sizeof(struct device_info)); + if (!enum_devices) + return 0; + +diff --git a/grub-core/lib/libgcrypt/cipher/ac.c b/grub-core/lib/libgcrypt/cipher/ac.c +index f5e946a2d8f..63f6fcd11ef 100644 +--- a/grub-core/lib/libgcrypt/cipher/ac.c ++++ b/grub-core/lib/libgcrypt/cipher/ac.c +@@ -185,7 +185,7 @@ ac_data_mpi_copy (gcry_ac_mpi_t *data_mpis, unsigned int data_mpis_n, + gcry_mpi_t mpi; + char *label; + +- data_mpis_new = gcry_malloc (sizeof (*data_mpis_new) * data_mpis_n); ++ data_mpis_new = gcry_calloc (data_mpis_n, sizeof (*data_mpis_new)); + if (! data_mpis_new) + { + err = gcry_error_from_errno (errno); +@@ -572,7 +572,7 @@ _gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp, + } + + /* Add MPI list. */ +- arg_list = gcry_malloc (sizeof (*arg_list) * (data_n + 1)); ++ arg_list = gcry_calloc (data_n + 1, sizeof (*arg_list)); + if (! arg_list) + { + err = gcry_error_from_errno (errno); +@@ -1283,7 +1283,7 @@ ac_data_construct (const char *identifier, int include_flags, + /* We build a list of arguments to pass to + gcry_sexp_build_array(). */ + data_length = _gcry_ac_data_length (data); +- arg_list = gcry_malloc (sizeof (*arg_list) * (data_length * 2)); ++ arg_list = gcry_calloc (data_length, sizeof (*arg_list) * 2); + if (! arg_list) + { + err = gcry_error_from_errno (errno); +@@ -1593,7 +1593,7 @@ _gcry_ac_key_pair_generate (gcry_ac_handle_t handle, unsigned int nbits, + arg_list_n += 2; + + /* Allocate list. */ +- arg_list = gcry_malloc (sizeof (*arg_list) * arg_list_n); ++ arg_list = gcry_calloc (arg_list_n, sizeof (*arg_list)); + if (! arg_list) + { + err = gcry_error_from_errno (errno); +diff --git a/grub-core/lib/libgcrypt/cipher/primegen.c b/grub-core/lib/libgcrypt/cipher/primegen.c +index 2788e349fa9..b12e79b1922 100644 +--- a/grub-core/lib/libgcrypt/cipher/primegen.c ++++ b/grub-core/lib/libgcrypt/cipher/primegen.c +@@ -383,7 +383,7 @@ prime_generate_internal (int need_q_factor, + } + + /* Allocate an array to track pool usage. */ +- pool_in_use = gcry_malloc (n * sizeof *pool_in_use); ++ pool_in_use = gcry_calloc (n, sizeof *pool_in_use); + if (!pool_in_use) + { + err = gpg_err_code_from_errno (errno); +@@ -765,7 +765,7 @@ gen_prime (unsigned int nbits, int secret, int randomlevel, + if (nbits < 16) + log_fatal ("can't generate a prime with less than %d bits\n", 16); + +- mods = gcry_xmalloc( no_of_small_prime_numbers * sizeof *mods ); ++ mods = gcry_xcalloc( no_of_small_prime_numbers, sizeof *mods); + /* Make nbits fit into gcry_mpi_t implementation. */ + val_2 = mpi_alloc_set_ui( 2 ); + val_3 = mpi_alloc_set_ui( 3); +diff --git a/grub-core/lib/libgcrypt/cipher/pubkey.c b/grub-core/lib/libgcrypt/cipher/pubkey.c +index 910982141e0..ca087ad75b9 100644 +--- a/grub-core/lib/libgcrypt/cipher/pubkey.c ++++ b/grub-core/lib/libgcrypt/cipher/pubkey.c +@@ -2941,7 +2941,7 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey) + * array to a format string, so we have to do it this way :-(. */ + /* FIXME: There is now such a format specifier, so we can + change the code to be more clear. */ +- arg_list = malloc (nelem * sizeof *arg_list); ++ arg_list = calloc (nelem, sizeof *arg_list); + if (!arg_list) + { + rc = gpg_err_code_from_syserror (); +@@ -3233,7 +3233,7 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey) + } + strcpy (p, "))"); + +- arg_list = malloc (nelem * sizeof *arg_list); ++ arg_list = calloc (nelem, sizeof *arg_list); + if (!arg_list) + { + rc = gpg_err_code_from_syserror (); +diff --git a/grub-core/lib/priority_queue.c b/grub-core/lib/priority_queue.c +index 659be0b7f40..7d5e7c05aab 100644 +--- a/grub-core/lib/priority_queue.c ++++ b/grub-core/lib/priority_queue.c +@@ -92,7 +92,7 @@ grub_priority_queue_new (grub_size_t elsize, + { + struct grub_priority_queue *ret; + void *els; +- els = grub_malloc (elsize * 8); ++ els = grub_calloc (8, elsize); + if (!els) + return 0; + ret = (struct grub_priority_queue *) grub_malloc (sizeof (*ret)); +diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c +index 7263cbc0463..9b12f29e1d9 100644 +--- a/grub-core/lib/reed_solomon.c ++++ b/grub-core/lib/reed_solomon.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#define xcalloc calloc + #define xmalloc malloc + #define grub_memset memset + #define grub_memcpy memcpy +@@ -158,11 +159,9 @@ rs_encode (gf_single_t *data, grub_size_t s, grub_size_t rs) + gf_single_t *rs_polynomial; + int i, j; + gf_single_t *m; +- m = xmalloc ((s + rs) * sizeof (gf_single_t)); ++ m = xcalloc (s + rs, sizeof (gf_single_t)); + grub_memcpy (m, data, s * sizeof (gf_single_t)); +- grub_memset (m + s, 0, rs * sizeof (gf_single_t)); +- rs_polynomial = xmalloc ((rs + 1) * sizeof (gf_single_t)); +- grub_memset (rs_polynomial, 0, (rs + 1) * sizeof (gf_single_t)); ++ rs_polynomial = xcalloc (rs + 1, sizeof (gf_single_t)); + rs_polynomial[rs] = 1; + /* Multiply with X - a^r */ + for (j = 0; j < rs; j++) +diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c +index f759c7f41f4..7ea72069a45 100644 +--- a/grub-core/lib/relocator.c ++++ b/grub-core/lib/relocator.c +@@ -495,9 +495,9 @@ malloc_in_range (struct grub_relocator *rel, + } + #endif + +- eventt = grub_malloc (maxevents * sizeof (events[0])); ++ eventt = grub_calloc (maxevents, sizeof (events[0])); + counter = grub_malloc ((DIGITSORT_MASK + 2) * sizeof (counter[0])); +- events = grub_malloc (maxevents * sizeof (events[0])); ++ events = grub_calloc (maxevents, sizeof (events[0])); + if (!events || !eventt || !counter) + { + grub_dprintf ("relocator", "events or counter allocation failed %d\n", +@@ -953,7 +953,7 @@ malloc_in_range (struct grub_relocator *rel, + #endif + unsigned cural = 0; + int oom = 0; +- res->subchunks = grub_malloc (sizeof (res->subchunks[0]) * nallocs); ++ res->subchunks = grub_calloc (nallocs, sizeof (res->subchunks[0])); + if (!res->subchunks) + oom = 1; + res->nsubchunks = nallocs; +@@ -1552,8 +1552,8 @@ grub_relocator_prepare_relocs (struct grub_relocator *rel, grub_addr_t addr, + count[(chunk->src & 0xff) + 1]++; + } + } +- from = grub_malloc (nchunks * sizeof (sorted[0])); +- to = grub_malloc (nchunks * sizeof (sorted[0])); ++ from = grub_calloc (nchunks, sizeof (sorted[0])); ++ to = grub_calloc (nchunks, sizeof (sorted[0])); + if (!from || !to) + { + grub_free (from); +diff --git a/grub-core/loader/arm/linux.c b/grub-core/loader/arm/linux.c +index 62cbe75d34e..1b195e0899e 100644 +--- a/grub-core/loader/arm/linux.c ++++ b/grub-core/loader/arm/linux.c +@@ -79,7 +79,7 @@ linux_prepare_atag (void) + + /* some place for cmdline, initrd and terminator. */ + tmp_size = get_atag_size (atag_orig) + 20 + (arg_size) / 4; +- tmp_atag = grub_malloc (tmp_size * sizeof (grub_uint32_t)); ++ tmp_atag = grub_calloc (tmp_size, sizeof (grub_uint32_t)); + if (!tmp_atag) + return grub_errno; + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index db1ffeefc93..3d600fa6bd5 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -119,18 +119,23 @@ static void + copy_file_path (grub_efi_file_path_device_path_t *fp, + const char *str, grub_efi_uint16_t len) + { +- grub_efi_char16_t *p; ++ grub_efi_char16_t *p, *path_name; + grub_efi_uint16_t size; + + fp->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE; + fp->header.subtype = GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE; + +- size = grub_utf8_to_utf16 (fp->path_name, len * GRUB_MAX_UTF16_PER_UTF8, ++ path_name = grub_calloc (len, GRUB_MAX_UTF16_PER_UTF8 * sizeof (*path_name)); ++ if (!path_name) ++ return; ++ ++ size = grub_utf8_to_utf16 (path_name, len * GRUB_MAX_UTF16_PER_UTF8, + (const grub_uint8_t *) str, len, 0); +- for (p = fp->path_name; p < fp->path_name + size; p++) ++ for (p = path_name; p < path_name + size; p++) + if (*p == '/') + *p = '\\'; + ++ grub_memcpy (fp->path_name, path_name, size * sizeof (*fp->path_name)); + /* File Path is NULL terminated */ + fp->path_name[size++] = '\0'; + fp->header.length = size * sizeof (grub_efi_char16_t) + sizeof (*fp); +diff --git a/grub-core/loader/i386/bsdXX.c b/grub-core/loader/i386/bsdXX.c +index 9e36cd4b651..6c8906fe878 100644 +--- a/grub-core/loader/i386/bsdXX.c ++++ b/grub-core/loader/i386/bsdXX.c +@@ -48,7 +48,7 @@ read_headers (grub_file_t file, const char *filename, Elf_Ehdr *e, char **shdr) + if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS)) + return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic")); + +- *shdr = grub_malloc (e->e_shnum * e->e_shentsize); ++ *shdr = grub_calloc (e->e_shnum, e->e_shentsize); + if (! *shdr) + return grub_errno; + +diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c +index e83e1e9725d..875048e1353 100644 +--- a/grub-core/loader/i386/xnu.c ++++ b/grub-core/loader/i386/xnu.c +@@ -292,7 +292,7 @@ grub_xnu_devprop_add_property_utf8 (struct grub_xnu_devprop_device_descriptor *d + return grub_errno; + + len = grub_strlen (name); +- utf16 = grub_malloc (sizeof (grub_uint16_t) * len); ++ utf16 = grub_calloc (len, sizeof (grub_uint16_t)); + if (!utf16) + { + grub_free (utf8); +@@ -328,7 +328,7 @@ grub_xnu_devprop_add_property_utf16 (struct grub_xnu_devprop_device_descriptor * + grub_uint16_t *utf16; + grub_err_t err; + +- utf16 = grub_malloc (sizeof (grub_uint16_t) * namelen); ++ utf16 = grub_calloc (namelen, sizeof (grub_uint16_t)); + if (!utf16) + return grub_errno; + grub_memcpy (utf16, name, sizeof (grub_uint16_t) * namelen); +diff --git a/grub-core/loader/macho.c b/grub-core/loader/macho.c +index 59b195e27ea..f61341af515 100644 +--- a/grub-core/loader/macho.c ++++ b/grub-core/loader/macho.c +@@ -97,7 +97,7 @@ grub_macho_file (grub_file_t file, const char *filename, int is_64bit) + if (grub_file_seek (macho->file, sizeof (struct grub_macho_fat_header)) + == (grub_off_t) -1) + goto fail; +- archs = grub_malloc (sizeof (struct grub_macho_fat_arch) * narchs); ++ archs = grub_calloc (narchs, sizeof (struct grub_macho_fat_arch)); + if (!archs) + goto fail; + if (grub_file_read (macho->file, archs, +diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c +index 9dc21a1ba48..c0ff1239dbf 100644 +--- a/grub-core/loader/multiboot_elfxx.c ++++ b/grub-core/loader/multiboot_elfxx.c +@@ -164,7 +164,7 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi + { + grub_uint8_t *shdr, *shdrptr; + +- shdr = grub_malloc (ehdr->e_shnum * ehdr->e_shentsize); ++ shdr = grub_calloc (ehdr->e_shnum, ehdr->e_shentsize); + if (!shdr) + return grub_errno; + +diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c +index faffccc9744..fdf61b6f9f7 100644 +--- a/grub-core/loader/xnu.c ++++ b/grub-core/loader/xnu.c +@@ -791,7 +791,7 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)), + if (grub_be_to_cpu32 (head.magic) == GRUB_MACHO_FAT_MAGIC) + { + narchs = grub_be_to_cpu32 (head.nfat_arch); +- archs = grub_malloc (sizeof (struct grub_macho_fat_arch) * narchs); ++ archs = grub_calloc (narchs, sizeof (struct grub_macho_fat_arch)); + if (! archs) + { + grub_file_close (file); +diff --git a/grub-core/mmap/mmap.c b/grub-core/mmap/mmap.c +index 6a31cbae325..57b4e9a72a9 100644 +--- a/grub-core/mmap/mmap.c ++++ b/grub-core/mmap/mmap.c +@@ -143,9 +143,9 @@ grub_mmap_iterate (grub_memory_hook_t hook, void *hook_data) + + /* Initialize variables. */ + ctx.scanline_events = (struct grub_mmap_scan *) +- grub_malloc (sizeof (struct grub_mmap_scan) * 2 * mmap_num); ++ grub_calloc (mmap_num, sizeof (struct grub_mmap_scan) * 2); + +- present = grub_zalloc (sizeof (present[0]) * current_priority); ++ present = grub_calloc (current_priority, sizeof (present[0])); + + if (! ctx.scanline_events || !present) + { +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index 249ca0c2dc6..4cfb3908031 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -1338,7 +1338,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), + if (ncards == 0) + return grub_error (GRUB_ERR_NET_NO_CARD, N_("no network card found")); + +- ifaces = grub_zalloc (ncards * sizeof (ifaces[0])); ++ ifaces = grub_calloc (ncards, sizeof (ifaces[0])); + if (!ifaces) + return grub_errno; + +diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c +index 0b771fb10a5..695a920ac44 100644 +--- a/grub-core/net/dns.c ++++ b/grub-core/net/dns.c +@@ -276,8 +276,8 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), + ptr++; + ptr += 4; + } +- *data->addresses = grub_malloc (sizeof ((*data->addresses)[0]) +- * grub_cpu_to_be16 (head->ancount)); ++ *data->addresses = grub_calloc (grub_be_to_cpu16 (head->ancount), ++ sizeof ((*data->addresses)[0])); + if (!*data->addresses) + { + grub_errno = GRUB_ERR_NONE; +@@ -397,8 +397,8 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), + dns_cache[h].addresses = 0; + dns_cache[h].name = grub_strdup (data->oname); + dns_cache[h].naddresses = *data->naddresses; +- dns_cache[h].addresses = grub_malloc (*data->naddresses +- * sizeof (dns_cache[h].addresses[0])); ++ dns_cache[h].addresses = grub_calloc (*data->naddresses, ++ sizeof (dns_cache[h].addresses[0])); + dns_cache[h].limit_time = grub_get_time_ms () + 1000 * ttl_all; + if (!dns_cache[h].addresses || !dns_cache[h].name) + { +@@ -470,7 +470,7 @@ grub_net_dns_lookup (const char *name, + } + } + +- sockets = grub_malloc (sizeof (sockets[0]) * n_servers); ++ sockets = grub_calloc (n_servers, sizeof (sockets[0])); + if (!sockets) + return grub_errno; + +diff --git a/grub-core/net/net.c b/grub-core/net/net.c +index cfe4cb62760..80310ff4e7a 100644 +--- a/grub-core/net/net.c ++++ b/grub-core/net/net.c +@@ -353,8 +353,8 @@ grub_cmd_ipv6_autoconf (struct grub_command *cmd __attribute__ ((unused)), + ncards++; + } + +- ifaces = grub_zalloc (ncards * sizeof (ifaces[0])); +- slaacs = grub_zalloc (ncards * sizeof (slaacs[0])); ++ ifaces = grub_calloc (ncards, sizeof (ifaces[0])); ++ slaacs = grub_calloc (ncards, sizeof (slaacs[0])); + if (!ifaces || !slaacs) + { + grub_free (ifaces); +diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c +index 3e4c337da74..33b8b9cae79 100644 +--- a/grub-core/normal/charset.c ++++ b/grub-core/normal/charset.c +@@ -203,7 +203,7 @@ grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg, + { + grub_size_t msg_len = grub_strlen (msg); + +- *unicode_msg = grub_malloc (msg_len * sizeof (grub_uint32_t)); ++ *unicode_msg = grub_calloc (msg_len, sizeof (grub_uint32_t)); + + if (!*unicode_msg) + return -1; +@@ -488,7 +488,7 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen, + } + else + { +- n = grub_malloc (sizeof (n[0]) * (out->ncomb + 1)); ++ n = grub_calloc (out->ncomb + 1, sizeof (n[0])); + if (!n) + { + grub_errno = GRUB_ERR_NONE; +@@ -842,7 +842,7 @@ grub_bidi_line_logical_to_visual (const grub_uint32_t *logical, + } \ + } + +- visual = grub_malloc (sizeof (visual[0]) * logical_len); ++ visual = grub_calloc (logical_len, sizeof (visual[0])); + if (!visual) + return -1; + +@@ -1154,8 +1154,8 @@ grub_bidi_logical_to_visual (const grub_uint32_t *logical, + { + const grub_uint32_t *line_start = logical, *ptr; + struct grub_unicode_glyph *visual_ptr; +- *visual_out = visual_ptr = grub_malloc (3 * sizeof (visual_ptr[0]) +- * (logical_len + 2)); ++ *visual_out = visual_ptr = grub_calloc (logical_len + 2, ++ 3 * sizeof (visual_ptr[0])); + if (!visual_ptr) + return -1; + for (ptr = logical; ptr <= logical + logical_len; ptr++) +diff --git a/grub-core/normal/cmdline.c b/grub-core/normal/cmdline.c +index 204d15a4bb8..aa6fd85d791 100644 +--- a/grub-core/normal/cmdline.c ++++ b/grub-core/normal/cmdline.c +@@ -41,7 +41,7 @@ grub_err_t + grub_set_history (int newsize) + { + grub_uint32_t **old_hist_lines = hist_lines; +- hist_lines = grub_malloc (sizeof (grub_uint32_t *) * newsize); ++ hist_lines = grub_calloc (newsize, sizeof (grub_uint32_t *)); + + /* Copy the old lines into the new buffer. */ + if (old_hist_lines) +@@ -114,7 +114,7 @@ static void + grub_history_set (int pos, grub_uint32_t *s, grub_size_t len) + { + grub_free (hist_lines[pos]); +- hist_lines[pos] = grub_malloc ((len + 1) * sizeof (grub_uint32_t)); ++ hist_lines[pos] = grub_calloc (len + 1, sizeof (grub_uint32_t)); + if (!hist_lines[pos]) + { + grub_print_error (); +@@ -349,7 +349,7 @@ grub_cmdline_get (const char *prompt_translated) + char *ret; + unsigned nterms; + +- buf = grub_malloc (max_len * sizeof (grub_uint32_t)); ++ buf = grub_calloc (max_len, sizeof (grub_uint32_t)); + if (!buf) + return 0; + +@@ -377,7 +377,7 @@ grub_cmdline_get (const char *prompt_translated) + FOR_ACTIVE_TERM_OUTPUTS(cur) + nterms++; + +- cl_terms = grub_malloc (sizeof (cl_terms[0]) * nterms); ++ cl_terms = grub_calloc (nterms, sizeof (cl_terms[0])); + if (!cl_terms) + { + grub_free (buf); +@@ -385,7 +385,7 @@ grub_cmdline_get (const char *prompt_translated) + } + cl_term_cur = cl_terms; + +- unicode_msg = grub_malloc (msg_len * sizeof (grub_uint32_t)); ++ unicode_msg = grub_calloc (msg_len, sizeof (grub_uint32_t)); + if (!unicode_msg) + { + grub_free (buf); +@@ -494,7 +494,7 @@ grub_cmdline_get (const char *prompt_translated) + grub_uint32_t *insert; + + insertlen = grub_strlen (insertu8); +- insert = grub_malloc ((insertlen + 1) * sizeof (grub_uint32_t)); ++ insert = grub_calloc (insertlen + 1, sizeof (grub_uint32_t)); + if (!insert) + { + grub_free (insertu8); +@@ -601,7 +601,7 @@ grub_cmdline_get (const char *prompt_translated) + + grub_free (kill_buf); + +- kill_buf = grub_malloc ((n + 1) * sizeof(grub_uint32_t)); ++ kill_buf = grub_calloc (n + 1, sizeof (grub_uint32_t)); + if (grub_errno) + { + grub_print_error (); +diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c +index 62e5db1fef8..dc1ac1dd1e1 100644 +--- a/grub-core/normal/menu_entry.c ++++ b/grub-core/normal/menu_entry.c +@@ -95,8 +95,8 @@ init_line (struct screen *screen, struct line *linep) + { + linep->len = 0; + linep->max_len = 80; +- linep->buf = grub_malloc ((linep->max_len + 1) * sizeof (linep->buf[0])); +- linep->pos = grub_zalloc (screen->nterms * sizeof (linep->pos[0])); ++ linep->buf = grub_calloc (linep->max_len + 1, sizeof (linep->buf[0])); ++ linep->pos = grub_calloc (screen->nterms, sizeof (linep->pos[0])); + if (! linep->buf || !linep->pos) + { + grub_free (linep->buf); +@@ -281,7 +281,7 @@ update_screen (struct screen *screen, struct per_term_screen *term_screen, + pos = linep->pos + (term_screen - screen->terms); + + if (!*pos) +- *pos = grub_zalloc ((linep->len + 1) * sizeof (**pos)); ++ *pos = grub_calloc (linep->len + 1, sizeof (**pos)); + + if (i == region_start || linep == screen->lines + screen->line + || (i > region_start && mode == ALL_LINES)) +@@ -463,7 +463,7 @@ insert_string (struct screen *screen, const char *s, int update) + + /* Insert the string. */ + current_linep = screen->lines + screen->line; +- unicode_msg = grub_malloc ((p - s) * sizeof (grub_uint32_t)); ++ unicode_msg = grub_calloc (p - s, sizeof (grub_uint32_t)); + + if (!unicode_msg) + return 0; +@@ -1012,7 +1012,7 @@ complete (struct screen *screen, int continuous, int update) + if (completion_buffer.buf) + { + buflen = grub_strlen (completion_buffer.buf); +- ucs4 = grub_malloc (sizeof (grub_uint32_t) * (buflen + 1)); ++ ucs4 = grub_calloc (buflen + 1, sizeof (grub_uint32_t)); + + if (!ucs4) + { +@@ -1254,7 +1254,7 @@ grub_menu_entry_run (grub_menu_entry_t entry) + for (i = 0; i < (unsigned) screen->num_lines; i++) + { + grub_free (screen->lines[i].pos); +- screen->lines[i].pos = grub_zalloc (screen->nterms * sizeof (screen->lines[i].pos[0])); ++ screen->lines[i].pos = grub_calloc (screen->nterms, sizeof (screen->lines[i].pos[0])); + if (! screen->lines[i].pos) + { + grub_print_error (); +@@ -1263,7 +1263,7 @@ grub_menu_entry_run (grub_menu_entry_t entry) + } + } + +- screen->terms = grub_zalloc (screen->nterms * sizeof (screen->terms[0])); ++ screen->terms = grub_calloc (screen->nterms, sizeof (screen->terms[0])); + if (!screen->terms) + { + grub_print_error (); +diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c +index 33b208bcf44..5019ffa6c63 100644 +--- a/grub-core/normal/menu_text.c ++++ b/grub-core/normal/menu_text.c +@@ -78,7 +78,7 @@ grub_print_message_indented_real (const char *msg, int margin_left, + grub_size_t msg_len = grub_strlen (msg) + 2; + int ret = 0; + +- unicode_msg = grub_malloc (msg_len * sizeof (grub_uint32_t)); ++ unicode_msg = grub_calloc (msg_len, sizeof (grub_uint32_t)); + + if (!unicode_msg) + return 0; +@@ -167,7 +167,7 @@ print_entry (int y, int highlight, grub_menu_entry_t entry, + + title = entry ? entry->title : ""; + title_len = grub_strlen (title); +- unicode_title = grub_malloc (title_len * sizeof (*unicode_title)); ++ unicode_title = grub_calloc (title_len, sizeof (*unicode_title)); + if (! unicode_title) + /* XXX How to show this error? */ + return; +diff --git a/grub-core/normal/term.c b/grub-core/normal/term.c +index 4c2238b2589..bbfd4c211e9 100644 +--- a/grub-core/normal/term.c ++++ b/grub-core/normal/term.c +@@ -264,7 +264,7 @@ grub_term_save_pos (void) + FOR_ACTIVE_TERM_OUTPUTS(cur) + cnt++; + +- ret = grub_malloc (cnt * sizeof (ret[0])); ++ ret = grub_calloc (cnt, sizeof (ret[0])); + if (!ret) + return NULL; + +@@ -1013,7 +1013,7 @@ grub_xnputs (const char *str, grub_size_t msg_len) + + grub_error_push (); + +- unicode_str = grub_malloc (msg_len * sizeof (grub_uint32_t)); ++ unicode_str = grub_calloc (msg_len, sizeof (grub_uint32_t)); + + grub_error_pop (); + +diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c +index 6a7784a4ea2..32fd962ec47 100644 +--- a/grub-core/osdep/linux/getroot.c ++++ b/grub-core/osdep/linux/getroot.c +@@ -168,7 +168,7 @@ grub_util_raid_getmembers (const char *name, int bootable) + if (ret != 0) + grub_util_error (_("ioctl GET_ARRAY_INFO error: %s"), strerror (errno)); + +- devicelist = xmalloc ((info.nr_disks + 1) * sizeof (char *)); ++ devicelist = xcalloc (info.nr_disks + 1, sizeof (char *)); + + for (i = 0, j = 0; j < info.nr_disks; i++) + { +@@ -241,7 +241,7 @@ grub_find_root_devices_from_btrfs (const char *dir) + return NULL; + } + +- ret = xmalloc ((fsi.num_devices + 1) * sizeof (ret[0])); ++ ret = xcalloc (fsi.num_devices + 1, sizeof (ret[0])); + + for (i = 1; i <= fsi.max_id && j < fsi.num_devices; i++) + { +@@ -391,7 +391,7 @@ grub_find_root_devices_from_mountinfo (const char *dir, char **relroot) + if (! fp) + return NULL; /* fall through to other methods */ + +- entries = xmalloc (entry_max * sizeof (*entries)); ++ entries = xcalloc (entry_max, sizeof (*entries)); + + /* First, build a list of relevant visible mounts. */ + while (getline (&buf, &len, fp) > 0) +diff --git a/grub-core/osdep/unix/config.c b/grub-core/osdep/unix/config.c +index f4b0bb466f7..604af82e892 100644 +--- a/grub-core/osdep/unix/config.c ++++ b/grub-core/osdep/unix/config.c +@@ -89,7 +89,7 @@ grub_util_load_config (struct grub_util_config *cfg) + argv[0] = "sh"; + argv[1] = "-c"; + +- script = xmalloc (4 * strlen (cfgfile) + 300); ++ script = xcalloc (4, strlen (cfgfile) + 300); + + ptr = script; + memcpy (ptr, ". '", 3); +diff --git a/grub-core/osdep/windows/getroot.c b/grub-core/osdep/windows/getroot.c +index 661d9546192..eada663b261 100644 +--- a/grub-core/osdep/windows/getroot.c ++++ b/grub-core/osdep/windows/getroot.c +@@ -59,7 +59,7 @@ grub_get_mount_point (const TCHAR *path) + + for (ptr = path; *ptr; ptr++); + allocsize = (ptr - path + 10) * 2; +- out = xmalloc (allocsize * sizeof (out[0])); ++ out = xcalloc (allocsize, sizeof (out[0])); + + /* When pointing to EFI system partition GetVolumePathName fails + for ESP root and returns abberant information for everything +diff --git a/grub-core/osdep/windows/hostdisk.c b/grub-core/osdep/windows/hostdisk.c +index 9127e9263b1..959a87c157b 100644 +--- a/grub-core/osdep/windows/hostdisk.c ++++ b/grub-core/osdep/windows/hostdisk.c +@@ -111,7 +111,7 @@ grub_util_get_windows_path_real (const char *path) + + while (1) + { +- fpa = xmalloc (alloc * sizeof (fpa[0])); ++ fpa = xcalloc (alloc, sizeof (fpa[0])); + + len = GetFullPathName (tpath, alloc, fpa, NULL); + if (len >= alloc) +@@ -393,7 +393,7 @@ grub_util_fd_opendir (const char *name) + for (l = 0; name_windows[l]; l++); + for (l--; l >= 0 && (name_windows[l] == '\\' || name_windows[l] == '/'); l--); + l++; +- pattern = xmalloc ((l + 3) * sizeof (pattern[0])); ++ pattern = xcalloc (l + 3, sizeof (pattern[0])); + memcpy (pattern, name_windows, l * sizeof (pattern[0])); + pattern[l] = '\\'; + pattern[l + 1] = '*'; +diff --git a/grub-core/osdep/windows/init.c b/grub-core/osdep/windows/init.c +index 98c325c203d..ef7d2807795 100644 +--- a/grub-core/osdep/windows/init.c ++++ b/grub-core/osdep/windows/init.c +@@ -161,7 +161,7 @@ grub_util_host_init (int *argc __attribute__ ((unused)), + LPWSTR *targv; + + targv = CommandLineToArgvW (tcmdline, argc); +- *argv = xmalloc ((*argc + 1) * sizeof (argv[0])); ++ *argv = xcalloc (*argc + 1, sizeof (argv[0])); + + for (i = 0; i < *argc; i++) + (*argv)[i] = grub_util_tchar_to_utf8 (targv[i]); +diff --git a/grub-core/osdep/windows/platform.c b/grub-core/osdep/windows/platform.c +index d217efe1704..9fe999731eb 100644 +--- a/grub-core/osdep/windows/platform.c ++++ b/grub-core/osdep/windows/platform.c +@@ -225,8 +225,8 @@ grub_install_register_efi (grub_device_t efidir_grub_dev, + grub_util_error ("%s", _("no EFI routines are available when running in BIOS mode")); + + distrib8_len = grub_strlen (efi_distributor); +- distributor16 = xmalloc ((distrib8_len + 1) * GRUB_MAX_UTF16_PER_UTF8 +- * sizeof (grub_uint16_t)); ++ distributor16 = xcalloc (distrib8_len + 1, ++ GRUB_MAX_UTF16_PER_UTF8 * sizeof (grub_uint16_t)); + distrib16_len = grub_utf8_to_utf16 (distributor16, distrib8_len * GRUB_MAX_UTF16_PER_UTF8, + (const grub_uint8_t *) efi_distributor, + distrib8_len, 0); +diff --git a/grub-core/osdep/windows/relpath.c b/grub-core/osdep/windows/relpath.c +index cb0861744ae..478e8ef14d5 100644 +--- a/grub-core/osdep/windows/relpath.c ++++ b/grub-core/osdep/windows/relpath.c +@@ -72,7 +72,7 @@ grub_make_system_path_relative_to_its_root (const char *path) + if (dirwindows[0] && dirwindows[1] == ':') + offset = 2; + } +- ret = xmalloc (sizeof (ret[0]) * (flen - offset + 2)); ++ ret = xcalloc (flen - offset + 2, sizeof (ret[0])); + if (dirwindows[offset] != '\\' + && dirwindows[offset] != '/' + && dirwindows[offset]) +diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c +index 83bcba77914..5fae4cad059 100644 +--- a/grub-core/partmap/gpt.c ++++ b/grub-core/partmap/gpt.c +@@ -199,7 +199,7 @@ gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, + *nsectors = ctx.len; + if (*nsectors > max_nsectors) + *nsectors = max_nsectors; +- *sectors = grub_malloc (*nsectors * sizeof (**sectors)); ++ *sectors = grub_calloc (*nsectors, sizeof (**sectors)); + if (!*sectors) + return grub_errno; + for (i = 0; i < *nsectors; i++) +diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c +index 46c406bff1f..d604f5a0e55 100644 +--- a/grub-core/partmap/msdos.c ++++ b/grub-core/partmap/msdos.c +@@ -337,7 +337,7 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, + avail_nsectors = *nsectors; + if (*nsectors > max_nsectors) + *nsectors = max_nsectors; +- *sectors = grub_malloc (*nsectors * sizeof (**sectors)); ++ *sectors = grub_calloc (*nsectors, sizeof (**sectors)); + if (!*sectors) + return grub_errno; + for (i = 0; i < *nsectors; i++) +diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c +index cec9539a47c..043b4c4bb66 100644 +--- a/grub-core/script/execute.c ++++ b/grub-core/script/execute.c +@@ -586,7 +586,7 @@ gettext_append (struct grub_script_argv *result, const char *orig_str) + for (iptr = orig_str; *iptr; iptr++) + if (*iptr == '$') + dollar_cnt++; +- ctx.allowed_strings = grub_malloc (sizeof (ctx.allowed_strings[0]) * dollar_cnt); ++ ctx.allowed_strings = grub_calloc (dollar_cnt, sizeof (ctx.allowed_strings[0])); + + if (parse_string (orig_str, gettext_save_allow, &ctx, 0)) + goto fail; +diff --git a/grub-core/tests/fake_input.c b/grub-core/tests/fake_input.c +index 2d60852989c..b5eb516be2d 100644 +--- a/grub-core/tests/fake_input.c ++++ b/grub-core/tests/fake_input.c +@@ -49,7 +49,7 @@ grub_terminal_input_fake_sequence (int *seq_in, int nseq_in) + saved = grub_term_inputs; + if (seq) + grub_free (seq); +- seq = grub_malloc (nseq_in * sizeof (seq[0])); ++ seq = grub_calloc (nseq_in, sizeof (seq[0])); + if (!seq) + return; + +diff --git a/grub-core/tests/video_checksum.c b/grub-core/tests/video_checksum.c +index 74d5b65e5c7..44d0810698a 100644 +--- a/grub-core/tests/video_checksum.c ++++ b/grub-core/tests/video_checksum.c +@@ -336,7 +336,7 @@ grub_video_capture_write_bmp (const char *fname, + { + case 4: + { +- grub_uint8_t *buffer = xmalloc (mode_info->width * 3); ++ grub_uint8_t *buffer = xcalloc (3, mode_info->width); + grub_uint32_t rmask = ((1 << mode_info->red_mask_size) - 1); + grub_uint32_t gmask = ((1 << mode_info->green_mask_size) - 1); + grub_uint32_t bmask = ((1 << mode_info->blue_mask_size) - 1); +@@ -367,7 +367,7 @@ grub_video_capture_write_bmp (const char *fname, + } + case 3: + { +- grub_uint8_t *buffer = xmalloc (mode_info->width * 3); ++ grub_uint8_t *buffer = xcalloc (3, mode_info->width); + grub_uint32_t rmask = ((1 << mode_info->red_mask_size) - 1); + grub_uint32_t gmask = ((1 << mode_info->green_mask_size) - 1); + grub_uint32_t bmask = ((1 << mode_info->blue_mask_size) - 1); +@@ -407,7 +407,7 @@ grub_video_capture_write_bmp (const char *fname, + } + case 2: + { +- grub_uint8_t *buffer = xmalloc (mode_info->width * 3); ++ grub_uint8_t *buffer = xcalloc (3, mode_info->width); + grub_uint16_t rmask = ((1 << mode_info->red_mask_size) - 1); + grub_uint16_t gmask = ((1 << mode_info->green_mask_size) - 1); + grub_uint16_t bmask = ((1 << mode_info->blue_mask_size) - 1); +diff --git a/grub-core/video/capture.c b/grub-core/video/capture.c +index 4f83c744116..4d3195e017b 100644 +--- a/grub-core/video/capture.c ++++ b/grub-core/video/capture.c +@@ -89,7 +89,7 @@ grub_video_capture_start (const struct grub_video_mode_info *mode_info, + framebuffer.mode_info = *mode_info; + framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); + +- framebuffer.ptr = grub_malloc (framebuffer.mode_info.height * framebuffer.mode_info.pitch); ++ framebuffer.ptr = grub_calloc (framebuffer.mode_info.height, framebuffer.mode_info.pitch); + if (!framebuffer.ptr) + return grub_errno; + +diff --git a/grub-core/video/emu/sdl.c b/grub-core/video/emu/sdl.c +index a2f639f66de..0ebab6f57dd 100644 +--- a/grub-core/video/emu/sdl.c ++++ b/grub-core/video/emu/sdl.c +@@ -172,7 +172,7 @@ grub_video_sdl_set_palette (unsigned int start, unsigned int count, + if (start + count > mode_info.number_of_colors) + count = mode_info.number_of_colors - start; + +- tmp = grub_malloc (count * sizeof (tmp[0])); ++ tmp = grub_calloc (count, sizeof (tmp[0])); + for (i = 0; i < count; i++) + { + tmp[i].r = palette_data[i].r; +diff --git a/grub-core/video/i386/pc/vga.c b/grub-core/video/i386/pc/vga.c +index 01f47112d37..b2f776c997b 100644 +--- a/grub-core/video/i386/pc/vga.c ++++ b/grub-core/video/i386/pc/vga.c +@@ -127,7 +127,7 @@ grub_video_vga_setup (unsigned int width, unsigned int height, + + vga_height = height ? : 480; + +- framebuffer.temporary_buffer = grub_malloc (vga_height * VGA_WIDTH); ++ framebuffer.temporary_buffer = grub_calloc (vga_height, VGA_WIDTH); + framebuffer.front_page = 0; + framebuffer.back_page = 0; + if (!framebuffer.temporary_buffer) +diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c +index 1f03f88d396..0a1c6584dd3 100644 +--- a/grub-core/video/readers/png.c ++++ b/grub-core/video/readers/png.c +@@ -309,7 +309,7 @@ grub_png_decode_image_header (struct grub_png_data *data) + if (data->is_16bit || data->is_gray || data->is_palette) + #endif + { +- data->image_data = grub_malloc (data->image_height * data->row_bytes); ++ data->image_data = grub_calloc (data->image_height, data->row_bytes); + if (grub_errno) + return grub_errno; + +diff --git a/util/getroot.c b/util/getroot.c +index e70061099b3..f523c63b933 100644 +--- a/util/getroot.c ++++ b/util/getroot.c +@@ -218,7 +218,7 @@ make_device_name (const char *drive) + char *ret, *ptr; + const char *iptr; + +- ret = xmalloc (strlen (drive) * 2); ++ ret = xcalloc (2, strlen (drive)); + ptr = ret; + for (iptr = drive; *iptr; iptr++) + { +diff --git a/util/grub-file.c b/util/grub-file.c +index 9989dfe7b6b..6f4ca6c2091 100644 +--- a/util/grub-file.c ++++ b/util/grub-file.c +@@ -54,7 +54,7 @@ main (int argc, char *argv[]) + + grub_util_host_init (&argc, &argv); + +- argv2 = xmalloc (argc * sizeof (argv2[0])); ++ argv2 = xcalloc (argc, sizeof (argv2[0])); + + if (argc == 2 && strcmp (argv[1], "--version") == 0) + { +diff --git a/util/grub-fstest.c b/util/grub-fstest.c +index 31af2a7ad9c..77f12ca93ce 100644 +--- a/util/grub-fstest.c ++++ b/util/grub-fstest.c +@@ -734,7 +734,7 @@ main (int argc, char *argv[]) + + grub_util_host_init (&argc, &argv); + +- args = xmalloc (argc * sizeof (args[0])); ++ args = xcalloc (argc, sizeof (args[0])); + + argp_parse (&argp, argc, argv, 0, 0, 0); + +diff --git a/util/grub-install-common.c b/util/grub-install-common.c +index c8bedcb2e59..d49a93d4740 100644 +--- a/util/grub-install-common.c ++++ b/util/grub-install-common.c +@@ -280,7 +280,7 @@ handle_install_list (struct install_list *il, const char *val, + il->n_entries++; + } + il->n_alloc = il->n_entries + 1; +- il->entries = xmalloc (il->n_alloc * sizeof (il->entries[0])); ++ il->entries = xcalloc (il->n_alloc, sizeof (il->entries[0])); + ptr = val; + for (ce = il->entries; ; ce++) + { +diff --git a/util/grub-install.c b/util/grub-install.c +index 947a2d2ddf5..28132b66bea 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -624,6 +624,8 @@ device_map_check_duplicates (const char *dev_map) + if (! fp) + return; + ++ d = xcalloc (alloced, sizeof (d[0])); ++ + while (fgets (buf, sizeof (buf), fp)) + { + char *p = buf; +@@ -1224,7 +1226,7 @@ main (int argc, char *argv[]) + ndev++; + } + +- grub_drives = xmalloc (sizeof (grub_drives[0]) * (ndev + 1)); ++ grub_drives = xcalloc (ndev + 1, sizeof (grub_drives[0])); + + for (curdev = grub_devices, curdrive = grub_drives; *curdev; curdev++, + curdrive++) +diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c +index d1bc95e350d..b03a6089905 100644 +--- a/util/grub-mkimagexx.c ++++ b/util/grub-mkimagexx.c +@@ -1375,7 +1375,7 @@ SUFFIX (locate_sections) (const char *kernel_path, + if (image_target->elf_target == EM_AARCH64) + *all_align = 4096; + +- section_addresses = xmalloc (sizeof (*section_addresses) * num_sections); ++ section_addresses = xcalloc (num_sections, sizeof (*section_addresses)); + memset (section_addresses, 0, sizeof (*section_addresses) * num_sections); + + current_address = 0; +@@ -1512,7 +1512,7 @@ SUFFIX (load_image) (const char *kernel_path, size_t *exec_size, + exec_size, kernel_sz, align, + image_target); + +- section_vaddresses = xmalloc (sizeof (*section_addresses) * num_sections); ++ section_vaddresses = xcalloc (num_sections, sizeof (*section_addresses)); + + for (i = 0; i < num_sections; i++) + section_vaddresses[i] = section_addresses[i] + image_target->vaddr_offset; +diff --git a/util/grub-mkstandalone.c b/util/grub-mkstandalone.c +index 8e2a2b8c27a..1d6edcf3315 100644 +--- a/util/grub-mkstandalone.c ++++ b/util/grub-mkstandalone.c +@@ -295,7 +295,7 @@ main (int argc, char *argv[]) + grub_util_host_init (&argc, &argv); + grub_util_disable_fd_syncs (); + +- files = xmalloc ((argc + 1) * sizeof (files[0])); ++ files = xcalloc (argc + 1, sizeof (files[0])); + + argp_parse (&argp, argc, argv, 0, 0, 0); + +diff --git a/util/grub-pe2elf.c b/util/grub-pe2elf.c +index f4abf70a3f3..bc326eb91c6 100644 +--- a/util/grub-pe2elf.c ++++ b/util/grub-pe2elf.c +@@ -100,9 +100,9 @@ write_section_data (FILE* fp, const char *name, char *image, + char *pe_strtab = (image + pe_chdr->symtab_offset + + pe_chdr->num_symbols * sizeof (struct grub_pe32_symbol)); + +- section_map = xmalloc ((2 * pe_chdr->num_sections + 5) * sizeof (int)); ++ section_map = xcalloc (2 * pe_chdr->num_sections + 5, sizeof (int)); + section_map[0] = 0; +- shdr = xmalloc ((2 * pe_chdr->num_sections + 5) * sizeof (shdr[0])); ++ shdr = xcalloc (2 * pe_chdr->num_sections + 5, sizeof (shdr[0])); + idx = 1; + idx_reloc = pe_chdr->num_sections + 1; + +@@ -233,7 +233,7 @@ write_reloc_section (FILE* fp, const char *name, char *image, + + pe_sec = pe_shdr + shdr[i].sh_link; + pe_rel = (struct grub_pe32_reloc *) (image + pe_sec->relocations_offset); +- rel = (elf_reloc_t *) xmalloc (pe_sec->num_relocations * sizeof (elf_reloc_t)); ++ rel = (elf_reloc_t *) xcalloc (pe_sec->num_relocations, sizeof (elf_reloc_t)); + num_rels = 0; + modified = 0; + +@@ -365,12 +365,10 @@ write_symbol_table (FILE* fp, const char *name, char *image, + pe_symtab = (struct grub_pe32_symbol *) (image + pe_chdr->symtab_offset); + pe_strtab = (char *) (pe_symtab + pe_chdr->num_symbols); + +- symtab = (Elf_Sym *) xmalloc ((pe_chdr->num_symbols + 1) * +- sizeof (Elf_Sym)); +- memset (symtab, 0, (pe_chdr->num_symbols + 1) * sizeof (Elf_Sym)); ++ symtab = (Elf_Sym *) xcalloc (pe_chdr->num_symbols + 1, sizeof (Elf_Sym)); + num_syms = 1; + +- symtab_map = (int *) xmalloc (pe_chdr->num_symbols * sizeof (int)); ++ symtab_map = (int *) xcalloc (pe_chdr->num_symbols, sizeof (int)); + + for (i = 0; i < (int) pe_chdr->num_symbols; + i += pe_symtab->num_aux + 1, pe_symtab += pe_symtab->num_aux + 1) +diff --git a/util/grub-probe.c b/util/grub-probe.c +index ecb7b6bbdf2..731b61df89b 100644 +--- a/util/grub-probe.c ++++ b/util/grub-probe.c +@@ -304,8 +304,8 @@ probe (const char *path, char **device_names, char delim) + grub_util_pull_device (*curdev); + ndev++; + } +- +- drives_names = xmalloc (sizeof (drives_names[0]) * (ndev + 1)); ++ ++ drives_names = xcalloc (ndev + 1, sizeof (drives_names[0])); + + for (curdev = device_names, curdrive = drives_names; *curdev; curdev++, + curdrive++) +diff --git a/include/grub/unicode.h b/include/grub/unicode.h +index a0403e91f9a..4de986a8576 100644 +--- a/include/grub/unicode.h ++++ b/include/grub/unicode.h +@@ -293,7 +293,7 @@ grub_unicode_glyph_dup (const struct grub_unicode_glyph *in) + grub_memcpy (out, in, sizeof (*in)); + if (in->ncomb > ARRAY_SIZE (out->combining_inline)) + { +- out->combining_ptr = grub_malloc (in->ncomb * sizeof (out->combining_ptr[0])); ++ out->combining_ptr = grub_calloc (in->ncomb, sizeof (out->combining_ptr[0])); + if (!out->combining_ptr) + { + grub_free (out); +@@ -315,7 +315,7 @@ grub_unicode_set_glyph (struct grub_unicode_glyph *out, + grub_memcpy (out, in, sizeof (*in)); + if (in->ncomb > ARRAY_SIZE (out->combining_inline)) + { +- out->combining_ptr = grub_malloc (in->ncomb * sizeof (out->combining_ptr[0])); ++ out->combining_ptr = grub_calloc (in->ncomb, sizeof (out->combining_ptr[0])); + if (!out->combining_ptr) + return; + grub_memcpy (out->combining_ptr, in->combining_ptr, +-- +2.26.2 + diff --git a/SOURCES/0303-malloc-Use-overflow-checking-primitives-where-we-do-.patch b/SOURCES/0303-malloc-Use-overflow-checking-primitives-where-we-do-.patch new file mode 100644 index 0000000..725fc84 --- /dev/null +++ b/SOURCES/0303-malloc-Use-overflow-checking-primitives-where-we-do-.patch @@ -0,0 +1,1330 @@ +From 27fe6083630c57641231d2056220288135b111ef Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 15 Jun 2020 12:28:27 -0400 +Subject: [PATCH 303/336] malloc: Use overflow checking primitives where we do + complex allocations + +This attempts to fix the places where we do the following where +arithmetic_expr may include unvalidated data: + + X = grub_malloc(arithmetic_expr); + +It accomplishes this by doing the arithmetic ahead of time using grub_add(), +grub_sub(), grub_mul() and testing for overflow before proceeding. + +Among other issues, this fixes: + - allocation of integer overflow in grub_video_bitmap_create() + reported by Chris Coulson, + - allocation of integer overflow in grub_png_decode_image_header() + reported by Chris Coulson, + - allocation of integer overflow in grub_squash_read_symlink() + reported by Chris Coulson, + - allocation of integer overflow in grub_ext2_read_symlink() + reported by Chris Coulson, + - allocation of integer overflow in read_section_as_string() + reported by Chris Coulson. + +Fixes: CVE-2020-14309, CVE-2020-14310, CVE-2020-14311 + +Signed-off-by: Peter Jones +Reviewed-by: Daniel Kiper +Upstream-commit-id: 5fb2befbf04 +--- + grub-core/commands/legacycfg.c | 29 ++++++++++++++---- + grub-core/commands/wildcard.c | 36 ++++++++++++++++++---- + grub-core/disk/ldm.c | 32 ++++++++++++++------ + grub-core/font/font.c | 7 ++++- + grub-core/fs/btrfs.c | 29 ++++++++++++------ + grub-core/fs/ext2.c | 10 ++++++- + grub-core/fs/iso9660.c | 55 +++++++++++++++++++++++----------- + grub-core/fs/sfs.c | 27 +++++++++++++---- + grub-core/fs/squash4.c | 45 +++++++++++++++++++++------- + grub-core/fs/udf.c | 42 +++++++++++++++++--------- + grub-core/fs/xfs.c | 11 ++++--- + grub-core/fs/zfs/zfs.c | 22 +++++++++----- + grub-core/fs/zfs/zfscrypt.c | 7 ++++- + grub-core/lib/arg.c | 20 +++++++++++-- + grub-core/loader/i386/bsd.c | 8 ++++- + grub-core/net/dns.c | 9 +++++- + grub-core/normal/charset.c | 10 +++++-- + grub-core/normal/cmdline.c | 14 +++++++-- + grub-core/normal/menu_entry.c | 14 +++++++-- + grub-core/script/argv.c | 16 ++++++++-- + grub-core/script/lexer.c | 21 +++++++++++-- + grub-core/video/bitmap.c | 25 ++++++++++------ + grub-core/video/readers/png.c | 13 ++++++-- + 23 files changed, 387 insertions(+), 115 deletions(-) + +diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c +index d1127fa8968..155357a51d0 100644 +--- a/grub-core/commands/legacycfg.c ++++ b/grub-core/commands/legacycfg.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -97,13 +98,22 @@ legacy_file (const char *filename) + if (newsuffix) + { + char *t; +- ++ grub_size_t sz; ++ ++ if (grub_add (grub_strlen (suffix), grub_strlen (newsuffix), &sz) || ++ grub_add (sz, 1, &sz)) ++ { ++ grub_errno = GRUB_ERR_OUT_OF_RANGE; ++ goto fail_0; ++ } ++ + t = suffix; +- suffix = grub_realloc (suffix, grub_strlen (suffix) +- + grub_strlen (newsuffix) + 1); ++ suffix = grub_realloc (suffix, sz); + if (!suffix) + { + grub_free (t); ++ ++ fail_0: + grub_free (entrysrc); + grub_free (parsed); + grub_free (newsuffix); +@@ -147,13 +157,22 @@ legacy_file (const char *filename) + else + { + char *t; ++ grub_size_t sz; ++ ++ if (grub_add (grub_strlen (entrysrc), grub_strlen (parsed), &sz) || ++ grub_add (sz, 1, &sz)) ++ { ++ grub_errno = GRUB_ERR_OUT_OF_RANGE; ++ goto fail_1; ++ } + + t = entrysrc; +- entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc) +- + grub_strlen (parsed) + 1); ++ entrysrc = grub_realloc (entrysrc, sz); + if (!entrysrc) + { + grub_free (t); ++ ++ fail_1: + grub_free (parsed); + grub_free (suffix); + return grub_errno; +diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c +index 0f40e041541..2383e0f99c7 100644 +--- a/grub-core/commands/wildcard.c ++++ b/grub-core/commands/wildcard.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + #include + +@@ -48,6 +49,7 @@ merge (char **dest, char **ps) + int i; + int j; + char **p; ++ grub_size_t sz; + + if (! dest) + return ps; +@@ -60,7 +62,12 @@ merge (char **dest, char **ps) + for (j = 0; ps[j]; j++) + ; + +- p = grub_realloc (dest, sizeof (char*) * (i + j + 1)); ++ if (grub_add (i, j, &sz) || ++ grub_add (sz, 1, &sz) || ++ grub_mul (sz, sizeof (char *), &sz)) ++ return dest; ++ ++ p = grub_realloc (dest, sz); + if (! p) + { + grub_free (dest); +@@ -115,8 +122,15 @@ make_regex (const char *start, const char *end, regex_t *regexp) + char ch; + int i = 0; + unsigned len = end - start; +- char *buffer = grub_malloc (len * 2 + 2 + 1); /* worst case size. */ ++ char *buffer; ++ grub_size_t sz; + ++ /* Worst case size is (len * 2 + 2 + 1). */ ++ if (grub_mul (len, 2, &sz) || ++ grub_add (sz, 3, &sz)) ++ return 1; ++ ++ buffer = grub_malloc (sz); + if (! buffer) + return 1; + +@@ -226,6 +240,7 @@ match_devices_iter (const char *name, void *data) + struct match_devices_ctx *ctx = data; + char **t; + char *buffer; ++ grub_size_t sz; + + /* skip partitions if asked to. */ + if (ctx->noparts && grub_strchr (name, ',')) +@@ -239,11 +254,16 @@ match_devices_iter (const char *name, void *data) + if (regexec (ctx->regexp, buffer, 0, 0, 0)) + { + grub_dprintf ("expand", "not matched\n"); ++ fail: + grub_free (buffer); + return 0; + } + +- t = grub_realloc (ctx->devs, sizeof (char*) * (ctx->ndev + 2)); ++ if (grub_add (ctx->ndev, 2, &sz) || ++ grub_mul (sz, sizeof (char *), &sz)) ++ goto fail; ++ ++ t = grub_realloc (ctx->devs, sz); + if (! t) + return 1; + +@@ -296,6 +316,7 @@ match_files_iter (const char *name, const struct grub_dirhook_info *info, + struct match_files_ctx *ctx = data; + char **t; + char *buffer; ++ grub_size_t sz; + + /* skip . and .. names */ + if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0) +@@ -311,9 +332,14 @@ match_files_iter (const char *name, const struct grub_dirhook_info *info, + if (! buffer) + return 1; + +- t = grub_realloc (ctx->files, sizeof (char*) * (ctx->nfile + 2)); +- if (! t) ++ if (grub_add (ctx->nfile, 2, &sz) || ++ grub_mul (sz, sizeof (char *), &sz)) ++ goto fail; ++ ++ t = grub_realloc (ctx->files, sz); ++ if (!t) + { ++ fail: + grub_free (buffer); + return 1; + } +diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c +index 97a482705d0..b1a57f2d2ad 100644 +--- a/grub-core/disk/ldm.c ++++ b/grub-core/disk/ldm.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #ifdef GRUB_UTIL + #include +@@ -289,6 +290,7 @@ make_vg (grub_disk_t disk, + struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE + / sizeof (struct grub_ldm_vblk)]; + unsigned i; ++ grub_size_t sz; + err = grub_disk_read (disk, cursec, 0, + sizeof(vblk), &vblk); + if (err) +@@ -350,7 +352,13 @@ make_vg (grub_disk_t disk, + grub_free (lv); + goto fail2; + } +- lv->name = grub_malloc (*ptr + 1); ++ if (grub_add (*ptr, 1, &sz)) ++ { ++ grub_free (lv->internal_id); ++ grub_free (lv); ++ goto fail2; ++ } ++ lv->name = grub_malloc (sz); + if (!lv->name) + { + grub_free (lv->internal_id); +@@ -599,10 +607,13 @@ make_vg (grub_disk_t disk, + if (lv->segments->node_alloc == lv->segments->node_count) + { + void *t; +- lv->segments->node_alloc *= 2; +- t = grub_realloc (lv->segments->nodes, +- sizeof (*lv->segments->nodes) +- * lv->segments->node_alloc); ++ grub_size_t sz; ++ ++ if (grub_mul (lv->segments->node_alloc, 2, &lv->segments->node_alloc) || ++ grub_mul (lv->segments->node_alloc, sizeof (*lv->segments->nodes), &sz)) ++ goto fail2; ++ ++ t = grub_realloc (lv->segments->nodes, sz); + if (!t) + goto fail2; + lv->segments->nodes = t; +@@ -723,10 +734,13 @@ make_vg (grub_disk_t disk, + if (comp->segment_alloc == comp->segment_count) + { + void *t; +- comp->segment_alloc *= 2; +- t = grub_realloc (comp->segments, +- comp->segment_alloc +- * sizeof (*comp->segments)); ++ grub_size_t sz; ++ ++ if (grub_mul (comp->segment_alloc, 2, &comp->segment_alloc) || ++ grub_mul (comp->segment_alloc, sizeof (*comp->segments), &sz)) ++ goto fail2; ++ ++ t = grub_realloc (comp->segments, sz); + if (!t) + goto fail2; + comp->segments = t; +diff --git a/grub-core/font/font.c b/grub-core/font/font.c +index b5f43d992a4..71d3f78b88a 100644 +--- a/grub-core/font/font.c ++++ b/grub-core/font/font.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -360,9 +361,13 @@ static char * + read_section_as_string (struct font_file_section *section) + { + char *str; ++ grub_size_t sz; + grub_ssize_t ret; + +- str = grub_malloc (section->length + 1); ++ if (grub_add (section->length, 1, &sz)) ++ return NULL; ++ ++ str = grub_malloc (sz); + if (!str) + return 0; + +diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c +index db57875f490..fb5ab2b3deb 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -292,9 +293,13 @@ save_ref (struct grub_btrfs_leaf_descriptor *desc, + if (desc->allocated < desc->depth) + { + void *newdata; +- desc->allocated *= 2; +- newdata = grub_realloc (desc->data, sizeof (desc->data[0]) +- * desc->allocated); ++ grub_size_t sz; ++ ++ if (grub_mul (desc->allocated, 2, &desc->allocated) || ++ grub_mul (desc->allocated, sizeof (desc->data[0]), &sz)) ++ return GRUB_ERR_OUT_OF_RANGE; ++ ++ newdata = grub_realloc (desc->data, sz); + if (!newdata) + return grub_errno; + desc->data = newdata; +@@ -589,15 +594,21 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan) + if (data->n_devices_attached > data->n_devices_allocated) + { + void *tmp; +- data->n_devices_allocated = 2 * data->n_devices_attached + 1; +- data->devices_attached +- = grub_realloc (tmp = data->devices_attached, +- data->n_devices_allocated +- * sizeof (data->devices_attached[0])); ++ grub_size_t sz; ++ ++ 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)) ++ goto fail; ++ ++ data->devices_attached = grub_realloc (tmp = data->devices_attached, sz); + if (!data->devices_attached) + { +- grub_device_close (ctx.dev_found); + data->devices_attached = tmp; ++ ++ fail: ++ if (ctx.dev_found) ++ grub_device_close (ctx.dev_found); + return NULL; + } + } +diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c +index 5f7a2b9d5bd..2fda8d09caa 100644 +--- a/grub-core/fs/ext2.c ++++ b/grub-core/fs/ext2.c +@@ -46,6 +46,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -631,6 +632,7 @@ grub_ext2_read_symlink (grub_fshelp_node_t node) + { + char *symlink; + struct grub_fshelp_node *diro = node; ++ grub_size_t sz; + + if (! diro->inode_read) + { +@@ -639,7 +641,13 @@ grub_ext2_read_symlink (grub_fshelp_node_t node) + return 0; + } + +- symlink = grub_malloc (grub_le_to_cpu32 (diro->inode.size) + 1); ++ if (grub_add (grub_le_to_cpu32 (diro->inode.size), 1, &sz)) ++ { ++ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); ++ return NULL; ++ } ++ ++ symlink = grub_malloc (sz); + if (! symlink) + return 0; + +diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c +index 2fe433ceb54..d6dc55b5803 100644 +--- a/grub-core/fs/iso9660.c ++++ b/grub-core/fs/iso9660.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -528,11 +529,16 @@ struct iterate_dir_ctx + static void + add_part (struct iterate_dir_ctx *ctx, + const char *part, +- int len2) ++ grub_size_t len2) + { +- int size = ctx->symlink ? grub_strlen (ctx->symlink) : 0; ++ grub_size_t size = ctx->symlink ? grub_strlen (ctx->symlink) : 0; ++ grub_size_t sz; + +- ctx->symlink = grub_realloc (ctx->symlink, size + len2 + 1); ++ if (grub_add (size, len2, &sz) || ++ grub_add (sz, 1, &sz)) ++ return; ++ ++ ctx->symlink = grub_realloc (ctx->symlink, sz); + if (! ctx->symlink) + return; + +@@ -560,17 +566,24 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry, + { + grub_size_t off = 0, csize = 1; + char *old; ++ grub_size_t sz; ++ + csize = entry->len - 5; + old = ctx->filename; + if (ctx->filename_alloc) + { + off = grub_strlen (ctx->filename); +- ctx->filename = grub_realloc (ctx->filename, csize + off + 1); ++ if (grub_add (csize, off, &sz) || ++ grub_add (sz, 1, &sz)) ++ return GRUB_ERR_OUT_OF_RANGE; ++ ctx->filename = grub_realloc (ctx->filename, sz); + } + else + { + off = 0; +- ctx->filename = grub_zalloc (csize + 1); ++ if (grub_add (csize, 1, &sz)) ++ return GRUB_ERR_OUT_OF_RANGE; ++ ctx->filename = grub_zalloc (sz); + } + if (!ctx->filename) + { +@@ -780,14 +793,18 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, + if (node->have_dirents >= node->alloc_dirents) + { + struct grub_fshelp_node *new_node; +- node->alloc_dirents *= 2; +- new_node = grub_realloc (node, +- sizeof (struct grub_fshelp_node) +- + ((node->alloc_dirents +- - ARRAY_SIZE (node->dirents)) +- * sizeof (node->dirents[0]))); ++ grub_size_t sz; ++ ++ if (grub_mul (node->alloc_dirents, 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)) ++ goto fail_0; ++ ++ new_node = grub_realloc (node, sz); + if (!new_node) + { ++ fail_0: + if (ctx.filename_alloc) + grub_free (ctx.filename); + grub_free (node); +@@ -803,14 +820,18 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, + * sizeof (node->dirents[0]) < grub_strlen (ctx.symlink) + 1) + { + struct grub_fshelp_node *new_node; +- new_node = grub_realloc (node, +- sizeof (struct grub_fshelp_node) +- + ((node->alloc_dirents +- - ARRAY_SIZE (node->dirents)) +- * sizeof (node->dirents[0])) +- + grub_strlen (ctx.symlink) + 1); ++ grub_size_t sz; ++ ++ if (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) + 1, &sz) || ++ grub_add (sz, grub_strlen (ctx.symlink), &sz)) ++ goto fail_1; ++ ++ new_node = grub_realloc (node, sz); + if (!new_node) + { ++ fail_1: + if (ctx.filename_alloc) + grub_free (ctx.filename); + grub_free (node); +diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c +index 754cad880f5..4f68808a891 100644 +--- a/grub-core/fs/sfs.c ++++ b/grub-core/fs/sfs.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -302,10 +303,15 @@ grub_sfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + if (node->cache && node->cache_size >= node->cache_allocated) + { + struct cache_entry *e = node->cache; +- e = grub_realloc (node->cache,node->cache_allocated * 2 +- * sizeof (e[0])); ++ grub_size_t sz; ++ ++ if (grub_mul (node->cache_allocated, 2 * sizeof (e[0]), &sz)) ++ goto fail; ++ ++ e = grub_realloc (node->cache, sz); + if (!e) + { ++ fail: + grub_errno = 0; + grub_free (node->cache); + node->cache = 0; +@@ -472,10 +478,16 @@ grub_sfs_create_node (struct grub_fshelp_node **node, + grub_size_t len = grub_strlen (name); + grub_uint8_t *name_u8; + int ret; ++ grub_size_t sz; ++ ++ if (grub_mul (len, GRUB_MAX_UTF8_PER_LATIN1, &sz) || ++ grub_add (sz, 1, &sz)) ++ return 1; ++ + *node = grub_malloc (sizeof (**node)); + if (!*node) + return 1; +- name_u8 = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); ++ name_u8 = grub_malloc (sz); + if (!name_u8) + { + grub_free (*node); +@@ -719,8 +731,13 @@ grub_sfs_label (grub_device_t device, char **label) + data = grub_sfs_mount (disk); + if (data) + { +- grub_size_t len = grub_strlen (data->label); +- *label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); ++ grub_size_t sz, len = grub_strlen (data->label); ++ ++ if (grub_mul (len, GRUB_MAX_UTF8_PER_LATIN1, &sz) || ++ grub_add (sz, 1, &sz)) ++ return GRUB_ERR_OUT_OF_RANGE; ++ ++ *label = grub_malloc (sz); + if (*label) + *grub_latin1_to_utf8 ((grub_uint8_t *) *label, + (const grub_uint8_t *) data->label, +diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c +index b97b34440ed..d9d87ee35c7 100644 +--- a/grub-core/fs/squash4.c ++++ b/grub-core/fs/squash4.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + + #include "xz.h" +@@ -459,7 +460,17 @@ grub_squash_read_symlink (grub_fshelp_node_t node) + { + char *ret; + grub_err_t err; +- ret = grub_malloc (grub_le_to_cpu32 (node->ino.symlink.namelen) + 1); ++ grub_size_t sz; ++ ++ if (grub_add (grub_le_to_cpu32 (node->ino.symlink.namelen), 1, &sz)) ++ { ++ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); ++ return NULL; ++ } ++ ++ ret = grub_malloc (sz); ++ if (!ret) ++ return NULL; + + err = read_chunk (node->data, ret, + grub_le_to_cpu32 (node->ino.symlink.namelen), +@@ -506,11 +517,16 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, + + { + grub_fshelp_node_t node; +- node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); ++ grub_size_t sz; ++ ++ if (grub_mul (dir->stsize, sizeof (dir->stack[0]), &sz) || ++ grub_add (sz, sizeof (*node), &sz)) ++ return 0; ++ ++ node = grub_malloc (sz); + if (!node) + return 0; +- grub_memcpy (node, dir, +- sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); ++ grub_memcpy (node, dir, sz); + if (hook (".", GRUB_FSHELP_DIR, node, hook_data)) + return 1; + +@@ -518,12 +534,15 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, + { + grub_err_t err; + +- node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); ++ if (grub_mul (dir->stsize, sizeof (dir->stack[0]), &sz) || ++ grub_add (sz, sizeof (*node), &sz)) ++ return 0; ++ ++ node = grub_malloc (sz); + if (!node) + return 0; + +- grub_memcpy (node, dir, +- sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); ++ grub_memcpy (node, dir, sz); + + node->stsize--; + err = read_chunk (dir->data, &node->ino, sizeof (node->ino), +@@ -557,6 +576,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, + enum grub_fshelp_filetype filetype = GRUB_FSHELP_REG; + struct grub_squash_dirent di; + struct grub_squash_inode ino; ++ grub_size_t sz; + + err = read_chunk (dir->data, &di, sizeof (di), + grub_le_to_cpu64 (dir->data->sb.diroffset) +@@ -589,13 +609,16 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, + if (grub_le_to_cpu16 (di.type) == SQUASH_TYPE_SYMLINK) + filetype = GRUB_FSHELP_SYMLINK; + +- node = grub_malloc (sizeof (*node) +- + (dir->stsize + 1) * sizeof (dir->stack[0])); ++ if (grub_add (dir->stsize, 1, &sz) || ++ grub_mul (sz, sizeof (dir->stack[0]), &sz) || ++ grub_add (sz, sizeof (*node), &sz)) ++ return 0; ++ ++ node = grub_malloc (sz); + if (! node) + return 0; + +- grub_memcpy (node, dir, +- sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); ++ grub_memcpy (node, dir, sz - sizeof(dir->stack[0])); + + node->ino = ino; + node->stack[node->stsize].ino_chunk = grub_le_to_cpu32 (dh.ino_chunk); +diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c +index 488f35a3ee5..99b001f2066 100644 +--- a/grub-core/fs/udf.c ++++ b/grub-core/fs/udf.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -853,9 +854,19 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf) + utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; + } + if (!outbuf) +- outbuf = grub_malloc (utf16len * GRUB_MAX_UTF8_PER_UTF16 + 1); ++ { ++ grub_size_t size; ++ ++ if (grub_mul (utf16len, GRUB_MAX_UTF8_PER_UTF16, &size) || ++ grub_add (size, 1, &size)) ++ goto fail; ++ ++ outbuf = grub_malloc (size); ++ } + if (outbuf) + *grub_utf16_to_utf8 ((grub_uint8_t *) outbuf, utf16, utf16len) = '\0'; ++ ++ fail: + grub_free (utf16); + return outbuf; + } +@@ -949,7 +960,7 @@ grub_udf_read_symlink (grub_fshelp_node_t node) + grub_size_t sz = U64 (node->block.fe.file_size); + grub_uint8_t *raw; + const grub_uint8_t *ptr; +- char *out, *optr; ++ char *out = NULL, *optr; + + if (sz < 4) + return NULL; +@@ -957,14 +968,16 @@ grub_udf_read_symlink (grub_fshelp_node_t node) + if (!raw) + return NULL; + if (grub_udf_read_file (node, NULL, NULL, 0, sz, (char *) raw) < 0) +- { +- grub_free (raw); +- return NULL; +- } ++ goto fail_1; + +- out = grub_malloc (sz * 2 + 1); ++ if (grub_mul (sz, 2, &sz) || ++ grub_add (sz, 1, &sz)) ++ goto fail_0; ++ ++ out = grub_malloc (sz); + if (!out) + { ++ fail_0: + grub_free (raw); + return NULL; + } +@@ -975,17 +988,18 @@ grub_udf_read_symlink (grub_fshelp_node_t node) + { + grub_size_t s; + if ((grub_size_t) (ptr - raw + 4) > sz) +- goto fail; ++ goto fail_1; + if (!(ptr[2] == 0 && ptr[3] == 0)) +- goto fail; ++ goto fail_1; + s = 4 + ptr[1]; + if ((grub_size_t) (ptr - raw + s) > sz) +- goto fail; ++ goto fail_1; + switch (*ptr) + { + case 1: + if (ptr[1]) +- goto fail; ++ goto fail_1; ++ /* Fallthrough. */ + case 2: + /* in 4 bytes. out: 1 byte. */ + optr = out; +@@ -1009,11 +1023,11 @@ grub_udf_read_symlink (grub_fshelp_node_t node) + if (optr != out) + *optr++ = '/'; + if (!read_string (ptr + 4, s - 4, optr)) +- goto fail; ++ goto fail_1; + optr += grub_strlen (optr); + break; + default: +- goto fail; ++ goto fail_1; + } + ptr += s; + } +@@ -1021,7 +1035,7 @@ grub_udf_read_symlink (grub_fshelp_node_t node) + grub_free (raw); + return out; + +- fail: ++ fail_1: + grub_free (raw); + grub_free (out); + grub_error (GRUB_ERR_BAD_FS, "invalid symlink"); +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 852155b1bf3..c2d1a587929 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -863,6 +864,7 @@ static struct grub_xfs_data * + grub_xfs_mount (grub_disk_t disk) + { + struct grub_xfs_data *data = 0; ++ grub_size_t sz; + + data = grub_zalloc (sizeof (struct grub_xfs_data)); + if (!data) +@@ -877,10 +879,11 @@ grub_xfs_mount (grub_disk_t disk) + if (!grub_xfs_sb_valid(data)) + goto fail; + +- data = grub_realloc (data, +- sizeof (struct grub_xfs_data) +- - sizeof (struct grub_xfs_inode) +- + grub_xfs_inode_size(data) + 1); ++ if (grub_add (grub_xfs_inode_size (data), ++ sizeof (struct grub_xfs_data) - sizeof (struct grub_xfs_inode) + 1, &sz)) ++ goto fail; ++ ++ data = grub_realloc (data, sz); + + if (! data) + goto fail; +diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c +index 3d7351de37c..6fd21f975f5 100644 +--- a/grub-core/fs/zfs/zfs.c ++++ b/grub-core/fs/zfs/zfs.c +@@ -55,6 +55,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -769,11 +770,14 @@ fill_vdev_info (struct grub_zfs_data *data, + if (data->n_devices_attached > data->n_devices_allocated) + { + void *tmp; +- data->n_devices_allocated = 2 * data->n_devices_attached + 1; +- data->devices_attached +- = grub_realloc (tmp = data->devices_attached, +- data->n_devices_allocated +- * sizeof (data->devices_attached[0])); ++ grub_size_t sz; ++ ++ 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)) ++ return GRUB_ERR_OUT_OF_RANGE; ++ ++ data->devices_attached = grub_realloc (tmp = data->devices_attached, sz); + if (!data->devices_attached) + { + data->devices_attached = tmp; +@@ -3396,14 +3400,18 @@ grub_zfs_nvlist_lookup_nvlist (const char *nvlist, const char *name) + { + char *nvpair; + char *ret; +- grub_size_t size; ++ grub_size_t size, sz; + int found; + + found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair, + &size, 0); + if (!found) + return 0; +- ret = grub_zalloc (size + 3 * sizeof (grub_uint32_t)); ++ ++ if (grub_add (size, 3 * sizeof (grub_uint32_t), &sz)) ++ return 0; ++ ++ ret = grub_zalloc (sz); + if (!ret) + return 0; + grub_memcpy (ret, nvlist, sizeof (grub_uint32_t)); +diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c +index 88dae72efc4..6b98f3de98f 100644 +--- a/grub-core/fs/zfs/zfscrypt.c ++++ b/grub-core/fs/zfs/zfscrypt.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -82,9 +83,13 @@ grub_zfs_add_key (grub_uint8_t *key_in, + int passphrase) + { + struct grub_zfs_wrap_key *key; ++ grub_size_t sz; ++ + if (!passphrase && keylen > 32) + keylen = 32; +- key = grub_malloc (sizeof (*key) + keylen); ++ if (grub_add (sizeof (*key), keylen, &sz)) ++ return GRUB_ERR_OUT_OF_RANGE; ++ key = grub_malloc (sz); + if (!key) + return grub_errno; + key->is_passphrase = passphrase; +diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c +index fd7744a6ff6..3288609a5e1 100644 +--- a/grub-core/lib/arg.c ++++ b/grub-core/lib/arg.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + /* Built-in parser for default options. */ + static const struct grub_arg_option help_options[] = +@@ -216,7 +217,13 @@ static inline grub_err_t + add_arg (char ***argl, int *num, char *s) + { + char **p = *argl; +- *argl = grub_realloc (*argl, (++(*num) + 1) * sizeof (char *)); ++ grub_size_t sz; ++ ++ if (grub_add (++(*num), 1, &sz) || ++ grub_mul (sz, sizeof (char *), &sz)) ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); ++ ++ *argl = grub_realloc (*argl, sz); + if (! *argl) + { + grub_free (p); +@@ -431,6 +438,7 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc, + grub_size_t argcnt; + struct grub_arg_list *list; + const struct grub_arg_option *options; ++ grub_size_t sz0, sz1; + + options = extcmd->options; + if (! options) +@@ -443,7 +451,15 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc, + argcnt += ((grub_size_t) argc + 1) / 2 + 1; /* max possible for any option */ + } + +- list = grub_zalloc (sizeof (*list) * i + sizeof (char*) * argcnt); ++ if (grub_mul (sizeof (*list), i, &sz0) || ++ grub_mul (sizeof (char *), argcnt, &sz1) || ++ grub_add (sz0, sz1, &sz0)) ++ { ++ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); ++ return 0; ++ } ++ ++ list = grub_zalloc (sz0); + if (! list) + return 0; + +diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c +index b671f59b62a..dc62800df45 100644 +--- a/grub-core/loader/i386/bsd.c ++++ b/grub-core/loader/i386/bsd.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + #ifdef GRUB_MACHINE_PCBIOS + #include + #endif +@@ -1006,11 +1007,16 @@ grub_netbsd_add_modules (void) + struct grub_netbsd_btinfo_modules *mods; + unsigned i; + grub_err_t err; ++ grub_size_t sz; + + for (mod = netbsd_mods; mod; mod = mod->next) + modcnt++; + +- mods = grub_malloc (sizeof (*mods) + sizeof (mods->mods[0]) * modcnt); ++ if (grub_mul (modcnt, sizeof (mods->mods[0]), &sz) || ++ grub_add (sz, sizeof (*mods), &sz)) ++ return GRUB_ERR_OUT_OF_RANGE; ++ ++ mods = grub_malloc (sz); + if (!mods) + return grub_errno; + +diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c +index 695a920ac44..bded12f22eb 100644 +--- a/grub-core/net/dns.c ++++ b/grub-core/net/dns.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + struct dns_cache_element + { +@@ -51,9 +52,15 @@ grub_net_add_dns_server (const struct grub_net_network_level_address *s) + { + int na = dns_servers_alloc * 2; + struct grub_net_network_level_address *ns; ++ grub_size_t sz; ++ + if (na < 8) + na = 8; +- ns = grub_realloc (dns_servers, na * sizeof (ns[0])); ++ ++ if (grub_mul (na, sizeof (ns[0]), &sz)) ++ return GRUB_ERR_OUT_OF_RANGE; ++ ++ ns = grub_realloc (dns_servers, sz); + if (!ns) + return grub_errno; + dns_servers_alloc = na; +diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c +index 33b8b9cae79..2143ff7cd89 100644 +--- a/grub-core/normal/charset.c ++++ b/grub-core/normal/charset.c +@@ -48,6 +48,7 @@ + #include + #include + #include ++#include + + #if HAVE_FONT_SOURCE + #include "widthspec.h" +@@ -464,6 +465,7 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen, + { + struct grub_unicode_combining *n; + unsigned j; ++ grub_size_t sz; + + if (!haveout) + continue; +@@ -477,10 +479,14 @@ 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)) + { +- n = grub_realloc (out->combining_ptr, +- sizeof (n[0]) * (out->ncomb + 1)); ++ if (grub_add (out->ncomb, 1, &sz) || ++ grub_mul (sz, sizeof (n[0]), &sz)) ++ goto fail; ++ ++ n = grub_realloc (out->combining_ptr, sz); + if (!n) + { ++ fail: + grub_errno = GRUB_ERR_NONE; + continue; + } +diff --git a/grub-core/normal/cmdline.c b/grub-core/normal/cmdline.c +index aa6fd85d791..7a40c9b6d4c 100644 +--- a/grub-core/normal/cmdline.c ++++ b/grub-core/normal/cmdline.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + static grub_uint32_t *kill_buf; + +@@ -307,12 +308,21 @@ cl_insert (struct cmdline_term *cl_terms, unsigned nterms, + if (len + (*llen) >= (*max_len)) + { + grub_uint32_t *nbuf; +- (*max_len) *= 2; +- nbuf = grub_realloc ((*buf), sizeof (grub_uint32_t) * (*max_len)); ++ grub_size_t sz; ++ ++ if (grub_mul (*max_len, 2, max_len) || ++ grub_mul (*max_len, sizeof (grub_uint32_t), &sz)) ++ { ++ grub_errno = GRUB_ERR_OUT_OF_RANGE; ++ goto fail; ++ } ++ ++ nbuf = grub_realloc ((*buf), sz); + if (nbuf) + (*buf) = nbuf; + else + { ++ fail: + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + (*max_len) /= 2; +diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c +index dc1ac1dd1e1..79308a719d0 100644 +--- a/grub-core/normal/menu_entry.c ++++ b/grub-core/normal/menu_entry.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + enum update_mode + { +@@ -113,10 +114,19 @@ ensure_space (struct line *linep, int extra) + { + if (linep->max_len < linep->len + extra) + { +- linep->max_len = 2 * (linep->len + extra); +- linep->buf = grub_realloc (linep->buf, (linep->max_len + 1) * sizeof (linep->buf[0])); ++ grub_size_t sz0, sz1; ++ ++ if (linep->len < 0 || extra < 0 || ++ grub_add ((unsigned long)linep->len, (unsigned long)extra, &sz0) || ++ grub_mul (sz0, 2, &sz0) || ++ grub_add (sz0, 1, &sz1) || ++ grub_mul (sz1, sizeof (linep->buf[0]), &sz1)) ++ return 0; ++ ++ linep->buf = grub_realloc (linep->buf, sz1); + if (! linep->buf) + return 0; ++ linep->max_len = sz0; + } + + return 1; +diff --git a/grub-core/script/argv.c b/grub-core/script/argv.c +index 217ec5d1e1b..5751fdd5708 100644 +--- a/grub-core/script/argv.c ++++ b/grub-core/script/argv.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + /* Return nearest power of two that is >= v. */ + static unsigned +@@ -81,11 +82,16 @@ int + grub_script_argv_next (struct grub_script_argv *argv) + { + char **p = argv->args; ++ grub_size_t sz; + + if (argv->args && argv->argc && argv->args[argv->argc - 1] == 0) + return 0; + +- p = grub_realloc (p, round_up_exp ((argv->argc + 2) * sizeof (char *))); ++ if (grub_add (argv->argc, 2, &sz) || ++ grub_mul (sz, sizeof (char *), &sz)) ++ return 1; ++ ++ p = grub_realloc (p, round_up_exp (sz)); + if (! p) + return 1; + +@@ -105,13 +111,19 @@ grub_script_argv_append (struct grub_script_argv *argv, const char *s, + { + grub_size_t a; + char *p = argv->args[argv->argc - 1]; ++ grub_size_t sz; + + if (! s) + return 0; + + a = p ? grub_strlen (p) : 0; + +- p = grub_realloc (p, round_up_exp ((a + slen + 1) * sizeof (char))); ++ if (grub_add (a, slen, &sz) || ++ grub_add (sz, 1, &sz) || ++ grub_mul (sz, sizeof (char), &sz)) ++ return 1; ++ ++ p = grub_realloc (p, round_up_exp (sz)); + if (! p) + return 1; + +diff --git a/grub-core/script/lexer.c b/grub-core/script/lexer.c +index 128d2382268..1c8bca0a322 100644 +--- a/grub-core/script/lexer.c ++++ b/grub-core/script/lexer.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #define yytext_ptr char * + #include "grub_script.tab.h" +@@ -110,10 +111,14 @@ grub_script_lexer_record (struct grub_parser_param *parser, char *str) + old = lexer->recording; + if (lexer->recordlen < len) + lexer->recordlen = len; +- lexer->recordlen *= 2; ++ ++ if (grub_mul (lexer->recordlen, 2, &lexer->recordlen)) ++ goto fail; ++ + lexer->recording = grub_realloc (lexer->recording, lexer->recordlen); + if (!lexer->recording) + { ++ fail: + grub_free (old); + lexer->recordpos = 0; + lexer->recordlen = 0; +@@ -130,7 +135,7 @@ int + grub_script_lexer_yywrap (struct grub_parser_param *parserstate, + const char *input) + { +- grub_size_t len = 0; ++ grub_size_t len = 0, sz; + char *p = 0; + char *line = 0; + YY_BUFFER_STATE buffer; +@@ -167,12 +172,22 @@ grub_script_lexer_yywrap (struct grub_parser_param *parserstate, + } + else if (len && line[len - 1] != '\n') + { +- p = grub_realloc (line, len + 2); ++ if (grub_add (len, 2, &sz)) ++ { ++ grub_free (line); ++ grub_script_yyerror (parserstate, N_("overflow is detected")); ++ return 1; ++ } ++ ++ p = grub_realloc (line, sz); + if (p) + { + p[len++] = '\n'; + p[len] = '\0'; + } ++ else ++ grub_free (line); ++ + line = p; + } + +diff --git a/grub-core/video/bitmap.c b/grub-core/video/bitmap.c +index b2e0315665b..6256e209a6b 100644 +--- a/grub-core/video/bitmap.c ++++ b/grub-core/video/bitmap.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -58,7 +59,7 @@ grub_video_bitmap_create (struct grub_video_bitmap **bitmap, + enum grub_video_blit_format blit_format) + { + struct grub_video_mode_info *mode_info; +- unsigned int size; ++ grub_size_t size; + + if (!bitmap) + return grub_error (GRUB_ERR_BUG, "invalid argument"); +@@ -137,19 +138,25 @@ grub_video_bitmap_create (struct grub_video_bitmap **bitmap, + + mode_info->pitch = width * mode_info->bytes_per_pixel; + +- /* Calculate size needed for the data. */ +- size = (width * mode_info->bytes_per_pixel) * height; ++ /* Calculate size needed for the data. */ ++ if (grub_mul (width, mode_info->bytes_per_pixel, &size) || ++ grub_mul (size, height, &size)) ++ { ++ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); ++ goto fail; ++ } + + (*bitmap)->data = grub_zalloc (size); + if (! (*bitmap)->data) +- { +- grub_free (*bitmap); +- *bitmap = 0; +- +- return grub_errno; +- } ++ goto fail; + + return GRUB_ERR_NONE; ++ ++ fail: ++ grub_free (*bitmap); ++ *bitmap = NULL; ++ ++ return grub_errno; + } + + /* Frees all resources allocated by bitmap. */ +diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c +index 0a1c6584dd3..39560f56fdc 100644 +--- a/grub-core/video/readers/png.c ++++ b/grub-core/video/readers/png.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -301,9 +302,17 @@ grub_png_decode_image_header (struct grub_png_data *data) + data->bpp <<= 1; + + data->color_bits = color_bits; +- data->row_bytes = data->image_width * data->bpp; ++ ++ if (grub_mul (data->image_width, data->bpp, &data->row_bytes)) ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); ++ + if (data->color_bits <= 4) +- data->row_bytes = (data->image_width * data->color_bits + 7) / 8; ++ { ++ if (grub_mul (data->image_width, data->color_bits + 7, &data->row_bytes)) ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); ++ ++ data->row_bytes >>= 3; ++ } + + #ifndef GRUB_CPU_WORDS_BIGENDIAN + if (data->is_16bit || data->is_gray || data->is_palette) +-- +2.26.2 + diff --git a/SOURCES/0304-iso9660-Don-t-leak-memory-on-realloc-failures.patch b/SOURCES/0304-iso9660-Don-t-leak-memory-on-realloc-failures.patch new file mode 100644 index 0000000..3494d8d --- /dev/null +++ b/SOURCES/0304-iso9660-Don-t-leak-memory-on-realloc-failures.patch @@ -0,0 +1,69 @@ +From 73b56b15b1951e1cbff50fa86ac55faabf5a4176 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Sat, 4 Jul 2020 12:25:09 -0400 +Subject: [PATCH 304/336] iso9660: Don't leak memory on realloc() failures + +Signed-off-by: Peter Jones +Reviewed-by: Daniel Kiper +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 d6dc55b5803..f1611c5e311 100644 +--- a/grub-core/fs/iso9660.c ++++ b/grub-core/fs/iso9660.c +@@ -533,14 +533,20 @@ add_part (struct iterate_dir_ctx *ctx, + { + grub_size_t 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 + diff --git a/SOURCES/0305-font-Do-not-load-more-than-one-NAME-section.patch b/SOURCES/0305-font-Do-not-load-more-than-one-NAME-section.patch new file mode 100644 index 0000000..6432e54 --- /dev/null +++ b/SOURCES/0305-font-Do-not-load-more-than-one-NAME-section.patch @@ -0,0 +1,38 @@ +From fff5140620c52db3b7ebca5921d1d237b1dcc7ae Mon Sep 17 00:00:00 2001 +From: Daniel Kiper +Date: Tue, 7 Jul 2020 15:36:26 +0200 +Subject: [PATCH 305/336] 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 +Signed-off-by: Daniel Kiper +Reviewed-by: Jan Setje-Eilers +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 71d3f78b88a..5ff5f438b40 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 + diff --git a/SOURCES/0306-gfxmenu-Fix-double-free-in-load_image.patch b/SOURCES/0306-gfxmenu-Fix-double-free-in-load_image.patch new file mode 100644 index 0000000..b9282d7 --- /dev/null +++ b/SOURCES/0306-gfxmenu-Fix-double-free-in-load_image.patch @@ -0,0 +1,36 @@ +From eb7980539440795b87bb3ab15397855700e4cfb1 Mon Sep 17 00:00:00 2001 +From: Alexey Makhalov +Date: Wed, 8 Jul 2020 20:41:56 +0000 +Subject: [PATCH 306/336] 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 +Reviewed-by: Daniel Kiper +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 + diff --git a/SOURCES/0307-xnu-Fix-double-free-in-grub_xnu_devprop_add_property.patch b/SOURCES/0307-xnu-Fix-double-free-in-grub_xnu_devprop_add_property.patch new file mode 100644 index 0000000..fc809db --- /dev/null +++ b/SOURCES/0307-xnu-Fix-double-free-in-grub_xnu_devprop_add_property.patch @@ -0,0 +1,57 @@ +From 45c4c44de701e867c093ef7cc73faadfef28adf0 Mon Sep 17 00:00:00 2001 +From: Alexey Makhalov +Date: Wed, 8 Jul 2020 21:30:43 +0000 +Subject: [PATCH 307/336] 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 +Reviewed-by: Daniel Kiper +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 875048e1353..424488a9f7c 100644 +--- a/grub-core/loader/i386/xnu.c ++++ b/grub-core/loader/i386/xnu.c +@@ -259,20 +259,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); +- grub_free (prop->name); +- grub_free (prop->name16); +- 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 + diff --git a/SOURCES/0308-lzma-Make-sure-we-don-t-dereference-past-array.patch b/SOURCES/0308-lzma-Make-sure-we-don-t-dereference-past-array.patch new file mode 100644 index 0000000..d07d633 --- /dev/null +++ b/SOURCES/0308-lzma-Make-sure-we-don-t-dereference-past-array.patch @@ -0,0 +1,52 @@ +From 41487914bf5fe814c80011a55c510700cdec5dff Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Thu, 9 Jul 2020 03:05:23 +0000 +Subject: [PATCH 308/336] 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 +Reviewed-by: Daniel Kiper +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 + diff --git a/SOURCES/0309-term-Fix-overflow-on-user-inputs.patch b/SOURCES/0309-term-Fix-overflow-on-user-inputs.patch new file mode 100644 index 0000000..9eff113 --- /dev/null +++ b/SOURCES/0309-term-Fix-overflow-on-user-inputs.patch @@ -0,0 +1,66 @@ +From a5fa3f370171482c7cdcb44af99e24040d1632ce Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Tue, 7 Jul 2020 15:12:25 -0400 +Subject: [PATCH 309/336] 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 +Reviewed-by: Daniel Kiper +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 7cb7909c8cf..aea9ffd0af7 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] == '\e' +-- +2.26.2 + diff --git a/SOURCES/0310-udf-Fix-memory-leak.patch b/SOURCES/0310-udf-Fix-memory-leak.patch new file mode 100644 index 0000000..9c20757 --- /dev/null +++ b/SOURCES/0310-udf-Fix-memory-leak.patch @@ -0,0 +1,56 @@ +From 7ba278675832c85846faa7191a958a84cb7ace11 Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Tue, 7 Jul 2020 22:02:31 -0400 +Subject: [PATCH 310/336] udf: Fix memory leak + +Fixes: CID 73796 + +Signed-off-by: Konrad Rzeszutek Wilk +Reviewed-by: Daniel Kiper +Reviewed-by: Jan Setje-Eilers +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 99b001f2066..c23c0120f49 100644 +--- a/grub-core/fs/udf.c ++++ b/grub-core/fs/udf.c +@@ -909,8 +909,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. */ +@@ -932,11 +934,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 + diff --git a/SOURCES/0311-multiboot2-Fix-memory-leak-if-grub_create_loader_cmd.patch b/SOURCES/0311-multiboot2-Fix-memory-leak-if-grub_create_loader_cmd.patch new file mode 100644 index 0000000..c895735 --- /dev/null +++ b/SOURCES/0311-multiboot2-Fix-memory-leak-if-grub_create_loader_cmd.patch @@ -0,0 +1,47 @@ +From 0f008fb687338498ee7d84980a7aca6aa4dec919 Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Fri, 26 Jun 2020 10:51:43 -0400 +Subject: [PATCH 311/336] multiboot2: Fix memory leak if + grub_create_loader_cmdline() fails + +Fixes: CID 292468 + +Signed-off-by: Konrad Rzeszutek Wilk +Reviewed-by: Daniel Kiper +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 83e8919fa9a..7e01dfb5ee7 100644 +--- a/grub-core/loader/multiboot_mbi2.c ++++ b/grub-core/loader/multiboot_mbi2.c +@@ -957,6 +957,7 @@ grub_multiboot_add_module (grub_addr_t start, grub_size_t size, + { + struct module *newmod; + grub_size_t len = 0; ++ grub_err_t err; + + newmod = grub_malloc (sizeof (*newmod)); + if (!newmod) +@@ -975,8 +976,14 @@ grub_multiboot_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 + diff --git a/SOURCES/0312-tftp-Do-not-use-priority-queue.patch b/SOURCES/0312-tftp-Do-not-use-priority-queue.patch new file mode 100644 index 0000000..2a0f2ae --- /dev/null +++ b/SOURCES/0312-tftp-Do-not-use-priority-queue.patch @@ -0,0 +1,289 @@ +From c883f21166fe105f25a7ee3919f9cb3e93b992c9 Mon Sep 17 00:00:00 2001 +From: Alexey Makhalov +Date: Thu, 9 Jul 2020 08:10:40 +0000 +Subject: [PATCH 312/336] 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 +Reviewed-by: Daniel Kiper +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 + #include + #include +-#include + #include + + 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 + diff --git a/SOURCES/0313-relocator-Protect-grub_relocator_alloc_chunk_addr-in.patch b/SOURCES/0313-relocator-Protect-grub_relocator_alloc_chunk_addr-in.patch new file mode 100644 index 0000000..6c6a7c0 --- /dev/null +++ b/SOURCES/0313-relocator-Protect-grub_relocator_alloc_chunk_addr-in.patch @@ -0,0 +1,166 @@ +From b3725e88e9124bcdc77b962bf25863e2e50d7fc2 Mon Sep 17 00:00:00 2001 +From: Alexey Makhalov +Date: Wed, 15 Jul 2020 06:42:37 +0000 +Subject: [PATCH 313/336] 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 +Reviewed-by: Daniel Kiper +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 | 21 ++++++++++++++++----- + grub-core/loader/xnu.c | 11 +++++++---- + 4 files changed, 37 insertions(+), 13 deletions(-) + +diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c +index 656c75fd7e8..1a36979a5ec 100644 +--- a/grub-core/loader/i386/linux.c ++++ b/grub-core/loader/i386/linux.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -586,9 +587,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 c2e5fa9abcc..4a801a7ab08 100644 +--- a/grub-core/loader/i386/pc/linux.c ++++ b/grub-core/loader/i386/pc/linux.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + 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 c16b4b24937..b6ec98bed98 100644 +--- a/grub-core/loader/i386/xen.c ++++ b/grub-core/loader/i386/xen.c +@@ -39,6 +39,8 @@ + #include + #include + #include ++#include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -397,6 +399,11 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)), + grub_file_t file; + grub_elf_t elf; + grub_err_t err; ++ void *kern_chunk_src; ++ 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")); +@@ -448,9 +455,8 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)), + if (!relocator) + goto fail; + +- grub_relocator_chunk_t ch; +- grub_addr_t kern_start = xen_inf.kern_start - xen_inf.paddr_offset; +- grub_addr_t kern_end = xen_inf.kern_end - xen_inf.paddr_offset; ++ kern_start = xen_inf.kern_start - xen_inf.paddr_offset; ++ kern_end = xen_inf.kern_end - xen_inf.paddr_offset; + + if (xen_inf.has_hypercall_page) + { +@@ -465,8 +471,13 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)), + + max_addr = ALIGN_UP (kern_end, PAGE_SIZE); + +- err = grub_relocator_alloc_chunk_addr (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 fdf61b6f9f7..66731d2528b 100644 +--- a/grub-core/loader/xnu.c ++++ b/grub-core/loader/xnu.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + 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 + diff --git a/SOURCES/0314-relocator-Protect-grub_relocator_alloc_chunk_align-m.patch b/SOURCES/0314-relocator-Protect-grub_relocator_alloc_chunk_align-m.patch new file mode 100644 index 0000000..e8a1aed --- /dev/null +++ b/SOURCES/0314-relocator-Protect-grub_relocator_alloc_chunk_align-m.patch @@ -0,0 +1,314 @@ +From 940b7872052d8539c7699e6323fda9467c87f67c Mon Sep 17 00:00:00 2001 +From: Alexey Makhalov +Date: Wed, 8 Jul 2020 01:44:38 +0000 +Subject: [PATCH 314/336] 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 +Reviewed-by: Daniel Kiper +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/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 | 5 ++--- + grub-core/loader/multiboot_mbi2.c | 11 ++++++---- + grub-core/loader/xnu_resume.c | 2 +- + include/grub/relocator.h | 29 +++++++++++++++++++++++++++ + 12 files changed, 65 insertions(+), 51 deletions(-) + +diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c +index ffaf25f088d..08f6821f20c 100644 +--- a/grub-core/lib/i386/relocator.c ++++ b/grub-core/lib/i386/relocator.c +@@ -84,11 +84,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; + +@@ -126,13 +125,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; + +@@ -184,11 +180,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/loader/i386/linux.c b/grub-core/loader/i386/linux.c +index 1a36979a5ec..8531ca17437 100644 +--- a/grub-core/loader/i386/linux.c ++++ b/grub-core/loader/i386/linux.c +@@ -230,9 +230,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 f10c087f724..adda5fd3a87 100644 +--- a/grub-core/loader/i386/multiboot_mbi.c ++++ b/grub-core/loader/i386/multiboot_mbi.c +@@ -445,10 +445,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 4a801a7ab08..f217f5071b6 100644 +--- a/grub-core/loader/i386/pc/linux.c ++++ b/grub-core/loader/i386/pc/linux.c +@@ -457,10 +457,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 4a3e8c5dfa2..f4bfd1d8b20 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 e4e696e8f89..e2d3a8b5b2e 100644 +--- a/grub-core/loader/multiboot.c ++++ b/grub-core/loader/multiboot.c +@@ -343,7 +343,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 c0ff1239dbf..6d87f08976f 100644 +--- a/grub-core/loader/multiboot_elfxx.c ++++ b/grub-core/loader/multiboot_elfxx.c +@@ -201,9 +201,8 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, + &ch, 0, +- (0xffffffff - sh->sh_size) +- + 1, sh->sh_size, +- sh->sh_addralign, ++ UP_TO_TOP32 (sh->sh_size), ++ sh->sh_size, sh->sh_addralign, + GRUB_RELOCATOR_PREFERENCE_NONE, + 0); + if (err) +diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c +index 7e01dfb5ee7..e99d3177a4a 100644 +--- a/grub-core/loader/multiboot_mbi2.c ++++ b/grub-core/loader/multiboot_mbi2.c +@@ -235,15 +235,18 @@ grub_multiboot_load (grub_file_t file, const char *filename) + grub_size_t code_size; + void *source; + grub_relocator_chunk_t ch; ++ int preference = GRUB_RELOCATOR_PREFERENCE_NONE; + + if (addr_tag->bss_end_addr) + code_size = (addr_tag->bss_end_addr - load_addr); + else + code_size = load_size; + +- err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, +- &ch, load_addr, +- code_size); ++ err = grub_relocator_alloc_chunk_align_safe (grub_multiboot_relocator, ++ &ch, load_addr, ++ UP_TO_TOP32(load_addr), ++ code_size, 0, preference, ++ keep_bs); + if (err) + { + grub_dprintf ("multiboot_loader", "Error loading aout kludge\n"); +@@ -647,7 +650,7 @@ grub_multiboot_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_multiboot_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 + diff --git a/SOURCES/0315-script-Remove-unused-fields-from-grub_script_functio.patch b/SOURCES/0315-script-Remove-unused-fields-from-grub_script_functio.patch new file mode 100644 index 0000000..6c364b9 --- /dev/null +++ b/SOURCES/0315-script-Remove-unused-fields-from-grub_script_functio.patch @@ -0,0 +1,34 @@ +From 1f12e039922b59787070bb311da86d16e498da66 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Fri, 10 Jul 2020 11:21:14 +0100 +Subject: [PATCH 315/336] script: Remove unused fields from + grub_script_function struct + +Signed-off-by: Chris Coulson +Reviewed-by: Daniel Kiper +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 + diff --git a/SOURCES/0316-script-Avoid-a-use-after-free-when-redefining-a-func.patch b/SOURCES/0316-script-Avoid-a-use-after-free-when-redefining-a-func.patch new file mode 100644 index 0000000..dc6cc67 --- /dev/null +++ b/SOURCES/0316-script-Avoid-a-use-after-free-when-redefining-a-func.patch @@ -0,0 +1,108 @@ +From 0950880ab9a53d7632ca849ad2375352a3c2c972 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Fri, 10 Jul 2020 14:41:45 +0100 +Subject: [PATCH 316/336] 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 +Reviewed-by: Daniel Kiper +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 043b4c4bb66..52ccbd9965b 100644 +--- a/grub-core/script/execute.c ++++ b/grub-core/script/execute.c +@@ -855,7 +855,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 1d60e9de2f3..26b72e52556 100644 +--- a/grub-core/script/parser.y ++++ b/grub-core/script/parser.y +@@ -290,7 +290,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 = $3; +-- +2.26.2 + diff --git a/SOURCES/0317-relocator-Fix-grub_relocator_alloc_chunk_align-top-m.patch b/SOURCES/0317-relocator-Fix-grub_relocator_alloc_chunk_align-top-m.patch new file mode 100644 index 0000000..08e3c7d --- /dev/null +++ b/SOURCES/0317-relocator-Fix-grub_relocator_alloc_chunk_align-top-m.patch @@ -0,0 +1,46 @@ +From f759247e7706c921d1300e67a7ebcb5a997d43aa Mon Sep 17 00:00:00 2001 +From: Alexey Makhalov +Date: Fri, 17 Jul 2020 05:17:26 +0000 +Subject: [PATCH 317/336] 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 +Reviewed-by: Daniel Kiper +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 7ea72069a45..833ace70eb3 100644 +--- a/grub-core/lib/relocator.c ++++ b/grub-core/lib/relocator.c +@@ -1376,8 +1376,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 + diff --git a/SOURCES/0318-hfsplus-fix-two-more-overflows.patch b/SOURCES/0318-hfsplus-fix-two-more-overflows.patch new file mode 100644 index 0000000..f96e42f --- /dev/null +++ b/SOURCES/0318-hfsplus-fix-two-more-overflows.patch @@ -0,0 +1,57 @@ +From 7bfc4727df287c0cf642cf4861c7ede073996f96 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Sun, 19 Jul 2020 14:43:31 -0400 +Subject: [PATCH 318/336] 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 +Reviewed-by: Darren Kenny +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 05016ee98a4..2ef0b8d3fec 100644 +--- a/grub-core/fs/hfsplus.c ++++ b/grub-core/fs/hfsplus.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -469,8 +470,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; + +@@ -709,8 +714,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 + diff --git a/SOURCES/0319-lvm-fix-two-more-potential-data-dependent-alloc-over.patch b/SOURCES/0319-lvm-fix-two-more-potential-data-dependent-alloc-over.patch new file mode 100644 index 0000000..0413ff3 --- /dev/null +++ b/SOURCES/0319-lvm-fix-two-more-potential-data-dependent-alloc-over.patch @@ -0,0 +1,113 @@ +From f4e192a971ed2144fde43946d6574f970b9e2e20 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Sun, 19 Jul 2020 15:48:20 -0400 +Subject: [PATCH 319/336] 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 +Signed-off-by: Darren Kenny +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 680a796cb48..e3268d1a28d 100644 +--- a/grub-core/disk/lvm.c ++++ b/grub-core/disk/lvm.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #ifdef GRUB_UTIL + #include +@@ -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\n"); + #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 + diff --git a/SOURCES/0320-emu-make-grub_free-NULL-safe.patch b/SOURCES/0320-emu-make-grub_free-NULL-safe.patch new file mode 100644 index 0000000..59dce1e --- /dev/null +++ b/SOURCES/0320-emu-make-grub_free-NULL-safe.patch @@ -0,0 +1,34 @@ +From b074ba5bfbfc70c09b35a8e276c54cdce13e088d Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Sun, 19 Jul 2020 16:08:08 -0400 +Subject: [PATCH 320/336] 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 +Reviewed-by: Darren Kenny +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 + diff --git a/SOURCES/0321-efi-fix-some-malformed-device-path-arithmetic-errors.patch b/SOURCES/0321-efi-fix-some-malformed-device-path-arithmetic-errors.patch new file mode 100644 index 0000000..8725fe0 --- /dev/null +++ b/SOURCES/0321-efi-fix-some-malformed-device-path-arithmetic-errors.patch @@ -0,0 +1,252 @@ +From 9db27e9db2d0c2f147d6ea3c2f60dd6620af5fbf Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Sun, 19 Jul 2020 16:53:27 -0400 +Subject: [PATCH 321/336] 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 +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 4bd7ca210ad..42c68307f3f 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -325,7 +325,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); +@@ -335,9 +335,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; + } + +@@ -353,7 +359,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); +@@ -369,8 +375,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; + + dup_name = grub_calloc (len, sizeof (*dup_name)); +@@ -442,7 +455,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; + } +@@ -487,7 +519,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); +@@ -959,7 +991,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; +@@ -995,5 +1031,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 3d600fa6bd5..b90dfd6c5a6 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 424488a9f7c..8a68e49ad76 100644 +--- a/grub-core/loader/i386/xnu.c ++++ b/grub-core/loader/i386/xnu.c +@@ -512,14 +512,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 fbd1c4b529d..9860fd16189 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -613,6 +613,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) +@@ -621,13 +622,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 + diff --git a/SOURCES/0322-Fix-a-regression-caused-by-efi-fix-some-malformed-de.patch b/SOURCES/0322-Fix-a-regression-caused-by-efi-fix-some-malformed-de.patch new file mode 100644 index 0000000..e27a103 --- /dev/null +++ b/SOURCES/0322-Fix-a-regression-caused-by-efi-fix-some-malformed-de.patch @@ -0,0 +1,88 @@ +From a5c5bcf1ac7b0057496b10a030fe1d9d24eb2775 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Wed, 22 Jul 2020 17:06:04 +0100 +Subject: [PATCH 322/336] 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 b90dfd6c5a6..dbcdf333b62 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 + diff --git a/SOURCES/0323-update-safemath-with-fallback-code-for-gcc-older-tha.patch b/SOURCES/0323-update-safemath-with-fallback-code-for-gcc-older-tha.patch new file mode 100644 index 0000000..329ac4b --- /dev/null +++ b/SOURCES/0323-update-safemath-with-fallback-code-for-gcc-older-tha.patch @@ -0,0 +1,151 @@ +From 6c4c027abfb58272a3604db4094733b4388c1638 Mon Sep 17 00:00:00 2001 +From: Alexander Burmashev +Date: Wed, 22 Jul 2020 06:04:38 -0700 +Subject: [PATCH 323/336] 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 +, 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 +--- + 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 , 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 ++#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 + diff --git a/SOURCES/0324-efi-Free-malloc-regions-on-exit.patch b/SOURCES/0324-efi-Free-malloc-regions-on-exit.patch new file mode 100644 index 0000000..7065bb1 --- /dev/null +++ b/SOURCES/0324-efi-Free-malloc-regions-on-exit.patch @@ -0,0 +1,158 @@ +From 6bea96c79a0c25cfd4ca1e0ff203fa7600be5a58 Mon Sep 17 00:00:00 2001 +From: Alexander Graf +Date: Thu, 31 Aug 2017 16:40:19 +0200 +Subject: [PATCH 324/336] efi: Free malloc regions on exit + +When we exit grub, we don't free all the memory that we allocated earlier +for our heap region. This can cause problems with setups where you try +to descend the boot order using "exit" entries, such as PXE -> HD boot +scenarios. + +Signed-off-by: Alexander Graf +Reviewed-by: Daniel Kiper +Upstream-commit-id: 92bfc33db98 +--- + grub-core/kern/efi/init.c | 1 + + grub-core/kern/efi/mm.c | 82 +++++++++++++++++++++++++++++++++++++++ + include/grub/efi/efi.h | 1 + + 3 files changed, 84 insertions(+) + +diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c +index c5d8a76144a..e8bf993f6d4 100644 +--- a/grub-core/kern/efi/init.c ++++ b/grub-core/kern/efi/init.c +@@ -111,4 +111,5 @@ grub_efi_fini (void) + { + grub_efidisk_fini (); + grub_console_fini (); ++ grub_efi_memory_fini (); + } +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index ddeca6073f6..abe9c70557f 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -49,6 +49,70 @@ static grub_efi_uintn_t finish_desc_size; + static grub_efi_uint32_t finish_desc_version; + int grub_efi_is_finished = 0; + ++/* ++ * We need to roll back EFI allocations on exit. Remember allocations that ++ * we'll free on exit. ++ */ ++struct efi_allocation; ++struct efi_allocation { ++ grub_efi_physical_address_t address; ++ grub_efi_uint64_t pages; ++ struct efi_allocation *next; ++}; ++static struct efi_allocation *efi_allocated_memory; ++ ++static void ++grub_efi_store_alloc (grub_efi_physical_address_t address, ++ grub_efi_uintn_t pages) ++{ ++ grub_efi_boot_services_t *b; ++ struct efi_allocation *alloc; ++ grub_efi_status_t status; ++ ++ b = grub_efi_system_table->boot_services; ++ status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA, ++ sizeof(*alloc), (void**)&alloc); ++ ++ if (status == GRUB_EFI_SUCCESS) ++ { ++ alloc->next = efi_allocated_memory; ++ alloc->address = address; ++ alloc->pages = pages; ++ efi_allocated_memory = alloc; ++ } ++ else ++ grub_printf ("Could not malloc memory to remember EFI allocation. " ++ "Exiting GRUB won't free all memory.\n"); ++} ++ ++static void ++grub_efi_drop_alloc (grub_efi_physical_address_t address, ++ grub_efi_uintn_t pages) ++{ ++ struct efi_allocation *ea, *eap; ++ grub_efi_boot_services_t *b; ++ ++ b = grub_efi_system_table->boot_services; ++ ++ for (eap = NULL, ea = efi_allocated_memory; ea; eap = ea, ea = ea->next) ++ { ++ if (ea->address != address || ea->pages != pages) ++ continue; ++ ++ /* Remove the current entry from the list. */ ++ if (eap) ++ eap->next = ea->next; ++ else ++ efi_allocated_memory = ea->next; ++ ++ /* Then free the memory backing it. */ ++ efi_call_1 (b->free_pool, ea); ++ ++ /* And leave, we're done. */ ++ break; ++ } ++} ++ + /* Allocate pages below a specified address */ + void * + grub_efi_allocate_pages_max (grub_efi_physical_address_t max, +@@ -78,6 +142,8 @@ grub_efi_allocate_pages_max (grub_efi_physical_address_t max, + return 0; + } + ++ grub_efi_store_alloc (address, pages); ++ + return (void *) ((grub_addr_t) address); + } + +@@ -139,6 +205,8 @@ grub_efi_free_pages (grub_efi_physical_address_t address, + + b = grub_efi_system_table->boot_services; + efi_call_2 (b->free_pages, address, pages); ++ ++ grub_efi_drop_alloc (address, pages); + } + + #if defined (__i386__) || defined (__x86_64__) +@@ -446,6 +514,20 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + grub_fatal ("too little memory"); + } + ++void ++grub_efi_memory_fini (void) ++{ ++ /* ++ * Free all stale allocations. grub_efi_free_pages() will remove ++ * the found entry from the list and it will always find the first ++ * list entry (efi_allocated_memory is the list start). Hence we ++ * remove all entries from the list until none is left altogether. ++ */ ++ while (efi_allocated_memory) ++ grub_efi_free_pages (efi_allocated_memory->address, ++ efi_allocated_memory->pages); ++} ++ + #if 0 + /* Print the memory map. */ + static void +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index 9a2da0eb38d..f761bbb1389 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -51,6 +51,7 @@ EXPORT_FUNC(grub_efi_get_memory_map) (grub_efi_uintn_t *memory_map_size, + grub_efi_uintn_t *map_key, + grub_efi_uintn_t *descriptor_size, + grub_efi_uint32_t *descriptor_version); ++void grub_efi_memory_fini (void); + grub_efi_loaded_image_t *EXPORT_FUNC(grub_efi_get_loaded_image) (grub_efi_handle_t image_handle); + void EXPORT_FUNC(grub_efi_print_device_path) (grub_efi_device_path_t *dp); + char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp); +-- +2.26.2 + diff --git a/SOURCES/0325-efi-Fix-use-after-free-in-halt-reboot-path.patch b/SOURCES/0325-efi-Fix-use-after-free-in-halt-reboot-path.patch new file mode 100644 index 0000000..3e4e83f --- /dev/null +++ b/SOURCES/0325-efi-Fix-use-after-free-in-halt-reboot-path.patch @@ -0,0 +1,145 @@ +From e6c7a7c575e47632116d62456513f7617efcba2a Mon Sep 17 00:00:00 2001 +From: Alexey Makhalov +Date: Mon, 20 Jul 2020 23:03:05 +0000 +Subject: [PATCH 325/336] 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 +Reviewed-by: Darren Kenny +--- + grub-core/kern/arm/efi/init.c | 3 +++ + grub-core/kern/efi/efi.c | 7 ++++--- + 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 + + 6 files changed, 24 insertions(+), 8 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/efi/efi.c b/grub-core/kern/efi/efi.c +index 42c68307f3f..6c4099a685d 100644 +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -162,9 +162,10 @@ grub_exit (int retval) + if (retval == 0) + rc = GRUB_EFI_SUCCESS; + +- grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); +- efi_call_4 (grub_efi_system_table->boot_services->exit, +- grub_efi_image_handle, rc, 0, 0); ++ 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, rc, 0, NULL); + for (;;) ; + } + +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 + diff --git a/SOURCES/0326-build-grub-module-verifier-make-output-more-useful.patch b/SOURCES/0326-build-grub-module-verifier-make-output-more-useful.patch new file mode 100644 index 0000000..bad7d81 --- /dev/null +++ b/SOURCES/0326-build-grub-module-verifier-make-output-more-useful.patch @@ -0,0 +1,236 @@ +From a0951a168054fa30a1c1d48b5edf066d8e08900d Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Sat, 18 Jul 2020 18:28:14 -0400 +Subject: [PATCH 326/336] build-grub-module-verifier: make output more useful + +- show the user which module has the error +- show which section relocation errors are in +- show which relocation is in error + +Signed-off-by: Peter Jones +--- + util/grub-module-verifier.c | 4 +-- + util/grub-module-verifierXX.c | 61 ++++++++++++++++++---------------- + include/grub/module_verifier.h | 4 +-- + 3 files changed, 36 insertions(+), 33 deletions(-) + +diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c +index 405c9117051..4acbad38421 100644 +--- a/util/grub-module-verifier.c ++++ b/util/grub-module-verifier.c +@@ -137,8 +137,8 @@ main (int argc, char **argv) + module_size = grub_util_get_image_size (argv[1]); + module_img = grub_util_read_image (argv[1]); + if (archs[arch].voidp_sizeof == 8) +- grub_module_verify64(module_img, module_size, &archs[arch]); ++ grub_module_verify64(module_img, module_size, &archs[arch], argv[1]); + else +- grub_module_verify32(module_img, module_size, &archs[arch]); ++ grub_module_verify32(module_img, module_size, &archs[arch], argv[1]); + return 0; + } +diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c +index 9c04caa63b4..aecb45e9c87 100644 +--- a/util/grub-module-verifierXX.c ++++ b/util/grub-module-verifierXX.c +@@ -151,14 +151,14 @@ find_section (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, const c + } + + static void +-check_license (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) ++check_license (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, const char *filename) + { + Elf_Shdr *s = find_section (arch, e, ".module_license"); + if (s && (strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv3") == 0 + || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv3+") == 0 + || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv2+") == 0)) + return; +- grub_util_error ("incompatible license"); ++ grub_util_error ("%s: incompatible license", filename); + } + + static Elf_Sym * +@@ -185,7 +185,7 @@ get_symtab (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, Elf_Word + } + + static void +-check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) ++check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, const char * filename) + { + Elf_Sym *sym; + Elf_Word size, entsize; +@@ -199,10 +199,10 @@ check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) + Elf_Shdr *s = find_section (arch, e, ".moddeps"); + + if (!s) +- grub_util_error ("no symbol table and no .moddeps section"); ++ grub_util_error ("%s: no symbol table and no .moddeps section", filename); + + if (!s->sh_size) +- grub_util_error ("no symbol table and empty .moddeps section"); ++ grub_util_error ("%s: no symbol table and empty .moddeps section", filename); + + return; + } +@@ -223,7 +223,7 @@ check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) + break; + + default: +- return grub_util_error ("unknown symbol type `%d'", (int) type); ++ return grub_util_error ("%s: unknown symbol type `%d'", filename, (int) type); + } + } + } +@@ -250,26 +250,29 @@ is_symbol_local(Elf_Sym *sym) + + static void + section_check_relocations (const struct grub_module_verifier_arch *arch, void *ehdr, +- Elf_Shdr *s, size_t target_seg_size) ++ Elf_Shdr *s, size_t target_seg_size, const char * filename) + { + Elf_Rel *rel, *max; + Elf_Sym *symtab; + Elf_Word symtabsize, symtabentsize; ++ unsigned int r; + + symtab = get_symtab (arch, ehdr, &symtabsize, &symtabentsize); + if (!symtab) +- grub_util_error ("relocation without symbol table"); ++ grub_util_error ("%s: relocation without symbol table", filename); + + for (rel = (Elf_Rel *) ((char *) ehdr + grub_target_to_host (s->sh_offset)), +- max = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_size)); ++ max = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_size)), ++ r = 0; + rel < max; +- rel = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_entsize))) ++ rel = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_entsize)), ++ r++) + { + Elf_Sym *sym; + unsigned i; + + if (target_seg_size < grub_target_to_host (rel->r_offset)) +- grub_util_error ("reloc offset is out of the segment"); ++ grub_util_error ("%s: reloc offset is out of the segment", filename); + + grub_uint32_t type = ELF_R_TYPE (grub_target_to_host (rel->r_info)); + +@@ -282,22 +285,22 @@ section_check_relocations (const struct grub_module_verifier_arch *arch, void *e + if (arch->supported_relocations[i] != -1) + continue; + if (!arch->short_relocations) +- grub_util_error ("unsupported relocation 0x%x", type); ++ grub_util_error ("%s: relocation %u has unsupported type 0x%x", filename, r, type); + for (i = 0; arch->short_relocations[i] != -1; i++) + if (type == arch->short_relocations[i]) + break; + if (arch->short_relocations[i] == -1) +- grub_util_error ("unsupported relocation 0x%x", type); ++ grub_util_error ("%s: relocation %u has unsupported type 0x%x", filename, r, type); + sym = (Elf_Sym *) ((char *) symtab + symtabentsize * ELF_R_SYM (grub_target_to_host (rel->r_info))); + + if (is_symbol_local (sym)) + continue; +- grub_util_error ("relocation 0x%x is not module-local", type); ++ grub_util_error ("%s: relocation %d with type 0x%x is not module-local", filename, r, type); + } + } + + static void +-check_relocations (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) ++check_relocations (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, const char * filename) + { + Elf_Shdr *s; + unsigned i; +@@ -310,27 +313,27 @@ check_relocations (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e) + Elf_Shdr *ts; + + if (grub_target_to_host32 (s->sh_type) == SHT_REL && !(arch->flags & GRUB_MODULE_VERIFY_SUPPORTS_REL)) +- grub_util_error ("unsupported SHT_REL"); ++ grub_util_error ("%s: section %d is unsupported SHT_REL", filename, i); + if (grub_target_to_host32 (s->sh_type) == SHT_RELA && !(arch->flags & GRUB_MODULE_VERIFY_SUPPORTS_RELA)) +- grub_util_error ("unsupported SHT_RELA"); ++ grub_util_error ("%s: section %d is unsupported SHT_RELA", filename, i); + + /* Find the target segment. */ + if (grub_target_to_host32 (s->sh_info) >= grub_target_to_host16 (e->e_shnum)) +- grub_util_error ("orphaned reloc section"); ++ grub_util_error ("%s: section %d is orphaned reloc", filename, i); + ts = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff) + grub_target_to_host32 (s->sh_info) * grub_target_to_host16 (e->e_shentsize)); + +- section_check_relocations (arch, e, s, grub_target_to_host (ts->sh_size)); ++ section_check_relocations (arch, e, s, grub_target_to_host (ts->sh_size), filename); + } + } + + void +-SUFFIX(grub_module_verify) (void *module_img, size_t size, const struct grub_module_verifier_arch *arch) ++SUFFIX(grub_module_verify) (void *module_img, size_t size, const struct grub_module_verifier_arch *arch, const char * filename) + { + Elf_Ehdr *e = module_img; + + /* Check the header size. */ + if (size < sizeof (Elf_Ehdr)) +- grub_util_error ("ELF header smaller than expected"); ++ grub_util_error ("%s: ELF header smaller than expected", filename); + + /* Check the magic numbers. */ + if (e->e_ident[EI_MAG0] != ELFMAG0 +@@ -339,33 +342,33 @@ SUFFIX(grub_module_verify) (void *module_img, size_t size, const struct grub_mod + || e->e_ident[EI_MAG3] != ELFMAG3 + || e->e_ident[EI_VERSION] != EV_CURRENT + || grub_target_to_host32 (e->e_version) != EV_CURRENT) +- grub_util_error ("invalid arch-independent ELF magic"); ++ grub_util_error ("%s: invalid arch-independent ELF magic", filename); + + if (e->e_ident[EI_CLASS] != ELFCLASSXX + || e->e_ident[EI_DATA] != (arch->bigendian ? ELFDATA2MSB : ELFDATA2LSB) + || grub_target_to_host16 (e->e_machine) != arch->machine) +- grub_util_error ("invalid arch-dependent ELF magic"); ++ grub_util_error ("%s: invalid arch-dependent ELF magic", filename); + + if (grub_target_to_host16 (e->e_type) != ET_REL) + { +- grub_util_error ("this ELF file is not of the right type"); ++ grub_util_error ("%s: this ELF file is not of the right type", filename); + } + + /* Make sure that every section is within the core. */ + if (size < grub_target_to_host (e->e_shoff) + + (grub_uint32_t) grub_target_to_host16 (e->e_shentsize) * grub_target_to_host16(e->e_shnum)) + { +- grub_util_error ("ELF sections outside core"); ++ grub_util_error ("%s: ELF sections outside core", filename); + } + +- check_license (arch, e); ++ check_license (arch, e, filename); + + Elf_Shdr *s; + + s = find_section (arch, e, ".modname"); + if (!s) +- grub_util_error ("no module name found"); ++ grub_util_error ("%s: no module name found", filename); + +- check_symbols(arch, e); +- check_relocations(arch, e); ++ check_symbols(arch, e, filename); ++ check_relocations(arch, e, filename); + } +diff --git a/include/grub/module_verifier.h b/include/grub/module_verifier.h +index 6cddff30f2e..7dd0fa18ec8 100644 +--- a/include/grub/module_verifier.h ++++ b/include/grub/module_verifier.h +@@ -16,5 +16,5 @@ struct grub_module_verifier_arch { + const int *short_relocations; + }; + +-void grub_module_verify64(void *module_img, size_t module_size, const struct grub_module_verifier_arch *arch); +-void grub_module_verify32(void *module_img, size_t module_size, const struct grub_module_verifier_arch *arch); ++void grub_module_verify64(void *module_img, size_t module_size, const struct grub_module_verifier_arch *arch, const char * filename); ++void grub_module_verify32(void *module_img, size_t module_size, const struct grub_module_verifier_arch *arch, const char * filename); +-- +2.26.2 + diff --git a/SOURCES/0327-efi-dhcp-fix-some-allocation-error-checking.patch b/SOURCES/0327-efi-dhcp-fix-some-allocation-error-checking.patch new file mode 100644 index 0000000..847e792 --- /dev/null +++ b/SOURCES/0327-efi-dhcp-fix-some-allocation-error-checking.patch @@ -0,0 +1,40 @@ +From 66ca8a14dae8a2afdeffd93f6560f655c040f93a Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Sun, 19 Jul 2020 17:11:06 -0400 +Subject: [PATCH 327/336] efi+dhcp: fix some allocation error checking. + +Signed-off-by: Peter Jones +--- + 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 + diff --git a/SOURCES/0328-efi-http-fix-some-allocation-error-checking.patch b/SOURCES/0328-efi-http-fix-some-allocation-error-checking.patch new file mode 100644 index 0000000..c201150 --- /dev/null +++ b/SOURCES/0328-efi-http-fix-some-allocation-error-checking.patch @@ -0,0 +1,42 @@ +From 5a964a7f388dd0ecf865fc0fde802b561aab2fb6 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Sun, 19 Jul 2020 17:14:15 -0400 +Subject: [PATCH 328/336] efi+http: fix some allocation error checking. + +Signed-off-by: Peter Jones +--- + 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 + diff --git a/SOURCES/0329-efi-ip-46-_config.c-fix-some-potential-allocation-ov.patch b/SOURCES/0329-efi-ip-46-_config.c-fix-some-potential-allocation-ov.patch new file mode 100644 index 0000000..5b7ac9e --- /dev/null +++ b/SOURCES/0329-efi-ip-46-_config.c-fix-some-potential-allocation-ov.patch @@ -0,0 +1,141 @@ +From ed7411d55fd5eae7b6c540e99cb2f41156d3e4c5 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Sun, 19 Jul 2020 17:27:00 -0400 +Subject: [PATCH 329/336] 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 +--- + grub-core/net/efi/ip4_config.c | 28 ++++++++++++++++++++-------- + grub-core/net/efi/ip6_config.c | 13 ++++++++++--- + 2 files changed, 30 insertions(+), 11 deletions(-) + +diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c +index 313c818b184..0f729b47cbd 100644 +--- a/grub-core/net/efi/ip4_config.c ++++ b/grub-core/net/efi/ip4_config.c +@@ -4,15 +4,20 @@ + #include + #include + #include ++#include + + 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; +@@ -56,7 +61,8 @@ 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, ncolon = 0; ++ grub_size_t i; ++ int ncolon = 0; + const char *ptr = val; + + /* Check that is not an IPv6 address */ +@@ -238,14 +244,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 +265,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 017c4d05bc7..a46f6f9b685 100644 +--- a/grub-core/net/efi/ip6_config.c ++++ b/grub-core/net/efi/ip6_config.c +@@ -3,6 +3,7 @@ + #include + #include + #include ++#include + + 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 + diff --git a/SOURCES/0330-Fix-up-some-types-for-gcc-4.8-compat-safemath.h.patch b/SOURCES/0330-Fix-up-some-types-for-gcc-4.8-compat-safemath.h.patch new file mode 100644 index 0000000..24b5186 --- /dev/null +++ b/SOURCES/0330-Fix-up-some-types-for-gcc-4.8-compat-safemath.h.patch @@ -0,0 +1,219 @@ +From 69af5fe86a8d3788c1bb95cbbacdb7d9b3f774d7 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 23 Jul 2020 15:02:48 -0400 +Subject: [PATCH 330/336] 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 +--- + 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 e3268d1a28d..5fa9f562e4f 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 5ff5f438b40..1239ac5e73f 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 fb5ab2b3deb..918f7b7b22f 100644 +--- a/grub-core/fs/btrfs.c ++++ b/grub-core/fs/btrfs.c +@@ -294,10 +294,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) +@@ -595,12 +600,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 2fda8d09caa..8459193c82c 100644 +--- a/grub-core/fs/ext2.c ++++ b/grub-core/fs/ext2.c +@@ -641,7 +641,8 @@ grub_ext2_read_symlink (grub_fshelp_node_t node) + return 0; + } + +- 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 2ef0b8d3fec..d9833f94414 100644 +--- a/grub-core/fs/hfsplus.c ++++ b/grub-core/fs/hfsplus.c +@@ -472,7 +472,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 f1611c5e311..af6eed7d484 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); + } +@@ -811,7 +811,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 2143ff7cd89..d89c0dafd52 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 + diff --git a/SOURCES/0331-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch b/SOURCES/0331-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch new file mode 100644 index 0000000..fa4d858 --- /dev/null +++ b/SOURCES/0331-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch @@ -0,0 +1,51 @@ +From f3c1a5319b5342362fcb8819c3df0dd790e4f3e6 Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Fri, 24 Jul 2020 17:18:09 +0100 +Subject: [PATCH 331/336] 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 +--- + 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 7166ec17f8f..95dbb9e20af 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -93,7 +94,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; + +@@ -104,7 +105,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 + diff --git a/SOURCES/0332-linux-loader-avoid-overflow-on-initrd-size-calculati.patch b/SOURCES/0332-linux-loader-avoid-overflow-on-initrd-size-calculati.patch new file mode 100644 index 0000000..e055036 --- /dev/null +++ b/SOURCES/0332-linux-loader-avoid-overflow-on-initrd-size-calculati.patch @@ -0,0 +1,29 @@ +From ca8b750f4c618cecddb3c2694509dc19daeae46a Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 24 Jul 2020 13:57:27 -0400 +Subject: [PATCH 332/336] linux loader: avoid overflow on initrd size + calculation + +Signed-off-by: Peter Jones +--- + 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 be6fa0f4d45..2305281df04 100644 +--- a/grub-core/loader/linux.c ++++ b/grub-core/loader/linux.c +@@ -151,8 +151,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 + diff --git a/SOURCES/0333-linuxefi-fail-kernel-validation-without-shim-protoco.patch b/SOURCES/0333-linuxefi-fail-kernel-validation-without-shim-protoco.patch new file mode 100644 index 0000000..c5c7f17 --- /dev/null +++ b/SOURCES/0333-linuxefi-fail-kernel-validation-without-shim-protoco.patch @@ -0,0 +1,104 @@ +From 02bdaed98f9a17a06f71ce7e21d9af2bd6547dfc Mon Sep 17 00:00:00 2001 +From: Dimitri John Ledkov +Date: Wed, 22 Jul 2020 11:31:43 +0100 +Subject: [PATCH 333/336] 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 +Signed-off-by: Dimitri John Ledkov +--- + grub-core/loader/arm64/linux.c | 12 ++++++++---- + grub-core/loader/efi/chainloader.c | 4 +--- + grub-core/loader/efi/linux.c | 1 + + grub-core/loader/i386/efi/linux.c | 13 ++++++++----- + 4 files changed, 18 insertions(+), 12 deletions(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index 1eb332a892c..d0a428d05fc 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -439,11 +439,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 dbcdf333b62..001766bdf68 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -1082,9 +1082,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + + return 0; + } +- +- grub_file_close (file); +- grub_device_close (dev); ++ // -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 7fe7201a388..d9b5380cfd3 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 95dbb9e20af..c146bc58e3d 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -201,12 +201,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- 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 + diff --git a/SOURCES/0334-linux-Fix-integer-overflows-in-initrd-size-handling.patch b/SOURCES/0334-linux-Fix-integer-overflows-in-initrd-size-handling.patch new file mode 100644 index 0000000..a51b5ce --- /dev/null +++ b/SOURCES/0334-linux-Fix-integer-overflows-in-initrd-size-handling.patch @@ -0,0 +1,168 @@ +From ea5144a3ca0b58e785dd9729e6c2d6a81e18870c Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Sat, 25 Jul 2020 12:15:37 +0100 +Subject: [PATCH 334/336] 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 +Reviewed-by: Jan Setje-Eilers +--- + 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 2305281df04..951f7556fb4 100644 +--- a/grub-core/loader/linux.c ++++ b/grub-core/loader/linux.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + + struct newc_head + { +@@ -98,13 +99,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++); +@@ -130,14 +131,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 +@@ -174,26 +183,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; +@@ -208,19 +224,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 +@@ -261,8 +287,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 + diff --git a/SOURCES/centos-ca-secureboot.der b/SOURCES/centos-ca-secureboot.der deleted file mode 100644 index 44a2563..0000000 Binary files a/SOURCES/centos-ca-secureboot.der and /dev/null differ diff --git a/SOURCES/centossecureboot001.crt b/SOURCES/centossecureboot001.crt deleted file mode 100644 index c67b0f3..0000000 --- a/SOURCES/centossecureboot001.crt +++ /dev/null @@ -1,81 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: - b6:16:15:71:72:fb:31:7e - Signature Algorithm: sha256WithRSAEncryption - Issuer: CN=CentOS Secure Boot (CA key 1)/emailAddress=security@centos.org - Validity - Not Before: Aug 1 11:47:30 2018 GMT - Not After : Dec 31 11:47:30 2037 GMT - Subject: CN=CentOS Secure Boot (key 1)/emailAddress=security@centos.org - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - RSA Public Key: (2048 bit) - Modulus (2048 bit): - 00:c1:a3:6a:f4:2d:71:83:6c:21:ca:0c:b7:ac:fa: - 76:80:43:03:40:87:5d:de:e9:1e:df:ad:e7:2b:51: - cb:f8:31:0f:9a:db:ab:23:25:04:11:05:57:7d:f2: - 4b:8d:1e:b3:75:78:1d:b9:57:8b:18:0b:bb:7e:e3: - 24:0f:6a:40:5f:2b:4f:03:a5:85:94:d2:f9:08:a0: - bc:db:a5:ea:4f:7f:e8:7c:d1:a9:f8:f0:9c:25:18: - 00:14:c4:c4:35:7d:1d:4c:8a:8d:95:f8:ed:65:97: - a5:a4:da:7d:cb:f0:33:3b:b7:03:94:68:47:05:57: - 6c:96:91:ac:14:f2:e3:f6:6d:4a:18:cf:68:8a:35: - 6f:8e:26:99:7f:db:c9:83:54:c2:c3:bf:ad:45:a0: - aa:a0:86:5f:20:b1:86:1b:ae:b7:28:15:11:f9:65: - 53:5d:70:33:9b:a3:c7:b5:c8:11:ff:55:3b:e7:46: - f1:6c:6b:8c:bb:f2:9f:36:23:b1:2d:23:2f:8f:4f: - 6c:a8:cc:ae:f5:56:9e:22:6c:0e:9a:4a:b1:bd:b2: - 76:15:5c:05:85:b8:5e:dc:8c:a5:c3:e0:75:51:a4: - 94:9b:03:2e:7b:f8:d3:b9:dd:7f:88:ce:2e:2f:28: - 4c:b4:92:2f:e6:e0:67:0a:d0:ff:c5:d2:79:a6:ef: - 94:0f - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: critical - CA:FALSE - X509v3 Key Usage: - Digital Signature - X509v3 Subject Key Identifier: - F0:37:C6:EA:EC:36:D4:05:7A:52:6C:0E:C6:D5:A9:5B:32:4E:E1:29 - X509v3 Authority Key Identifier: - keyid:54:EC:81:85:89:3E:E9:1A:DB:08:F7:44:88:54:7E:8E:3F:74:3A:F3 - - Signature Algorithm: sha256WithRSAEncryption - 97:97:ba:a6:0b:5b:bb:84:39:2e:ef:8b:51:9a:89:bb:65:3c: - dc:15:d0:5a:88:c5:af:ce:93:f5:c1:74:98:15:59:a9:38:da: - 11:fd:46:d5:4f:23:7c:03:1f:ae:0c:70:93:94:a7:61:2f:4b: - 2f:5f:bb:cc:8a:d7:4a:24:66:73:85:b4:19:13:fc:6a:61:4a: - 28:1f:a2:38:f4:72:90:03:c4:3e:64:63:8b:fb:15:22:22:4e: - b9:43:d9:b4:3d:3a:60:c1:4d:3a:09:85:68:7a:bc:3b:f9:ef: - f3:f5:e9:c9:4f:80:8c:c6:e9:cb:ef:28:44:b0:5d:d4:9e:4f: - 0f:02:9a:65:aa:98:35:b4:6f:d2:80:e3:08:ef:12:d0:17:56: - a6:a1:42:1e:1d:ab:e5:33:c0:fd:88:0d:40:42:81:c8:27:30: - 17:07:57:3e:05:9d:aa:05:0e:5b:3a:79:b4:29:aa:7c:42:5a: - ad:43:59:fb:34:4d:dc:62:58:63:e4:fb:de:bb:fd:6c:4e:97: - 58:f4:b9:99:4a:71:fe:7f:16:50:55:25:46:39:96:9b:88:6c: - 75:19:33:9e:70:b3:04:82:fe:16:a8:8e:22:47:83:6d:16:77: - da:26:ad:31:d8:06:6d:c5:7e:46:4b:21:ab:ae:ec:2a:93:71: - da:7f:89:1d ------BEGIN CERTIFICATE----- -MIIDdTCCAl2gAwIBAgIJALYWFXFy+zF+MA0GCSqGSIb3DQEBCwUAMEwxJjAkBgNV -BAMMHUNlbnRPUyBTZWN1cmUgQm9vdCAoQ0Ega2V5IDEpMSIwIAYJKoZIhvcNAQkB -FhNzZWN1cml0eUBjZW50b3Mub3JnMB4XDTE4MDgwMTExNDczMFoXDTM3MTIzMTEx -NDczMFowSTEjMCEGA1UEAxMaQ2VudE9TIFNlY3VyZSBCb290IChrZXkgMSkxIjAg -BgkqhkiG9w0BCQEWE3NlY3VyaXR5QGNlbnRvcy5vcmcwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDBo2r0LXGDbCHKDLes+naAQwNAh13e6R7frecrUcv4 -MQ+a26sjJQQRBVd98kuNHrN1eB25V4sYC7t+4yQPakBfK08DpYWU0vkIoLzbpepP -f+h80an48JwlGAAUxMQ1fR1Mio2V+O1ll6Wk2n3L8DM7twOUaEcFV2yWkawU8uP2 -bUoYz2iKNW+OJpl/28mDVMLDv61FoKqghl8gsYYbrrcoFRH5ZVNdcDObo8e1yBH/ -VTvnRvFsa4y78p82I7EtIy+PT2yozK71Vp4ibA6aSrG9snYVXAWFuF7cjKXD4HVR -pJSbAy57+NO53X+Izi4vKEy0ki/m4GcK0P/F0nmm75QPAgMBAAGjXTBbMAwGA1Ud -EwEB/wQCMAAwCwYDVR0PBAQDAgeAMB0GA1UdDgQWBBTwN8bq7DbUBXpSbA7G1alb -Mk7hKTAfBgNVHSMEGDAWgBRU7IGFiT7pGtsI90SIVH6OP3Q68zANBgkqhkiG9w0B -AQsFAAOCAQEAl5e6pgtbu4Q5Lu+LUZqJu2U83BXQWojFr86T9cF0mBVZqTjaEf1G -1U8jfAMfrgxwk5SnYS9LL1+7zIrXSiRmc4W0GRP8amFKKB+iOPRykAPEPmRji/sV -IiJOuUPZtD06YMFNOgmFaHq8O/nv8/XpyU+AjMbpy+8oRLBd1J5PDwKaZaqYNbRv -0oDjCO8S0BdWpqFCHh2r5TPA/YgNQEKByCcwFwdXPgWdqgUOWzp5tCmqfEJarUNZ -+zRN3GJYY+T73rv9bE6XWPS5mUpx/n8WUFUlRjmWm4hsdRkznnCzBIL+FqiOIkeD -bRZ32iatMdgGbcV+Rkshq67sKpNx2n+JHQ== ------END CERTIFICATE----- diff --git a/SOURCES/grub.macros b/SOURCES/grub.macros index 9736cf5..49340b8 100644 --- a/SOURCES/grub.macros +++ b/SOURCES/grub.macros @@ -101,6 +101,16 @@ -e 's/-m64//g' \\\ ) %{nil} %endif +%ifarch %{ix86} +%global target_cpu_name %{_arch} +%global grub_target_name %{_arch}-pc + +%global legacy_target_cpu_name i386 +%global legacy_package_arch pc +%global platform pc + +%global with_legacy_arch 0 +%endif %ifarch aarch64 %global efiarch aa64 @@ -152,6 +162,14 @@ %global with_efi_common 1 %global with_legacy_common 0 %endif +%ifarch %{ix86} +%global with_efi_arch 0 +%global with_alt_efi_arch 0 +%global with_efi_common 0 +%global with_legacy_common 1 +%global with_legacy_utils 1 +%global with_legacy_arch 0 +%endif %if 0%{with_efi_common} %global common_srcdir grub-%{grubefiarch}-%{tarversion} @@ -241,8 +259,8 @@ This subpackage provides optional components of grub used with removeable media %setup -D -q -T -a 0 -n grub-%{tarversion} \ cd grub-%{tarversion} \ rm -fv docs/*.info \ -cp %{SOURCE5} unifont.pcf.gz \ -cp %{SOURCE6} .gitignore \ +cp %{SOURCE3} unifont.pcf.gz \ +cp %{SOURCE4} .gitignore \ git init \ echo '![[:digit:]][[:digit:]]_*.in' > util/grub.d/.gitignore \ echo '!*.[[:digit:]]' > util/.gitignore \ @@ -309,8 +327,10 @@ done \ -p /EFI/%{efidir} -d grub-core ${GRUB_MODULES} \ %{4}./grub-mkimage -O %{1} -o %{3}.orig \\\ -p /EFI/BOOT -d grub-core ${GRUB_MODULES} \ -%{expand:%%{pesign -s -i %{2}.orig -o %{2} -a %{5} -c %{6} -n %{7}}} \ -%{expand:%%{pesign -s -i %{3}.orig -o %{3} -a %{5} -c %{6} -n %{7}}} \ +%{expand:%%{pesign -s -i %{2}.orig -o %{2}.one -a %{5} -c %{6} -n %{7}}} \ +%{expand:%%{pesign -s -i %{3}.orig -o %{3}.one -a %{5} -c %{6} -n %{7}}} \ +%{expand:%%{pesign -s -i %{2}.one -o %{2} -a %{8} -c %{9} -n %{10}}} \ +%{expand:%%{pesign -s -i %{3}.one -o %{3} -a %{8} -c %{9} -n %{10}}} \ %{nil} %else %define mkimage() \ @@ -327,18 +347,18 @@ GRUB_MODULES=" all_video boot btrfs cat chain configfile echo \\\ gzio halt hfsplus iso9660 jpeg loadenv loopback \\\ lvm mdraid09 mdraid1x minicmd normal part_apple \\\ part_msdos part_gpt password_pbkdf2 png reboot \\\ - search search_fs_uuid search_fs_file \\\ + regexp search search_fs_uuid search_fs_file \\\ search_label serial sleep syslinuxcfg test tftp \\\ video xfs" \ GRUB_MODULES+=%{efi_modules} \ -%{expand:%%{mkimage %{1} %{2} %{3} %{4} %{5} %{6} %{7}}} \ +%{expand:%%{mkimage %{1} %{2} %{3} %{4} %{5} %{6} %{7} %{8} %{9} %{10}}} \ %{nil} %define do_primary_efi_build() \ cd grub-%{1}-%{tarversion} \ %{expand:%%do_efi_configure %%{4} %%{5}} \ %do_efi_build_all \ -%{expand:%%do_efi_build_images %{grub_target_name} %{2} %{3} ./ %{6} %{7} %{8}}\ +%{expand:%%do_efi_build_images %{grub_target_name} %{2} %{3} ./ %{6} %{7} %{8} %{9} %{10} %{11}}\ cd .. \ %{nil} @@ -347,7 +367,7 @@ cd grub-%{1}-%{tarversion} \ %{expand:%%do_efi_configure %%{4} %%{5}} \ %do_efi_build_modules \ %{expand:%%do_efi_link_utils %{grubefiarch}} \ -%{expand:%%do_efi_build_images %{alt_grub_target_name} %{2} %{3} ../grub-%{grubefiarch}-%{tarversion}/ %{6} %{7} %{8}} \ +%{expand:%%do_efi_build_images %{alt_grub_target_name} %{2} %{3} ../grub-%{grubefiarch}-%{tarversion}/ %{6} %{7} %{8} %{9} %{10} %{11}} \ cd .. \ %{nil} diff --git a/SOURCES/grub.patches b/SOURCES/grub.patches index 5fda75b..9d0ffd1 100644 --- a/SOURCES/grub.patches +++ b/SOURCES/grub.patches @@ -287,3 +287,48 @@ Patch0286: 0286-efinet-also-use-the-firmware-acceleration-for-http.patch Patch0287: 0287-Make-root_url-reflect-the-protocol-hostname-of-our-b.patch Patch0288: 0288-efi-uga-Fix-PCIe-LER-when-GRUB2-accesses-non-enabled.patch Patch0289: 0289-efidisk-prevent-errors-from-diskfilter-scan-of-remov.patch +Patch0290: 0290-Prepend-prefix-when-HTTP-path-is-relative.patch +Patch0291: 0291-efi-http-Export-fw-http-_path-variables-to-make-them.patch +Patch0292: 0292-efi-http-Enclose-literal-IPv6-addresses-in-square-br.patch +Patch0293: 0293-efi-net-Allow-to-specify-a-port-number-in-addresses.patch +Patch0294: 0294-efi-ip4_config-Improve-check-to-detect-literal-IPv6-.patch +Patch0295: 0295-efi-net-Print-a-debug-message-if-parsing-the-address.patch +Patch0296: 0296-btrfs-avoid-used-uninitialized-error-with-GCC7.patch +Patch0297: 0297-build-Use-AC_HEADER_MAJOR-to-find-device-macros.patch +Patch0298: 0298-Fix-build-with-glibc-2.20.patch +Patch0299: 0299-yylex-Make-lexer-fatal-errors-actually-be-fatal.patch +Patch0300: 0300-safemath-Add-some-arithmetic-primitives-that-check-f.patch +Patch0301: 0301-calloc-Make-sure-we-always-have-an-overflow-checking.patch +Patch0302: 0302-calloc-Use-calloc-at-most-places.patch +Patch0303: 0303-malloc-Use-overflow-checking-primitives-where-we-do-.patch +Patch0304: 0304-iso9660-Don-t-leak-memory-on-realloc-failures.patch +Patch0305: 0305-font-Do-not-load-more-than-one-NAME-section.patch +Patch0306: 0306-gfxmenu-Fix-double-free-in-load_image.patch +Patch0307: 0307-xnu-Fix-double-free-in-grub_xnu_devprop_add_property.patch +Patch0308: 0308-lzma-Make-sure-we-don-t-dereference-past-array.patch +Patch0309: 0309-term-Fix-overflow-on-user-inputs.patch +Patch0310: 0310-udf-Fix-memory-leak.patch +Patch0311: 0311-multiboot2-Fix-memory-leak-if-grub_create_loader_cmd.patch +Patch0312: 0312-tftp-Do-not-use-priority-queue.patch +Patch0313: 0313-relocator-Protect-grub_relocator_alloc_chunk_addr-in.patch +Patch0314: 0314-relocator-Protect-grub_relocator_alloc_chunk_align-m.patch +Patch0315: 0315-script-Remove-unused-fields-from-grub_script_functio.patch +Patch0316: 0316-script-Avoid-a-use-after-free-when-redefining-a-func.patch +Patch0317: 0317-relocator-Fix-grub_relocator_alloc_chunk_align-top-m.patch +Patch0318: 0318-hfsplus-fix-two-more-overflows.patch +Patch0319: 0319-lvm-fix-two-more-potential-data-dependent-alloc-over.patch +Patch0320: 0320-emu-make-grub_free-NULL-safe.patch +Patch0321: 0321-efi-fix-some-malformed-device-path-arithmetic-errors.patch +Patch0322: 0322-Fix-a-regression-caused-by-efi-fix-some-malformed-de.patch +Patch0323: 0323-update-safemath-with-fallback-code-for-gcc-older-tha.patch +Patch0324: 0324-efi-Free-malloc-regions-on-exit.patch +Patch0325: 0325-efi-Fix-use-after-free-in-halt-reboot-path.patch +Patch0326: 0326-build-grub-module-verifier-make-output-more-useful.patch +Patch0327: 0327-efi-dhcp-fix-some-allocation-error-checking.patch +Patch0328: 0328-efi-http-fix-some-allocation-error-checking.patch +Patch0329: 0329-efi-ip-46-_config.c-fix-some-potential-allocation-ov.patch +Patch0330: 0330-Fix-up-some-types-for-gcc-4.8-compat-safemath.h.patch +Patch0331: 0331-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch +Patch0332: 0332-linux-loader-avoid-overflow-on-initrd-size-calculati.patch +Patch0333: 0333-linuxefi-fail-kernel-validation-without-shim-protoco.patch +Patch0334: 0334-linux-Fix-integer-overflows-in-initrd-size-handling.patch diff --git a/SOURCES/redhatsecureboot301.cer b/SOURCES/redhatsecureboot301.cer new file mode 100644 index 0000000..4ff8b79 Binary files /dev/null and b/SOURCES/redhatsecureboot301.cer differ diff --git a/SOURCES/redhatsecureboot502.cer b/SOURCES/redhatsecureboot502.cer new file mode 100644 index 0000000..be0b5e2 Binary files /dev/null and b/SOURCES/redhatsecureboot502.cer differ diff --git a/SOURCES/redhatsecurebootca3.cer b/SOURCES/redhatsecurebootca3.cer new file mode 100644 index 0000000..b235400 Binary files /dev/null and b/SOURCES/redhatsecurebootca3.cer differ diff --git a/SOURCES/redhatsecurebootca5.cer b/SOURCES/redhatsecurebootca5.cer new file mode 100644 index 0000000..dfb0284 Binary files /dev/null and b/SOURCES/redhatsecurebootca5.cer differ diff --git a/SOURCES/secureboot.cer b/SOURCES/secureboot.cer deleted file mode 100644 index 4ff8b79..0000000 Binary files a/SOURCES/secureboot.cer and /dev/null differ diff --git a/SOURCES/securebootca.cer b/SOURCES/securebootca.cer deleted file mode 100644 index b235400..0000000 Binary files a/SOURCES/securebootca.cer and /dev/null differ diff --git a/SPECS/grub2.spec b/SPECS/grub2.spec index f1b7336..f198c72 100644 --- a/SPECS/grub2.spec +++ b/SPECS/grub2.spec @@ -1,23 +1,12 @@ %undefine _hardened_build -%global flagday 1:2.02-0.76.el7.centos.1 + %global tarversion 2.02~beta2 %undefine _missing_build_ids_terminate_build -%define pesign_name centossecureboot001 - -%ifarch i686 -%define platform pc -%define legacy_package_arch i386 -%define legacy_target_cpu_name i386 -%define target_cpu_name i386 -%endif -%ifarch x86_64 -%define mock 1 -%endif Name: grub2 Epoch: 1 Version: 2.02 -Release: 0.81%{?dist}%{?buildid} +Release: 0.86%{?dist}%{?buildid} Summary: Bootloader with support for Linux, Multiboot and more Group: System Environment/Base License: GPLv3+ @@ -26,11 +15,12 @@ Source0: ftp://alpha.gnu.org/gnu/grub/grub-%{tarversion}.tar.xz #Source0: ftp://ftp.gnu.org/gnu/grub/grub-%%{tarversion}.tar.xz Source1: grub.macros Source2: grub.patches -Source3: centos-ca-secureboot.der -Source4: centossecureboot001.crt -#(source removed) -Source5: http://unifoundry.com/unifont-5.1.20080820.pcf.gz -Source6: gitignore +Source3: http://unifoundry.com/unifont-5.1.20080820.pcf.gz +Source4: gitignore +Source5: redhatsecurebootca3.cer +Source6: redhatsecureboot301.cer +Source7: redhatsecurebootca5.cer +Source8: redhatsecureboot502.cer %include %{SOURCE1} @@ -63,11 +53,8 @@ BuildRequires: pesign >= 0.99-8 %if %{?_with_ccache: 1}%{?!_with_ccache: 0} BuildRequires: ccache %endif -%if 0%{?centos} -%global efidir centos -%endif -ExcludeArch: s390 s390x %{arm} +ExcludeArch: s390 s390x %{arm} %{?ix86} Obsoletes: %{name} <= %{flagday} %if 0%{with_legacy_arch} @@ -152,11 +139,6 @@ This subpackage provides tools for support of all platforms. %prep %setup -T -c -n grub-%{tarversion} %do_common_setup -sed -i.orig -e 's@/efi/EFI/redhat/@/efi/EFI/%{efidir}/@' \ - grub-%{tarversion}/util/grub-setpassword.in -touch --reference=grub-%{tarversion}/util/grub-setpassword.in.orig \ - grub-%{tarversion}/util/grub-setpassword.in -rm -f grub-%{tarversion}/util/grub-setpassword.in.orig %if 0%{with_efi_arch} %do_setup %{grubefiarch} %endif @@ -169,10 +151,10 @@ rm -f grub-%{tarversion}/util/grub-setpassword.in.orig %build %if 0%{with_efi_arch} -%do_primary_efi_build %{grubefiarch} %{grubefiname} %{grubeficdname} %{_target_platform} "'%{efi_cflags}'" %{SOURCE3} %{SOURCE4} %{pesign_name} +%do_primary_efi_build %{grubefiarch} %{grubefiname} %{grubeficdname} %{_target_platform} "'%{efi_cflags}'" %{SOURCE5} %{SOURCE6} redhatsecureboot301 %{SOURCE7} %{SOURCE8} redhatsecureboot502 %endif %if 0%{with_alt_efi_arch} -%do_alt_efi_build %{grubaltefiarch} %{grubaltefiname} %{grubalteficdname} %{_alt_target_platform} "'%{alt_efi_cflags}'" %{SOURCE3} %{SOURCE4} %{pesign_name} +%do_alt_efi_build %{grubaltefiarch} %{grubaltefiname} %{grubalteficdname} %{_alt_target_platform} "'%{alt_efi_cflags}'" %{SOURCE5} %{SOURCE6} redhatsecureboot301 %{SOURCE7} %{SOURCE8} redhatsecureboot502 %endif %if 0%{with_legacy_arch}%{with_legacy_utils} %do_legacy_build %{grublegacyarch} @@ -484,9 +466,21 @@ fi %endif %changelog -* Tue Mar 31 2020 CentOS Sources - 2.02-0.81.el7.centos -- Roll in CentOS Secureboot keys -- Move the edidir to be CentOS, so people can co-install fedora, rhel and centos +* Tue Jul 28 2020 Peter Jones - 2.02-0.86 +- Fix several CVEs: + Resolves: CVE-2020-10713 + Resolves: CVE-2020-14308 + Resolves: CVE-2020-14309 + Resolves: CVE-2020-14310 + Resolves: CVE-2020-14311 + +* Mon Mar 23 2020 Javier Martinez Canillas - 2.02-0.82 +- Prepend prefix when HTTP path is relative +- efi/http: Export {fw,http}_path variables to make them global +- efi/http: Enclose literal IPv6 addresses in square brackets +- efi/net: Allow to specify a port number in addresses +- efi/ip4_config: Improve check to detect literal IPv6 addresses +- efi/net: Print a debug message if parsing the address fails * Fri Sep 13 2019 Javier Martinez Canillas - 2.02-0.81 - Only make grub2-tools Obsoletes and Provides grub2-tools-efi for x86_64