]> git.proxmox.com Git - efi-boot-shim.git/blame - replacements.c
Add more hashes that we want to blacklist
[efi-boot-shim.git] / replacements.c
CommitLineData
cbef697a
PJ
1/*
2 * shim - trivial UEFI first-stage bootloader
3 *
4 * Copyright 2012 Red Hat, Inc <mjg@redhat.com>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Significant portions of this code are derived from Tianocore
32 * (http://tianocore.sf.net) and are Copyright 2009-2012 Intel
33 * Corporation.
34 */
35
36/* Chemical agents lend themselves to covert use in sabotage against
37 * which it is exceedingly difficult to visualize any really effective
38 * defense... I will not dwell upon this use of CBW because, as one
39 * pursues the possibilities of such covert uses, one discovers that the
40 * scenarios resemble that in which the components of a nuclear weapon
41 * are smuggled into New York City and assembled in the basement of the
42 * Empire State Building.
43 * In other words, once the possibility is recognized to exist, about
44 * all that one can do is worry about it.
45 * -- Dr. Ivan L Bennett, Jr., testifying before the Subcommittee on
46 * National Security Policy and Scientific Developments, November 20,
47 * 1969.
48 */
49
50#include <efi.h>
51#include <efiapi.h>
52#include <efilib.h>
f892ac66 53
cbef697a 54#include "shim.h"
cbef697a
PJ
55
56static EFI_SYSTEM_TABLE *systab;
57
f892ac66
MTL
58EFI_SYSTEM_TABLE *
59get_active_systab(void)
60{
61 if (systab)
62 return systab;
63 return ST;
64}
65
cf90edff 66static typeof(systab->BootServices->LoadImage) system_load_image;
cbef697a
PJ
67static typeof(systab->BootServices->StartImage) system_start_image;
68static typeof(systab->BootServices->Exit) system_exit;
69static typeof(systab->BootServices->ExitBootServices) system_exit_boot_services;
70
cf90edff
PJ
71static EFI_HANDLE last_loaded_image;
72
98a99578 73void
cbef697a
PJ
74unhook_system_services(void)
75{
277127d1
AB
76 if (!systab)
77 return;
78
cf90edff 79 systab->BootServices->LoadImage = system_load_image;
cbef697a
PJ
80 systab->BootServices->StartImage = system_start_image;
81 systab->BootServices->ExitBootServices = system_exit_boot_services;
f892ac66 82 gBS = systab->BootServices;
cbef697a
PJ
83}
84
cf90edff
PJ
85static EFI_STATUS EFIAPI
86load_image(BOOLEAN BootPolicy, EFI_HANDLE ParentImageHandle,
87 EFI_DEVICE_PATH *DevicePath, VOID *SourceBuffer,
88 UINTN SourceSize, EFI_HANDLE *ImageHandle)
89{
f892ac66 90 EFI_STATUS efi_status;
cf90edff 91
f892ac66
MTL
92 unhook_system_services();
93 efi_status = gBS->LoadImage(BootPolicy, ParentImageHandle, DevicePath,
94 SourceBuffer, SourceSize, ImageHandle);
cf90edff 95 hook_system_services(systab);
f892ac66 96 if (EFI_ERROR(efi_status))
cf90edff
PJ
97 last_loaded_image = NULL;
98 else
99 last_loaded_image = *ImageHandle;
f892ac66 100 return efi_status;
cf90edff
PJ
101}
102
cbef697a 103static EFI_STATUS EFIAPI
f892ac66 104replacement_start_image(EFI_HANDLE image_handle, UINTN *exit_data_size, CHAR16 **exit_data)
cbef697a 105{
f892ac66 106 EFI_STATUS efi_status;
cbef697a 107 unhook_system_services();
cf90edff 108
cf90edff
PJ
109 if (image_handle == last_loaded_image) {
110 loader_is_participating = 1;
111 uninstall_shim_protocols();
112 }
f892ac66
MTL
113 efi_status = gBS->StartImage(image_handle, exit_data_size, exit_data);
114 if (EFI_ERROR(efi_status)) {
cf90edff 115 if (image_handle == last_loaded_image) {
f892ac66 116 EFI_STATUS efi_status2 = install_shim_protocols();
cf90edff 117
f892ac66
MTL
118 if (EFI_ERROR(efi_status2)) {
119 console_print(L"Something has gone seriously wrong: %r\n",
120 efi_status2);
121 console_print(L"shim cannot continue, sorry.\n");
b6f94dbe 122 msleep(5000000);
f892ac66
MTL
123 gRT->ResetSystem(EfiResetShutdown,
124 EFI_SECURITY_VIOLATION,
125 0, NULL);
cf90edff
PJ
126 }
127 }
cbef697a 128 hook_system_services(systab);
cf90edff
PJ
129 loader_is_participating = 0;
130 }
f892ac66 131 return efi_status;
cbef697a
PJ
132}
133
134static EFI_STATUS EFIAPI
135exit_boot_services(EFI_HANDLE image_key, UINTN map_key)
136{
f892ac66
MTL
137 if (loader_is_participating ||
138 verification_method == VERIFIED_BY_HASH) {
cbef697a 139 unhook_system_services();
f892ac66
MTL
140 EFI_STATUS efi_status;
141 efi_status = gBS->ExitBootServices(image_key, map_key);
142 if (EFI_ERROR(efi_status))
cbef697a 143 hook_system_services(systab);
f892ac66 144 return efi_status;
cbef697a
PJ
145 }
146
f892ac66
MTL
147 console_print(L"Bootloader has not verified loaded image.\n");
148 console_print(L"System is compromised. halting.\n");
b6f94dbe 149 msleep(5000000);
f892ac66 150 gRT->ResetSystem(EfiResetShutdown, EFI_SECURITY_VIOLATION, 0, NULL);
cbef697a
PJ
151 return EFI_SECURITY_VIOLATION;
152}
153
154static EFI_STATUS EFIAPI
1042fd7c 155do_exit(EFI_HANDLE ImageHandle, EFI_STATUS ExitStatus,
d3819813 156 UINTN ExitDataSize, CHAR16 *ExitData)
cbef697a 157{
f892ac66 158 EFI_STATUS efi_status;
cbef697a 159
d3819813
MTL
160 shim_fini();
161
f892ac66
MTL
162 efi_status = gBS->Exit(ImageHandle, ExitStatus,
163 ExitDataSize, ExitData);
164 if (EFI_ERROR(efi_status)) {
165 EFI_STATUS efi_status2 = shim_init();
d3819813 166
f892ac66
MTL
167 if (EFI_ERROR(efi_status2)) {
168 console_print(L"Something has gone seriously wrong: %r\n",
169 efi_status2);
170 console_print(L"shim cannot continue, sorry.\n");
b6f94dbe 171 msleep(5000000);
f892ac66
MTL
172 gRT->ResetSystem(EfiResetShutdown,
173 EFI_SECURITY_VIOLATION, 0, NULL);
d3819813
MTL
174 }
175 }
f892ac66 176 return efi_status;
cbef697a
PJ
177}
178
cbef697a
PJ
179void
180hook_system_services(EFI_SYSTEM_TABLE *local_systab)
181{
cbef697a 182 systab = local_systab;
f892ac66 183 gBS = systab->BootServices;
cbef697a
PJ
184
185 /* We need to hook various calls to make this work... */
186
cf90edff
PJ
187 /* We need LoadImage() hooked so that fallback.c can load shim
188 * without having to fake LoadImage as well. This allows it
189 * to call the system LoadImage(), and have us track the output
f892ac66
MTL
190 * and mark loader_is_participating in replacement_start_image. This
191 * means anything added by fallback has to be verified by the system
192 * db, which we want to preserve anyway, since that's all launching
cf90edff
PJ
193 * through BDS gives us. */
194 system_load_image = systab->BootServices->LoadImage;
195 systab->BootServices->LoadImage = load_image;
196
cbef697a
PJ
197 /* we need StartImage() so that we can allow chain booting to an
198 * image trusted by the firmware */
199 system_start_image = systab->BootServices->StartImage;
f892ac66 200 systab->BootServices->StartImage = replacement_start_image;
cbef697a
PJ
201
202 /* we need to hook ExitBootServices() so a) we can enforce the policy
203 * and b) we can unwrap when we're done. */
204 system_exit_boot_services = systab->BootServices->ExitBootServices;
205 systab->BootServices->ExitBootServices = exit_boot_services;
d3819813
MTL
206}
207
208void
209unhook_exit(void)
210{
211 systab->BootServices->Exit = system_exit;
f892ac66 212 gBS = systab->BootServices;
d3819813
MTL
213}
214
215void
216hook_exit(EFI_SYSTEM_TABLE *local_systab)
217{
218 systab = local_systab;
f892ac66 219 gBS = local_systab->BootServices;
cbef697a
PJ
220
221 /* we need to hook Exit() so that we can allow users to quit the
222 * bootloader and still e.g. start a new one or run an internal
223 * shell. */
224 system_exit = systab->BootServices->Exit;
1042fd7c 225 systab->BootServices->Exit = do_exit;
cbef697a 226}