Merge ~ubuntu-uefi-team/grub/+git/ubuntu:ubuntu into ~ubuntu-core-dev/grub/+git/ubuntu:ubuntu
- Git
- lp:~ubuntu-uefi-team/grub/+git/ubuntu
- ubuntu
- Merge into ubuntu
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merge reported by: | Mate Kukri | ||||||||||||
Merged at revision: | f1625e10dda448f9592c1f2b3142a43cf9b5d46b | ||||||||||||
Proposed branch: | ~ubuntu-uefi-team/grub/+git/ubuntu:ubuntu | ||||||||||||
Merge into: | ~ubuntu-core-dev/grub/+git/ubuntu:ubuntu | ||||||||||||
Diff against target: |
2339 lines (+1674/-237) 24 files modified
debian/build-efi-images (+6/-0) debian/changelog (+26/-0) debian/control (+2/-0) debian/grub-sort-version (+2/-2) debian/patches/grub-sort-version.patch (+16/-1) debian/patches/kern-efi-mm-Change-grub_efi_allocate_pages_real-to-call-s.patch (+36/-0) debian/patches/kern-efi-mm-Change-grub_efi_mm_add_regions-to-keep-track-.patch (+69/-0) debian/patches/kern-efi-mm-Detect-calls-to-grub_efi_drop_alloc-with-wron.patch (+34/-0) debian/patches/nx/efi-Disallow-fallback-to-legacy-Linux-loader-when-shim-sa.patch (+116/-0) debian/patches/nx/modules-Don-t-allocate-space-for-non-allocable-sections.patch (+37/-0) debian/patches/nx/modules-load-module-sections-at-page-aligned-addresses.patch (+390/-0) debian/patches/nx/modules-strip-.llvm_addrsig-sections-and-similar.patch (+41/-0) debian/patches/nx/nx-add-memory-attribute-get-set-API.patch (+252/-0) debian/patches/nx/nx-set-page-permissions-for-loaded-modules.patch (+222/-0) debian/patches/nx/nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch (+49/-0) debian/patches/nx/peimage-Add-memory-attribute-support.patch (+132/-0) debian/patches/secure-boot/efi-use-peimage-shim.patch (+151/-227) debian/patches/series (+11/-0) debian/patches/suse-grub.texi-add-net_bootp6-document.patch (+3/-3) debian/patches/ubuntu-fix-lzma-decompressor-objcopy.patch (+1/-1) debian/patches/ubuntu-support-initrd-less-boot.patch (+1/-1) debian/rules (+3/-0) debian/sbat.ubuntu.csv.in (+2/-2) debian/test_grub_sort_version.py (+72/-0) |
||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Julian Andres Klode | Pending | ||
Review via email: mp+461796@code.launchpad.net |
Commit message
Description of the change
- f8ebfa5... by Mate Kukri
-
Increase SBAT level to "grub.ubuntu,2" and "grub.peimage,2"
- 4858769... by Mate Kukri
-
Revert peimage to re-use GRUB's image handle (LP: #2057679) (LP: #2054127)
peimage sometimes has to load things such as systemd-stub that will pass
their ImageHandle to the firmware's LoadImage() as ParentImageHandle.Such a ParentImageHandle must always come from the firmware itself,
otherwise LoadImage() asserts.Reverting to the old implementation also fixes LP: #2054127 as systab
hook installation will again be done in StartImage(). - 0efc7d0... by Mate Kukri
-
d/build-efi-images: Make sure downstream didn't remove peimage SBAT entry
- 2e09b0d... by Mate Kukri
-
releasing package grub2 version 2.12-1ubuntu5
- 67b61d4... by Mate Kukri
-
Add 2.12-1ubuntu6 to changelog
- 4be2e5f... by Mate Kukri
-
releasing package grub2 version 2.12-1ubuntu7
- 44ab0d1... by Mate Kukri
-
peimage: Ignore empty sections when checking for bounds
These checks were assuming empty sections to overlap, this is wrong, and
was preventing things like Xen from booting. - 21fab0b... by Mate Kukri
-
peimage: Make sure partially loaded images are unloaded on error
- 83485b1... by Mate Kukri
-
Cherry-pick upstream efi mm patches to avoid crashing at exit on Mu
- f1625e1... by Mate Kukri
-
Implement support for UEFI NX mitigation
- Cherry-picked relevant upstream NX patches
- Implemented support for NX in peimage
Preview Diff
1 | diff --git a/debian/build-efi-images b/debian/build-efi-images |
2 | index d17e225..2f847f2 100755 |
3 | --- a/debian/build-efi-images |
4 | +++ b/debian/build-efi-images |
5 | @@ -33,6 +33,12 @@ efi_name="$6" |
6 | sbat_csv="$7" |
7 | efi_vendor="${8:-$(dpkg-vendor --query vendor | tr '[:upper:]' '[:lower:]')}" |
8 | |
9 | +# make sure downstreams didn't mess up sbat.csv |
10 | +if ! grep -q ^grub.peimage $sbat_csv; then |
11 | + echo Missing sbat entry for "grub.peimage" >&2 |
12 | + exit 1 |
13 | +fi |
14 | + |
15 | # mkfs.msdos may not be on the default PATH. |
16 | export PATH="$PATH:/sbin:/usr/sbin" |
17 | |
18 | diff --git a/debian/changelog b/debian/changelog |
19 | index bc37a14..b9aae02 100644 |
20 | --- a/debian/changelog |
21 | +++ b/debian/changelog |
22 | @@ -1,3 +1,29 @@ |
23 | +grub2 (2.12-1ubuntu7) noble; urgency=medium |
24 | + |
25 | + * d/p/grub-sort-version.patch: Also patch grub-mkconfig to export GRUB_FLAVOUR_ORDER |
26 | + * d/grub-sort-version: Update regex to correctly match kernel flavour |
27 | + * d/grub-sort-version: Append `-0` to abi strings before passing to python-apt (Fixes LP: #2041827) |
28 | + * debian/: Add tests for grub-sort-version |
29 | + * Revert peimage to re-use GRUB's image handle (LP: #2057679) (LP: #2054127) |
30 | + * Increase SBAT level to "grub.ubuntu,2" and "grub.peimage,2" |
31 | + * d/build-efi-images: Make sure downstream didn't remove peimage SBAT entry |
32 | + * SECURITY UPDATE: Use-after-free in peimage module [LP: #2054127] |
33 | + - CVE-2024-2312 |
34 | + |
35 | + -- Mate Kukri <mate.kukri@canonical.com> Thu, 04 Apr 2024 11:12:35 +0100 |
36 | + |
37 | +grub2 (2.12-1ubuntu6) noble; urgency=medium |
38 | + |
39 | + * No-change rebuild for CVE-2024-3094 |
40 | + |
41 | + -- Steve Langasek <steve.langasek@ubuntu.com> Sun, 31 Mar 2024 08:54:41 +0000 |
42 | + |
43 | +grub2 (2.12-1ubuntu5) noble; urgency=medium |
44 | + |
45 | + * No-change rebuild for libefivar1t64 on riscv64. |
46 | + |
47 | + -- Steve Langasek <steve.langasek@ubuntu.com> Thu, 07 Mar 2024 09:18:17 +0000 |
48 | + |
49 | grub2 (2.12-1ubuntu4) noble; urgency=medium |
50 | |
51 | * d/grub-multi-install: Treat missing `cloud_style_installation` debconf as |
52 | diff --git a/debian/control b/debian/control |
53 | index efd46e3..3cc18db 100644 |
54 | --- a/debian/control |
55 | +++ b/debian/control |
56 | @@ -7,6 +7,8 @@ Uploaders: Felix Zielcke <fzielcke@z-51.de>, Jordi Mallach <jordi@debian.org>, S |
57 | Build-Depends: debhelper-compat (= 13), |
58 | patchutils, |
59 | python3, |
60 | + python3-apt, |
61 | + python3-pytest, |
62 | flex, |
63 | bison, |
64 | gawk, |
65 | diff --git a/debian/grub-sort-version b/debian/grub-sort-version |
66 | index 6e47231..40a6eda 100755 |
67 | --- a/debian/grub-sort-version |
68 | +++ b/debian/grub-sort-version |
69 | @@ -28,7 +28,7 @@ class KernelABI: |
70 | if self._index != other._index: |
71 | # Ordering is reversed, what should be considered highest comes first. |
72 | return self._index > other._index |
73 | - return apt_pkg.version_compare(self.abi, other.abi) < 0 |
74 | + return apt_pkg.version_compare(f"{self.abi}-0", f"{other.abi}-0") < 0 |
75 | |
76 | |
77 | def main() -> None: |
78 | @@ -43,7 +43,7 @@ def main() -> None: |
79 | |
80 | order = [] |
81 | for flavour in os.environ.get("GRUB_FLAVOUR_ORDER", "").split(): |
82 | - order.append(re.compile(f"[0-9]*-{flavour}$")) |
83 | + order.append(re.compile(f"[\\s\\S]*-{flavour}(\\s*\\d*)$")) |
84 | |
85 | versions = [KernelABI(line.rstrip(), order) for line in sys.stdin] |
86 | versions.sort(reverse=args.reverse) |
87 | diff --git a/debian/patches/grub-sort-version.patch b/debian/patches/grub-sort-version.patch |
88 | index d885c50..8e6385c 100644 |
89 | --- a/debian/patches/grub-sort-version.patch |
90 | +++ b/debian/patches/grub-sort-version.patch |
91 | @@ -6,9 +6,24 @@ We need to have support for GRUB_FLAVOUR_ORDER and it's arguably |
92 | the easiest way to hook this in, although you might be able to |
93 | write this as an awk script or something. |
94 | --- |
95 | + util/grub-mkconfig.in | 3 ++- |
96 | util/grub-mkconfig_lib.in | 15 +-------------- |
97 | - 1 file changed, 1 insertion(+), 14 deletions(-) |
98 | + 2 files changed, 3 insertions(+), 15 deletions(-) |
99 | |
100 | +diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in |
101 | +index 46b036b..0b1adf5 100644 |
102 | +--- a/util/grub-mkconfig.in |
103 | ++++ b/util/grub-mkconfig.in |
104 | +@@ -270,7 +270,8 @@ export GRUB_DEFAULT \ |
105 | + GRUB_RECORDFAIL_TIMEOUT \ |
106 | + GRUB_RECOVERY_TITLE \ |
107 | + GRUB_FORCE_PARTUUID \ |
108 | +- GRUB_DISABLE_INITRD |
109 | ++ GRUB_DISABLE_INITRD \ |
110 | ++ GRUB_FLAVOUR_ORDER |
111 | + |
112 | + if test "x${grub_cfg}" != "x"; then |
113 | + rm -f "${grub_cfg}.new" |
114 | diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in |
115 | index 121df9a..cabac83 100644 |
116 | --- a/util/grub-mkconfig_lib.in |
117 | diff --git a/debian/patches/kern-efi-mm-Change-grub_efi_allocate_pages_real-to-call-s.patch b/debian/patches/kern-efi-mm-Change-grub_efi_allocate_pages_real-to-call-s.patch |
118 | new file mode 100644 |
119 | index 0000000..0764e5e |
120 | --- /dev/null |
121 | +++ b/debian/patches/kern-efi-mm-Change-grub_efi_allocate_pages_real-to-call-s.patch |
122 | @@ -0,0 +1,36 @@ |
123 | +From: Mate Kukri <mate.kukri@canonical.com> |
124 | +Date: Tue, 11 Jun 2024 15:21:33 +0100 |
125 | +Subject: kern/efi/mm: Change grub_efi_allocate_pages_real() to call |
126 | + semantically correct free function |
127 | + |
128 | +If the firmware happens to return 0 as an address of allocated pages, |
129 | +grub_efi_allocate_pages_real() tries to allocate a new set of pages, |
130 | +and then free the ones at address 0. |
131 | + |
132 | +However at that point grub_efi_store_alloc() wasn't yet called, so |
133 | +freeing the pages at 0 using grub_efi_free_pages() which calls |
134 | +grub_efi_drop_alloc() isn't necessary, so let's call b->free_pages() |
135 | +instead. |
136 | + |
137 | +The call to grub_efi_drop_alloc() doesn't seem particularly harmful, |
138 | +because it seems to do nothing if the allocation it is asked to drop |
139 | +isn't on the list, but the call to it is obviously unnecessary here. |
140 | + |
141 | +Signed-off-by: Mate Kukri <mate.kukri@canonical.com> |
142 | +--- |
143 | + grub-core/kern/efi/mm.c | 2 +- |
144 | + 1 file changed, 1 insertion(+), 1 deletion(-) |
145 | + |
146 | +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c |
147 | +index 4fec188..6613191 100644 |
148 | +--- a/grub-core/kern/efi/mm.c |
149 | ++++ b/grub-core/kern/efi/mm.c |
150 | +@@ -150,7 +150,7 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, |
151 | + so reallocate another one. */ |
152 | + address = GRUB_EFI_MAX_USABLE_ADDRESS; |
153 | + status = b->allocate_pages (alloctype, memtype, pages, &address); |
154 | +- grub_efi_free_pages (0, pages); |
155 | ++ b->free_pages (0, pages); |
156 | + if (status != GRUB_EFI_SUCCESS) |
157 | + { |
158 | + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); |
159 | diff --git a/debian/patches/kern-efi-mm-Change-grub_efi_mm_add_regions-to-keep-track-.patch b/debian/patches/kern-efi-mm-Change-grub_efi_mm_add_regions-to-keep-track-.patch |
160 | new file mode 100644 |
161 | index 0000000..96bebaf |
162 | --- /dev/null |
163 | +++ b/debian/patches/kern-efi-mm-Change-grub_efi_mm_add_regions-to-keep-track-.patch |
164 | @@ -0,0 +1,69 @@ |
165 | +From: Mate Kukri <mate.kukri@canonical.com> |
166 | +Date: Tue, 11 Jun 2024 15:19:48 +0100 |
167 | +Subject: kern/efi/mm: Change grub_efi_mm_add_regions() to keep track of map |
168 | + allocation size |
169 | + |
170 | +If the map was too big for the initial allocation, it was freed and replaced |
171 | +with a bigger one, but the free call still used the hard-coded size. |
172 | + |
173 | +Seems like this wasn't hit for a long time, because most firmware maps |
174 | +fit into 12K. |
175 | + |
176 | +This bug was trigerred on Project Mu firmware with a big memory map, and |
177 | +results in the heap getting trashed and the firmware ASSERTING on |
178 | +corrupted heap guard values when GRUB exits. |
179 | + |
180 | +Signed-off-by: Mate Kukri <mate.kukri@canonical.com> |
181 | +--- |
182 | + grub-core/kern/efi/mm.c | 14 +++++++------- |
183 | + 1 file changed, 7 insertions(+), 7 deletions(-) |
184 | + |
185 | +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c |
186 | +index 6a6fba8..4fec188 100644 |
187 | +--- a/grub-core/kern/efi/mm.c |
188 | ++++ b/grub-core/kern/efi/mm.c |
189 | +@@ -574,13 +574,15 @@ grub_efi_mm_add_regions (grub_size_t required_bytes, unsigned int flags) |
190 | + grub_efi_memory_descriptor_t *memory_map_end; |
191 | + grub_efi_memory_descriptor_t *filtered_memory_map; |
192 | + grub_efi_memory_descriptor_t *filtered_memory_map_end; |
193 | ++ grub_efi_uintn_t alloc_size; |
194 | + grub_efi_uintn_t map_size; |
195 | + grub_efi_uintn_t desc_size; |
196 | + grub_err_t err; |
197 | + int mm_status; |
198 | + |
199 | + /* Prepare a memory region to store two memory maps. */ |
200 | +- memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); |
201 | ++ alloc_size = 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE); |
202 | ++ memory_map = grub_efi_allocate_any_pages (alloc_size); |
203 | + if (! memory_map) |
204 | + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for memory map"); |
205 | + |
206 | +@@ -591,14 +593,13 @@ grub_efi_mm_add_regions (grub_size_t required_bytes, unsigned int flags) |
207 | + |
208 | + if (mm_status == 0) |
209 | + { |
210 | +- grub_efi_free_pages |
211 | +- ((grub_efi_physical_address_t) ((grub_addr_t) memory_map), |
212 | +- 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); |
213 | ++ grub_efi_free_pages ((grub_efi_physical_address_t) (grub_addr_t) memory_map, alloc_size); |
214 | + |
215 | + /* Freeing/allocating operations may increase memory map size. */ |
216 | + map_size += desc_size * 32; |
217 | + |
218 | +- memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (map_size)); |
219 | ++ alloc_size = 2 * BYTES_TO_PAGES (map_size); |
220 | ++ memory_map = grub_efi_allocate_any_pages (alloc_size); |
221 | + if (! memory_map) |
222 | + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for new memory map"); |
223 | + |
224 | +@@ -642,8 +643,7 @@ grub_efi_mm_add_regions (grub_size_t required_bytes, unsigned int flags) |
225 | + #endif |
226 | + |
227 | + /* Release the memory maps. */ |
228 | +- grub_efi_free_pages ((grub_addr_t) memory_map, |
229 | +- 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); |
230 | ++ grub_efi_free_pages ((grub_efi_physical_address_t) (grub_addr_t) memory_map, alloc_size); |
231 | + |
232 | + return GRUB_ERR_NONE; |
233 | + } |
234 | diff --git a/debian/patches/kern-efi-mm-Detect-calls-to-grub_efi_drop_alloc-with-wron.patch b/debian/patches/kern-efi-mm-Detect-calls-to-grub_efi_drop_alloc-with-wron.patch |
235 | new file mode 100644 |
236 | index 0000000..9de1acd |
237 | --- /dev/null |
238 | +++ b/debian/patches/kern-efi-mm-Detect-calls-to-grub_efi_drop_alloc-with-wron.patch |
239 | @@ -0,0 +1,34 @@ |
240 | +From: Mate Kukri <mate.kukri@canonical.com> |
241 | +Date: Wed, 12 Jun 2024 09:29:29 +0100 |
242 | +Subject: kern/efi/mm: Detect calls to grub_efi_drop_alloc() with wrong page |
243 | + counts |
244 | + |
245 | +Silently keeping entries in the list if the address matches, but the |
246 | +page count doesn't is a bad idea, and can lead to double frees. |
247 | + |
248 | +grub_efi_free_pages() have already freed parts of this block by this |
249 | +point, and thus keeping the whole block in the list and freeing it again |
250 | +at exit can lead to double frees. |
251 | + |
252 | +Signed-off-by: Mate Kukri <mate.kukri@canonical.com> |
253 | +--- |
254 | + grub-core/kern/efi/mm.c | 6 ++++-- |
255 | + 1 file changed, 4 insertions(+), 2 deletions(-) |
256 | + |
257 | +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c |
258 | +index 6613191..d45d0e2 100644 |
259 | +--- a/grub-core/kern/efi/mm.c |
260 | ++++ b/grub-core/kern/efi/mm.c |
261 | +@@ -95,8 +95,10 @@ grub_efi_drop_alloc (grub_efi_physical_address_t address, |
262 | + |
263 | + for (eap = NULL, ea = efi_allocated_memory; ea; eap = ea, ea = ea->next) |
264 | + { |
265 | +- if (ea->address != address || ea->pages != pages) |
266 | +- continue; |
267 | ++ if (ea->address != address) |
268 | ++ continue; |
269 | ++ if (ea->pages != pages) |
270 | ++ grub_fatal ("grub_efi_drop_alloc() called with wrong page count"); |
271 | + |
272 | + /* Remove the current entry from the list. */ |
273 | + if (eap) |
274 | diff --git a/debian/patches/nx/efi-Disallow-fallback-to-legacy-Linux-loader-when-shim-sa.patch b/debian/patches/nx/efi-Disallow-fallback-to-legacy-Linux-loader-when-shim-sa.patch |
275 | new file mode 100644 |
276 | index 0000000..ecb6371 |
277 | --- /dev/null |
278 | +++ b/debian/patches/nx/efi-Disallow-fallback-to-legacy-Linux-loader-when-shim-sa.patch |
279 | @@ -0,0 +1,116 @@ |
280 | +From: Mate Kukri <mate.kukri@canonical.com> |
281 | +Date: Fri, 31 May 2024 13:00:37 +0100 |
282 | +Subject: efi: Disallow fallback to legacy Linux loader when shim says NX is |
283 | + required. |
284 | + |
285 | +Signed-off-by: Mate Kukri <mate.kukri@canonical.com> |
286 | +--- |
287 | + grub-core/kern/efi/sb.c | 28 ++++++++++++++++++++++++++++ |
288 | + grub-core/loader/efi/linux.c | 13 ++++++++----- |
289 | + include/grub/efi/api.h | 2 ++ |
290 | + include/grub/efi/sb.h | 2 ++ |
291 | + 4 files changed, 40 insertions(+), 5 deletions(-) |
292 | + |
293 | +diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c |
294 | +index 80cfa08..8eb6bce 100644 |
295 | +--- a/grub-core/kern/efi/sb.c |
296 | ++++ b/grub-core/kern/efi/sb.c |
297 | +@@ -218,3 +218,31 @@ grub_shim_lock_verifier_setup (void) |
298 | + grub_env_set ("shim_lock", "y"); |
299 | + grub_env_export ("shim_lock"); |
300 | + } |
301 | ++ |
302 | ++int |
303 | ++grub_efi_check_nx_required (void) |
304 | ++{ |
305 | ++ int nx_required = 1; /* assume required, unless we can prove otherwise */ |
306 | ++ grub_efi_status_t status; |
307 | ++ grub_size_t mok_policy_sz = 0; |
308 | ++ char *mok_policy = NULL; |
309 | ++ grub_uint32_t mok_policy_attrs = 0; |
310 | ++ |
311 | ++ status = grub_efi_get_variable_with_attributes ("MokPolicy", |
312 | ++ &(grub_guid_t) GRUB_EFI_SHIM_LOCK_GUID, |
313 | ++ &mok_policy_sz, |
314 | ++ (void **)&mok_policy, |
315 | ++ &mok_policy_attrs); |
316 | ++ if (status != GRUB_EFI_SUCCESS || |
317 | ++ mok_policy_sz != 1 || |
318 | ++ mok_policy == NULL || |
319 | ++ mok_policy_attrs != GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS) |
320 | ++ goto out; |
321 | ++ |
322 | ++ nx_required = !!(mok_policy[0] & GRUB_MOK_POLICY_NX_REQUIRED); |
323 | ++ |
324 | ++ out: |
325 | ++ grub_free (mok_policy); |
326 | ++ |
327 | ++ return nx_required; |
328 | ++} |
329 | +diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c |
330 | +index 2b891d6..47ef165 100644 |
331 | +--- a/grub-core/loader/efi/linux.c |
332 | ++++ b/grub-core/loader/efi/linux.c |
333 | +@@ -29,6 +29,7 @@ |
334 | + #include <grub/efi/fdtload.h> |
335 | + #include <grub/efi/memory.h> |
336 | + #include <grub/efi/pe32.h> |
337 | ++#include <grub/efi/sb.h> |
338 | + #include <grub/i18n.h> |
339 | + #include <grub/lib/cmdline.h> |
340 | + #include <grub/verify.h> |
341 | +@@ -473,21 +474,23 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), |
342 | + |
343 | + kernel_size = grub_file_size (file); |
344 | + |
345 | +- if (grub_arch_efi_linux_load_image_header (file, &lh) != GRUB_ERR_NONE) |
346 | + #if !defined(__i386__) && !defined(__x86_64__) |
347 | ++ if (grub_arch_efi_linux_load_image_header (file, &lh) != GRUB_ERR_NONE) |
348 | + goto fail; |
349 | + #else |
350 | +- goto fallback; |
351 | +- |
352 | +- if (!initrd_use_loadfile2) |
353 | ++ if (grub_arch_efi_linux_load_image_header (file, &lh) != GRUB_ERR_NONE || |
354 | ++ !initrd_use_loadfile2) |
355 | + { |
356 | ++ /* We cannot use the legacy loader when NX is required */ |
357 | ++ if (grub_efi_check_nx_required()) |
358 | ++ goto fail; |
359 | ++ |
360 | + /* |
361 | + * This is a EFI stub image but it is too old to implement the LoadFile2 |
362 | + * based initrd loading scheme, and Linux/x86 does not support the DT |
363 | + * based method either. So fall back to the x86-specific loader that |
364 | + * enters Linux in EFI mode but without going through its EFI stub. |
365 | + */ |
366 | +-fallback: |
367 | + grub_file_close (file); |
368 | + return grub_cmd_linux_x86_legacy (cmd, argc, argv); |
369 | + } |
370 | +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h |
371 | +index 699bccf..343f968 100644 |
372 | +--- a/include/grub/efi/api.h |
373 | ++++ b/include/grub/efi/api.h |
374 | +@@ -2023,6 +2023,8 @@ struct grub_efi_dt_fixup |
375 | + }; |
376 | + typedef struct grub_efi_dt_fixup grub_efi_dt_fixup_t; |
377 | + |
378 | ++#define GRUB_MOK_POLICY_NX_REQUIRED 0x1 |
379 | ++ |
380 | + struct grub_efi_shim_lock_protocol |
381 | + { |
382 | + /* |
383 | +diff --git a/include/grub/efi/sb.h b/include/grub/efi/sb.h |
384 | +index 30c4335..83ba311 100644 |
385 | +--- a/include/grub/efi/sb.h |
386 | ++++ b/include/grub/efi/sb.h |
387 | +@@ -33,6 +33,8 @@ EXPORT_FUNC (grub_efi_get_secureboot) (void); |
388 | + |
389 | + extern void |
390 | + grub_shim_lock_verifier_setup (void); |
391 | ++extern int |
392 | ++EXPORT_FUNC (grub_efi_check_nx_required) (void); |
393 | + #else |
394 | + static inline grub_uint8_t |
395 | + grub_efi_get_secureboot (void) |
396 | diff --git a/debian/patches/nx/modules-Don-t-allocate-space-for-non-allocable-sections.patch b/debian/patches/nx/modules-Don-t-allocate-space-for-non-allocable-sections.patch |
397 | new file mode 100644 |
398 | index 0000000..4721e2d |
399 | --- /dev/null |
400 | +++ b/debian/patches/nx/modules-Don-t-allocate-space-for-non-allocable-sections.patch |
401 | @@ -0,0 +1,37 @@ |
402 | +From: Peter Jones <pjones@redhat.com> |
403 | +Date: Mon, 21 Mar 2022 16:56:10 -0400 |
404 | +Subject: modules: Don't allocate space for non-allocable sections. |
405 | + |
406 | +Currently when loading grub modules, we allocate space for all sections, |
407 | +including those without SHF_ALLOC set. We then copy the sections that |
408 | +/do/ have SHF_ALLOC set into the allocated memory, leaving some of our |
409 | +allocation untouched forever. Additionally, on platforms with GOT |
410 | +fixups and trampolines, we currently compute alignment round-ups for the |
411 | +sections and sections with sh_size = 0. |
412 | + |
413 | +This patch removes the extra space from the allocation computation, and |
414 | +makes the allocation computation loop skip empty sections as the loading |
415 | +loop does. |
416 | + |
417 | +Signed-off-by: Peter Jones <pjones@redhat.com> |
418 | +Signed-off-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com> |
419 | +Signed-off-by: Mate Kukri <mate.kukri@canonical.com> |
420 | +Reviewed-By: Vladimir Serbinenko |
421 | +--- |
422 | + grub-core/kern/dl.c | 3 +++ |
423 | + 1 file changed, 3 insertions(+) |
424 | + |
425 | +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c |
426 | +index 0bf40ca..37db9fa 100644 |
427 | +--- a/grub-core/kern/dl.c |
428 | ++++ b/grub-core/kern/dl.c |
429 | +@@ -237,6 +237,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) |
430 | + i < e->e_shnum; |
431 | + i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) |
432 | + { |
433 | ++ if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC)) |
434 | ++ continue; |
435 | ++ |
436 | + tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size; |
437 | + if (talign < s->sh_addralign) |
438 | + talign = s->sh_addralign; |
439 | diff --git a/debian/patches/nx/modules-load-module-sections-at-page-aligned-addresses.patch b/debian/patches/nx/modules-load-module-sections-at-page-aligned-addresses.patch |
440 | new file mode 100644 |
441 | index 0000000..a652ea3 |
442 | --- /dev/null |
443 | +++ b/debian/patches/nx/modules-load-module-sections-at-page-aligned-addresses.patch |
444 | @@ -0,0 +1,390 @@ |
445 | +From: Mate Kukri <mate.kukri@canonical.com> |
446 | +Date: Mon, 21 Mar 2022 17:45:40 -0400 |
447 | +Subject: modules: load module sections at page-aligned addresses |
448 | + |
449 | +Currently we load module sections at whatever alignment gcc+ld happened |
450 | +to dump into the ELF section header, which is often less then the page |
451 | +size. Since NX protections are page based, this alignment must be |
452 | +rounded up to page size on platforms supporting NX protections. |
453 | + |
454 | +This patch switches most EFI platforms to load module sections at 4kB |
455 | +page-aligned addresses. To do so, it adds an new per-arch function, |
456 | +grub_arch_dl_min_alignment(), which returns the alignment needed for |
457 | +dynamically loaded sections (in bytes). Currently it sets it to 4096 |
458 | +when GRUB_MACHINE_EFI is true on x86_64, i386, arm, arm64, and emu, and |
459 | +1-byte alignment on everything else. |
460 | + |
461 | +It then changes the allocation size computation and the loader code in |
462 | +grub_dl_load_segments() to align the locations and sizes up to these |
463 | +boundaries, and fills any added padding with zeros. |
464 | + |
465 | +All of this happens before relocations are applied, so the relocations |
466 | +factor that in with no change. |
467 | + |
468 | +Original-Author: Peter Jones <pjones@redhat.com> |
469 | +Original-Author: Laszlo Ersek <lersek@redhat.com> |
470 | +Signed-off-by: Mate Kukri <mate.kukri@canonical.com> |
471 | +--- |
472 | + docs/grub-dev.texi | 6 ++--- |
473 | + grub-core/kern/arm/dl.c | 13 +++++++++++ |
474 | + grub-core/kern/arm64/dl.c | 13 +++++++++++ |
475 | + grub-core/kern/dl.c | 53 +++++++++++++++++++++++++++++++-------------- |
476 | + grub-core/kern/emu/full.c | 13 +++++++++++ |
477 | + grub-core/kern/i386/dl.c | 13 +++++++++++ |
478 | + grub-core/kern/ia64/dl.c | 9 ++++++++ |
479 | + grub-core/kern/mips/dl.c | 8 +++++++ |
480 | + grub-core/kern/powerpc/dl.c | 9 ++++++++ |
481 | + grub-core/kern/riscv/dl.c | 13 +++++++++++ |
482 | + grub-core/kern/sparc64/dl.c | 9 ++++++++ |
483 | + grub-core/kern/x86_64/dl.c | 13 +++++++++++ |
484 | + include/grub/dl.h | 2 ++ |
485 | + 13 files changed, 155 insertions(+), 19 deletions(-) |
486 | + |
487 | +diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi |
488 | +index 1276c59..2f782cd 100644 |
489 | +--- a/docs/grub-dev.texi |
490 | ++++ b/docs/grub-dev.texi |
491 | +@@ -996,9 +996,9 @@ declare startup asm file ($cpu_$platform_startup) as well as any other files |
492 | + (e.g. init.c and callwrap.S) (e.g. $cpu_$platform = kern/$cpu/$platform/init.c). |
493 | + At this stage you will also need to add dummy dl.c and cache.S with functions |
494 | + grub_err_t grub_arch_dl_check_header (void *ehdr), grub_err_t |
495 | +-grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c) and |
496 | +-void grub_arch_sync_caches (void *address, grub_size_t len) (cache.S). They |
497 | +-won't be used for now. |
498 | ++grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c), grub_uint32_t |
499 | ++grub_arch_dl_min_alignment (void), and void grub_arch_sync_caches (void |
500 | ++*address, grub_size_t len) (cache.S). They won't be used for now. |
501 | + |
502 | + You will need to create directory include/$cpu/$platform and a file |
503 | + include/$cpu/types.h. The latter following this template: |
504 | +diff --git a/grub-core/kern/arm/dl.c b/grub-core/kern/arm/dl.c |
505 | +index eab9d17..9260737 100644 |
506 | +--- a/grub-core/kern/arm/dl.c |
507 | ++++ b/grub-core/kern/arm/dl.c |
508 | +@@ -278,3 +278,16 @@ grub_arch_dl_check_header (void *ehdr) |
509 | + |
510 | + return GRUB_ERR_NONE; |
511 | + } |
512 | ++ |
513 | ++/* |
514 | ++ * Tell the loader what our minimum section alignment is. |
515 | ++ */ |
516 | ++grub_size_t |
517 | ++grub_arch_dl_min_alignment (void) |
518 | ++{ |
519 | ++#ifdef GRUB_MACHINE_EFI |
520 | ++ return 4096; |
521 | ++#else |
522 | ++ return 1; |
523 | ++#endif |
524 | ++} |
525 | +diff --git a/grub-core/kern/arm64/dl.c b/grub-core/kern/arm64/dl.c |
526 | +index a2b5789..95c6d5b 100644 |
527 | +--- a/grub-core/kern/arm64/dl.c |
528 | ++++ b/grub-core/kern/arm64/dl.c |
529 | +@@ -196,3 +196,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, |
530 | + |
531 | + return GRUB_ERR_NONE; |
532 | + } |
533 | ++ |
534 | ++/* |
535 | ++ * Tell the loader what our minimum section alignment is. |
536 | ++ */ |
537 | ++grub_size_t |
538 | ++grub_arch_dl_min_alignment (void) |
539 | ++{ |
540 | ++#ifdef GRUB_MACHINE_EFI |
541 | ++ return 4096; |
542 | ++#else |
543 | ++ return 1; |
544 | ++#endif |
545 | ++} |
546 | +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c |
547 | +index 37db9fa..8338f74 100644 |
548 | +--- a/grub-core/kern/dl.c |
549 | ++++ b/grub-core/kern/dl.c |
550 | +@@ -224,25 +224,35 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) |
551 | + { |
552 | + unsigned i; |
553 | + const Elf_Shdr *s; |
554 | +- grub_size_t tsize = 0, talign = 1; |
555 | ++ grub_size_t tsize = 0, talign = 1, arch_addralign = 1; |
556 | + #if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \ |
557 | + !defined (__loongarch__) |
558 | + grub_size_t tramp; |
559 | ++ grub_size_t tramp_align; |
560 | + grub_size_t got; |
561 | ++ grub_size_t got_align; |
562 | + grub_err_t err; |
563 | + #endif |
564 | + char *ptr; |
565 | + |
566 | ++ arch_addralign = grub_arch_dl_min_alignment (); |
567 | ++ |
568 | + for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); |
569 | + i < e->e_shnum; |
570 | + i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) |
571 | + { |
572 | ++ grub_size_t sh_addralign; |
573 | ++ grub_size_t sh_size; |
574 | ++ |
575 | + if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC)) |
576 | + continue; |
577 | + |
578 | +- tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size; |
579 | +- if (talign < s->sh_addralign) |
580 | +- talign = s->sh_addralign; |
581 | ++ sh_addralign = ALIGN_UP(s->sh_addralign, arch_addralign); |
582 | ++ sh_size = ALIGN_UP(s->sh_size, sh_addralign); |
583 | ++ |
584 | ++ tsize = ALIGN_UP (tsize, sh_addralign) + sh_size; |
585 | ++ if (talign < sh_addralign) |
586 | ++ talign = sh_addralign; |
587 | + } |
588 | + |
589 | + #if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \ |
590 | +@@ -250,12 +260,18 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) |
591 | + err = grub_arch_dl_get_tramp_got_size (e, &tramp, &got); |
592 | + if (err) |
593 | + return err; |
594 | +- tsize += ALIGN_UP (tramp, GRUB_ARCH_DL_TRAMP_ALIGN); |
595 | +- if (talign < GRUB_ARCH_DL_TRAMP_ALIGN) |
596 | +- talign = GRUB_ARCH_DL_TRAMP_ALIGN; |
597 | +- tsize += ALIGN_UP (got, GRUB_ARCH_DL_GOT_ALIGN); |
598 | +- if (talign < GRUB_ARCH_DL_GOT_ALIGN) |
599 | +- talign = GRUB_ARCH_DL_GOT_ALIGN; |
600 | ++ tramp_align = GRUB_ARCH_DL_TRAMP_ALIGN; |
601 | ++ if (tramp_align < arch_addralign) |
602 | ++ tramp_align = arch_addralign; |
603 | ++ tsize += ALIGN_UP (tramp, tramp_align); |
604 | ++ if (talign < tramp_align) |
605 | ++ talign = tramp_align; |
606 | ++ got_align = GRUB_ARCH_DL_GOT_ALIGN; |
607 | ++ if (got_align < arch_addralign) |
608 | ++ got_align = arch_addralign; |
609 | ++ tsize += ALIGN_UP (got, got_align); |
610 | ++ if (talign < got_align) |
611 | ++ talign = got_align; |
612 | + #endif |
613 | + |
614 | + #ifdef GRUB_MACHINE_EMU |
615 | +@@ -272,6 +288,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) |
616 | + i < e->e_shnum; |
617 | + i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize)) |
618 | + { |
619 | ++ grub_size_t sh_addralign = ALIGN_UP(s->sh_addralign, arch_addralign); |
620 | ++ grub_size_t sh_size = ALIGN_UP(s->sh_size, sh_addralign); |
621 | ++ |
622 | + if (s->sh_flags & SHF_ALLOC) |
623 | + { |
624 | + grub_dl_segment_t seg; |
625 | +@@ -284,17 +303,19 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) |
626 | + { |
627 | + void *addr; |
628 | + |
629 | +- ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, s->sh_addralign); |
630 | ++ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, sh_addralign); |
631 | + addr = ptr; |
632 | +- ptr += s->sh_size; |
633 | ++ ptr += sh_size; |
634 | + |
635 | + switch (s->sh_type) |
636 | + { |
637 | + case SHT_PROGBITS: |
638 | + grub_memcpy (addr, (char *) e + s->sh_offset, s->sh_size); |
639 | ++ grub_memset ((char *)addr + s->sh_size, 0, |
640 | ++ sh_size - s->sh_size); |
641 | + break; |
642 | + case SHT_NOBITS: |
643 | +- grub_memset (addr, 0, s->sh_size); |
644 | ++ grub_memset (addr, 0, sh_size); |
645 | + break; |
646 | + } |
647 | + |
648 | +@@ -303,7 +324,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) |
649 | + else |
650 | + seg->addr = 0; |
651 | + |
652 | +- seg->size = s->sh_size; |
653 | ++ seg->size = sh_size; |
654 | + seg->section = i; |
655 | + seg->next = mod->segment; |
656 | + mod->segment = seg; |
657 | +@@ -311,11 +332,11 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) |
658 | + } |
659 | + #if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \ |
660 | + !defined (__loongarch__) |
661 | +- ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_TRAMP_ALIGN); |
662 | ++ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, tramp_align); |
663 | + mod->tramp = ptr; |
664 | + mod->trampptr = ptr; |
665 | + ptr += tramp; |
666 | +- ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_GOT_ALIGN); |
667 | ++ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, got_align); |
668 | + mod->got = ptr; |
669 | + mod->gotptr = ptr; |
670 | + ptr += got; |
671 | +diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c |
672 | +index e8d63b1..1de1c28 100644 |
673 | +--- a/grub-core/kern/emu/full.c |
674 | ++++ b/grub-core/kern/emu/full.c |
675 | +@@ -67,3 +67,16 @@ grub_arch_dl_init_linker (void) |
676 | + } |
677 | + #endif |
678 | + |
679 | ++ |
680 | ++/* |
681 | ++ * Tell the loader what our minimum section alignment is. |
682 | ++ */ |
683 | ++grub_size_t |
684 | ++grub_arch_dl_min_alignment (void) |
685 | ++{ |
686 | ++#ifdef GRUB_MACHINE_EFI |
687 | ++ return 4096; |
688 | ++#else |
689 | ++ return 1; |
690 | ++#endif |
691 | ++} |
692 | +diff --git a/grub-core/kern/i386/dl.c b/grub-core/kern/i386/dl.c |
693 | +index 1346da5..d6b4681 100644 |
694 | +--- a/grub-core/kern/i386/dl.c |
695 | ++++ b/grub-core/kern/i386/dl.c |
696 | +@@ -79,3 +79,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, |
697 | + |
698 | + return GRUB_ERR_NONE; |
699 | + } |
700 | ++ |
701 | ++/* |
702 | ++ * Tell the loader what our minimum section alignment is. |
703 | ++ */ |
704 | ++grub_size_t |
705 | ++grub_arch_dl_min_alignment (void) |
706 | ++{ |
707 | ++#ifdef GRUB_MACHINE_EFI |
708 | ++ return 4096; |
709 | ++#else |
710 | ++ return 1; |
711 | ++#endif |
712 | ++} |
713 | +diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c |
714 | +index db59300..92d82c5 100644 |
715 | +--- a/grub-core/kern/ia64/dl.c |
716 | ++++ b/grub-core/kern/ia64/dl.c |
717 | +@@ -148,3 +148,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, |
718 | + } |
719 | + return GRUB_ERR_NONE; |
720 | + } |
721 | ++ |
722 | ++/* |
723 | ++ * Tell the loader what our minimum section alignment is. |
724 | ++ */ |
725 | ++grub_size_t |
726 | ++grub_arch_dl_min_alignment (void) |
727 | ++{ |
728 | ++ return 1; |
729 | ++} |
730 | +diff --git a/grub-core/kern/mips/dl.c b/grub-core/kern/mips/dl.c |
731 | +index 5b02f97..db41189 100644 |
732 | +--- a/grub-core/kern/mips/dl.c |
733 | ++++ b/grub-core/kern/mips/dl.c |
734 | +@@ -272,3 +272,11 @@ grub_arch_dl_init_linker (void) |
735 | + grub_dl_register_symbol ("_gp_disp", &_gp_disp_dummy, 0, 0); |
736 | + } |
737 | + |
738 | ++/* |
739 | ++ * Tell the loader what our minimum section alignment is. |
740 | ++ */ |
741 | ++grub_size_t |
742 | ++grub_arch_dl_min_alignment (void) |
743 | ++{ |
744 | ++ return 1; |
745 | ++} |
746 | +diff --git a/grub-core/kern/powerpc/dl.c b/grub-core/kern/powerpc/dl.c |
747 | +index 7b6418e..0eb8bc5 100644 |
748 | +--- a/grub-core/kern/powerpc/dl.c |
749 | ++++ b/grub-core/kern/powerpc/dl.c |
750 | +@@ -167,3 +167,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, |
751 | + |
752 | + return GRUB_ERR_NONE; |
753 | + } |
754 | ++ |
755 | ++/* |
756 | ++ * Tell the loader what our minimum section alignment is. |
757 | ++ */ |
758 | ++grub_size_t |
759 | ++grub_arch_dl_min_alignment (void) |
760 | ++{ |
761 | ++ return 1; |
762 | ++} |
763 | +diff --git a/grub-core/kern/riscv/dl.c b/grub-core/kern/riscv/dl.c |
764 | +index 896653b..1fa085b 100644 |
765 | +--- a/grub-core/kern/riscv/dl.c |
766 | ++++ b/grub-core/kern/riscv/dl.c |
767 | +@@ -344,3 +344,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, |
768 | + |
769 | + return GRUB_ERR_NONE; |
770 | + } |
771 | ++ |
772 | ++/* |
773 | ++ * Tell the loader what our minimum section alignment is. |
774 | ++ */ |
775 | ++grub_size_t |
776 | ++grub_arch_dl_min_alignment (void) |
777 | ++{ |
778 | ++#ifdef GRUB_MACHINE_EFI |
779 | ++ return 4096; |
780 | ++#else |
781 | ++ return 1; |
782 | ++#endif |
783 | ++} |
784 | +diff --git a/grub-core/kern/sparc64/dl.c b/grub-core/kern/sparc64/dl.c |
785 | +index f3d9601..f054f08 100644 |
786 | +--- a/grub-core/kern/sparc64/dl.c |
787 | ++++ b/grub-core/kern/sparc64/dl.c |
788 | +@@ -189,3 +189,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, |
789 | + |
790 | + return GRUB_ERR_NONE; |
791 | + } |
792 | ++ |
793 | ++/* |
794 | ++ * Tell the loader what our minimum section alignment is. |
795 | ++ */ |
796 | ++grub_size_t |
797 | ++grub_arch_dl_min_alignment (void) |
798 | ++{ |
799 | ++ return 1; |
800 | ++} |
801 | +diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c |
802 | +index e5a8bdc..a105dc5 100644 |
803 | +--- a/grub-core/kern/x86_64/dl.c |
804 | ++++ b/grub-core/kern/x86_64/dl.c |
805 | +@@ -119,3 +119,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, |
806 | + |
807 | + return GRUB_ERR_NONE; |
808 | + } |
809 | ++ |
810 | ++/* |
811 | ++ * Tell the loader what our minimum section alignment is. |
812 | ++ */ |
813 | ++grub_size_t |
814 | ++grub_arch_dl_min_alignment (void) |
815 | ++{ |
816 | ++#ifdef GRUB_MACHINE_EFI |
817 | ++ return 4096; |
818 | ++#else |
819 | ++ return 1; |
820 | ++#endif |
821 | ++} |
822 | +diff --git a/include/grub/dl.h b/include/grub/dl.h |
823 | +index cd1f46c..e890210 100644 |
824 | +--- a/include/grub/dl.h |
825 | ++++ b/include/grub/dl.h |
826 | +@@ -264,6 +264,8 @@ grub_err_t grub_arch_dl_check_header (void *ehdr); |
827 | + grub_err_t |
828 | + grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, |
829 | + Elf_Shdr *s, grub_dl_segment_t seg); |
830 | ++grub_size_t |
831 | ++grub_arch_dl_min_alignment (void); |
832 | + #endif |
833 | + |
834 | + #if defined (_mips) |
835 | diff --git a/debian/patches/nx/modules-strip-.llvm_addrsig-sections-and-similar.patch b/debian/patches/nx/modules-strip-.llvm_addrsig-sections-and-similar.patch |
836 | new file mode 100644 |
837 | index 0000000..a60c07b |
838 | --- /dev/null |
839 | +++ b/debian/patches/nx/modules-strip-.llvm_addrsig-sections-and-similar.patch |
840 | @@ -0,0 +1,41 @@ |
841 | +From: Peter Jones <pjones@redhat.com> |
842 | +Date: Thu, 24 Feb 2022 16:40:11 -0500 |
843 | +Subject: modules: strip .llvm_addrsig sections and similar. |
844 | + |
845 | +Currently grub modules built with clang or gcc have several sections |
846 | +which we don't actually need or support. |
847 | + |
848 | +We already have a list of section to skip in genmod.sh, and this patch |
849 | +adds the following sections to that list (as well as a few newlines): |
850 | + |
851 | +.note.gnu.property |
852 | +.llvm* |
853 | + |
854 | +Note that the glob there won't work without a new enough linker, but the |
855 | +failure is just reversion to the status quo, so that's not a big problem. |
856 | + |
857 | +Signed-off-by: Peter Jones <pjones@redhat.com> |
858 | +Signed-off-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com> |
859 | +Signed-off-by: Mate Kukri <mate.kukri@canonical.com> |
860 | +Reviewed-By: Vladimir Serbinenko |
861 | +--- |
862 | + grub-core/genmod.sh.in | 5 ++++- |
863 | + 1 file changed, 4 insertions(+), 1 deletion(-) |
864 | + |
865 | +diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in |
866 | +index e57c4d9..337753c 100644 |
867 | +--- a/grub-core/genmod.sh.in |
868 | ++++ b/grub-core/genmod.sh.in |
869 | +@@ -57,8 +57,11 @@ if test x@TARGET_APPLE_LINKER@ != x1; then |
870 | + @TARGET_STRIP@ --strip-unneeded \ |
871 | + -K grub_mod_init -K grub_mod_fini \ |
872 | + -K _grub_mod_init -K _grub_mod_fini \ |
873 | +- -R .note.gnu.gold-version -R .note.GNU-stack \ |
874 | ++ -R .note.GNU-stack \ |
875 | ++ -R .note.gnu.gold-version \ |
876 | ++ -R .note.gnu.property \ |
877 | + -R .gnu.build.attributes \ |
878 | ++ -R '.llvm*' \ |
879 | + -R .rel.gnu.build.attributes \ |
880 | + -R .rela.gnu.build.attributes \ |
881 | + -R .eh_frame -R .rela.eh_frame -R .rel.eh_frame \ |
882 | diff --git a/debian/patches/nx/nx-add-memory-attribute-get-set-API.patch b/debian/patches/nx/nx-add-memory-attribute-get-set-API.patch |
883 | new file mode 100644 |
884 | index 0000000..cf58691 |
885 | --- /dev/null |
886 | +++ b/debian/patches/nx/nx-add-memory-attribute-get-set-API.patch |
887 | @@ -0,0 +1,252 @@ |
888 | +From: Mate Kukri <mate.kukri@canonical.com> |
889 | +Date: Tue, 22 Mar 2022 10:56:21 -0400 |
890 | +Subject: nx: add memory attribute get/set API |
891 | + |
892 | +For NX, we need to set the page access permission attributes for write |
893 | +and execute permissions. |
894 | + |
895 | +This patch adds two new primitives, grub_set_mem_attrs() and |
896 | +grub_clear_mem_attrs(), and associated constant definitions, to be used |
897 | +for that purpose. |
898 | + |
899 | +For most platforms, it adds a dummy implementation that returns |
900 | +GRUB_ERR_NONE. |
901 | + |
902 | +On EFI platforms, it implements the primitives using the EFI |
903 | +Memory Attribute Protocol (defined in UEFI 2.10 specification). |
904 | + |
905 | +Original-Author: Peter Jones <pjones@redhat.com> |
906 | +Signed-off-by: Mate Kukri <mate.kukri@canonical.com> |
907 | +--- |
908 | + grub-core/kern/efi/mm.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++ |
909 | + include/grub/efi/api.h | 25 ++++++++++ |
910 | + include/grub/mm.h | 33 +++++++++++++ |
911 | + 3 files changed, 185 insertions(+) |
912 | + |
913 | +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c |
914 | +index d45d0e2..790094c 100644 |
915 | +--- a/grub-core/kern/efi/mm.c |
916 | ++++ b/grub-core/kern/efi/mm.c |
917 | +@@ -689,3 +689,130 @@ grub_efi_get_ram_base(grub_addr_t *base_addr) |
918 | + return GRUB_ERR_NONE; |
919 | + } |
920 | + #endif |
921 | ++ |
922 | ++static inline grub_uint64_t |
923 | ++grub_mem_attrs_to_uefi_mem_attrs (grub_uint64_t attrs) |
924 | ++{ |
925 | ++ grub_uint64_t ret = GRUB_EFI_MEMORY_RP | |
926 | ++ GRUB_EFI_MEMORY_RO | |
927 | ++ GRUB_EFI_MEMORY_XP; |
928 | ++ |
929 | ++ if (attrs & GRUB_MEM_ATTR_R) |
930 | ++ ret &= ~GRUB_EFI_MEMORY_RP; |
931 | ++ |
932 | ++ if (attrs & GRUB_MEM_ATTR_W) |
933 | ++ ret &= ~GRUB_EFI_MEMORY_RO; |
934 | ++ |
935 | ++ if (attrs & GRUB_MEM_ATTR_X) |
936 | ++ ret &= ~GRUB_EFI_MEMORY_XP; |
937 | ++ |
938 | ++ return ret; |
939 | ++} |
940 | ++ |
941 | ++static inline grub_uint64_t |
942 | ++uefi_mem_attrs_to_grub_mem_attrs (grub_uint64_t attrs) |
943 | ++{ |
944 | ++ grub_uint64_t ret = GRUB_MEM_ATTR_R | |
945 | ++ GRUB_MEM_ATTR_W | |
946 | ++ GRUB_MEM_ATTR_X; |
947 | ++ |
948 | ++ if (attrs & GRUB_EFI_MEMORY_RP) |
949 | ++ ret &= ~GRUB_MEM_ATTR_R; |
950 | ++ |
951 | ++ if (attrs & GRUB_EFI_MEMORY_RO) |
952 | ++ ret &= ~GRUB_MEM_ATTR_W; |
953 | ++ |
954 | ++ if (attrs & GRUB_EFI_MEMORY_XP) |
955 | ++ ret &= ~GRUB_MEM_ATTR_X; |
956 | ++ |
957 | ++ return ret; |
958 | ++} |
959 | ++ |
960 | ++grub_err_t |
961 | ++grub_get_mem_attrs (grub_addr_t addr, grub_size_t size, grub_uint64_t *attrs) |
962 | ++{ |
963 | ++ grub_efi_memory_attribute_protocol_t *proto; |
964 | ++ grub_efi_physical_address_t physaddr = addr; |
965 | ++ grub_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID; |
966 | ++ grub_efi_status_t efi_status; |
967 | ++ |
968 | ++ if (physaddr & 0xfff || size & 0xfff || size == 0 || attrs == NULL) |
969 | ++ { |
970 | ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, |
971 | ++ N_("grub_get_mem_attrs() called with invalid arguments")); |
972 | ++ } |
973 | ++ |
974 | ++ proto = grub_efi_locate_protocol (&protocol_guid, 0); |
975 | ++ if (!proto) |
976 | ++ { |
977 | ++ /* No protocol -> do nothing, all memory is RWX in boot services */ |
978 | ++ *attrs = GRUB_MEM_ATTR_R | GRUB_MEM_ATTR_W | GRUB_MEM_ATTR_X; |
979 | ++ return GRUB_ERR_NONE; |
980 | ++ } |
981 | ++ |
982 | ++ efi_status = proto->get_memory_attributes(proto, physaddr, size, attrs); |
983 | ++ if (efi_status != GRUB_EFI_SUCCESS) |
984 | ++ { |
985 | ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, |
986 | ++ N_("grub_get_mem_attrs() called with invalid arguments")); |
987 | ++ } |
988 | ++ |
989 | ++ *attrs = uefi_mem_attrs_to_grub_mem_attrs (*attrs); |
990 | ++ |
991 | ++ grub_dprintf ("nx", "get 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR":%c%c%c\n", |
992 | ++ addr, addr + size - 1, |
993 | ++ (*attrs & GRUB_MEM_ATTR_R) ? 'r' : '-', |
994 | ++ (*attrs & GRUB_MEM_ATTR_W) ? 'w' : '-', |
995 | ++ (*attrs & GRUB_MEM_ATTR_X) ? 'x' : '-'); |
996 | ++ |
997 | ++ return GRUB_ERR_NONE; |
998 | ++} |
999 | ++ |
1000 | ++grub_err_t |
1001 | ++grub_update_mem_attrs (grub_addr_t addr, grub_size_t size, |
1002 | ++ grub_uint64_t set_attrs, grub_uint64_t clear_attrs) |
1003 | ++{ |
1004 | ++ grub_efi_memory_attribute_protocol_t *proto; |
1005 | ++ grub_efi_physical_address_t physaddr = addr; |
1006 | ++ grub_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID; |
1007 | ++ grub_efi_status_t efi_status = GRUB_EFI_SUCCESS; |
1008 | ++ grub_uint64_t uefi_set_attrs, uefi_clear_attrs; |
1009 | ++ |
1010 | ++ |
1011 | ++ if (physaddr & 0xfff || size & 0xfff || size == 0) |
1012 | ++ { |
1013 | ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, |
1014 | ++ N_("grub_update_mem_attrs() called with invalid arguments")); |
1015 | ++ } |
1016 | ++ |
1017 | ++ proto = grub_efi_locate_protocol (&protocol_guid, 0); |
1018 | ++ if (!proto) |
1019 | ++ { |
1020 | ++ /* No protocol -> do nothing, all memory is RWX in boot services */ |
1021 | ++ return GRUB_ERR_NONE; |
1022 | ++ } |
1023 | ++ |
1024 | ++ uefi_set_attrs = grub_mem_attrs_to_uefi_mem_attrs (set_attrs); |
1025 | ++ uefi_clear_attrs = grub_mem_attrs_to_uefi_mem_attrs (clear_attrs); |
1026 | ++ if (uefi_set_attrs) |
1027 | ++ efi_status = proto->set_memory_attributes(proto, physaddr, size, uefi_set_attrs); |
1028 | ++ if (efi_status == GRUB_EFI_SUCCESS && uefi_clear_attrs) |
1029 | ++ efi_status = proto->clear_memory_attributes(proto, physaddr, size, uefi_clear_attrs); |
1030 | ++ |
1031 | ++ if (efi_status != GRUB_EFI_SUCCESS) |
1032 | ++ { |
1033 | ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, |
1034 | ++ N_("grub_update_mem_attrs() called with invalid arguments")); |
1035 | ++ } |
1036 | ++ |
1037 | ++ grub_dprintf ("nx", "set +%s%s%s -%s%s%s on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR"\n", |
1038 | ++ (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "", |
1039 | ++ (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "", |
1040 | ++ (set_attrs & GRUB_MEM_ATTR_X) ? "x" : "", |
1041 | ++ (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "", |
1042 | ++ (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "", |
1043 | ++ (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : "", |
1044 | ++ addr, addr + size - 1); |
1045 | ++ |
1046 | ++ return GRUB_ERR_NONE; |
1047 | ++} |
1048 | +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h |
1049 | +index a89bf3d..699bccf 100644 |
1050 | +--- a/include/grub/efi/api.h |
1051 | ++++ b/include/grub/efi/api.h |
1052 | +@@ -393,6 +393,11 @@ |
1053 | + {0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f } \ |
1054 | + } |
1055 | + |
1056 | ++#define GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID \ |
1057 | ++ { 0xf4560cf6, 0x40ec, 0x4b4a, \ |
1058 | ++ { 0xa1, 0x92, 0xbf, 0x1d, 0x57, 0xd0, 0xb1, 0x89 } \ |
1059 | ++ } |
1060 | ++ |
1061 | + struct grub_efi_sal_system_table |
1062 | + { |
1063 | + grub_uint32_t signature; |
1064 | +@@ -2214,4 +2219,24 @@ struct initrd_media_device_path { |
1065 | + } GRUB_PACKED; |
1066 | + typedef struct initrd_media_device_path initrd_media_device_path_t; |
1067 | + |
1068 | ++struct grub_efi_memory_attribute_protocol |
1069 | ++{ |
1070 | ++ grub_efi_status_t (__grub_efi_api *get_memory_attributes) ( |
1071 | ++ struct grub_efi_memory_attribute_protocol *this, |
1072 | ++ grub_efi_physical_address_t base_address, |
1073 | ++ grub_efi_uint64_t length, |
1074 | ++ grub_efi_uint64_t *attributes); |
1075 | ++ grub_efi_status_t (__grub_efi_api *set_memory_attributes) ( |
1076 | ++ struct grub_efi_memory_attribute_protocol *this, |
1077 | ++ grub_efi_physical_address_t base_address, |
1078 | ++ grub_efi_uint64_t length, |
1079 | ++ grub_efi_uint64_t attributes); |
1080 | ++ grub_efi_status_t (__grub_efi_api *clear_memory_attributes) ( |
1081 | ++ struct grub_efi_memory_attribute_protocol *this, |
1082 | ++ grub_efi_physical_address_t base_address, |
1083 | ++ grub_efi_uint64_t length, |
1084 | ++ grub_efi_uint64_t attributes); |
1085 | ++}; |
1086 | ++typedef struct grub_efi_memory_attribute_protocol grub_efi_memory_attribute_protocol_t; |
1087 | ++ |
1088 | + #endif /* ! GRUB_EFI_API_HEADER */ |
1089 | +diff --git a/include/grub/mm.h b/include/grub/mm.h |
1090 | +index f3bf87f..dcccfe3 100644 |
1091 | +--- a/include/grub/mm.h |
1092 | ++++ b/include/grub/mm.h |
1093 | +@@ -23,6 +23,7 @@ |
1094 | + #include <grub/err.h> |
1095 | + #include <grub/types.h> |
1096 | + #include <grub/symbol.h> |
1097 | ++#include <grub/err.h> |
1098 | + #include <config.h> |
1099 | + |
1100 | + #ifndef NULL |
1101 | +@@ -56,6 +57,38 @@ void *EXPORT_FUNC(grub_realloc) (void *ptr, grub_size_t size); |
1102 | + void *EXPORT_FUNC(grub_memalign) (grub_size_t align, grub_size_t size); |
1103 | + #endif |
1104 | + |
1105 | ++#define GRUB_MEM_ATTR_R 0x0000000000000004LLU |
1106 | ++#define GRUB_MEM_ATTR_W 0x0000000000000002LLU |
1107 | ++#define GRUB_MEM_ATTR_X 0x0000000000000001LLU |
1108 | ++ |
1109 | ++#ifdef GRUB_MACHINE_EFI |
1110 | ++grub_err_t EXPORT_FUNC(grub_get_mem_attrs) (grub_addr_t addr, |
1111 | ++ grub_size_t size, |
1112 | ++ grub_uint64_t *attrs); |
1113 | ++grub_err_t EXPORT_FUNC(grub_update_mem_attrs) (grub_addr_t addr, |
1114 | ++ grub_size_t size, |
1115 | ++ grub_uint64_t set_attrs, |
1116 | ++ grub_uint64_t clear_attrs); |
1117 | ++#else /* !GRUB_MACHINE_EFI */ |
1118 | ++static inline grub_err_t |
1119 | ++grub_get_mem_attrs (grub_addr_t addr __attribute__((__unused__)), |
1120 | ++ grub_size_t size __attribute__((__unused__)), |
1121 | ++ grub_uint64_t *attrs __attribute__((__unused__))) |
1122 | ++{ |
1123 | ++ *attrs = GRUB_MEM_ATTR_R | GRUB_MEM_ATTR_W | GRUB_MEM_ATTR_X; |
1124 | ++ return GRUB_ERR_NONE; |
1125 | ++} |
1126 | ++ |
1127 | ++static inline grub_err_t |
1128 | ++grub_update_mem_attrs (grub_addr_t addr __attribute__((__unused__)), |
1129 | ++ grub_size_t size __attribute__((__unused__)), |
1130 | ++ grub_uint64_t set_attrs __attribute__((__unused__)), |
1131 | ++ grub_uint64_t clear_attrs __attribute__((__unused__))) |
1132 | ++{ |
1133 | ++ return GRUB_ERR_NONE; |
1134 | ++} |
1135 | ++#endif /* GRUB_MACHINE_EFI */ |
1136 | ++ |
1137 | + void grub_mm_check_real (const char *file, int line); |
1138 | + #define grub_mm_check() grub_mm_check_real (GRUB_FILE, __LINE__); |
1139 | + |
1140 | diff --git a/debian/patches/nx/nx-set-page-permissions-for-loaded-modules.patch b/debian/patches/nx/nx-set-page-permissions-for-loaded-modules.patch |
1141 | new file mode 100644 |
1142 | index 0000000..f4eecc9 |
1143 | --- /dev/null |
1144 | +++ b/debian/patches/nx/nx-set-page-permissions-for-loaded-modules.patch |
1145 | @@ -0,0 +1,222 @@ |
1146 | +From: Mate Kukri <mate.kukri@canonical.com> |
1147 | +Date: Mon, 21 Mar 2022 17:46:35 -0400 |
1148 | +Subject: nx: set page permissions for loaded modules. |
1149 | + |
1150 | +For NX, we need to set write and executable permissions on the sections |
1151 | +of grub modules when we load them. |
1152 | + |
1153 | +On sections with SHF_ALLOC set, which is typically everything except |
1154 | +.modname and the symbol and string tables, this patch clears the Read |
1155 | +Only flag on sections that have the ELF flag SHF_WRITE set, and clears |
1156 | +the No eXecute flag on sections with SHF_EXECINSTR set. In all other |
1157 | +cases it sets both flags. |
1158 | + |
1159 | +Original-Author: Peter Jones <pjones@redhat.com> |
1160 | +Original-Author: Robbie Harwood <rharwood@redhat.com> |
1161 | +Original-Author: Laszlo Ersek <lersek@redhat.com> |
1162 | +Signed-off-by: Mate Kukri <mate.kukri@canonical.com> |
1163 | +--- |
1164 | + grub-core/kern/dl.c | 104 +++++++++++++++++++++++++++++++++++++++++++++------- |
1165 | + include/grub/dl.h | 46 +++++++++++++++++++++++ |
1166 | + 2 files changed, 137 insertions(+), 13 deletions(-) |
1167 | + |
1168 | +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c |
1169 | +index 8338f74..3341d78 100644 |
1170 | +--- a/grub-core/kern/dl.c |
1171 | ++++ b/grub-core/kern/dl.c |
1172 | +@@ -616,25 +616,97 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr) |
1173 | + grub_dl_segment_t seg; |
1174 | + grub_err_t err; |
1175 | + |
1176 | +- /* Find the target segment. */ |
1177 | +- for (seg = mod->segment; seg; seg = seg->next) |
1178 | +- if (seg->section == s->sh_info) |
1179 | +- break; |
1180 | ++ seg = grub_dl_find_segment(mod, s->sh_info); |
1181 | ++ if (!seg) |
1182 | ++ continue; |
1183 | + |
1184 | +- if (seg) |
1185 | +- { |
1186 | +- if (!mod->symtab) |
1187 | +- return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table"); |
1188 | ++ if (!mod->symtab) |
1189 | ++ return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table"); |
1190 | + |
1191 | +- err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg); |
1192 | +- if (err) |
1193 | +- return err; |
1194 | +- } |
1195 | ++ err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg); |
1196 | ++ if (err) |
1197 | ++ return err; |
1198 | + } |
1199 | + |
1200 | + return GRUB_ERR_NONE; |
1201 | + } |
1202 | + |
1203 | ++/* Only define this on EFI to save space in core */ |
1204 | ++#ifdef GRUB_MACHINE_EFI |
1205 | ++static grub_err_t |
1206 | ++grub_dl_set_mem_attrs (grub_dl_t mod, void *ehdr) |
1207 | ++{ |
1208 | ++ unsigned i; |
1209 | ++ const Elf_Shdr *s; |
1210 | ++ const Elf_Ehdr *e = ehdr; |
1211 | ++ grub_err_t err; |
1212 | ++#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) |
1213 | ++ grub_size_t arch_addralign = grub_arch_dl_min_alignment (); |
1214 | ++ grub_addr_t tgaddr; |
1215 | ++ grub_size_t tgsz; |
1216 | ++#endif |
1217 | ++ |
1218 | ++ for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); |
1219 | ++ i < e->e_shnum; |
1220 | ++ i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) |
1221 | ++ { |
1222 | ++ grub_dl_segment_t seg; |
1223 | ++ grub_uint64_t set_attrs = GRUB_MEM_ATTR_R; |
1224 | ++ grub_uint64_t clear_attrs = GRUB_MEM_ATTR_W|GRUB_MEM_ATTR_X; |
1225 | ++ |
1226 | ++ seg = grub_dl_find_segment(mod, i); |
1227 | ++ if (!seg) |
1228 | ++ continue; |
1229 | ++ |
1230 | ++ if (seg->size == 0 || !(s->sh_flags & SHF_ALLOC)) |
1231 | ++ continue; |
1232 | ++ |
1233 | ++ if (s->sh_flags & SHF_WRITE) |
1234 | ++ { |
1235 | ++ set_attrs |= GRUB_MEM_ATTR_W; |
1236 | ++ clear_attrs &= ~GRUB_MEM_ATTR_W; |
1237 | ++ } |
1238 | ++ |
1239 | ++ if (s->sh_flags & SHF_EXECINSTR) |
1240 | ++ { |
1241 | ++ set_attrs |= GRUB_MEM_ATTR_X; |
1242 | ++ clear_attrs &= ~GRUB_MEM_ATTR_X; |
1243 | ++ } |
1244 | ++ |
1245 | ++ err = grub_update_mem_attrs ((grub_addr_t)(seg->addr), seg->size, |
1246 | ++ set_attrs, clear_attrs); |
1247 | ++ if (err != GRUB_ERR_NONE) |
1248 | ++ return err; |
1249 | ++ } |
1250 | ++ |
1251 | ++#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) |
1252 | ++ tgaddr = grub_min((grub_addr_t)mod->tramp, (grub_addr_t)mod->got); |
1253 | ++ tgsz = grub_max((grub_addr_t)mod->trampptr, (grub_addr_t)mod->gotptr) - tgaddr; |
1254 | ++ |
1255 | ++ if (tgsz) |
1256 | ++ { |
1257 | ++ tgsz = ALIGN_UP(tgsz, arch_addralign); |
1258 | ++ |
1259 | ++ if (tgaddr < (grub_addr_t)mod->base || |
1260 | ++ tgsz > (grub_addr_t)-1 - tgaddr || |
1261 | ++ tgaddr + tgsz > (grub_addr_t)mod->base + mod->sz) |
1262 | ++ return grub_error (GRUB_ERR_BUG, |
1263 | ++ "BUG: trying to protect pages outside of module " |
1264 | ++ "allocation (\"%s\"): module base %p, size 0x%" |
1265 | ++ PRIxGRUB_SIZE "; tramp/GOT base 0x%" PRIxGRUB_ADDR |
1266 | ++ ", size 0x%" PRIxGRUB_SIZE, |
1267 | ++ mod->name, mod->base, mod->sz, tgaddr, tgsz); |
1268 | ++ err = grub_update_mem_attrs (tgaddr, tgsz, GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_X, |
1269 | ++ GRUB_MEM_ATTR_W); |
1270 | ++ if (err != GRUB_ERR_NONE) |
1271 | ++ return err; |
1272 | ++ } |
1273 | ++#endif |
1274 | ++ |
1275 | ++ return GRUB_ERR_NONE; |
1276 | ++} |
1277 | ++#endif |
1278 | ++ |
1279 | + /* Load a module from core memory. */ |
1280 | + grub_dl_t |
1281 | + grub_dl_load_core_noinit (void *addr, grub_size_t size) |
1282 | +@@ -668,6 +740,7 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) |
1283 | + mod->ref_count = 1; |
1284 | + |
1285 | + grub_dprintf ("modules", "relocating to %p\n", mod); |
1286 | ++ |
1287 | + /* Me, Vladimir Serbinenko, hereby I add this module check as per new |
1288 | + GNU module policy. Note that this license check is informative only. |
1289 | + Modules have to be licensed under GPLv3 or GPLv3+ (optionally |
1290 | +@@ -681,7 +754,12 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) |
1291 | + || grub_dl_resolve_dependencies (mod, e) |
1292 | + || grub_dl_load_segments (mod, e) |
1293 | + || grub_dl_resolve_symbols (mod, e) |
1294 | +- || grub_dl_relocate_symbols (mod, e)) |
1295 | ++ || grub_dl_relocate_symbols (mod, e) |
1296 | ++#ifdef GRUB_MACHINE_EFI |
1297 | ++ || grub_dl_set_mem_attrs (mod, e)) |
1298 | ++#else |
1299 | ++ ) |
1300 | ++#endif |
1301 | + { |
1302 | + mod->fini = 0; |
1303 | + grub_dl_unload (mod); |
1304 | +diff --git a/include/grub/dl.h b/include/grub/dl.h |
1305 | +index e890210..00aaa9c 100644 |
1306 | +--- a/include/grub/dl.h |
1307 | ++++ b/include/grub/dl.h |
1308 | +@@ -27,6 +27,7 @@ |
1309 | + #include <grub/elf.h> |
1310 | + #include <grub/list.h> |
1311 | + #include <grub/misc.h> |
1312 | ++#include <grub/mm.h> |
1313 | + #endif |
1314 | + |
1315 | + /* |
1316 | +@@ -254,6 +255,51 @@ grub_dl_is_persistent (grub_dl_t mod) |
1317 | + return mod->persistent; |
1318 | + } |
1319 | + |
1320 | ++#pragma GCC diagnostic ignored "-Wcast-align" |
1321 | ++ |
1322 | ++static inline const char * |
1323 | ++grub_dl_get_section_name (const Elf_Ehdr *e, const Elf_Shdr *s) |
1324 | ++{ |
1325 | ++ Elf_Shdr *str_s; |
1326 | ++ const char *str; |
1327 | ++ |
1328 | ++ str_s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); |
1329 | ++ str = (char *) e + str_s->sh_offset; |
1330 | ++ |
1331 | ++ return str + s->sh_name; |
1332 | ++} |
1333 | ++ |
1334 | ++static inline long |
1335 | ++grub_dl_find_section_index (Elf_Ehdr *e, const char *name) |
1336 | ++{ |
1337 | ++ Elf_Shdr *s; |
1338 | ++ const char *str; |
1339 | ++ unsigned i; |
1340 | ++ |
1341 | ++ s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); |
1342 | ++ str = (char *) e + s->sh_offset; |
1343 | ++ |
1344 | ++ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); |
1345 | ++ i < e->e_shnum; |
1346 | ++ i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) |
1347 | ++ if (grub_strcmp (str + s->sh_name, name) == 0) |
1348 | ++ return (long)i; |
1349 | ++ return -1; |
1350 | ++} |
1351 | ++ |
1352 | ++/* Return the segment for a section of index N */ |
1353 | ++static inline grub_dl_segment_t |
1354 | ++grub_dl_find_segment (grub_dl_t mod, unsigned n) |
1355 | ++{ |
1356 | ++ grub_dl_segment_t seg; |
1357 | ++ |
1358 | ++ for (seg = mod->segment; seg; seg = seg->next) |
1359 | ++ if (seg->section == n) |
1360 | ++ return seg; |
1361 | ++ |
1362 | ++ return NULL; |
1363 | ++} |
1364 | ++ |
1365 | + #endif |
1366 | + |
1367 | + grub_err_t grub_dl_register_symbol (const char *name, void *addr, |
1368 | diff --git a/debian/patches/nx/nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch b/debian/patches/nx/nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch |
1369 | new file mode 100644 |
1370 | index 0000000..95f90f0 |
1371 | --- /dev/null |
1372 | +++ b/debian/patches/nx/nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch |
1373 | @@ -0,0 +1,49 @@ |
1374 | +From: Mate Kukri <mate.kukri@canonical.com> |
1375 | +Date: Tue, 22 Mar 2022 10:57:20 -0400 |
1376 | +Subject: nx: set the nx compatible flag in EFI grub images |
1377 | + |
1378 | +For NX, we need the grub binary to announce that it is compatible with |
1379 | +the NX feature. This implies that when loading the executable grub |
1380 | +image, several attributes are true: |
1381 | + |
1382 | +- the binary doesn't need an executable stack |
1383 | +- the binary doesn't need sections to be both executable and writable |
1384 | +- the binary knows how to use the EFI Memory Attributes protocol on code |
1385 | + it is loading. |
1386 | + |
1387 | +This patch |
1388 | +- adds a definition for the PE DLL Characteristics flag GRUB_PE32_NX_COMPAT |
1389 | +- changes grub-mkimage to set that flag. |
1390 | + |
1391 | +Original-Author: Peter Jones <pjones@redhat.com> |
1392 | +Signed-off-by: Mate Kukri <mate.kukri@canonical.com> |
1393 | +--- |
1394 | + include/grub/efi/pe32.h | 2 ++ |
1395 | + util/mkimage.c | 1 + |
1396 | + 2 files changed, 3 insertions(+) |
1397 | + |
1398 | +diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h |
1399 | +index 4e6e9d2..9887e14 100644 |
1400 | +--- a/include/grub/efi/pe32.h |
1401 | ++++ b/include/grub/efi/pe32.h |
1402 | +@@ -231,6 +231,8 @@ struct grub_pe64_optional_header |
1403 | + |
1404 | + #define GRUB_PE32_SUBSYSTEM_EFI_APPLICATION 10 |
1405 | + |
1406 | ++#define GRUB_PE32_NX_COMPAT 0x0100 |
1407 | ++ |
1408 | + #define GRUB_PE32_NUM_DATA_DIRECTORIES 16 |
1409 | + |
1410 | + struct grub_pe32_section_table |
1411 | +diff --git a/util/mkimage.c b/util/mkimage.c |
1412 | +index ee0e6f6..dfd757a 100644 |
1413 | +--- a/util/mkimage.c |
1414 | ++++ b/util/mkimage.c |
1415 | +@@ -1403,6 +1403,7 @@ grub_install_generate_image (const char *dir, const char *prefix, |
1416 | + #pragma GCC diagnostic push |
1417 | + #pragma GCC diagnostic ignored "-Wdangling-pointer" |
1418 | + #endif |
1419 | ++ PE_OHDR (o32, o64, dll_characteristics) = grub_host_to_target16 (GRUB_PE32_NX_COMPAT); |
1420 | + PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size); |
1421 | + PE_OHDR (o32, o64, entry_addr) = grub_host_to_target32 (layout.start_address); |
1422 | + PE_OHDR (o32, o64, image_base) = 0; |
1423 | diff --git a/debian/patches/nx/peimage-Add-memory-attribute-support.patch b/debian/patches/nx/peimage-Add-memory-attribute-support.patch |
1424 | new file mode 100644 |
1425 | index 0000000..8950430 |
1426 | --- /dev/null |
1427 | +++ b/debian/patches/nx/peimage-Add-memory-attribute-support.patch |
1428 | @@ -0,0 +1,132 @@ |
1429 | +From: Mate Kukri <mate.kukri@canonical.com> |
1430 | +Date: Wed, 12 Jun 2024 15:08:04 +0100 |
1431 | +Subject: peimage: Add memory attribute support |
1432 | + |
1433 | +--- |
1434 | + grub-core/loader/efi/peimage.c | 68 ++++++++++++++++++++++++++++++++++++++++-- |
1435 | + 1 file changed, 65 insertions(+), 3 deletions(-) |
1436 | + |
1437 | +diff --git a/grub-core/loader/efi/peimage.c b/grub-core/loader/efi/peimage.c |
1438 | +index e28f020..22d7e1a 100644 |
1439 | +--- a/grub-core/loader/efi/peimage.c |
1440 | ++++ b/grub-core/loader/efi/peimage.c |
1441 | +@@ -8,6 +8,7 @@ |
1442 | + #include <grub/efi/efi.h> |
1443 | + #include <grub/efi/pe32.h> |
1444 | + #include <grub/efi/peimage.h> |
1445 | ++#include <grub/efi/sb.h> |
1446 | + #include <grub/env.h> |
1447 | + #include <grub/misc.h> |
1448 | + #include <grub/mm.h> |
1449 | +@@ -22,6 +23,7 @@ struct image_info |
1450 | + void *data; |
1451 | + grub_efi_uint32_t data_size; |
1452 | + grub_efi_device_path_t *file_path; |
1453 | ++ grub_efi_uint8_t nx_compat; |
1454 | + grub_efi_uint16_t machine; |
1455 | + grub_efi_uint16_t num_sections; |
1456 | + struct grub_pe32_section_table *section; |
1457 | +@@ -145,6 +147,8 @@ check_pe_header (struct image_info *info) |
1458 | + grub_error (GRUB_ERR_BAD_OS, "expected EFI application"); |
1459 | + return GRUB_EFI_LOAD_ERROR; |
1460 | + } |
1461 | ++ info->nx_compat = |
1462 | ++ (pe32_header->dll_characteristics & GRUB_PE32_NX_COMPAT) != 0; |
1463 | + info->section_alignment = pe32_header->section_alignment; |
1464 | + info->image_base = pe32_header->image_base; |
1465 | + info->image_size = pe32_header->image_size; |
1466 | +@@ -171,6 +175,8 @@ check_pe_header (struct image_info *info) |
1467 | + grub_error (GRUB_ERR_BAD_OS, "expected EFI application"); |
1468 | + return GRUB_EFI_LOAD_ERROR; |
1469 | + } |
1470 | ++ info->nx_compat = |
1471 | ++ (pe64_header->dll_characteristics & GRUB_PE32_NX_COMPAT) != 0; |
1472 | + info->section_alignment = pe64_header->section_alignment; |
1473 | + info->image_base = pe64_header->image_base; |
1474 | + info->image_size = pe64_header->image_size; |
1475 | +@@ -196,6 +202,19 @@ check_pe_header (struct image_info *info) |
1476 | + return GRUB_EFI_LOAD_ERROR; |
1477 | + } |
1478 | + |
1479 | ++ /* NOTE: shim_lock->verify() also enforces this, so this |
1480 | ++ * check won't be hit when used with shim */ |
1481 | ++ if (grub_efi_check_nx_required() && !info->nx_compat) |
1482 | ++ { |
1483 | ++ grub_error (GRUB_ERR_BAD_OS, "NX policy violation"); |
1484 | ++ return GRUB_EFI_SECURITY_VIOLATION; |
1485 | ++ } |
1486 | ++ if (info->nx_compat && info->section_alignment < GRUB_EFI_PAGE_SIZE) |
1487 | ++ { |
1488 | ++ grub_error (GRUB_ERR_BAD_OS, "NX compatible image with sub-page section alignment"); |
1489 | ++ return GRUB_EFI_LOAD_ERROR; |
1490 | ++ } |
1491 | ++ |
1492 | + if ((unsigned long)info->section |
1493 | + + info->num_sections * sizeof (*info->section) |
1494 | + > (unsigned long)info->data + info->data_size) |
1495 | +@@ -221,6 +240,9 @@ load_sections (struct image_info *info) |
1496 | + { |
1497 | + struct grub_pe32_section_table *section; |
1498 | + unsigned long align_mask = 0xfff; |
1499 | ++ grub_addr_t section_addr; |
1500 | ++ grub_err_t err; |
1501 | ++ grub_uint64_t section_set_mem_attr, section_clear_mem_attr; |
1502 | + |
1503 | + /* Section alignment must be a power of two */ |
1504 | + if (info->section_alignment & (info->section_alignment - 1)) |
1505 | +@@ -264,12 +286,52 @@ load_sections (struct image_info *info) |
1506 | + return GRUB_EFI_LOAD_ERROR; |
1507 | + } |
1508 | + |
1509 | +- grub_memset ((void *)((unsigned long)info->image_addr + section->virtual_address), |
1510 | +- 0, section->virtual_size); |
1511 | ++ section_addr = (grub_addr_t)info->image_addr + section->virtual_address; |
1512 | ++ |
1513 | ++ grub_memset ((void *) section_addr, 0, section->virtual_size); |
1514 | + grub_memcpy ( |
1515 | +- (void *)((unsigned long)info->image_addr + section->virtual_address), |
1516 | ++ (void *) section_addr, |
1517 | + (void *)((unsigned long)info->data + section->raw_data_offset), |
1518 | + section->raw_data_size); |
1519 | ++ |
1520 | ++ if (!info->nx_compat) |
1521 | ++ continue; |
1522 | ++ |
1523 | ++ if (section_addr & (GRUB_EFI_PAGE_SIZE - 1)) |
1524 | ++ { |
1525 | ++ grub_error (GRUB_ERR_BAD_OS, "NX compatible image with badly aligned section"); |
1526 | ++ return GRUB_EFI_LOAD_ERROR; |
1527 | ++ } |
1528 | ++ |
1529 | ++ if ((section->characteristics & GRUB_PE32_SCN_MEM_WRITE) && (section->characteristics & GRUB_PE32_SCN_MEM_EXECUTE)) |
1530 | ++ { |
1531 | ++ grub_error (GRUB_ERR_BAD_OS, "NX compatible image with W|X section"); |
1532 | ++ return GRUB_EFI_LOAD_ERROR; |
1533 | ++ } |
1534 | ++ |
1535 | ++ section_set_mem_attr = 0; |
1536 | ++ section_clear_mem_attr = 0; |
1537 | ++ if (section->characteristics & GRUB_PE32_SCN_MEM_READ) |
1538 | ++ section_set_mem_attr |= GRUB_MEM_ATTR_R; |
1539 | ++ else |
1540 | ++ section_clear_mem_attr |= GRUB_MEM_ATTR_R; |
1541 | ++ if (section->characteristics & GRUB_PE32_SCN_MEM_WRITE) |
1542 | ++ section_set_mem_attr |= GRUB_MEM_ATTR_W; |
1543 | ++ else |
1544 | ++ section_clear_mem_attr |= GRUB_MEM_ATTR_W; |
1545 | ++ if (section->characteristics & GRUB_PE32_SCN_MEM_EXECUTE) |
1546 | ++ section_set_mem_attr |= GRUB_MEM_ATTR_X; |
1547 | ++ else |
1548 | ++ section_clear_mem_attr |= GRUB_MEM_ATTR_X; |
1549 | ++ |
1550 | ++ err = grub_update_mem_attrs (section_addr, |
1551 | ++ GRUB_EFI_BYTES_TO_PAGES(section->virtual_size) * GRUB_EFI_PAGE_SIZE, |
1552 | ++ section_set_mem_attr, section_clear_mem_attr); |
1553 | ++ if (err != GRUB_ERR_NONE) |
1554 | ++ { |
1555 | ++ grub_error (GRUB_ERR_BAD_OS, "Failed to set PE section memory attributes"); |
1556 | ++ return GRUB_EFI_LOAD_ERROR; |
1557 | ++ } |
1558 | + } |
1559 | + |
1560 | + info->entry_point = (void *)((unsigned long)info->entry_point |
1561 | diff --git a/debian/patches/secure-boot/efi-use-peimage-shim.patch b/debian/patches/secure-boot/efi-use-peimage-shim.patch |
1562 | index 505f92f..c05440e 100644 |
1563 | --- a/debian/patches/secure-boot/efi-use-peimage-shim.patch |
1564 | +++ b/debian/patches/secure-boot/efi-use-peimage-shim.patch |
1565 | @@ -30,9 +30,9 @@ Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> |
1566 | Signed-off-by: Julian Andres Klode <julian.klode@canonical.com> |
1567 | --- |
1568 | grub-core/Makefile.core.def | 12 + |
1569 | - grub-core/loader/efi/peimage.c | 902 +++++++++++++++++++++++++++++++++++++++++ |
1570 | + grub-core/loader/efi/peimage.c | 826 +++++++++++++++++++++++++++++++++++++++++ |
1571 | include/grub/efi/peimage.h | 19 + |
1572 | - 3 files changed, 933 insertions(+) |
1573 | + 3 files changed, 857 insertions(+) |
1574 | create mode 100644 grub-core/loader/efi/peimage.c |
1575 | create mode 100644 include/grub/efi/peimage.h |
1576 | |
1577 | @@ -61,10 +61,10 @@ index 333d3fe..c3ad031 100644 |
1578 | efi = loader/efi/fdt.c; |
1579 | diff --git a/grub-core/loader/efi/peimage.c b/grub-core/loader/efi/peimage.c |
1580 | new file mode 100644 |
1581 | -index 0000000..0387277 |
1582 | +index 0000000..e28f020 |
1583 | --- /dev/null |
1584 | +++ b/grub-core/loader/efi/peimage.c |
1585 | -@@ -0,0 +1,902 @@ |
1586 | +@@ -0,0 +1,826 @@ |
1587 | +/* peimage.c - load EFI PE binaries (for Secure Boot support) */ |
1588 | + |
1589 | +// SPDX-License-Identifier: GPL-3.0+ |
1590 | @@ -82,33 +82,39 @@ index 0000000..0387277 |
1591 | + |
1592 | +GRUB_MOD_LICENSE ("GPLv3+"); |
1593 | + |
1594 | -+ |
1595 | +static grub_dl_t my_mod; |
1596 | + |
1597 | +struct image_info |
1598 | +{ |
1599 | -+ grub_efi_loaded_image_t loaded_image; |
1600 | -+ |
1601 | -+ grub_efi_device_path_t *orig_file_path; |
1602 | -+ |
1603 | + void *data; |
1604 | + grub_efi_uint32_t data_size; |
1605 | ++ grub_efi_device_path_t *file_path; |
1606 | + grub_efi_uint16_t machine; |
1607 | + grub_efi_uint16_t num_sections; |
1608 | + struct grub_pe32_section_table *section; |
1609 | + struct grub_pe32_data_directory *reloc; |
1610 | + grub_uint64_t image_base; |
1611 | + grub_uint32_t section_alignment; |
1612 | ++ grub_uint32_t image_size; |
1613 | + grub_uint32_t header_size; |
1614 | + void *alloc_addr; |
1615 | + grub_uint32_t alloc_pages; |
1616 | -+ |
1617 | ++ void *image_addr; |
1618 | + grub_efi_status_t (__grub_efi_api *entry_point) ( |
1619 | -+ grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table); |
1620 | ++ grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table); |
1621 | ++}; |
1622 | + |
1623 | ++static struct |
1624 | ++{ |
1625 | + grub_jmp_buf jmp; |
1626 | ++ grub_efi_handle_t image_handle; |
1627 | + grub_efi_status_t exit_status; |
1628 | -+}; |
1629 | ++ grub_efi_status_t (__grub_efi_api *exit) (grub_efi_handle_t image_handle, |
1630 | ++ grub_efi_status_t exit_status, |
1631 | ++ grub_efi_uintn_t exit_data_size, |
1632 | ++ grub_efi_char16_t *exit_data); |
1633 | ++} started_image; |
1634 | ++ |
1635 | + |
1636 | +static grub_uint16_t machines[] = { |
1637 | +#if defined(__x86_64__) |
1638 | @@ -126,19 +132,6 @@ index 0000000..0387277 |
1639 | +#endif |
1640 | +}; |
1641 | + |
1642 | -+// Forward declare unload_image handler |
1643 | -+static grub_efi_status_t __grub_efi_api |
1644 | -+do_unload_image (grub_efi_handle_t image_handle); |
1645 | -+ |
1646 | -+// Original exit handler |
1647 | -+static grub_efi_status_t (__grub_efi_api *exit_orig) ( |
1648 | -+ grub_efi_handle_t image_handle, grub_efi_status_t exit_status, |
1649 | -+ grub_efi_uintn_t exit_data_size, grub_efi_char16_t *exit_data); |
1650 | -+ |
1651 | -+// Original unload_image handler |
1652 | -+static grub_efi_status_t (__grub_efi_api *unload_image_orig) ( |
1653 | -+ grub_efi_handle_t image_handle); |
1654 | -+ |
1655 | +/** |
1656 | + * check_machine_type() - check if the machine type matches the architecture |
1657 | + * |
1658 | @@ -221,7 +214,7 @@ index 0000000..0387277 |
1659 | + } |
1660 | + info->section_alignment = pe32_header->section_alignment; |
1661 | + info->image_base = pe32_header->image_base; |
1662 | -+ info->loaded_image.image_size = pe32_header->image_size; |
1663 | ++ info->image_size = pe32_header->image_size; |
1664 | + info->entry_point = (void *)(unsigned long)pe32_header->entry_addr; |
1665 | + info->header_size = pe32_header->header_size; |
1666 | + if (info->data_size < info->header_size) |
1667 | @@ -247,7 +240,7 @@ index 0000000..0387277 |
1668 | + } |
1669 | + info->section_alignment = pe64_header->section_alignment; |
1670 | + info->image_base = pe64_header->image_base; |
1671 | -+ info->loaded_image.image_size = pe64_header->image_size; |
1672 | ++ info->image_size = pe64_header->image_size; |
1673 | + info->entry_point = (void *)(unsigned long)pe64_header->entry_addr; |
1674 | + info->header_size = pe64_header->header_size; |
1675 | + if (info->data_size < info->header_size) |
1676 | @@ -306,8 +299,7 @@ index 0000000..0387277 |
1677 | + if (info->section_alignment > align_mask) |
1678 | + align_mask = info->section_alignment - 1; |
1679 | + |
1680 | -+ info->alloc_pages = GRUB_EFI_BYTES_TO_PAGES (info->loaded_image.image_size |
1681 | -+ + (align_mask & ~0xfffUL)); |
1682 | ++ info->alloc_pages = GRUB_EFI_BYTES_TO_PAGES (info->image_size + (align_mask & ~0xfffUL)); |
1683 | + |
1684 | + info->alloc_addr = grub_efi_allocate_pages_real ( |
1685 | + GRUB_EFI_MAX_USABLE_ADDRESS, info->alloc_pages, |
1686 | @@ -315,44 +307,40 @@ index 0000000..0387277 |
1687 | + if (!info->alloc_addr) |
1688 | + return GRUB_EFI_OUT_OF_RESOURCES; |
1689 | + |
1690 | -+ info->loaded_image.image_base |
1691 | ++ info->image_addr |
1692 | + = (void *)(((unsigned long)info->alloc_addr + align_mask) & ~align_mask); |
1693 | + |
1694 | -+ grub_memcpy (info->loaded_image.image_base, info->data, info->header_size); |
1695 | ++ grub_memcpy (info->image_addr, info->data, info->header_size); |
1696 | + for (section = &info->section[0]; |
1697 | + section < &info->section[info->num_sections]; ++section) |
1698 | + { |
1699 | -+ if (section->virtual_address < info->header_size |
1700 | -+ || (section->raw_data_size |
1701 | -+ && section->raw_data_offset < info->header_size)) |
1702 | ++ if ((section->raw_data_size && section->raw_data_offset < info->header_size) |
1703 | ++ || (section->virtual_size && section->virtual_address < info->header_size)) |
1704 | + { |
1705 | + grub_error (GRUB_ERR_BAD_OS, "section inside header"); |
1706 | + return GRUB_EFI_LOAD_ERROR; |
1707 | + } |
1708 | -+ if (section->raw_data_offset + section->raw_data_size > info->data_size) |
1709 | ++ if (section->raw_data_size && section->raw_data_offset + section->raw_data_size > info->data_size) |
1710 | + { |
1711 | + grub_error (GRUB_ERR_BAD_OS, "truncated image"); |
1712 | + return GRUB_EFI_LOAD_ERROR; |
1713 | + } |
1714 | -+ if (section->virtual_address + section->virtual_size |
1715 | -+ > info->loaded_image.image_size) |
1716 | ++ if (section->virtual_size && section->virtual_address + section->virtual_size > info->image_size) |
1717 | + { |
1718 | + grub_error (GRUB_ERR_BAD_OS, "section outside image"); |
1719 | + return GRUB_EFI_LOAD_ERROR; |
1720 | + } |
1721 | + |
1722 | -+ grub_memset ((void *)((unsigned long)info->loaded_image.image_base |
1723 | -+ + section->virtual_address), |
1724 | ++ grub_memset ((void *)((unsigned long)info->image_addr + section->virtual_address), |
1725 | + 0, section->virtual_size); |
1726 | + grub_memcpy ( |
1727 | -+ (void *)((unsigned long)info->loaded_image.image_base |
1728 | -+ + section->virtual_address), |
1729 | ++ (void *)((unsigned long)info->image_addr + section->virtual_address), |
1730 | + (void *)((unsigned long)info->data + section->raw_data_offset), |
1731 | + section->raw_data_size); |
1732 | + } |
1733 | + |
1734 | + info->entry_point = (void *)((unsigned long)info->entry_point |
1735 | -+ + (unsigned long)info->loaded_image.image_base); |
1736 | ++ + (unsigned long)info->image_addr); |
1737 | + |
1738 | + grub_dprintf ("linux", "sections loaded\n"); |
1739 | + |
1740 | @@ -560,7 +548,7 @@ index 0000000..0387277 |
1741 | + return GRUB_EFI_SUCCESS; |
1742 | + } |
1743 | + |
1744 | -+ if (info->reloc->rva + info->reloc->size > info->loaded_image.image_size) |
1745 | ++ if (info->reloc->rva + info->reloc->size > info->image_size) |
1746 | + { |
1747 | + grub_error (GRUB_ERR_BAD_OS, "relocation block outside image"); |
1748 | + return GRUB_EFI_LOAD_ERROR; |
1749 | @@ -570,10 +558,9 @@ index 0000000..0387277 |
1750 | + * The relocations are based on the difference between |
1751 | + * actual load address and the preferred base address. |
1752 | + */ |
1753 | -+ offset = (unsigned long)info->loaded_image.image_base - info->image_base; |
1754 | ++ offset = (unsigned long)info->image_addr - info->image_base; |
1755 | + |
1756 | -+ block = (void *)((unsigned long)info->loaded_image.image_base |
1757 | -+ + info->reloc->rva); |
1758 | ++ block = (void *)((unsigned long)info->image_addr + info->reloc->rva); |
1759 | + reloc_end = (void *)((unsigned long)block + info->reloc->size); |
1760 | + |
1761 | + for (; block < reloc_end; |
1762 | @@ -585,7 +572,7 @@ index 0000000..0387277 |
1763 | + |
1764 | + for (; reloc_entry < block_end; ++reloc_entry) |
1765 | + { |
1766 | -+ void *addr = (void *)((unsigned long)info->loaded_image.image_base |
1767 | ++ void *addr = (void *)((unsigned long)info->image_addr |
1768 | + + block->page_rva + (*reloc_entry & 0xfff)); |
1769 | + |
1770 | + reloc_type = *reloc_entry >> 12; |
1771 | @@ -687,254 +674,203 @@ index 0000000..0387277 |
1772 | +bad_reloc: |
1773 | + grub_error (GRUB_ERR_BAD_OS, "unsupported relocation type %d, rva 0x%08lx\n", |
1774 | + *reloc_entry >> 12, |
1775 | -+ (unsigned long)reloc_entry |
1776 | -+ - (unsigned long)info->loaded_image.image_base); |
1777 | ++ (unsigned long)reloc_entry - (unsigned long)info->image_addr); |
1778 | + return GRUB_EFI_LOAD_ERROR; |
1779 | +} |
1780 | + |
1781 | +/** |
1782 | -+ * exit_hook() - replacement for EFI_BOOT_SERVICES.Exit() |
1783 | ++ * efi_exit() - replacement for EFI_BOOT_SERVICES.Exit() |
1784 | + * |
1785 | + * This function is inserted into system table to trap invocations of |
1786 | + * EFI_BOOT_SERVICES.Exit(). If Exit() is called with our handle |
1787 | + * return to our start routine using a long jump. |
1788 | + * |
1789 | -+ * @image_handle: handle of the application as passed on entry |
1790 | -+ * @exit_status: the images exit code |
1791 | -+ * @exit_data_size: size of @exit_data |
1792 | -+ * @exit_data: null terminated string followed by optional data |
1793 | ++ * @image_handle: handle of the application as passed on entry |
1794 | ++ * @exit_status: the images exit code |
1795 | ++ * @exit_data_size: size of @exit_data |
1796 | ++ * @exit_data: null terminated string followed by optional data |
1797 | + */ |
1798 | +static grub_efi_status_t __grub_efi_api |
1799 | -+exit_hook (grub_efi_handle_t image_handle, grub_efi_status_t exit_status, |
1800 | -+ grub_efi_uintn_t exit_data_size, grub_efi_char16_t *exit_data) |
1801 | ++efi_exit (grub_efi_handle_t image_handle, grub_efi_status_t exit_status, |
1802 | ++ grub_efi_uintn_t exit_data_size, grub_efi_char16_t *exit_data) |
1803 | +{ |
1804 | -+ struct image_info *info; |
1805 | ++ grub_efi_system_table->boot_services->exit = started_image.exit; |
1806 | + |
1807 | + if (!image_handle) |
1808 | + return GRUB_EFI_INVALID_PARAMETER; |
1809 | + |
1810 | -+ info = grub_efi_open_protocol (image_handle, |
1811 | -+ &(grub_guid_t)GRUB_PEIMAGE_MARKER_GUID, |
1812 | -+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); |
1813 | -+ if (!info) |
1814 | ++ if (image_handle != started_image.image_handle) |
1815 | + { |
1816 | + grub_dprintf ("linux", "delegating Exit()\n"); |
1817 | -+ return exit_orig (image_handle, exit_status, exit_data_size, |
1818 | -+ (grub_efi_char16_t *)exit_data); |
1819 | ++ return started_image.exit (image_handle, exit_status, exit_data_size, |
1820 | ++ (grub_efi_char16_t *)exit_data); |
1821 | + } |
1822 | + |
1823 | -+ info->exit_status = exit_status; |
1824 | ++ started_image.exit_status = exit_status; |
1825 | + |
1826 | + if (exit_status != GRUB_EFI_SUCCESS) |
1827 | + { |
1828 | + grub_printf ("Application failed, r = %d\n", |
1829 | + (int)exit_status & 0x7fffffff); |
1830 | + if (exit_data_size && exit_data) |
1831 | -+ { |
1832 | ++ { |
1833 | + grub_printf ("exit message: "); |
1834 | + for (grub_efi_uintn_t pos = 0; |
1835 | + exit_data[pos] && pos < exit_data_size / 2; ++pos) |
1836 | + grub_printf ("%C", exit_data[pos]); |
1837 | + grub_printf ("\n"); |
1838 | -+ } |
1839 | ++ } |
1840 | + } |
1841 | + if (exit_data_size && exit_data) |
1842 | + { |
1843 | + /* exit data must be freed by the caller */ |
1844 | + grub_efi_system_table->boot_services->free_pool (exit_data); |
1845 | + } |
1846 | -+ grub_longjmp (info->jmp, 1); |
1847 | ++ grub_longjmp (started_image.jmp, 1); |
1848 | +} |
1849 | + |
1850 | ++static grub_efi_status_t __grub_efi_api |
1851 | ++do_unload_image (grub_efi_handle_t image_handle); |
1852 | ++ |
1853 | +/** |
1854 | -+ * unload_image_hook() - replacement for EFI_BOOT_SERVICES.UnloadImage() |
1855 | -+ * |
1856 | -+ * peimage only supports loading EFI Applications, which cannot be correctly |
1857 | -+ * unloaded while running. |
1858 | ++ * start_image() - our implementation of StartImage() |
1859 | + * |
1860 | -+ * Installing this hooks prevents that from happening. |
1861 | ++ * As we do not load the image via LoadImage() we need our own implementation |
1862 | ++ * of StartImage() to launch the PE-COFF image. |
1863 | + */ |
1864 | -+static grub_efi_status_t __grub_efi_api |
1865 | -+unload_image_hook (grub_efi_handle_t image_handle) |
1866 | ++static grub_efi_status_t |
1867 | ++start_image (struct image_info *info) |
1868 | +{ |
1869 | -+ if (grub_efi_open_protocol (image_handle, |
1870 | -+ &(grub_guid_t) GRUB_PEIMAGE_MARKER_GUID, |
1871 | -+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL)) |
1872 | -+ return GRUB_EFI_UNSUPPORTED; |
1873 | ++ int ret; |
1874 | ++ grub_efi_status_t status; |
1875 | ++ grub_efi_loaded_image_t *loaded_image; |
1876 | + |
1877 | -+ return unload_image_orig(image_handle); |
1878 | -+} |
1879 | ++ /* |
1880 | ++ * NOTE: We cannot easily comply with the UEFI specification and provide the |
1881 | ++ * child its own handle, otherwise things can go horribly wrong if said custom |
1882 | ++ * handle is passed to the firmware by child images |
1883 | ++ */ |
1884 | ++ started_image.image_handle = grub_efi_image_handle; |
1885 | + |
1886 | -+static grub_efi_status_t __grub_efi_api |
1887 | -+do_load_image (grub_efi_boolean_t boot_policy __attribute__ ((unused)), |
1888 | -+ grub_efi_handle_t parent_image_handle, |
1889 | -+ grub_efi_device_path_t *file_path, void *source_buffer, |
1890 | -+ grub_efi_uintn_t source_size, grub_efi_handle_t *image_handle) |
1891 | -+{ |
1892 | -+ grub_efi_status_t status; |
1893 | -+ struct image_info *info; |
1894 | ++ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); |
1895 | ++ if (loaded_image) |
1896 | ++ { |
1897 | ++ loaded_image->image_base = info->image_addr; |
1898 | ++ loaded_image->image_size = info->image_size; |
1899 | ++ |
1900 | ++ // Pass just the file path portion to the loaded image |
1901 | ++ loaded_image->file_path = info->file_path; |
1902 | ++ while (loaded_image->file_path && |
1903 | ++ (loaded_image->file_path->type != GRUB_EFI_MEDIA_DEVICE_PATH_TYPE |
1904 | ++ || loaded_image->file_path->subtype != GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)) |
1905 | ++ loaded_image->file_path = GRUB_EFI_NEXT_DEVICE_PATH (loaded_image->file_path); |
1906 | ++ } |
1907 | ++ else |
1908 | ++ { |
1909 | ++ grub_dprintf ("linux", "Loaded image protocol missing\n"); |
1910 | ++ } |
1911 | + |
1912 | -+ info = grub_efi_allocate_pages_real ( |
1913 | -+ GRUB_EFI_MAX_USABLE_ADDRESS, GRUB_EFI_BYTES_TO_PAGES (sizeof *info), |
1914 | -+ GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA); |
1915 | -+ if (!info) |
1916 | -+ return GRUB_EFI_OUT_OF_RESOURCES; |
1917 | ++ ret = grub_setjmp (started_image.jmp); |
1918 | ++ if (ret) |
1919 | ++ { |
1920 | ++ do_unload_image(started_image.image_handle); |
1921 | ++ started_image.image_handle = NULL; |
1922 | ++ return started_image.exit_status; |
1923 | ++ } |
1924 | + |
1925 | -+ grub_memset (info, 0, sizeof *info); |
1926 | ++ started_image.exit = grub_efi_system_table->boot_services->exit; |
1927 | ++ grub_efi_system_table->boot_services->exit = efi_exit; |
1928 | + |
1929 | -+ info->data = source_buffer; |
1930 | -+ info->data_size = source_size; |
1931 | ++ grub_dprintf ( |
1932 | ++ "linux", |
1933 | ++ "Executing image loaded at 0x%lx\nEntry point 0x%lx\nSize 0x%08x\n", |
1934 | ++ (unsigned long)info->image_addr, (unsigned long)info->entry_point, |
1935 | ++ info->image_size); |
1936 | + |
1937 | -+ // Save original device path |
1938 | -+ if (file_path) |
1939 | -+ info->orig_file_path = grub_efi_duplicate_device_path (file_path); |
1940 | ++ /* Invalidate the instruction cache */ |
1941 | ++ grub_arch_sync_caches (info->image_addr, info->image_size); |
1942 | + |
1943 | -+ // Split out file path |
1944 | -+ while (file_path |
1945 | -+ && (file_path->type != GRUB_EFI_MEDIA_DEVICE_PATH_TYPE |
1946 | -+ || file_path->subtype != GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)) |
1947 | -+ file_path = GRUB_EFI_NEXT_DEVICE_PATH (file_path); |
1948 | -+ if (file_path) |
1949 | -+ info->loaded_image.file_path = grub_efi_duplicate_device_path (file_path); |
1950 | ++ status = info->entry_point (started_image.image_handle, grub_efi_system_table); |
1951 | + |
1952 | -+ // Process PE image |
1953 | -+ status = check_pe_header (info); |
1954 | -+ if (status != GRUB_EFI_SUCCESS) |
1955 | -+ goto err; |
1956 | ++ grub_dprintf ("linux", "Application returned\n"); |
1957 | + |
1958 | -+ status = load_sections (info); |
1959 | -+ if (status != GRUB_EFI_SUCCESS) |
1960 | -+ goto err; |
1961 | ++ return efi_exit (started_image.image_handle, status, 0, NULL); |
1962 | ++} |
1963 | ++ |
1964 | ++static struct image_info info; |
1965 | ++ |
1966 | ++/* TODO: move the creation of the load options here */ |
1967 | ++static grub_efi_status_t __grub_efi_api |
1968 | ++do_load_image (grub_efi_boolean_t boot_policy __attribute__ ((unused)), |
1969 | ++ grub_efi_handle_t parent_image_handle __attribute__ ((unused)), |
1970 | ++ grub_efi_device_path_t *file_path, |
1971 | ++ void *source_buffer, grub_efi_uintn_t source_size, |
1972 | ++ grub_efi_handle_t *image_handle) |
1973 | ++{ |
1974 | ++ grub_efi_status_t ret = GRUB_EFI_SUCCESS; |
1975 | ++ if (info.data != NULL) |
1976 | ++ { |
1977 | ++ grub_error (GRUB_ERR_BAD_OS, "cannot load multiple images"); |
1978 | ++ return GRUB_EFI_LOAD_ERROR; |
1979 | ++ } |
1980 | ++ |
1981 | ++ grub_dl_ref (my_mod); |
1982 | ++ |
1983 | ++ info = (struct image_info){ |
1984 | ++ .data = source_buffer, |
1985 | ++ .data_size = source_size, |
1986 | ++ .file_path = grub_efi_duplicate_device_path(file_path), |
1987 | ++ }; |
1988 | + |
1989 | -+ status = relocate (info); |
1990 | -+ if (status != GRUB_EFI_SUCCESS) |
1991 | ++ ret = check_pe_header (&info); |
1992 | ++ if (ret != GRUB_EFI_SUCCESS) |
1993 | + goto err; |
1994 | + |
1995 | -+ // Setup EFI_LOADED_IMAGE_PROTOCOL |
1996 | -+ info->loaded_image.revision = GRUB_EFI_LOADED_IMAGE_REVISION; |
1997 | -+ info->loaded_image.parent_handle = parent_image_handle; |
1998 | -+ info->loaded_image.system_table = grub_efi_system_table; |
1999 | -+ info->loaded_image.image_code_type = GRUB_EFI_LOADER_CODE; |
2000 | -+ info->loaded_image.image_data_type = GRUB_EFI_LOADER_DATA; |
2001 | -+ |
2002 | -+ // Instruct EFI to create a new handle |
2003 | -+ *image_handle = NULL; |
2004 | -+ status |
2005 | -+ = grub_efi_system_table->boot_services |
2006 | -+ ->install_multiple_protocol_interfaces ( |
2007 | -+ image_handle, &(grub_guid_t)GRUB_PEIMAGE_MARKER_GUID, info, |
2008 | -+ &(grub_guid_t)GRUB_EFI_LOADED_IMAGE_GUID, &info->loaded_image, |
2009 | -+ &(grub_guid_t)GRUB_EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID, |
2010 | -+ info->orig_file_path, NULL); |
2011 | -+ if (status != GRUB_EFI_SUCCESS) |
2012 | ++ ret = load_sections (&info); |
2013 | ++ if (ret != GRUB_EFI_SUCCESS) |
2014 | + goto err; |
2015 | + |
2016 | -+ // Increment module refcount |
2017 | -+ grub_dl_ref (my_mod); |
2018 | ++ ret = relocate (&info); |
2019 | ++ if (ret != GRUB_EFI_SUCCESS) |
2020 | ++ goto err; |
2021 | + |
2022 | -+ return status; |
2023 | ++ *image_handle = grub_efi_image_handle; |
2024 | ++ return GRUB_EFI_SUCCESS; |
2025 | + |
2026 | +err: |
2027 | -+ if (info->alloc_addr) |
2028 | -+ grub_efi_free_pages ((unsigned long)info->alloc_addr, info->alloc_pages); |
2029 | -+ if (info->loaded_image.file_path) |
2030 | -+ grub_free (info->loaded_image.file_path); |
2031 | -+ if (info->orig_file_path) |
2032 | -+ grub_free (info->orig_file_path); |
2033 | -+ grub_efi_free_pages ((unsigned long)info, |
2034 | -+ GRUB_EFI_BYTES_TO_PAGES (sizeof *info)); |
2035 | -+ return status; |
2036 | ++ /* NOTE: do_unload_image() doesn't care about image_handle */ |
2037 | ++ do_unload_image (NULL); |
2038 | ++ return ret; |
2039 | +} |
2040 | + |
2041 | +static grub_efi_status_t __grub_efi_api |
2042 | -+do_start_image (grub_efi_handle_t image_handle, |
2043 | ++do_start_image (grub_efi_handle_t image_handle __attribute__ ((unused)), |
2044 | + grub_efi_uintn_t *exit_data_size __attribute__ ((unused)), |
2045 | + grub_efi_char16_t **exit_data __attribute__ ((unused))) |
2046 | +{ |
2047 | -+ grub_efi_status_t status; |
2048 | -+ struct image_info *info; |
2049 | -+ |
2050 | -+ info = grub_efi_open_protocol (image_handle, |
2051 | -+ &(grub_guid_t)GRUB_PEIMAGE_MARKER_GUID, |
2052 | -+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); |
2053 | -+ if (!info) |
2054 | ++ if (info.data == NULL) |
2055 | + { |
2056 | + grub_error (GRUB_ERR_BAD_OS, "image not loaded"); |
2057 | + return GRUB_EFI_LOAD_ERROR; |
2058 | + } |
2059 | -+ |
2060 | -+ if (grub_setjmp (info->jmp)) |
2061 | -+ { |
2062 | -+ status = info->exit_status; |
2063 | -+ do_unload_image (image_handle); |
2064 | -+ } |
2065 | -+ else |
2066 | -+ { |
2067 | -+ grub_dprintf ("linux", |
2068 | -+ "Executing image loaded at 0x%lx\n" |
2069 | -+ "Entry point 0x%lx\n" |
2070 | -+ "Size 0x%lx\n", |
2071 | -+ (unsigned long)info->loaded_image.image_base, |
2072 | -+ (unsigned long)info->entry_point, |
2073 | -+ (unsigned long)info->loaded_image.image_size); |
2074 | -+ |
2075 | -+ /* Invalidate the instruction cache */ |
2076 | -+ grub_arch_sync_caches (info->loaded_image.image_base, |
2077 | -+ info->loaded_image.image_size); |
2078 | -+ |
2079 | -+ status = info->entry_point (image_handle, grub_efi_system_table); |
2080 | -+ |
2081 | -+ grub_dprintf ("linux", "Application returned\n"); |
2082 | -+ |
2083 | -+ /* converge to the same exit path as if the image called |
2084 | -+ * boot_services->exit itself */ |
2085 | -+ exit_hook (image_handle, status, 0, NULL); |
2086 | -+ |
2087 | -+ /* image_handle is always valid above, thus exit_hook cannot |
2088 | -+ * return to here. if only GRUB had assert :( |
2089 | -+ grub_assert (false && "entered unreachable code"); |
2090 | -+ */ |
2091 | -+ } |
2092 | -+ |
2093 | -+ return status; |
2094 | ++ return start_image (&info); |
2095 | +} |
2096 | + |
2097 | +static grub_efi_status_t __grub_efi_api |
2098 | -+do_unload_image (grub_efi_handle_t image_handle) |
2099 | ++do_unload_image (grub_efi_handle_t image_handle __attribute__ ((unused))) |
2100 | +{ |
2101 | -+ grub_efi_status_t status; |
2102 | -+ struct image_info *info; |
2103 | -+ |
2104 | -+ info = grub_efi_open_protocol (image_handle, |
2105 | -+ &(grub_guid_t)GRUB_PEIMAGE_MARKER_GUID, |
2106 | -+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); |
2107 | -+ if (!info) |
2108 | ++ if (info.data == NULL) |
2109 | + { |
2110 | + grub_error (GRUB_ERR_BAD_OS, "image not loaded"); |
2111 | + return GRUB_EFI_LOAD_ERROR; |
2112 | + } |
2113 | -+ |
2114 | -+ status |
2115 | -+ = grub_efi_system_table->boot_services |
2116 | -+ ->uninstall_multiple_protocol_interfaces ( |
2117 | -+ image_handle, &(grub_guid_t)GRUB_PEIMAGE_MARKER_GUID, info, |
2118 | -+ &(grub_guid_t)GRUB_EFI_LOADED_IMAGE_GUID, &info->loaded_image, |
2119 | -+ &(grub_guid_t)GRUB_EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID, |
2120 | -+ info->orig_file_path, NULL); |
2121 | -+ if (status != GRUB_EFI_SUCCESS) |
2122 | -+ return GRUB_EFI_LOAD_ERROR; |
2123 | -+ |
2124 | -+ if (info->alloc_addr) |
2125 | -+ grub_efi_free_pages ((unsigned long)info->alloc_addr, info->alloc_pages); |
2126 | -+ if (info->loaded_image.file_path) |
2127 | -+ grub_free (info->loaded_image.file_path); |
2128 | -+ if (info->orig_file_path) |
2129 | -+ grub_free (info->orig_file_path); |
2130 | -+ |
2131 | -+ grub_efi_free_pages ((unsigned long)info, |
2132 | -+ GRUB_EFI_BYTES_TO_PAGES (sizeof *info)); |
2133 | ++ if (info.alloc_addr) |
2134 | ++ grub_efi_free_pages ((unsigned long)info.alloc_addr, info.alloc_pages); |
2135 | ++ if (info.file_path) |
2136 | ++ grub_free(info.file_path); |
2137 | + |
2138 | + grub_dl_unref (my_mod); |
2139 | ++ info = (struct image_info){}; |
2140 | + |
2141 | + return GRUB_EFI_SUCCESS; |
2142 | +} |
2143 | @@ -949,22 +885,10 @@ index 0000000..0387277 |
2144 | +{ |
2145 | + grub_efi_register_loader (&peimage_loader); |
2146 | + my_mod = mod; |
2147 | -+ |
2148 | -+ // Hook exit handler |
2149 | -+ exit_orig = grub_efi_system_table->boot_services->exit; |
2150 | -+ grub_efi_system_table->boot_services->exit = exit_hook; |
2151 | -+ // Hook unload_image handler |
2152 | -+ unload_image_orig = grub_efi_system_table->boot_services->unload_image; |
2153 | -+ grub_efi_system_table->boot_services->unload_image = unload_image_hook; |
2154 | +} |
2155 | + |
2156 | +GRUB_MOD_FINI (peimage) |
2157 | +{ |
2158 | -+ // Restore exit handler |
2159 | -+ grub_efi_system_table->boot_services->exit = exit_orig; |
2160 | -+ // Restore unload_image handler |
2161 | -+ grub_efi_system_table->boot_services->unload_image = unload_image_orig; |
2162 | -+ |
2163 | + grub_efi_unregister_loader (&peimage_loader); |
2164 | +} |
2165 | diff --git a/include/grub/efi/peimage.h b/include/grub/efi/peimage.h |
2166 | diff --git a/debian/patches/series b/debian/patches/series |
2167 | index 05de63a..ad6da55 100644 |
2168 | --- a/debian/patches/series |
2169 | +++ b/debian/patches/series |
2170 | @@ -111,3 +111,14 @@ Revert-kern-ieee1275-init-ppc64-Return-allocated-address-.patch |
2171 | Revert-kern-ieee1275-init-ppc64-Decide-by-request-whether.patch |
2172 | Revert-kern-ieee1275-init-ppc64-Introduce-a-request-for-r.patch |
2173 | grub-install-efi-title.patch |
2174 | +kern-efi-mm-Change-grub_efi_mm_add_regions-to-keep-track-.patch |
2175 | +kern-efi-mm-Change-grub_efi_allocate_pages_real-to-call-s.patch |
2176 | +kern-efi-mm-Detect-calls-to-grub_efi_drop_alloc-with-wron.patch |
2177 | +nx/modules-strip-.llvm_addrsig-sections-and-similar.patch |
2178 | +nx/modules-Don-t-allocate-space-for-non-allocable-sections.patch |
2179 | +nx/modules-load-module-sections-at-page-aligned-addresses.patch |
2180 | +nx/nx-add-memory-attribute-get-set-API.patch |
2181 | +nx/nx-set-page-permissions-for-loaded-modules.patch |
2182 | +nx/nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch |
2183 | +nx/efi-Disallow-fallback-to-legacy-Linux-loader-when-shim-sa.patch |
2184 | +nx/peimage-Add-memory-attribute-support.patch |
2185 | diff --git a/debian/patches/suse-grub.texi-add-net_bootp6-document.patch b/debian/patches/suse-grub.texi-add-net_bootp6-document.patch |
2186 | index a8a46b4..a84bdfb 100644 |
2187 | --- a/debian/patches/suse-grub.texi-add-net_bootp6-document.patch |
2188 | +++ b/debian/patches/suse-grub.texi-add-net_bootp6-document.patch |
2189 | @@ -13,10 +13,10 @@ Patch-Name: suse-grub.texi-add-net_bootp6-document.patch |
2190 | 1 file changed, 17 insertions(+) |
2191 | |
2192 | diff --git a/docs/grub.texi b/docs/grub.texi |
2193 | -index 584f6dc..4e6fb8d 100644 |
2194 | +index c2682be..c332de3 100644 |
2195 | --- a/docs/grub.texi |
2196 | +++ b/docs/grub.texi |
2197 | -@@ -5982,6 +5982,7 @@ Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}). |
2198 | +@@ -5973,6 +5973,7 @@ Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}). |
2199 | * net_add_dns:: Add a DNS server |
2200 | * net_add_route:: Add routing entry |
2201 | * net_bootp:: Perform a bootp/DHCP autoconfiguration |
2202 | @@ -24,7 +24,7 @@ index 584f6dc..4e6fb8d 100644 |
2203 | * net_del_addr:: Remove IP address from interface |
2204 | * net_del_dns:: Remove a DNS server |
2205 | * net_del_route:: Remove a route entry |
2206 | -@@ -6107,6 +6108,22 @@ Sets environment variable @samp{net_}@var{<card>}@samp{_boot_file} |
2207 | +@@ -6098,6 +6099,22 @@ Sets environment variable @samp{net_}@var{<card>}@samp{_boot_file} |
2208 | |
2209 | @end deffn |
2210 | |
2211 | diff --git a/debian/patches/ubuntu-fix-lzma-decompressor-objcopy.patch b/debian/patches/ubuntu-fix-lzma-decompressor-objcopy.patch |
2212 | index 311f938..2300117 100644 |
2213 | --- a/debian/patches/ubuntu-fix-lzma-decompressor-objcopy.patch |
2214 | +++ b/debian/patches/ubuntu-fix-lzma-decompressor-objcopy.patch |
2215 | @@ -15,7 +15,7 @@ Signed-off-by: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com> |
2216 | 1 file changed, 1 insertion(+), 1 deletion(-) |
2217 | |
2218 | diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def |
2219 | -index c3ad031..3d98edf 100644 |
2220 | +index 7b49f77..ae5c558 100644 |
2221 | --- a/grub-core/Makefile.core.def |
2222 | +++ b/grub-core/Makefile.core.def |
2223 | @@ -569,7 +569,7 @@ image = { |
2224 | diff --git a/debian/patches/ubuntu-support-initrd-less-boot.patch b/debian/patches/ubuntu-support-initrd-less-boot.patch |
2225 | index aac23f6..c883c7c 100644 |
2226 | --- a/debian/patches/ubuntu-support-initrd-less-boot.patch |
2227 | +++ b/debian/patches/ubuntu-support-initrd-less-boot.patch |
2228 | @@ -16,7 +16,7 @@ Patch-Name: ubuntu-support-initrd-less-boot.patch |
2229 | 3 files changed, 25 insertions(+), 4 deletions(-) |
2230 | |
2231 | diff --git a/docs/grub.texi b/docs/grub.texi |
2232 | -index b4825b7..584f6dc 100644 |
2233 | +index 990d8c7..c2682be 100644 |
2234 | --- a/docs/grub.texi |
2235 | +++ b/docs/grub.texi |
2236 | @@ -1615,6 +1615,19 @@ This option sets the English text of the string that will be displayed in |
2237 | diff --git a/debian/rules b/debian/rules |
2238 | index f806fec..5e2b379 100755 |
2239 | --- a/debian/rules |
2240 | +++ b/debian/rules |
2241 | @@ -253,6 +253,9 @@ debian/stamps/configure-grub-common: debian/stamps/configure-grub-$(COMMON_PLATF |
2242 | touch $@ |
2243 | |
2244 | debian/stamps/build-grub-common: debian/stamps/build-grub-$(COMMON_PLATFORM) |
2245 | +ifeq ($(with_check), yes) |
2246 | + pytest -q debian/test_grub_sort_version.py |
2247 | +endif |
2248 | touch $@ |
2249 | |
2250 | debian/stamps/configure-grub-none debian/stamps/configure-grub-pc debian/stamps/configure-grub-ieee1275 debian/stamps/configure-grub-coreboot debian/stamps/configure-grub-emu debian/stamps/configure-grub-uboot debian/stamps/configure-grub-yeeloong: |
2251 | diff --git a/debian/sbat.ubuntu.csv.in b/debian/sbat.ubuntu.csv.in |
2252 | index f33b573..0df0cc2 100644 |
2253 | --- a/debian/sbat.ubuntu.csv.in |
2254 | +++ b/debian/sbat.ubuntu.csv.in |
2255 | @@ -1,4 +1,4 @@ |
2256 | sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md |
2257 | grub,4,Free Software Foundation,grub,@UPSTREAM_VERSION@,https://www.gnu.org/software/grub/ |
2258 | -grub.ubuntu,1,Ubuntu,grub2,@DEB_VERSION@,https://www.ubuntu.com/ |
2259 | -grub.peimage,1,Canonical,grub2,@DEB_VERSION@,https://salsa.debian.org/grub-team/grub/-/blob/master/debian/patches/secure-boot/efi-use-peimage-shim.patch |
2260 | +grub.ubuntu,2,Ubuntu,grub2,@DEB_VERSION@,https://www.ubuntu.com/ |
2261 | +grub.peimage,2,Canonical,grub2,@DEB_VERSION@,https://salsa.debian.org/grub-team/grub/-/blob/master/debian/patches/secure-boot/efi-use-peimage-shim.patch |
2262 | diff --git a/debian/test_grub_sort_version.py b/debian/test_grub_sort_version.py |
2263 | new file mode 100755 |
2264 | index 0000000..8718ff4 |
2265 | --- /dev/null |
2266 | +++ b/debian/test_grub_sort_version.py |
2267 | @@ -0,0 +1,72 @@ |
2268 | +import os |
2269 | +import pytest |
2270 | +import subprocess |
2271 | + |
2272 | +GRUB_SORT_VERSION = "debian/grub-sort-version" |
2273 | + |
2274 | +def assert_grub_sort_version(input, output, flavour_order=""): |
2275 | + env = os.environ.copy() |
2276 | + env["LC_ALL"] = "C" |
2277 | + env["GRUB_FLAVOUR_ORDER"] = flavour_order |
2278 | + # Assert the output is as expected |
2279 | + result = subprocess.run([GRUB_SORT_VERSION], env=env, |
2280 | + input=input, encoding="utf-8", capture_output=True) |
2281 | + assert result.returncode == 0 |
2282 | + print(result.stdout) |
2283 | + assert result.stdout == output |
2284 | + # Then do the same in reverse mode too |
2285 | + result = subprocess.run([GRUB_SORT_VERSION, "-r"], env=env, |
2286 | + input=input, encoding="utf-8", capture_output=True) |
2287 | + assert result.returncode == 0 |
2288 | + assert result.stdout == "\n".join(output.rstrip().split("\n")[::-1]) + "\n" |
2289 | + |
2290 | +def test_empty_line(): |
2291 | + INPUT = """/boot/vmlinuz-6.5.0-10-generic 2 |
2292 | +/boot/vmlinuz-6.5.0-9-generic 2 |
2293 | + 2 |
2294 | +""" |
2295 | + |
2296 | + OUTPUT = """ 2 |
2297 | +/boot/vmlinuz-6.5.0-9-generic 2 |
2298 | +/boot/vmlinuz-6.5.0-10-generic 2 |
2299 | +""" |
2300 | + |
2301 | + assert_grub_sort_version(INPUT, OUTPUT) |
2302 | + |
2303 | +def test_custom_kernels(): |
2304 | + INPUT = """/boot/vmlinuz-6.6.0 2 |
2305 | +/boot/vmlinuz-6.5.0-10-generic 2 |
2306 | +/boot/vmlinuz-6.5.0-9-generic 2 |
2307 | +/boot/vmlinuz-6.5.9 2 |
2308 | +/boot/vmlinuz-6.5.8 2 |
2309 | +""" |
2310 | + |
2311 | + OUTPUT = """/boot/vmlinuz-6.5.0-9-generic 2 |
2312 | +/boot/vmlinuz-6.5.0-10-generic 2 |
2313 | +/boot/vmlinuz-6.5.8 2 |
2314 | +/boot/vmlinuz-6.5.9 2 |
2315 | +/boot/vmlinuz-6.6.0 2 |
2316 | +""" |
2317 | + |
2318 | + assert_grub_sort_version(INPUT, OUTPUT) |
2319 | + |
2320 | +def test_flavour_order(): |
2321 | + INPUT = """/boot/vmlinuz-6.5.0-10-generic 2 |
2322 | +/boot/vmlinuz-6.5.0-9-generic 2 |
2323 | +/boot/vmlinuz-6.5.0-9-aaa 2 |
2324 | +/boot/vmlinuz-6.5.0-9-aaa 1 |
2325 | +/boot/vmlinuz-6.5.8 2 |
2326 | +/boot/vmlinuz-6.5.9 2 |
2327 | +/boot/vmlinuz-6.6.0 2 |
2328 | +""" |
2329 | + |
2330 | + OUTPUT = """/boot/vmlinuz-6.5.8 2 |
2331 | +/boot/vmlinuz-6.5.9 2 |
2332 | +/boot/vmlinuz-6.6.0 2 |
2333 | +/boot/vmlinuz-6.5.0-9-aaa 1 |
2334 | +/boot/vmlinuz-6.5.0-9-aaa 2 |
2335 | +/boot/vmlinuz-6.5.0-9-generic 2 |
2336 | +/boot/vmlinuz-6.5.0-10-generic 2 |
2337 | +""" |
2338 | + |
2339 | + assert_grub_sort_version(INPUT, OUTPUT, flavour_order="generic aaa") |