diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi
index a9f4de631..ca40874e5 100644
--- a/docs/grub-dev.texi
+++ b/docs/grub-dev.texi
@@ -84,6 +84,7 @@ This edition documents version @value{VERSION}.
* Video Subsystem::
* PFF2 Font File Format::
* Graphical Menu Software Design::
+* Verifiers framework::
* Copying This Manual:: Copying This Manual
* Index::
@end menu
@@ -1949,6 +1950,63 @@ the graphics mode that was in use before @code{grub_video_setup()} was called
might fix some of the problems.
+@node Verifiers framework
+@chapter Verifiers framework
+
+To register your own verifier call @samp{grub_verifier_register} with a structure
+pointing to your functions.
+
+The interface is inspired by the hash interface with @samp{init}/@samp{write}/@samp{fini}.
+
+There are essentially 2 ways of using it, hashing and whole-file verification.
+
+With the hashing approach:
+During @samp{init} you decide whether you want to check the given file and init context.
+In @samp{write} you update your hashing state.
+In @samp{fini} you check that the hash matches the expected value/passes some check/...
+
+With whole-file verification:
+During @samp{init} you decide whether you want to check the given file and init context.
+In @samp{write} you verify the file and return an error if it fails.
+You don't have @samp{fini}.
+
+Additional @samp{verify_string} receives various strings like kernel parameters
+to verify. Returning no error means successful verification and an error stops
+the current action.
+
+Detailed description of the API:
+
+Every time a file is opened your @samp{init} function is called with file descriptor
+and file type. Your function can have the following outcomes:
+
+@itemize
+
+@item returning no error and setting @samp{*flags} to @samp{GRUB_VERIFY_FLAGS_DEFER_AUTH}.
+In this case verification is deferred to other active verifiers. Verification
+fails if nobody cares or selected verifier fails.
+
+@item returning no error and setting @samp{*flags} to @samp{GRUB_VERIFY_FLAGS_SKIP_VERIFICATION}.
+In this case your verifier will not be called anymore and it is assumed to have
+skipped verification.
+
+@item returning no error and not setting @samp{*flags} to @samp{GRUB_VERIFY_FLAGS_SKIP_VERIFICATION}
+In this case verification is done as described in the following section.
+
+@item returning an error. Then opening of the file will fail due to failed verification.
+
+@end itemize
+
+In the third case your @samp{write} will be called with chunks of the file. If
+you need the whole file in a single chunk then during @samp{init} set the bit
+@samp{GRUB_VERIFY_FLAGS_SINGLE_CHUNK} in @samp{*flags}. During @samp{init} you
+may set @samp{*context} if you need additional context. At every iteration you
+may return an error and the file will be considered as having failed the
+verification. If you return no error then verification continues.
+
+Optionally at the end of the file @samp{fini}, if it exists, is called with just
+the context. If you return no error during any of @samp{init}, @samp{write} and
+@samp{fini} then the file is considered as having succeded verification.
+
@node Copying This Manual
@appendix Copying This Manual
diff --git a/docs/grub.texi b/docs/grub.texi
index 137b894fa..514fdd1ca 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5465,6 +5465,7 @@ environment variables and commands are listed in the same order.
@menu
* Authentication and authorisation:: Users and access control
* Using digital signatures:: Booting digitally signed code
+* UEFI secure boot and shim:: Booting digitally signed PE files
@end menu
@node Authentication and authorisation
@@ -5627,6 +5628,20 @@ or BIOS) configuration to cause the machine to boot from a different
(attacker-controlled) device. GRUB is at best only one link in a
secure boot chain.
+@node UEFI secure boot and shim
+@section UEFI secure boot and shim support
+
+The GRUB, except the @command{chainloader} command, works with the UEFI secure
+boot and the shim. This functionality is provided by the shim_lock module. It
+is recommend to build in this and other required modules into the @file{core.img}.
+All modules not stored in the @file{core.img} and the ACPI tables for the
+@command{acpi} command have to be signed, e.g. using PGP. Additionally, the
+@command{iorw} and the @command{memrw} commands are prohibited if the UEFI
+secure boot is enabled. This is done due to security reasons. All above
+mentioned requirements are enforced by the shim_lock module. And itself it
+is a persistent module which means that it cannot be unloaded if it was
+loaded into the memory.
+
@node Platform limitations
@chapter Platform limitations
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 104513847..d1a00de90 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -99,6 +99,8 @@ KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/tis.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/slaunch.h
endif
if COND_i386_efi
@@ -108,6 +110,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/slaunch.h
endif
if COND_i386_coreboot
@@ -164,6 +167,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/slaunch.h
endif
if COND_ia64_efi
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 2c1d62cee..8ae66b6df 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -198,6 +198,8 @@ kernel = {
x86 = kern/i386/tsc.c;
x86 = kern/i386/tsc_pit.c;
+ x86 = kern/tpm.c;
+ x86 = kern/tis.c;
i386_efi = kern/i386/efi/tsc.c;
x86_64_efi = kern/i386/efi/tsc.c;
i386_efi = kern/i386/tsc_pmtimer.c;
@@ -889,12 +891,23 @@ module = {
};
module = {
- name = verify;
- common = commands/verify.c;
+ name = pgp;
+ common = commands/pgp.c;
cflags = '$(CFLAGS_POSIX)';
cppflags = '-I$(srcdir)/lib/posix_wrap';
};
+module = {
+ name = verifiers;
+ common = commands/verifiers.c;
+};
+
+module = {
+ name = shim_lock;
+ common = commands/efi/shim_lock.c;
+ enable = x86_64_efi;
+};
+
module = {
name = hdparm;
common = commands/hdparm.c;
@@ -1695,6 +1708,14 @@ module = {
enable = noemu;
};
+module = {
+ name = slaunch;
+ x86 = loader/i386/slaunch.c;
+ x86 = loader/i386/slaunch_txt.c;
+ x86 = loader/i386/slaunch_skinit.c;
+ enable = x86;
+};
+
module = {
name = fdt;
arm64 = loader/efi/fdt.c;
diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c
index 9f02f2201..5a1499aa0 100644
--- a/grub-core/commands/acpi.c
+++ b/grub-core/commands/acpi.c
@@ -635,7 +635,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
grub_size_t size;
char *buf;
- file = grub_file_open (args[i]);
+ file = grub_file_open (args[i], GRUB_FILE_TYPE_ACPI_TABLE);
if (! file)
{
free_tables ();
diff --git a/grub-core/commands/blocklist.c b/grub-core/commands/blocklist.c
index d1a47b504..944449b77 100644
--- a/grub-core/commands/blocklist.c
+++ b/grub-core/commands/blocklist.c
@@ -121,8 +121,8 @@ grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
- grub_file_filter_disable_compression ();
- file = grub_file_open (args[0]);
+ file = grub_file_open (args[0], GRUB_FILE_TYPE_PRINT_BLOCKLIST
+ | GRUB_FILE_TYPE_NO_DECOMPRESS);
if (! file)
return grub_errno;
diff --git a/grub-core/commands/cat.c b/grub-core/commands/cat.c
index 88d904436..ba5f0061a 100644
--- a/grub-core/commands/cat.c
+++ b/grub-core/commands/cat.c
@@ -56,7 +56,7 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args)
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
- file = grub_file_open (args[0]);
+ file = grub_file_open (args[0], GRUB_FILE_TYPE_CAT);
if (! file)
return grub_errno;
diff --git a/grub-core/commands/cmp.c b/grub-core/commands/cmp.c
index cc23ee67e..e9c3b25d3 100644
--- a/grub-core/commands/cmp.c
+++ b/grub-core/commands/cmp.c
@@ -45,8 +45,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
grub_printf_ (N_("Compare file `%s' with `%s':\n"), args[0],
args[1]);
- file1 = grub_file_open (args[0]);
- file2 = grub_file_open (args[1]);
+ file1 = grub_file_open (args[0], GRUB_FILE_TYPE_CMP);
+ file2 = grub_file_open (args[1], GRUB_FILE_TYPE_CMP);
if (! file1 || ! file2)
goto cleanup;
diff --git a/grub-core/commands/efi/loadbios.c b/grub-core/commands/efi/loadbios.c
index 132cadbc7..d41d521a4 100644
--- a/grub-core/commands/efi/loadbios.c
+++ b/grub-core/commands/efi/loadbios.c
@@ -169,7 +169,7 @@ grub_cmd_loadbios (grub_command_t cmd __attribute__ ((unused)),
if (argc > 1)
{
- file = grub_file_open (argv[1]);
+ file = grub_file_open (argv[1], GRUB_FILE_TYPE_VBE_DUMP);
if (! file)
return grub_errno;
@@ -183,7 +183,7 @@ grub_cmd_loadbios (grub_command_t cmd __attribute__ ((unused)),
return grub_errno;
}
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_VBE_DUMP);
if (! file)
return grub_errno;
diff --git a/grub-core/commands/efi/shim_lock.c b/grub-core/commands/efi/shim_lock.c
new file mode 100644
index 000000000..01246b0fc
--- /dev/null
+++ b/grub-core/commands/efi/shim_lock.c
@@ -0,0 +1,141 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2017 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ *
+ * EFI shim lock verifier.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define GRUB_EFI_SHIM_LOCK_GUID \
+ { 0x605dab50, 0xe046, 0x4300, \
+ { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } \
+ }
+
+struct grub_efi_shim_lock_protocol
+{
+ grub_efi_status_t
+ (*verify) (void *buffer, grub_uint32_t size);
+};
+typedef struct grub_efi_shim_lock_protocol grub_efi_shim_lock_protocol_t;
+
+static grub_efi_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID;
+static grub_efi_shim_lock_protocol_t *sl;
+
+/* List of modules which cannot be loaded if UEFI secure boot mode is enabled. */
+static const char * const disabled_mods[] = {"iorw", "memrw", NULL};
+
+static grub_err_t
+shim_lock_init (grub_file_t io, enum grub_file_type type,
+ void **context __attribute__ ((unused)),
+ enum grub_verify_flags *flags)
+{
+ const char *b, *e;
+ int i;
+
+ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
+
+ if (!sl)
+ return GRUB_ERR_NONE;
+
+ switch (type & GRUB_FILE_TYPE_MASK)
+ {
+ case GRUB_FILE_TYPE_GRUB_MODULE:
+ /* Establish GRUB module name. */
+ b = grub_strrchr (io->name, '/');
+ e = grub_strrchr (io->name, '.');
+
+ b = b ? (b + 1) : io->name;
+ e = e ? e : io->name + grub_strlen (io->name);
+ e = (e > b) ? e : io->name + grub_strlen (io->name);
+
+ for (i = 0; disabled_mods[i]; i++)
+ if (!grub_strncmp (b, disabled_mods[i], grub_strlen (b) - grub_strlen (e)))
+ {
+ grub_error (GRUB_ERR_ACCESS_DENIED,
+ N_("module cannot be loaded in UEFI secure boot mode: %s"),
+ io->name);
+ return GRUB_ERR_ACCESS_DENIED;
+ }
+
+ /* Fall through. */
+
+ case GRUB_FILE_TYPE_ACPI_TABLE:
+ *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH;
+
+ return GRUB_ERR_NONE;
+
+ case GRUB_FILE_TYPE_LINUX_KERNEL:
+ case GRUB_FILE_TYPE_MULTIBOOT_KERNEL:
+ case GRUB_FILE_TYPE_BSD_KERNEL:
+ case GRUB_FILE_TYPE_XNU_KERNEL:
+ case GRUB_FILE_TYPE_PLAN9_KERNEL:
+ for (i = 0; disabled_mods[i]; i++)
+ if (grub_dl_get (disabled_mods[i]))
+ {
+ grub_error (GRUB_ERR_ACCESS_DENIED,
+ N_("cannot boot due to dangerous module in memory: %s"),
+ disabled_mods[i]);
+ return GRUB_ERR_ACCESS_DENIED;
+ }
+
+ *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
+
+ /* Fall through. */
+
+ default:
+ return GRUB_ERR_NONE;
+ }
+}
+
+static grub_err_t
+shim_lock_write (void *context __attribute__ ((unused)), void *buf, grub_size_t size)
+{
+ if (sl->verify (buf, size) != GRUB_EFI_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim signature"));
+
+ return GRUB_ERR_NONE;
+}
+
+struct grub_file_verifier shim_lock =
+ {
+ .name = "shim_lock",
+ .init = shim_lock_init,
+ .write = shim_lock_write
+ };
+
+GRUB_MOD_INIT(shim_lock)
+{
+ sl = grub_efi_locate_protocol (&shim_lock_guid, 0);
+ grub_verifier_register (&shim_lock);
+
+ if (!sl)
+ return;
+
+ grub_dl_set_persistent (mod);
+}
+
+GRUB_MOD_FINI(shim_lock)
+{
+ grub_verifier_unregister (&shim_lock);
+}
diff --git a/grub-core/commands/file.c b/grub-core/commands/file.c
index 12fba99e0..9cacebf78 100644
--- a/grub-core/commands/file.c
+++ b/grub-core/commands/file.c
@@ -163,7 +163,7 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
if (type == -1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no type specified");
- file = grub_file_open (args[0]);
+ file = grub_file_open (args[0], GRUB_FILE_TYPE_XNU_KERNEL);
if (!file)
return grub_errno;
switch (type)
@@ -546,7 +546,8 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
case IS_XNU64:
case IS_XNU32:
{
- macho = grub_macho_open (args[0], (type == IS_XNU64));
+ macho = grub_macho_open (args[0], GRUB_FILE_TYPE_XNU_KERNEL,
+ (type == IS_XNU64));
if (!macho)
break;
/* FIXME: more checks? */
diff --git a/grub-core/commands/hashsum.c b/grub-core/commands/hashsum.c
index d18687351..456ba908b 100644
--- a/grub-core/commands/hashsum.c
+++ b/grub-core/commands/hashsum.c
@@ -113,7 +113,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
if (hash->mdlen > GRUB_CRYPTO_MAX_MDLEN)
return grub_error (GRUB_ERR_BUG, "mdlen is too long");
- hashlist = grub_file_open (hashfilename);
+ hashlist = grub_file_open (hashfilename, GRUB_FILE_TYPE_HASHLIST);
if (!hashlist)
return grub_errno;
@@ -141,17 +141,15 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
filename = grub_xasprintf ("%s/%s", prefix, p);
if (!filename)
return grub_errno;
- if (!uncompress)
- grub_file_filter_disable_compression ();
- file = grub_file_open (filename);
+ file = grub_file_open (filename, GRUB_FILE_TYPE_TO_HASH
+ | (!uncompress ? GRUB_FILE_TYPE_NO_DECOMPRESS
+ : GRUB_FILE_TYPE_NONE));
grub_free (filename);
}
else
- {
- if (!uncompress)
- grub_file_filter_disable_compression ();
- file = grub_file_open (p);
- }
+ file = grub_file_open (p, GRUB_FILE_TYPE_TO_HASH
+ | (!uncompress ? GRUB_FILE_TYPE_NO_DECOMPRESS
+ : GRUB_FILE_TYPE_NONE));
if (!file)
{
grub_file_close (hashlist);
@@ -242,9 +240,9 @@ grub_cmd_hashsum (struct grub_extcmd_context *ctxt,
grub_file_t file;
grub_err_t err;
unsigned j;
- if (!uncompress)
- grub_file_filter_disable_compression ();
- file = grub_file_open (args[i]);
+ file = grub_file_open (args[i], GRUB_FILE_TYPE_TO_HASH
+ | (!uncompress ? GRUB_FILE_TYPE_NO_DECOMPRESS
+ : GRUB_FILE_TYPE_NONE));
if (!file)
{
if (!keep)
diff --git a/grub-core/commands/hexdump.c b/grub-core/commands/hexdump.c
index 4c884b3a1..eaa12465b 100644
--- a/grub-core/commands/hexdump.c
+++ b/grub-core/commands/hexdump.c
@@ -90,7 +90,7 @@ grub_cmd_hexdump (grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_file_t file;
- file = grub_file_open (args[0]);
+ file = grub_file_open (args[0], GRUB_FILE_TYPE_HEXCAT);
if (! file)
return 0;
diff --git a/grub-core/commands/i386/pc/play.c b/grub-core/commands/i386/pc/play.c
index 7712e2a36..c81813105 100644
--- a/grub-core/commands/i386/pc/play.c
+++ b/grub-core/commands/i386/pc/play.c
@@ -93,7 +93,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
grub_uint32_t tempo;
grub_file_t file;
- file = grub_file_open (args[0]);
+ file = grub_file_open (args[0], GRUB_FILE_TYPE_AUDIO);
if (! file)
return grub_errno;
diff --git a/grub-core/commands/keylayouts.c b/grub-core/commands/keylayouts.c
index f35d3a369..c05d6128a 100644
--- a/grub-core/commands/keylayouts.c
+++ b/grub-core/commands/keylayouts.c
@@ -220,7 +220,7 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)),
else
filename = argv[0];
- file = grub_file_open (filename);
+ file = grub_file_open (filename, GRUB_FILE_TYPE_KEYBOARD_LAYOUT);
if (! file)
goto fail;
diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c
index b32f3c74c..db7a8f002 100644
--- a/grub-core/commands/legacycfg.c
+++ b/grub-core/commands/legacycfg.c
@@ -55,7 +55,7 @@ legacy_file (const char *filename)
if (!suffix)
return grub_errno;
- file = grub_file_open (filename);
+ file = grub_file_open (filename, GRUB_FILE_TYPE_CONFIG);
if (! file)
{
grub_free (suffix);
diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c
index acd93d123..3fd664aac 100644
--- a/grub-core/commands/loadenv.c
+++ b/grub-core/commands/loadenv.c
@@ -44,7 +44,8 @@ static const struct grub_arg_option options[] =
PUBKEY filter (that insists upon properly signed files) as well. PUBKEY
filter is restored before the function returns. */
static grub_file_t
-open_envblk_file (char *filename, int untrusted)
+open_envblk_file (char *filename,
+ enum grub_file_type type)
{
grub_file_t file;
char *buf = 0;
@@ -72,13 +73,7 @@ open_envblk_file (char *filename, int untrusted)
grub_strcpy (filename + len + 1, GRUB_ENVBLK_DEFCFG);
}
- /* The filters that are disabled will be re-enabled by the call to
- grub_file_open() after this particular file is opened. */
- grub_file_filter_disable_compression ();
- if (untrusted)
- grub_file_filter_disable_pubkey ();
-
- file = grub_file_open (filename);
+ file = grub_file_open (filename, type);
grub_free (buf);
return file;
@@ -171,7 +166,10 @@ grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc, char **args)
whitelist.list = args;
/* state[0] is the -f flag; state[1] is the --skip-sig flag */
- file = open_envblk_file ((state[0].set) ? state[0].arg : 0, state[1].set);
+ file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
+ GRUB_FILE_TYPE_LOADENV
+ | (state[1].set
+ ? GRUB_FILE_TYPE_SKIP_SIGNATURE : GRUB_FILE_TYPE_NONE));
if (! file)
return grub_errno;
@@ -206,7 +204,10 @@ grub_cmd_list_env (grub_extcmd_context_t ctxt,
grub_file_t file;
grub_envblk_t envblk;
- file = open_envblk_file ((state[0].set) ? state[0].arg : 0, 0);
+ file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
+ GRUB_FILE_TYPE_LOADENV
+ | (state[1].set
+ ? GRUB_FILE_TYPE_SKIP_SIGNATURE : GRUB_FILE_TYPE_NONE));
if (! file)
return grub_errno;
@@ -390,7 +391,8 @@ grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no variable is specified");
file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
- 1 /* allow untrusted */);
+ GRUB_FILE_TYPE_SAVEENV
+ | GRUB_FILE_TYPE_SKIP_SIGNATURE);
if (! file)
return grub_errno;
diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c
index 0eaf83652..f0d3c1cae 100644
--- a/grub-core/commands/ls.c
+++ b/grub-core/commands/ls.c
@@ -129,8 +129,8 @@ print_files_long (const char *filename, const struct grub_dirhook_info *info,
/* XXX: For ext2fs symlinks are detected as files while they
should be reported as directories. */
- grub_file_filter_disable_compression ();
- file = grub_file_open (pathname);
+ file = grub_file_open (pathname, GRUB_FILE_TYPE_GET_SIZE
+ | GRUB_FILE_TYPE_NO_DECOMPRESS);
if (! file)
{
grub_errno = 0;
@@ -225,8 +225,8 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
struct grub_dirhook_info info;
grub_errno = 0;
- grub_file_filter_disable_compression ();
- file = grub_file_open (dirname);
+ file = grub_file_open (dirname, GRUB_FILE_TYPE_GET_SIZE
+ | GRUB_FILE_TYPE_NO_DECOMPRESS);
if (! file)
goto fail;
diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c
index a3a118241..6bbce3128 100644
--- a/grub-core/commands/minicmd.c
+++ b/grub-core/commands/minicmd.c
@@ -43,7 +43,7 @@ grub_mini_cmd_cat (struct grub_command *cmd __attribute__ ((unused)),
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_CAT);
if (! file)
return grub_errno;
@@ -137,6 +137,9 @@ grub_mini_cmd_rmmod (struct grub_command *cmd __attribute__ ((unused)),
if (! mod)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such module");
+ if (grub_dl_is_persistent (mod))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "cannot unload persistent module");
+
if (grub_dl_unref (mod) <= 0)
grub_dl_unload (mod);
diff --git a/grub-core/commands/nativedisk.c b/grub-core/commands/nativedisk.c
index 2f56a870e..c278f377b 100644
--- a/grub-core/commands/nativedisk.c
+++ b/grub-core/commands/nativedisk.c
@@ -242,7 +242,8 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
if (! filename)
goto fail;
- file = grub_file_open (filename);
+ file = grub_file_open (filename,
+ GRUB_FILE_TYPE_GRUB_MODULE);
grub_free (filename);
if (! file)
goto fail;
diff --git a/grub-core/commands/parttool.c b/grub-core/commands/parttool.c
index 693e2cb42..22b46b187 100644
--- a/grub-core/commands/parttool.c
+++ b/grub-core/commands/parttool.c
@@ -193,7 +193,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
{
grub_file_t file;
- file = grub_file_open (filename);
+ file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE_LIST);
if (file)
{
char *buf = 0;
diff --git a/grub-core/commands/verify.c b/grub-core/commands/pgp.c
similarity index 70%
rename from grub-core/commands/verify.c
rename to grub-core/commands/pgp.c
index 67cb1c785..29e74a640 100644
--- a/grub-core/commands/verify.c
+++ b/grub-core/commands/pgp.c
@@ -30,16 +30,10 @@
#include
#include
#include
+#include
GRUB_MOD_LICENSE ("GPLv3+");
-struct grub_verified
-{
- grub_file_t file;
- void *buf;
-};
-typedef struct grub_verified *grub_verified_t;
-
enum
{
OPTION_SKIP_SIG = 0
@@ -445,23 +439,27 @@ rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
return ret;
}
+struct grub_pubkey_context
+{
+ grub_file_t sig;
+ struct signature_v4_header v4;
+ grub_uint8_t v;
+ const gcry_md_spec_t *hash;
+ void *hash_context;
+};
+
static grub_err_t
-grub_verify_signature_real (char *buf, grub_size_t size,
- grub_file_t f, grub_file_t sig,
- struct grub_public_key *pkey)
+grub_verify_signature_init (struct grub_pubkey_context *ctxt, grub_file_t sig)
{
grub_size_t len;
- grub_uint8_t v;
grub_uint8_t h;
grub_uint8_t t;
grub_uint8_t pk;
- const gcry_md_spec_t *hash;
- struct signature_v4_header v4;
grub_err_t err;
- grub_size_t i;
- gcry_mpi_t mpis[10];
grub_uint8_t type = 0;
+ grub_memset (ctxt, 0, sizeof (*ctxt));
+
err = read_packet_header (sig, &type, &len);
if (err)
return err;
@@ -469,18 +467,18 @@ grub_verify_signature_real (char *buf, grub_size_t size,
if (type != 0x2)
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
- if (grub_file_read (sig, &v, sizeof (v)) != sizeof (v))
+ if (grub_file_read (sig, &ctxt->v, sizeof (ctxt->v)) != sizeof (ctxt->v))
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
- if (v != 4)
+ if (ctxt->v != 4)
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
- if (grub_file_read (sig, &v4, sizeof (v4)) != sizeof (v4))
+ if (grub_file_read (sig, &ctxt->v4, sizeof (ctxt->v4)) != sizeof (ctxt->v4))
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
- h = v4.hash;
- t = v4.type;
- pk = v4.pkeyalgo;
+ h = ctxt->v4.hash;
+ t = ctxt->v4.type;
+ pk = ctxt->v4.pkeyalgo;
if (t != 0)
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
@@ -491,183 +489,233 @@ grub_verify_signature_real (char *buf, grub_size_t size,
if (pk >= ARRAY_SIZE (pkalgos) || pkalgos[pk].name == NULL)
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
- hash = grub_crypto_lookup_md_by_name (hashes[h]);
- if (!hash)
+ ctxt->hash = grub_crypto_lookup_md_by_name (hashes[h]);
+ if (!ctxt->hash)
return grub_error (GRUB_ERR_BAD_SIGNATURE, "hash `%s' not loaded", hashes[h]);
grub_dprintf ("crypt", "alive\n");
- {
- void *context = NULL;
- unsigned char *hval;
- grub_ssize_t rem = grub_be_to_cpu16 (v4.hashed_sub);
- grub_uint32_t headlen = grub_cpu_to_be32 (rem + 6);
- grub_uint8_t s;
- grub_uint16_t unhashed_sub;
- grub_ssize_t r;
- grub_uint8_t hash_start[2];
- gcry_mpi_t hmpi;
- grub_uint64_t keyid = 0;
- struct grub_public_subkey *sk;
- grub_uint8_t *readbuf = NULL;
-
- context = grub_zalloc (hash->contextsize);
- readbuf = grub_zalloc (READBUF_SIZE);
- if (!context || !readbuf)
- goto fail;
+ ctxt->sig = sig;
- hash->init (context);
- if (buf)
- hash->write (context, buf, size);
- else
- while (1)
- {
- r = grub_file_read (f, readbuf, READBUF_SIZE);
- if (r < 0)
- goto fail;
- if (r == 0)
- break;
- hash->write (context, readbuf, r);
- }
+ ctxt->hash_context = grub_zalloc (ctxt->hash->contextsize);
+ if (!ctxt->hash_context)
+ return grub_errno;
- hash->write (context, &v, sizeof (v));
- hash->write (context, &v4, sizeof (v4));
- while (rem)
- {
- r = grub_file_read (sig, readbuf,
- rem < READBUF_SIZE ? rem : READBUF_SIZE);
- if (r < 0)
- goto fail;
- if (r == 0)
- break;
- hash->write (context, readbuf, r);
- rem -= r;
- }
- hash->write (context, &v, sizeof (v));
- s = 0xff;
- hash->write (context, &s, sizeof (s));
- hash->write (context, &headlen, sizeof (headlen));
- r = grub_file_read (sig, &unhashed_sub, sizeof (unhashed_sub));
- if (r != sizeof (unhashed_sub))
- goto fail;
- {
- grub_uint8_t *ptr;
- grub_uint32_t l;
- rem = grub_be_to_cpu16 (unhashed_sub);
- if (rem > READBUF_SIZE)
- goto fail;
- r = grub_file_read (sig, readbuf, rem);
- if (r != rem)
- goto fail;
- for (ptr = readbuf; ptr < readbuf + rem; ptr += l)
- {
- if (*ptr < 192)
- l = *ptr++;
- else if (*ptr < 255)
- {
- if (ptr + 1 >= readbuf + rem)
- break;
- l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192;
- ptr += 2;
- }
- else
- {
- if (ptr + 5 >= readbuf + rem)
- break;
- l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1));
- ptr += 5;
- }
- if (*ptr == 0x10 && l >= 8)
- keyid = grub_get_unaligned64 (ptr + 1);
- }
- }
+ ctxt->hash->init (ctxt->hash_context);
- hash->final (context);
+ return GRUB_ERR_NONE;
+}
- grub_dprintf ("crypt", "alive\n");
+static grub_err_t
+grub_pubkey_write (void *ctxt_, void *buf, grub_size_t size)
+{
+ struct grub_pubkey_context *ctxt = ctxt_;
+ ctxt->hash->write (ctxt->hash_context, buf, size);
+ return GRUB_ERR_NONE;
+}
- hval = hash->read (context);
+static grub_err_t
+grub_verify_signature_real (struct grub_pubkey_context *ctxt,
+ struct grub_public_key *pkey)
+{
+ gcry_mpi_t mpis[10];
+ grub_uint8_t pk = ctxt->v4.pkeyalgo;
+ grub_size_t i;
+ grub_uint8_t *readbuf = NULL;
+ unsigned char *hval;
+ grub_ssize_t rem = grub_be_to_cpu16 (ctxt->v4.hashed_sub);
+ grub_uint32_t headlen = grub_cpu_to_be32 (rem + 6);
+ grub_uint8_t s;
+ grub_uint16_t unhashed_sub;
+ grub_ssize_t r;
+ grub_uint8_t hash_start[2];
+ gcry_mpi_t hmpi;
+ grub_uint64_t keyid = 0;
+ struct grub_public_subkey *sk;
+
+ readbuf = grub_malloc (READBUF_SIZE);
+ if (!readbuf)
+ goto fail;
- if (grub_file_read (sig, hash_start, sizeof (hash_start)) != sizeof (hash_start))
+ ctxt->hash->write (ctxt->hash_context, &ctxt->v, sizeof (ctxt->v));
+ ctxt->hash->write (ctxt->hash_context, &ctxt->v4, sizeof (ctxt->v4));
+ while (rem)
+ {
+ r = grub_file_read (ctxt->sig, readbuf,
+ rem < READBUF_SIZE ? rem : READBUF_SIZE);
+ if (r < 0)
+ goto fail;
+ if (r == 0)
+ break;
+ ctxt->hash->write (ctxt->hash_context, readbuf, r);
+ rem -= r;
+ }
+ ctxt->hash->write (ctxt->hash_context, &ctxt->v, sizeof (ctxt->v));
+ s = 0xff;
+ ctxt->hash->write (ctxt->hash_context, &s, sizeof (s));
+ ctxt->hash->write (ctxt->hash_context, &headlen, sizeof (headlen));
+ r = grub_file_read (ctxt->sig, &unhashed_sub, sizeof (unhashed_sub));
+ if (r != sizeof (unhashed_sub))
+ goto fail;
+ {
+ grub_uint8_t *ptr;
+ grub_uint32_t l;
+ rem = grub_be_to_cpu16 (unhashed_sub);
+ if (rem > READBUF_SIZE)
goto fail;
- if (grub_memcmp (hval, hash_start, sizeof (hash_start)) != 0)
+ r = grub_file_read (ctxt->sig, readbuf, rem);
+ if (r != rem)
goto fail;
+ for (ptr = readbuf; ptr < readbuf + rem; ptr += l)
+ {
+ if (*ptr < 192)
+ l = *ptr++;
+ else if (*ptr < 255)
+ {
+ if (ptr + 1 >= readbuf + rem)
+ break;
+ l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192;
+ ptr += 2;
+ }
+ else
+ {
+ if (ptr + 5 >= readbuf + rem)
+ break;
+ l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1));
+ ptr += 5;
+ }
+ if (*ptr == 0x10 && l >= 8)
+ keyid = grub_get_unaligned64 (ptr + 1);
+ }
+ }
- grub_dprintf ("crypt", "@ %x\n", (int)grub_file_tell (sig));
+ ctxt->hash->final (ctxt->hash_context);
- for (i = 0; i < pkalgos[pk].nmpisig; i++)
- {
- grub_uint16_t l;
- grub_size_t lb;
- grub_dprintf ("crypt", "alive\n");
- if (grub_file_read (sig, &l, sizeof (l)) != sizeof (l))
- goto fail;
- grub_dprintf ("crypt", "alive\n");
- lb = (grub_be_to_cpu16 (l) + 7) / 8;
- grub_dprintf ("crypt", "l = 0x%04x\n", grub_be_to_cpu16 (l));
- if (lb > READBUF_SIZE - sizeof (grub_uint16_t))
- goto fail;
- grub_dprintf ("crypt", "alive\n");
- if (grub_file_read (sig, readbuf + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb)
- goto fail;
- grub_dprintf ("crypt", "alive\n");
- grub_memcpy (readbuf, &l, sizeof (l));
- grub_dprintf ("crypt", "alive\n");
+ grub_dprintf ("crypt", "alive\n");
- if (gcry_mpi_scan (&mpis[i], GCRYMPI_FMT_PGP,
- readbuf, lb + sizeof (grub_uint16_t), 0))
- goto fail;
- grub_dprintf ("crypt", "alive\n");
- }
+ hval = ctxt->hash->read (ctxt->hash_context);
- if (pkey)
- sk = grub_crypto_pk_locate_subkey (keyid, pkey);
- else
- sk = grub_crypto_pk_locate_subkey_in_trustdb (keyid);
- if (!sk)
- {
- /* TRANSLATORS: %08x is 32-bit key id. */
- grub_error (GRUB_ERR_BAD_SIGNATURE, N_("public key %08x not found"),
- keyid);
+ if (grub_file_read (ctxt->sig, hash_start, sizeof (hash_start)) != sizeof (hash_start))
+ goto fail;
+ if (grub_memcmp (hval, hash_start, sizeof (hash_start)) != 0)
+ goto fail;
+
+ grub_dprintf ("crypt", "@ %x\n", (int)grub_file_tell (ctxt->sig));
+
+ for (i = 0; i < pkalgos[pk].nmpisig; i++)
+ {
+ grub_uint16_t l;
+ grub_size_t lb;
+ grub_dprintf ("crypt", "alive\n");
+ if (grub_file_read (ctxt->sig, &l, sizeof (l)) != sizeof (l))
goto fail;
- }
+ grub_dprintf ("crypt", "alive\n");
+ lb = (grub_be_to_cpu16 (l) + 7) / 8;
+ grub_dprintf ("crypt", "l = 0x%04x\n", grub_be_to_cpu16 (l));
+ if (lb > READBUF_SIZE - sizeof (grub_uint16_t))
+ goto fail;
+ grub_dprintf ("crypt", "alive\n");
+ if (grub_file_read (ctxt->sig, readbuf + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb)
+ goto fail;
+ grub_dprintf ("crypt", "alive\n");
+ grub_memcpy (readbuf, &l, sizeof (l));
+ grub_dprintf ("crypt", "alive\n");
+
+ if (gcry_mpi_scan (&mpis[i], GCRYMPI_FMT_PGP,
+ readbuf, lb + sizeof (grub_uint16_t), 0))
+ goto fail;
+ grub_dprintf ("crypt", "alive\n");
+ }
- if (pkalgos[pk].pad (&hmpi, hval, hash, sk))
+ if (pkey)
+ sk = grub_crypto_pk_locate_subkey (keyid, pkey);
+ else
+ sk = grub_crypto_pk_locate_subkey_in_trustdb (keyid);
+ if (!sk)
+ {
+ /* TRANSLATORS: %08x is 32-bit key id. */
+ grub_error (GRUB_ERR_BAD_SIGNATURE, N_("public key %08x not found"),
+ keyid);
goto fail;
- if (!*pkalgos[pk].algo)
- {
- grub_dl_load (pkalgos[pk].module);
- grub_errno = GRUB_ERR_NONE;
- }
+ }
- if (!*pkalgos[pk].algo)
- {
- grub_error (GRUB_ERR_BAD_SIGNATURE, N_("module `%s' isn't loaded"),
- pkalgos[pk].module);
- goto fail;
- }
- if ((*pkalgos[pk].algo)->verify (0, hmpi, mpis, sk->mpis, 0, 0))
+ if (pkalgos[pk].pad (&hmpi, hval, ctxt->hash, sk))
+ goto fail;
+ if (!*pkalgos[pk].algo)
+ {
+ grub_dl_load (pkalgos[pk].module);
+ grub_errno = GRUB_ERR_NONE;
+ }
+
+ if (!*pkalgos[pk].algo)
+ {
+ grub_error (GRUB_ERR_BAD_SIGNATURE, N_("module `%s' isn't loaded"),
+ pkalgos[pk].module);
goto fail;
+ }
+ if ((*pkalgos[pk].algo)->verify (0, hmpi, mpis, sk->mpis, 0, 0))
+ goto fail;
- grub_free (context);
- grub_free (readbuf);
+ grub_free (readbuf);
- return GRUB_ERR_NONE;
+ return GRUB_ERR_NONE;
- fail:
- grub_free (context);
- grub_free (readbuf);
- if (!grub_errno)
- return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
- return grub_errno;
- }
+ fail:
+ grub_free (readbuf);
+ if (!grub_errno)
+ return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
+ return grub_errno;
+}
+
+static void
+grub_pubkey_close_real (struct grub_pubkey_context *ctxt)
+{
+ if (ctxt->sig)
+ grub_file_close (ctxt->sig);
+ if (ctxt->hash_context)
+ grub_free (ctxt->hash_context);
+}
+
+static void
+grub_pubkey_close (void *ctxt)
+{
+ grub_pubkey_close_real (ctxt);
+ grub_free (ctxt);
}
grub_err_t
grub_verify_signature (grub_file_t f, grub_file_t sig,
struct grub_public_key *pkey)
{
- return grub_verify_signature_real (0, 0, f, sig, pkey);
+ grub_err_t err;
+ struct grub_pubkey_context ctxt;
+ grub_uint8_t *readbuf = NULL;
+
+ err = grub_verify_signature_init (&ctxt, sig);
+ if (err)
+ return err;
+
+ readbuf = grub_zalloc (READBUF_SIZE);
+ if (!readbuf)
+ goto fail;
+
+ while (1)
+ {
+ grub_ssize_t r;
+ r = grub_file_read (f, readbuf, READBUF_SIZE);
+ if (r < 0)
+ goto fail;
+ if (r == 0)
+ break;
+ err = grub_pubkey_write (&ctxt, readbuf, r);
+ if (err)
+ return err;
+ }
+
+ grub_verify_signature_real (&ctxt, pkey);
+ fail:
+ grub_pubkey_close_real (&ctxt);
+ return grub_errno;
}
static grub_err_t
@@ -680,10 +728,12 @@ grub_cmd_trust (grub_extcmd_context_t ctxt,
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
- grub_file_filter_disable_compression ();
- if (ctxt->state[OPTION_SKIP_SIG].set)
- grub_file_filter_disable_pubkey ();
- pkf = grub_file_open (args[0]);
+ pkf = grub_file_open (args[0],
+ GRUB_FILE_TYPE_PUBLIC_KEY_TRUST
+ | GRUB_FILE_TYPE_NO_DECOMPRESS
+ | (ctxt->state[OPTION_SKIP_SIG].set
+ ? GRUB_FILE_TYPE_SKIP_SIGNATURE
+ : GRUB_FILE_TYPE_NONE));
if (!pkf)
return grub_errno;
pk = grub_load_public_key (pkf);
@@ -771,10 +821,12 @@ grub_cmd_verify_signature (grub_extcmd_context_t ctxt,
if (argc > 2)
{
grub_file_t pkf;
- grub_file_filter_disable_compression ();
- if (ctxt->state[OPTION_SKIP_SIG].set)
- grub_file_filter_disable_pubkey ();
- pkf = grub_file_open (args[2]);
+ pkf = grub_file_open (args[2],
+ GRUB_FILE_TYPE_PUBLIC_KEY
+ | GRUB_FILE_TYPE_NO_DECOMPRESS
+ | (ctxt->state[OPTION_SKIP_SIG].set
+ ? GRUB_FILE_TYPE_SKIP_SIGNATURE
+ : GRUB_FILE_TYPE_NONE));
if (!pkf)
return grub_errno;
pk = grub_load_public_key (pkf);
@@ -786,16 +838,16 @@ grub_cmd_verify_signature (grub_extcmd_context_t ctxt,
grub_file_close (pkf);
}
- grub_file_filter_disable_all ();
- f = grub_file_open (args[0]);
+ f = grub_file_open (args[0], GRUB_FILE_TYPE_VERIFY_SIGNATURE);
if (!f)
{
err = grub_errno;
goto fail;
}
- grub_file_filter_disable_all ();
- sig = grub_file_open (args[1]);
+ sig = grub_file_open (args[1],
+ GRUB_FILE_TYPE_SIGNATURE
+ | GRUB_FILE_TYPE_NO_DECOMPRESS);
if (!sig)
{
err = grub_errno;
@@ -815,135 +867,52 @@ grub_cmd_verify_signature (grub_extcmd_context_t ctxt,
static int sec = 0;
-static void
-verified_free (grub_verified_t verified)
-{
- if (verified)
- {
- grub_free (verified->buf);
- grub_free (verified);
- }
-}
-
-static grub_ssize_t
-verified_read (struct grub_file *file, char *buf, grub_size_t len)
-{
- grub_verified_t verified = file->data;
-
- grub_memcpy (buf, (char *) verified->buf + file->offset, len);
- return len;
-}
-
static grub_err_t
-verified_close (struct grub_file *file)
-{
- grub_verified_t verified = file->data;
-
- grub_file_close (verified->file);
- verified_free (verified);
- file->data = 0;
-
- /* device and name are freed by parent */
- file->device = 0;
- file->name = 0;
-
- return grub_errno;
-}
-
-struct grub_fs verified_fs =
-{
- .name = "verified_read",
- .read = verified_read,
- .close = verified_close
-};
-
-static grub_file_t
-grub_pubkey_open (grub_file_t io, const char *filename)
+grub_pubkey_init (grub_file_t io, enum grub_file_type type __attribute__ ((unused)),
+ void **context, enum grub_verify_flags *flags)
{
grub_file_t sig;
char *fsuf, *ptr;
grub_err_t err;
- grub_file_filter_t curfilt[GRUB_FILE_FILTER_MAX];
- grub_file_t ret;
- grub_verified_t verified;
+ struct grub_pubkey_context *ctxt;
if (!sec)
- return io;
- if (io->device->disk &&
- (io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID
- || io->device->disk->dev->id == GRUB_DISK_DEVICE_PROCFS_ID))
- return io;
- fsuf = grub_malloc (grub_strlen (filename) + sizeof (".sig"));
+ {
+ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
+ return GRUB_ERR_NONE;
+ }
+
+ fsuf = grub_malloc (grub_strlen (io->name) + sizeof (".sig"));
if (!fsuf)
- return NULL;
- ptr = grub_stpcpy (fsuf, filename);
+ return grub_errno;
+ ptr = grub_stpcpy (fsuf, io->name);
grub_memcpy (ptr, ".sig", sizeof (".sig"));
- grub_memcpy (curfilt, grub_file_filters_enabled,
- sizeof (curfilt));
- grub_file_filter_disable_all ();
- sig = grub_file_open (fsuf);
- grub_memcpy (grub_file_filters_enabled, curfilt,
- sizeof (curfilt));
+ sig = grub_file_open (fsuf, GRUB_FILE_TYPE_SIGNATURE);
grub_free (fsuf);
if (!sig)
- return NULL;
-
- ret = grub_malloc (sizeof (*ret));
- if (!ret)
- {
- grub_file_close (sig);
- return NULL;
- }
- *ret = *io;
+ return grub_errno;
- ret->fs = &verified_fs;
- ret->not_easily_seekable = 0;
- if (ret->size >> (sizeof (grub_size_t) * GRUB_CHAR_BIT - 1))
- {
- grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
- "big file signature isn't implemented yet");
- grub_file_close (sig);
- grub_free (ret);
- return NULL;
- }
- verified = grub_malloc (sizeof (*verified));
- if (!verified)
+ ctxt = grub_malloc (sizeof (*ctxt));
+ if (!ctxt)
{
grub_file_close (sig);
- grub_free (ret);
- return NULL;
- }
- verified->buf = grub_malloc (ret->size);
- if (!verified->buf)
- {
- grub_file_close (sig);
- grub_free (verified);
- grub_free (ret);
- return NULL;
- }
- if (grub_file_read (io, verified->buf, ret->size) != (grub_ssize_t) ret->size)
- {
- if (!grub_errno)
- grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
- filename);
- grub_file_close (sig);
- verified_free (verified);
- grub_free (ret);
- return NULL;
+ return grub_errno;
}
-
- err = grub_verify_signature_real (verified->buf, ret->size, 0, sig, NULL);
- grub_file_close (sig);
+ err = grub_verify_signature_init (ctxt, sig);
if (err)
{
- verified_free (verified);
- grub_free (ret);
- return NULL;
+ grub_pubkey_close (ctxt);
+ return err;
}
- verified->file = io;
- ret->data = verified;
- return ret;
+ *context = ctxt;
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_pubkey_fini (void *ctxt)
+{
+ return grub_verify_signature_real (ctxt, NULL);
}
static char *
@@ -967,8 +936,16 @@ struct grub_fs pseudo_fs =
{
.name = "pseudo",
.read = pseudo_read
-};
+ };
+struct grub_file_verifier grub_pubkey_verifier =
+ {
+ .name = "pgp",
+ .init = grub_pubkey_init,
+ .fini = grub_pubkey_fini,
+ .write = grub_pubkey_write,
+ .close = grub_pubkey_close,
+ };
static grub_extcmd_t cmd, cmd_trust;
static grub_command_t cmd_distrust, cmd_list;
@@ -983,8 +960,6 @@ GRUB_MOD_INIT(verify)
sec = 1;
else
sec = 0;
-
- grub_file_filter_register (GRUB_FILE_FILTER_PUBKEY, grub_pubkey_open);
grub_register_variable_hook ("check_signatures", 0, grub_env_write_sec);
grub_env_export ("check_signatures");
@@ -1030,11 +1005,13 @@ GRUB_MOD_INIT(verify)
cmd_distrust = grub_register_command ("distrust", grub_cmd_distrust,
N_("PUBKEY_ID"),
N_("Remove PUBKEY_ID from trusted keys."));
+
+ grub_verifier_register (&grub_pubkey_verifier);
}
GRUB_MOD_FINI(verify)
{
- grub_file_filter_unregister (GRUB_FILE_FILTER_PUBKEY);
+ grub_verifier_unregister (&grub_pubkey_verifier);
grub_unregister_extcmd (cmd);
grub_unregister_extcmd (cmd_trust);
grub_unregister_command (cmd_list);
diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c
index 7dd32e445..ddda6e7c5 100644
--- a/grub-core/commands/search.c
+++ b/grub-core/commands/search.c
@@ -81,8 +81,8 @@ iterate_device (const char *name, void *data)
if (! buf)
return 1;
- grub_file_filter_disable_compression ();
- file = grub_file_open (buf);
+ file = grub_file_open (buf, GRUB_FILE_TYPE_FS_SEARCH
+ | GRUB_FILE_TYPE_NO_DECOMPRESS);
if (file)
{
found = 1;
diff --git a/grub-core/commands/test.c b/grub-core/commands/test.c
index 5f06642f6..13c6ed953 100644
--- a/grub-core/commands/test.c
+++ b/grub-core/commands/test.c
@@ -355,8 +355,8 @@ test_parse (char **args, int *argn, int argc)
if (grub_strcmp (args[*argn], "-s") == 0)
{
grub_file_t file;
- grub_file_filter_disable_compression ();
- file = grub_file_open (args[*argn + 1]);
+ file = grub_file_open (args[*argn + 1], GRUB_FILE_TYPE_GET_SIZE
+ | GRUB_FILE_TYPE_NO_DECOMPRESS);
update_val (file && (grub_file_size (file) != 0), &ctx);
if (file)
grub_file_close (file);
diff --git a/grub-core/commands/testload.c b/grub-core/commands/testload.c
index cfab6763d..ff01a0516 100644
--- a/grub-core/commands/testload.c
+++ b/grub-core/commands/testload.c
@@ -57,7 +57,7 @@ grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)),
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_TESTLOAD);
if (! file)
return grub_errno;
diff --git a/grub-core/commands/testspeed.c b/grub-core/commands/testspeed.c
index 042645f8d..c13a9b8d8 100644
--- a/grub-core/commands/testspeed.c
+++ b/grub-core/commands/testspeed.c
@@ -61,7 +61,7 @@ grub_cmd_testspeed (grub_extcmd_context_t ctxt, int argc, char **args)
if (buffer == NULL)
return grub_errno;
- file = grub_file_open (args[0]);
+ file = grub_file_open (args[0], GRUB_FILE_TYPE_TESTLOAD);
if (file == NULL)
goto quit;
diff --git a/grub-core/commands/verifiers.c b/grub-core/commands/verifiers.c
new file mode 100644
index 000000000..c638d5f43
--- /dev/null
+++ b/grub-core/commands/verifiers.c
@@ -0,0 +1,228 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2017 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ *
+ * Verifiers helper.
+ */
+
+#include
+#include
+#include
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+struct grub_file_verifier *grub_file_verifiers;
+
+struct grub_verified
+{
+ grub_file_t file;
+ void *buf;
+};
+typedef struct grub_verified *grub_verified_t;
+
+static void
+verified_free (grub_verified_t verified)
+{
+ if (verified)
+ {
+ grub_free (verified->buf);
+ grub_free (verified);
+ }
+}
+
+static grub_ssize_t
+verified_read (struct grub_file *file, char *buf, grub_size_t len)
+{
+ grub_verified_t verified = file->data;
+
+ grub_memcpy (buf, (char *) verified->buf + file->offset, len);
+ return len;
+}
+
+static grub_err_t
+verified_close (struct grub_file *file)
+{
+ grub_verified_t verified = file->data;
+
+ grub_file_close (verified->file);
+ verified_free (verified);
+ file->data = 0;
+
+ /* Device and name are freed by parent. */
+ file->device = 0;
+ file->name = 0;
+
+ return grub_errno;
+}
+
+struct grub_fs verified_fs =
+{
+ .name = "verified_read",
+ .read = verified_read,
+ .close = verified_close
+};
+
+static grub_file_t
+grub_verifiers_open (grub_file_t io, enum grub_file_type type)
+{
+ grub_verified_t verified = NULL;
+ struct grub_file_verifier *ver;
+ void *context;
+ grub_file_t ret = 0;
+ grub_err_t err;
+ int defer = 0;
+
+ grub_dprintf ("verify", "file: %s type: %d\n", io->name, type);
+
+ if ((type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_SIGNATURE
+ || (type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_VERIFY_SIGNATURE
+ || (type & GRUB_FILE_TYPE_SKIP_SIGNATURE))
+ return io;
+
+ if (io->device->disk &&
+ (io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID
+ || io->device->disk->dev->id == GRUB_DISK_DEVICE_PROCFS_ID))
+ return io;
+
+ FOR_LIST_ELEMENTS(ver, grub_file_verifiers)
+ {
+ enum grub_verify_flags flags = 0;
+ err = ver->init (io, type, &context, &flags);
+ if (err)
+ goto fail_noclose;
+ if (flags & GRUB_VERIFY_FLAGS_DEFER_AUTH)
+ {
+ defer = 1;
+ continue;
+ }
+ if (!(flags & GRUB_VERIFY_FLAGS_SKIP_VERIFICATION))
+ break;
+ }
+
+ if (!ver)
+ {
+ if (defer)
+ {
+ grub_error (GRUB_ERR_ACCESS_DENIED,
+ N_("verification requested but nobody cares: %s"), io->name);
+ goto fail_noclose;
+ }
+
+ /* No verifiers wanted to verify. Just return underlying file. */
+ return io;
+ }
+
+ ret = grub_malloc (sizeof (*ret));
+ if (!ret)
+ {
+ goto fail;
+ }
+ *ret = *io;
+
+ ret->fs = &verified_fs;
+ ret->not_easily_seekable = 0;
+ if (ret->size >> (sizeof (grub_size_t) * GRUB_CHAR_BIT - 1))
+ {
+ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ N_("big file signature isn't implemented yet"));
+ goto fail;
+ }
+ verified = grub_malloc (sizeof (*verified));
+ if (!verified)
+ {
+ goto fail;
+ }
+ verified->buf = grub_malloc (ret->size);
+ if (!verified->buf)
+ {
+ goto fail;
+ }
+ if (grub_file_read (io, verified->buf, ret->size) != (grub_ssize_t) ret->size)
+ {
+ if (!grub_errno)
+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
+ io->name);
+ goto fail;
+ }
+
+ err = ver->write (context, verified->buf, ret->size);
+ if (err)
+ goto fail;
+
+ err = ver->fini ? ver->fini (context) : GRUB_ERR_NONE;
+ if (err)
+ goto fail;
+
+ if (ver->close)
+ ver->close (context);
+
+ FOR_LIST_ELEMENTS_NEXT(ver, grub_file_verifiers)
+ {
+ enum grub_verify_flags flags = 0;
+ err = ver->init (io, type, &context, &flags);
+ if (err)
+ goto fail_noclose;
+ if (flags & GRUB_VERIFY_FLAGS_SKIP_VERIFICATION ||
+ /* Verification done earlier. So, we are happy here. */
+ flags & GRUB_VERIFY_FLAGS_DEFER_AUTH)
+ continue;
+ err = ver->write (context, verified->buf, ret->size);
+ if (err)
+ goto fail;
+
+ err = ver->fini ? ver->fini (context) : GRUB_ERR_NONE;
+ if (err)
+ goto fail;
+
+ if (ver->close)
+ ver->close (context);
+ }
+
+ verified->file = io;
+ ret->data = verified;
+ return ret;
+
+ fail:
+ ver->close (context);
+ fail_noclose:
+ verified_free (verified);
+ grub_free (ret);
+ return NULL;
+}
+
+grub_err_t
+grub_verify_string (char *str, enum grub_verify_string_type type)
+{
+ struct grub_file_verifier *ver;
+ FOR_LIST_ELEMENTS(ver, grub_file_verifiers)
+ {
+ grub_err_t err;
+ err = ver->verify_string ? ver->verify_string (str, type) : GRUB_ERR_NONE;
+ if (err)
+ return err;
+ }
+ return GRUB_ERR_NONE;
+}
+
+GRUB_MOD_INIT(verifiers)
+{
+ grub_file_filter_register (GRUB_FILE_FILTER_VERIFY, grub_verifiers_open);
+}
+
+GRUB_MOD_FINI(verifiers)
+{
+ grub_file_filter_unregister (GRUB_FILE_FILTER_VERIFY);
+}
diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c
index 2d8deaeaf..9406d931c 100644
--- a/grub-core/disk/loopback.c
+++ b/grub-core/disk/loopback.c
@@ -92,7 +92,8 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args)
if (argc < 2)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
- file = grub_file_open (args[1]);
+ file = grub_file_open (args[1], GRUB_FILE_TYPE_LOOPBACK
+ | GRUB_FILE_TYPE_NO_DECOMPRESS);
if (! file)
return grub_errno;
diff --git a/grub-core/efiemu/main.c b/grub-core/efiemu/main.c
index f6813b1ed..a81934725 100644
--- a/grub-core/efiemu/main.c
+++ b/grub-core/efiemu/main.c
@@ -187,7 +187,7 @@ grub_efiemu_load_file (const char *filename)
grub_file_t file;
grub_err_t err;
- file = grub_file_open (filename);
+ file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE);
if (! file)
return grub_errno;
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index 53d76a64d..85a292557 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -418,7 +418,7 @@ grub_font_load (const char *filename)
#endif
if (filename[0] == '(' || filename[0] == '/' || filename[0] == '+')
- file = grub_buffile_open (filename, 1024);
+ file = grub_buffile_open (filename, GRUB_FILE_TYPE_FONT, 1024);
else
{
const char *prefix = grub_env_get ("prefix");
@@ -438,7 +438,7 @@ grub_font_load (const char *filename)
ptr = grub_stpcpy (ptr, filename);
ptr = grub_stpcpy (ptr, ".pf2");
*ptr = 0;
- file = grub_buffile_open (fullname, 1024);
+ file = grub_buffile_open (fullname, GRUB_FILE_TYPE_FONT, 1024);
grub_free (fullname);
}
if (!file)
diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c
index 87eef621d..1402e0bc2 100644
--- a/grub-core/fs/zfs/zfscrypt.c
+++ b/grub-core/fs/zfs/zfscrypt.c
@@ -425,7 +425,7 @@ grub_cmd_zfs_key (grub_extcmd_context_t ctxt, int argc, char **args)
if (argc > 0)
{
grub_file_t file;
- file = grub_file_open (args[0]);
+ file = grub_file_open (args[0], GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY);
if (!file)
return grub_errno;
real_size = grub_file_read (file, buf, 1024);
diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c
index 4880cefe3..4d02e62c1 100644
--- a/grub-core/gettext/gettext.c
+++ b/grub-core/gettext/gettext.c
@@ -291,7 +291,7 @@ grub_mofile_open (struct grub_gettext_context *ctx,
/* Using fd_mo and not another variable because
it's needed for grub_gettext_get_info. */
- fd = grub_file_open (filename);
+ fd = grub_file_open (filename, GRUB_FILE_TYPE_GETTEXT_CATALOG);
if (!fd)
return grub_errno;
diff --git a/grub-core/gfxmenu/theme_loader.c b/grub-core/gfxmenu/theme_loader.c
index 02978392c..d6829bb5e 100644
--- a/grub-core/gfxmenu/theme_loader.c
+++ b/grub-core/gfxmenu/theme_loader.c
@@ -743,7 +743,7 @@ grub_gfxmenu_view_load_theme (grub_gfxmenu_view_t view, const char *theme_path)
p.view = view;
p.theme_dir = grub_get_dirname (theme_path);
- file = grub_file_open (theme_path);
+ file = grub_file_open (theme_path, GRUB_FILE_TYPE_THEME);
if (! file)
{
grub_free (p.theme_dir);
diff --git a/grub-core/io/bufio.c b/grub-core/io/bufio.c
index 22438277d..bb5b87662 100644
--- a/grub-core/io/bufio.c
+++ b/grub-core/io/bufio.c
@@ -43,7 +43,7 @@ typedef struct grub_bufio *grub_bufio_t;
static struct grub_fs grub_bufio_fs;
grub_file_t
-grub_bufio_open (grub_file_t io, int size)
+grub_bufio_open (grub_file_t io, grub_size_t size)
{
grub_file_t file;
grub_bufio_t bufio = 0;
@@ -57,7 +57,7 @@ grub_bufio_open (grub_file_t io, int size)
else if (size > GRUB_BUFIO_MAX_SIZE)
size = GRUB_BUFIO_MAX_SIZE;
- if ((size < 0) || ((unsigned) size > io->size))
+ if (size > io->size)
size = ((io->size > GRUB_BUFIO_MAX_SIZE) ? GRUB_BUFIO_MAX_SIZE :
io->size);
@@ -81,11 +81,11 @@ grub_bufio_open (grub_file_t io, int size)
}
grub_file_t
-grub_buffile_open (const char *name, int size)
+grub_buffile_open (const char *name, enum grub_file_type type, grub_size_t size)
{
grub_file_t io, file;
- io = grub_file_open (name);
+ io = grub_file_open (name, type);
if (! io)
return 0;
diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c
index 86ea8cfde..7760d8b97 100644
--- a/grub-core/io/gzio.c
+++ b/grub-core/io/gzio.c
@@ -1156,11 +1156,14 @@ initialize_tables (grub_gzio_t gzio)
even if IO does not contain data compressed by gzip, return a valid file
object. Note that this function won't close IO, even if an error occurs. */
static grub_file_t
-grub_gzio_open (grub_file_t io, const char *name __attribute__ ((unused)))
+grub_gzio_open (grub_file_t io, enum grub_file_type type)
{
grub_file_t file;
grub_gzio_t gzio = 0;
+ if (type & GRUB_FILE_TYPE_NO_DECOMPRESS)
+ return io;
+
file = (grub_file_t) grub_zalloc (sizeof (*file));
if (! file)
return 0;
diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c
index 7559c6c9c..84edf6dd2 100644
--- a/grub-core/io/lzopio.c
+++ b/grub-core/io/lzopio.c
@@ -407,12 +407,14 @@ test_header (grub_file_t file)
}
static grub_file_t
-grub_lzopio_open (grub_file_t io,
- const char *name __attribute__ ((unused)))
+grub_lzopio_open (grub_file_t io, enum grub_file_type type)
{
grub_file_t file;
grub_lzopio_t lzopio;
+ if (type & GRUB_FILE_TYPE_NO_DECOMPRESS)
+ return io;
+
file = (grub_file_t) grub_zalloc (sizeof (*file));
if (!file)
return 0;
diff --git a/grub-core/io/offset.c b/grub-core/io/offset.c
index ebed0ebe6..ec8e23208 100644
--- a/grub-core/io/offset.c
+++ b/grub-core/io/offset.c
@@ -69,7 +69,8 @@ grub_file_offset_close (grub_file_t file)
}
grub_file_t
-grub_file_offset_open (grub_file_t parent, grub_off_t start, grub_off_t size)
+grub_file_offset_open (grub_file_t parent, enum grub_file_type type,
+ grub_off_t start, grub_off_t size)
{
struct grub_offset_file *off_data;
grub_file_t off_file, last_off_file;
@@ -95,10 +96,10 @@ grub_file_offset_open (grub_file_t parent, grub_off_t start, grub_off_t size)
last_off_file = NULL;
for (filter = GRUB_FILE_FILTER_COMPRESSION_FIRST;
off_file && filter <= GRUB_FILE_FILTER_COMPRESSION_LAST; filter++)
- if (grub_file_filters_enabled[filter])
+ if (grub_file_filters[filter])
{
last_off_file = off_file;
- off_file = grub_file_filters_enabled[filter] (off_file, parent->name);
+ off_file = grub_file_filters[filter] (off_file, type);
}
if (!off_file)
diff --git a/grub-core/io/xzio.c b/grub-core/io/xzio.c
index a3536ad73..42afeedcd 100644
--- a/grub-core/io/xzio.c
+++ b/grub-core/io/xzio.c
@@ -169,12 +169,14 @@ test_footer (grub_file_t file)
}
static grub_file_t
-grub_xzio_open (grub_file_t io,
- const char *name __attribute__ ((unused)))
+grub_xzio_open (grub_file_t io, enum grub_file_type type)
{
grub_file_t file;
grub_xzio_t xzio;
+ if (type & GRUB_FILE_TYPE_NO_DECOMPRESS)
+ return io;
+
file = (grub_file_t) grub_zalloc (sizeof (*file));
if (!file)
return 0;
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index e394cd96f..f8d58f029 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -688,7 +688,7 @@ grub_dl_load_file (const char *filename)
grub_boot_time ("Loading module %s", filename);
- file = grub_file_open (filename);
+ file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE);
if (! file)
return 0;
diff --git a/grub-core/kern/elf.c b/grub-core/kern/elf.c
index 4f282c9cf..9d7149b38 100644
--- a/grub-core/kern/elf.c
+++ b/grub-core/kern/elf.c
@@ -136,12 +136,12 @@ grub_elf_file (grub_file_t file, const char *filename)
}
grub_elf_t
-grub_elf_open (const char *name)
+grub_elf_open (const char *name, enum grub_file_type type)
{
grub_file_t file;
grub_elf_t elf;
- file = grub_file_open (name);
+ file = grub_file_open (name, type);
if (! file)
return 0;
diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
index 668f8930b..643154237 100644
--- a/grub-core/kern/file.c
+++ b/grub-core/kern/file.c
@@ -28,8 +28,7 @@
void (*EXPORT_VAR (grub_grubnet_fini)) (void);
-grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX];
-grub_file_filter_t grub_file_filters_enabled[GRUB_FILE_FILTER_MAX];
+grub_file_filter_t grub_file_filters[GRUB_FILE_FILTER_MAX];
/* Get the device part of the filename NAME. It is enclosed by parentheses. */
char *
@@ -59,7 +58,7 @@ grub_file_get_device_name (const char *name)
}
grub_file_t
-grub_file_open (const char *name)
+grub_file_open (const char *name, enum grub_file_type type)
{
grub_device_t device = 0;
grub_file_t file = 0, last_file = 0;
@@ -114,18 +113,20 @@ grub_file_open (const char *name)
file->name = grub_strdup (name);
grub_errno = GRUB_ERR_NONE;
- for (filter = 0; file && filter < ARRAY_SIZE (grub_file_filters_enabled);
+ for (filter = 0; file && filter < ARRAY_SIZE (grub_file_filters);
filter++)
- if (grub_file_filters_enabled[filter])
+ if (grub_file_filters[filter])
{
last_file = file;
- file = grub_file_filters_enabled[filter] (file, name);
+ file = grub_file_filters[filter] (file, type);
+ if (file && file != last_file)
+ {
+ file->name = grub_strdup (name);
+ grub_errno = GRUB_ERR_NONE;
+ }
}
if (!file)
grub_file_close (last_file);
-
- grub_memcpy (grub_file_filters_enabled, grub_file_filters_all,
- sizeof (grub_file_filters_enabled));
return file;
@@ -137,9 +138,6 @@ grub_file_open (const char *name)
grub_free (file);
- grub_memcpy (grub_file_filters_enabled, grub_file_filters_all,
- sizeof (grub_file_filters_enabled));
-
return 0;
}
diff --git a/grub-core/kern/tis.c b/grub-core/kern/tis.c
new file mode 100644
index 000000000..0dfa0e658
--- /dev/null
+++ b/grub-core/kern/tis.c
@@ -0,0 +1,279 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (c) 2018 Daniel P. Smith, Apertus Solutions, LLC
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ *
+ * The code in this file is based on the article "Writing a TPM Device Driver"
+ * published on http://ptgmedia.pearsoncmg.com.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __x86_64__
+#define MMIO_BASE 0xFED40000ULL
+#else
+#define MMIO_BASE 0xFED40000
+#endif
+
+#define MAX_LOCALITY 4
+
+/* macros to access registers at locality ’’l’’ */
+#define ACCESS(l) (0x0000 | ((l) << 12))
+#define STS(l) (0x0018 | ((l) << 12))
+#define DATA_FIFO(l) (0x0024 | ((l) << 12))
+#define DID_VID(l) (0x0F00 | ((l) << 12))
+/* access bits */
+#define ACCESS_ACTIVE_LOCALITY 0x20 /* (R)*/
+#define ACCESS_RELINQUISH_LOCALITY 0x20 /* (W) */
+#define ACCESS_REQUEST_USE 0x02 /* (W) */
+/* status bits */
+#define STS_VALID 0x80 /* (R) */
+#define STS_COMMAND_READY 0x40 /* (R) */
+#define STS_DATA_AVAIL 0x10 /* (R) */
+#define STS_DATA_EXPECT 0x08 /* (R) */
+#define STS_GO 0x20 /* (W) */
+
+#define NO_LOCALITY 0xFF
+
+static grub_uint8_t locality = NO_LOCALITY;
+
+static grub_uint8_t
+grub_read8 (grub_uint32_t field)
+{
+ void *mmio_addr = (void*)(MMIO_BASE | field);
+
+ return grub_readb(mmio_addr);
+}
+
+static void
+grub_write8 (unsigned char val, grub_uint32_t field)
+{
+ void *mmio_addr = (void*)(MMIO_BASE | field);
+
+ grub_writeb(val, mmio_addr);
+}
+
+static grub_uint32_t
+grub_read32 (grub_uint32_t field)
+{
+ void *mmio_addr = (void*)(MMIO_BASE | field);
+
+ return grub_readl(mmio_addr);
+}
+
+__attribute__((unused)) /* TODO not used yet */
+static void
+grub_write32 (unsigned int val, grub_uint32_t field)
+{
+ void *mmio_addr = (void*)(MMIO_BASE | field);
+
+ grub_writel(val, mmio_addr);
+}
+
+static inline void
+grub_io_delay (void)
+{
+ __asm__ __volatile__ ("outb %al, $0x80");
+}
+
+static grub_uint32_t
+grub_burst_wait (void)
+{
+ grub_uint32_t count = 0;
+
+ while (count == 0)
+ {
+ count = grub_read8 (STS(locality) + 1);
+ count += grub_read8 (STS(locality) + 2) << 8;
+
+ if (count == 0)
+ grub_io_delay (); /* wait for FIFO to drain */
+ }
+
+ return count;
+}
+
+grub_uint8_t
+grub_tis_request_locality (grub_uint8_t l)
+{
+ grub_write8 (ACCESS_RELINQUISH_LOCALITY, ACCESS(locality));
+ grub_write8 (ACCESS_REQUEST_USE, ACCESS(l));
+
+ /* wait for locality to be granted */
+ if (grub_read8 (ACCESS(l) & ACCESS_ACTIVE_LOCALITY))
+ {
+ if (l <= MAX_LOCALITY)
+ locality = l;
+ else
+ locality = NO_LOCALITY;
+ }
+
+ return locality;
+}
+
+grub_uint8_t
+grub_tis_init (void)
+{
+ grub_uint32_t vendor;
+ grub_uint8_t i;
+
+ for (i=0; i<=MAX_LOCALITY; i++)
+ grub_write8 (ACCESS_RELINQUISH_LOCALITY, ACCESS(i));
+
+ if (grub_tis_request_locality (0) == NO_LOCALITY)
+ return 0;
+
+ vendor = grub_read32 (DID_VID(0));
+ if ((vendor & 0xFFFF) == 0xFFFF)
+ return 0;
+
+ return 1;
+}
+
+grub_size_t
+grub_tis_send (struct grub_tpm_cmd_buf *buf)
+{
+ grub_uint8_t status, *buf_ptr;
+ grub_uint32_t burstcnt = 0;
+ grub_uint32_t count = 0;
+
+ if (locality > MAX_LOCALITY)
+ return 0;
+
+ grub_write8 (STS_COMMAND_READY, STS(locality));
+
+ buf_ptr = (grub_uint8_t *) buf;
+
+ /* send all but the last byte */
+ while (count < (buf->size - 1))
+ {
+ burstcnt = grub_burst_wait();
+ for (; burstcnt > 0 && count < buf->size - 1; burstcnt--)
+ {
+ grub_write8 (buf_ptr[count], DATA_FIFO(locality));
+ count++;
+ }
+
+ /* check for overflow */
+ for (status = 0; (status & STS_VALID) == 0; )
+ status = grub_read8(STS(locality));
+
+ if ((status & STS_DATA_EXPECT) == 0)
+ return 0;
+ }
+
+ /* write last byte */
+ grub_write8 (buf_ptr[count], DATA_FIFO(locality));
+
+ /* make sure it stuck */
+ for (status = 0; (status & STS_VALID) == 0; )
+ status = grub_read8(STS(locality));
+
+ if ((status & STS_DATA_EXPECT) != 0)
+ return 0;
+
+ /* go and do it */
+ grub_write8 (STS_GO, STS(locality));
+
+ return (grub_size_t)count;
+}
+
+static grub_size_t
+grub_recv_data (unsigned char *buf, grub_size_t len)
+{
+ grub_size_t size = 0;
+ grub_uint8_t status, *bufptr;
+ grub_uint32_t burstcnt = 0;
+
+ bufptr = (grub_uint8_t *)buf;
+
+ status = grub_read8 (STS(locality));
+ while ((status & (STS_DATA_AVAIL | STS_VALID))
+ == (STS_DATA_AVAIL | STS_VALID)
+ && size < len)
+ {
+ burstcnt = grub_burst_wait ();
+ for (; burstcnt > 0 && size < len; burstcnt--)
+ {
+ *bufptr = grub_read8 (DATA_FIFO(locality));
+ bufptr++;
+ size++;
+ }
+
+ status = grub_read8 (STS(locality));
+ }
+
+ return size;
+}
+
+grub_size_t
+grub_tis_recv (struct grub_tpm_resp_buf *buf)
+{
+ grub_uint32_t expected;
+ grub_uint8_t status, *buf_ptr;
+ grub_size_t size = 0;
+
+ buf_ptr = (grub_uint8_t *)buf;
+
+ /* ensure that there is data available */
+ status = grub_read8 (STS(locality));
+ if ((status & (STS_DATA_AVAIL | STS_VALID))
+ != (STS_DATA_AVAIL | STS_VALID))
+ goto err;
+
+ /* read first 6 bytes, including tag and paramsize */
+ if ((size = grub_recv_data (buf_ptr, 6)) < 6)
+ goto err;
+
+ buf_ptr += 6;
+
+ expected = grub_be_to_cpu32 (buf->size);
+ if (expected > sizeof(struct grub_tpm_resp_buf))
+ goto err;
+
+ /* read all data, except last byte */
+ if ((size += grub_recv_data (buf_ptr, expected - 7))
+ < expected - 1)
+ goto err;
+
+ buf_ptr += expected - 7;
+
+ /* check for receive underflow */
+ status = grub_read8 (STS(locality));
+ if ((status & (STS_DATA_AVAIL | STS_VALID))
+ != (STS_DATA_AVAIL | STS_VALID))
+ goto err;
+
+ /* read last byte */
+ if ((size += grub_recv_data (buf_ptr, 1)) != expected)
+ goto err;
+
+ /* make sure we read everything */
+ status = grub_read8 (STS(locality));
+ if ((status & (STS_DATA_AVAIL | STS_VALID))
+ == (STS_DATA_AVAIL | STS_VALID))
+ goto err;
+
+ grub_write8 (STS_COMMAND_READY, STS(locality));
+
+ return size;
+err:
+ return 0;
+}
diff --git a/grub-core/kern/tpm.c b/grub-core/kern/tpm.c
new file mode 100644
index 000000000..03c1b5fbe
--- /dev/null
+++ b/grub-core/kern/tpm.c
@@ -0,0 +1,52 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (c) 2018 Daniel P. Smith, Apertus Solutions, LLC
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ *
+ * The code in this file is based on the article "Writing a TPM Device Driver"
+ * published on http://ptgmedia.pearsoncmg.com.
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+grub_uint8_t
+grub_tpm_pcr_extend (struct grub_tpm_digest *d)
+{
+ grub_size_t bytes;
+ struct grub_tpm_cmd_buf send;
+ struct grub_tpm_resp_buf resp;
+
+ send.tag = TPM_TAG_RQU_COMMAND;
+ send.size = sizeof(struct grub_tpm_extend_cmd) + 6;
+ send.cmd.extend.ordinal = TPM_ORD_EXTEND;
+ send.cmd.extend.pcr_num = d->pcr;
+ grub_memcpy(&(send.cmd.extend.digest), &(d->digest), sizeof(TPM_DIGEST));
+
+ if (send.size != grub_tis_send(&send))
+ return 0;
+
+ bytes = sizeof(struct grub_tpm_extend_resp) + 10;
+ if (bytes != grub_tis_recv(&resp))
+ return 0;
+
+ if (resp.result != TPM_SUCCESS)
+ return 0;
+
+ return 1;
+}
diff --git a/grub-core/lib/cmdline.c b/grub-core/lib/cmdline.c
index d5e10ee87..ed0b149dc 100644
--- a/grub-core/lib/cmdline.c
+++ b/grub-core/lib/cmdline.c
@@ -62,12 +62,13 @@ unsigned int grub_loader_cmdline_size (int argc, char *argv[])
return size;
}
-int grub_create_loader_cmdline (int argc, char *argv[], char *buf,
- grub_size_t size)
+grub_err_t
+grub_create_loader_cmdline (int argc, char *argv[], char *buf,
+ grub_size_t size, enum grub_verify_string_type type)
{
int i, space;
unsigned int arg_size;
- char *c;
+ char *c, *orig_buf = buf;
for (i = 0; i < argc; i++)
{
@@ -104,5 +105,5 @@ int grub_create_loader_cmdline (int argc, char *argv[], char *buf,
*buf = 0;
- return i;
+ return grub_verify_string (orig_buf, type);
}
diff --git a/grub-core/lib/syslinux_parse.c b/grub-core/lib/syslinux_parse.c
index 28ba3aef0..c96d85ee5 100644
--- a/grub-core/lib/syslinux_parse.c
+++ b/grub-core/lib/syslinux_parse.c
@@ -696,7 +696,7 @@ syslinux_parse_real (struct syslinux_menu *menu)
char *buf = NULL;
grub_err_t err = GRUB_ERR_NONE;
- file = grub_file_open (menu->filename);
+ file = grub_file_open (menu->filename, GRUB_FILE_TYPE_CONFIG);
if (!file)
return grub_errno;
while ((grub_free (buf), buf = grub_file_getline (file)))
diff --git a/grub-core/loader/arm/linux.c b/grub-core/loader/arm/linux.c
index e64c79a95..9addcb9a8 100644
--- a/grub-core/loader/arm/linux.c
+++ b/grub-core/loader/arm/linux.c
@@ -28,6 +28,7 @@
#include
#include
#include
+#include
GRUB_MOD_LICENSE ("GPLv3+");
@@ -399,8 +400,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* Create kernel command line. */
grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
- grub_create_loader_cmdline (argc, argv,
- linux_args + sizeof (LINUX_IMAGE) - 1, size);
+ err = grub_create_loader_cmdline (argc, argv,
+ linux_args + sizeof (LINUX_IMAGE) - 1, size,
+ GRUB_VERIFY_KERNEL_CMDLINE);
+ if (err)
+ goto fail;
return GRUB_ERR_NONE;
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
index 746edd104..4b1810082 100644
--- a/grub-core/loader/arm64/linux.c
+++ b/grub-core/loader/arm64/linux.c
@@ -31,6 +31,7 @@
#include
#include
#include
+#include
GRUB_MOD_LICENSE ("GPLv3+");
@@ -301,9 +302,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
- grub_create_loader_cmdline (argc, argv,
- linux_args + sizeof (LINUX_IMAGE) - 1,
- cmdline_size);
+ err = grub_create_loader_cmdline (argc, argv,
+ linux_args + sizeof (LINUX_IMAGE) - 1,
+ cmdline_size,
+ GRUB_VERIFY_KERNEL_CMDLINE);
+ if (err)
+ goto fail;
if (grub_errno == GRUB_ERR_NONE)
{
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
index adc856366..f706b1ac3 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -219,7 +219,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
b = grub_efi_system_table->boot_services;
- file = grub_file_open (filename);
+ file = grub_file_open (filename, GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE);
if (! file)
goto fail;
diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c
index 7f96515da..c26edb4a9 100644
--- a/grub-core/loader/i386/bsd.c
+++ b/grub-core/loader/i386/bsd.c
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
#ifdef GRUB_MACHINE_PCBIOS
#include
#endif
@@ -416,6 +417,8 @@ grub_freebsd_add_meta_module (const char *filename, const char *type,
grub_addr_t addr, grub_uint32_t size)
{
const char *name;
+ grub_err_t err;
+
name = grub_strrchr (filename, '/');
if (name)
name++;
@@ -469,6 +472,9 @@ grub_freebsd_add_meta_module (const char *filename, const char *type,
*(p++) = ' ';
}
*p = 0;
+ err = grub_verify_string (cmdline, GRUB_VERIFY_MODULE_CMDLINE);
+ if (err)
+ return err;
}
}
@@ -1457,7 +1463,7 @@ grub_bsd_load (int argc, char *argv[])
goto fail;
}
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_BSD_KERNEL);
if (!file)
goto fail;
@@ -1534,7 +1540,7 @@ grub_cmd_freebsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
if (err)
return err;
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_BSD_KERNEL);
if (! file)
return grub_errno;
@@ -1693,7 +1699,7 @@ grub_cmd_netbsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
{
grub_file_t file;
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_BSD_KERNEL);
if (! file)
return grub_errno;
@@ -1802,7 +1808,7 @@ grub_cmd_freebsd_loadenv (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_FREEBSD_ENV);
if ((!file) || (!file->size))
goto fail;
@@ -1907,7 +1913,7 @@ grub_cmd_freebsd_module (grub_command_t cmd __attribute__ ((unused)),
return 0;
}
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_FREEBSD_MODULE);
if ((!file) || (!file->size))
goto fail;
@@ -1958,7 +1964,7 @@ grub_netbsd_module_load (char *filename, grub_uint32_t type)
void *src;
grub_err_t err;
- file = grub_file_open (filename);
+ file = grub_file_open (filename, GRUB_FILE_TYPE_NETBSD_MODULE);
if ((!file) || (!file->size))
goto fail;
@@ -2048,7 +2054,7 @@ grub_cmd_freebsd_module_elf (grub_command_t cmd __attribute__ ((unused)),
return 0;
}
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_FREEBSD_MODULE_ELF);
if (!file)
return grub_errno;
if (!file->size)
@@ -2088,7 +2094,7 @@ grub_cmd_openbsd_ramdisk (grub_command_t cmd __attribute__ ((unused)),
if (!openbsd_ramdisk.max_size)
return grub_error (GRUB_ERR_BAD_OS, "your kOpenBSD doesn't support ramdisk");
- file = grub_file_open (args[0]);
+ file = grub_file_open (args[0], GRUB_FILE_TYPE_OPENBSD_RAMDISK);
if (! file)
return grub_errno;
diff --git a/grub-core/loader/i386/coreboot/chainloader.c b/grub-core/loader/i386/coreboot/chainloader.c
index 2cb78eee0..0a19ebb9c 100644
--- a/grub-core/loader/i386/coreboot/chainloader.c
+++ b/grub-core/loader/i386/coreboot/chainloader.c
@@ -439,7 +439,7 @@ grub_cmd_chain (grub_command_t cmd __attribute__ ((unused)),
grub_loader_unset ();
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_COREBOOT_CHAINLOADER);
if (!file)
return grub_errno;
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
index 083f9417c..b0d5e1fe6 100644
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -34,6 +34,7 @@
#include
#include
#include
+#include
#include
GRUB_MOD_LICENSE ("GPLv3+");
@@ -79,6 +80,8 @@ static grub_efi_uintn_t efi_mmap_size;
#else
static const grub_size_t efi_mmap_size = 0;
#endif
+static grub_err_t (*grub_slaunch_func) (struct grub_slaunch_params*) = NULL;
+static struct grub_slaunch_params slparams;
/* FIXME */
#if 0
@@ -95,6 +98,12 @@ static struct idt_descriptor idt_desc =
};
#endif
+void
+grub_linux_slaunch_set (grub_err_t (*sfunc) (struct grub_slaunch_params*))
+{
+ grub_slaunch_func = sfunc;
+}
+
static inline grub_size_t
page_align (grub_size_t size)
{
@@ -654,6 +663,15 @@ grub_linux_boot (void)
}
#endif
+ /* If a secondary loader was set for secure launch, call it here. */
+ if (grub_slaunch_func)
+ {
+ slparams.params = ctx.params;
+ slparams.real_mode_target = ctx.real_mode_target;
+ slparams.prot_mode_target = prot_mode_target;
+ return grub_slaunch_func (&slparams);
+ }
+
/* FIXME. */
/* asm volatile ("lidt %0" : : "m" (idt_desc)); */
state.ebp = state.edi = state.ebx = 0;
@@ -695,7 +713,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
if (! file)
goto fail;
@@ -1012,11 +1030,17 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (!linux_cmdline)
goto fail;
grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
- grub_create_loader_cmdline (argc, argv,
- linux_cmdline
- + sizeof (LINUX_IMAGE) - 1,
- maximal_cmdline_size
- - (sizeof (LINUX_IMAGE) - 1));
+ {
+ grub_err_t err;
+ err = grub_create_loader_cmdline (argc, argv,
+ linux_cmdline
+ + sizeof (LINUX_IMAGE) - 1,
+ maximal_cmdline_size
+ - (sizeof (LINUX_IMAGE) - 1),
+ GRUB_VERIFY_KERNEL_CMDLINE);
+ if (err)
+ goto fail;
+ }
len = prot_file_size;
if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno)
diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c
index dc98dbcae..ad3cc292f 100644
--- a/grub-core/loader/i386/multiboot_mbi.c
+++ b/grub-core/loader/i386/multiboot_mbi.c
@@ -673,10 +673,8 @@ grub_multiboot_init_mbi (int argc, char *argv[])
return grub_errno;
cmdline_size = len;
- grub_create_loader_cmdline (argc, argv, cmdline,
- cmdline_size);
-
- return GRUB_ERR_NONE;
+ return grub_create_loader_cmdline (argc, argv, cmdline,
+ cmdline_size, GRUB_VERIFY_KERNEL_CMDLINE);
}
grub_err_t
@@ -685,6 +683,7 @@ grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
{
struct module *newmod;
grub_size_t len = 0;
+ grub_err_t err;
newmod = grub_malloc (sizeof (*newmod));
if (!newmod)
@@ -704,8 +703,13 @@ grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
newmod->cmdline_size = len;
total_modcmd += ALIGN_UP (len, 4);
- grub_create_loader_cmdline (argc, argv, newmod->cmdline,
- newmod->cmdline_size);
+ err = grub_create_loader_cmdline (argc, argv, newmod->cmdline,
+ newmod->cmdline_size, GRUB_VERIFY_MODULE_CMDLINE);
+ if (err)
+ {
+ grub_free (newmod);
+ return grub_errno;
+ }
if (modules_last)
modules_last->next = newmod;
diff --git a/grub-core/loader/i386/pc/chainloader.c b/grub-core/loader/i386/pc/chainloader.c
index c79c4fe0f..54d717182 100644
--- a/grub-core/loader/i386/pc/chainloader.c
+++ b/grub-core/loader/i386/pc/chainloader.c
@@ -156,8 +156,8 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags)
grub_dl_ref (my_mod);
- grub_file_filter_disable_compression ();
- file = grub_file_open (filename);
+ file = grub_file_open (filename, GRUB_FILE_TYPE_PCCHAINLOADER
+ | GRUB_FILE_TYPE_NO_DECOMPRESS);
if (! file)
goto fail;
diff --git a/grub-core/loader/i386/pc/freedos.c b/grub-core/loader/i386/pc/freedos.c
index 478f3c513..aac6c9715 100644
--- a/grub-core/loader/i386/pc/freedos.c
+++ b/grub-core/loader/i386/pc/freedos.c
@@ -110,7 +110,7 @@ grub_cmd_freedos (grub_command_t cmd __attribute__ ((unused)),
if (!rel)
goto fail;
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_FREEDOS);
if (! file)
goto fail;
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
index a293b17aa..89c6a7436 100644
--- a/grub-core/loader/i386/pc/linux.c
+++ b/grub-core/loader/i386/pc/linux.c
@@ -139,7 +139,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
if (! file)
goto fail;
@@ -334,11 +334,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* Create kernel command line. */
grub_memcpy ((char *)grub_linux_real_chunk + GRUB_LINUX_CL_OFFSET,
LINUX_IMAGE, sizeof (LINUX_IMAGE));
- grub_create_loader_cmdline (argc, argv,
- (char *)grub_linux_real_chunk
- + GRUB_LINUX_CL_OFFSET + sizeof (LINUX_IMAGE) - 1,
- maximal_cmdline_size
- - (sizeof (LINUX_IMAGE) - 1));
+ err = grub_create_loader_cmdline (argc, argv,
+ (char *)grub_linux_real_chunk
+ + GRUB_LINUX_CL_OFFSET + sizeof (LINUX_IMAGE) - 1,
+ maximal_cmdline_size
+ - (sizeof (LINUX_IMAGE) - 1),
+ GRUB_VERIFY_KERNEL_CMDLINE);
+ if (err)
+ goto fail;
if (grub_linux_is_bzimage)
grub_linux_prot_target = GRUB_LINUX_BZIMAGE_ADDR;
diff --git a/grub-core/loader/i386/pc/ntldr.c b/grub-core/loader/i386/pc/ntldr.c
index 1b88f40d8..f0d74145b 100644
--- a/grub-core/loader/i386/pc/ntldr.c
+++ b/grub-core/loader/i386/pc/ntldr.c
@@ -90,7 +90,7 @@ grub_cmd_ntldr (grub_command_t cmd __attribute__ ((unused)),
if (!rel)
goto fail;
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_NTLDR);
if (! file)
goto fail;
diff --git a/grub-core/loader/i386/pc/plan9.c b/grub-core/loader/i386/pc/plan9.c
index 814a49d50..37550155d 100644
--- a/grub-core/loader/i386/pc/plan9.c
+++ b/grub-core/loader/i386/pc/plan9.c
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
GRUB_MOD_LICENSE ("GPLv3+");
@@ -413,7 +414,7 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
if (!rel)
goto fail;
- fill_ctx.file = grub_file_open (argv[0]);
+ fill_ctx.file = grub_file_open (argv[0], GRUB_FILE_TYPE_PLAN9_KERNEL);
if (! fill_ctx.file)
goto fail;
@@ -505,6 +506,7 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
configptr = grub_stpcpy (configptr, "bootfile=");
configptr = grub_stpcpy (configptr, bootpath);
*configptr++ = '\n';
+ char *cmdline = configptr;
{
int i;
for (i = 1; i < argc; i++)
@@ -513,6 +515,15 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
*configptr++ = '\n';
}
}
+
+ {
+ grub_err_t err;
+ *configptr = '\0';
+ err = grub_verify_string (cmdline, GRUB_VERIFY_KERNEL_CMDLINE);
+ if (err)
+ goto fail;
+ }
+
configptr = grub_stpcpy (configptr, fill_ctx.pmap);
{
diff --git a/grub-core/loader/i386/pc/pxechainloader.c b/grub-core/loader/i386/pc/pxechainloader.c
index e60c62b1b..acb061169 100644
--- a/grub-core/loader/i386/pc/pxechainloader.c
+++ b/grub-core/loader/i386/pc/pxechainloader.c
@@ -99,7 +99,7 @@ grub_cmd_pxechain (grub_command_t cmd __attribute__ ((unused)),
if (!rel)
goto fail;
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_PXECHAINLOADER);
if (! file)
goto fail;
diff --git a/grub-core/loader/i386/pc/truecrypt.c b/grub-core/loader/i386/pc/truecrypt.c
index 9ea4fde42..cbeeec7be 100644
--- a/grub-core/loader/i386/pc/truecrypt.c
+++ b/grub-core/loader/i386/pc/truecrypt.c
@@ -99,7 +99,7 @@ grub_cmd_truecrypt (grub_command_t cmd __attribute__ ((unused)),
grub_dl_ref (my_mod);
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_TRUECRYPT);
if (! file)
goto fail;
diff --git a/grub-core/loader/i386/slaunch.c b/grub-core/loader/i386/slaunch.c
new file mode 100644
index 000000000..ba2a5fc19
--- /dev/null
+++ b/grub-core/loader/i386/slaunch.c
@@ -0,0 +1,224 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+GRUB_MOD_LICENSE("GPLv3+");
+
+static grub_dl_t my_mod;
+static struct grub_slaunch_module *modules = NULL, *modules_last = NULL;
+static struct grub_relocator *relocator = NULL;
+
+struct grub_slaunch_module*
+grub_slaunch_get_modules( void)
+{
+ return modules;
+}
+
+static grub_err_t
+grub_slaunch_add_module (void *addr, grub_addr_t target, grub_size_t size)
+{
+ struct grub_slaunch_module *newmod;
+
+ newmod = grub_malloc (sizeof (*newmod));
+ if (!newmod)
+ return grub_errno;
+ newmod->addr = (grub_uint8_t*)addr;
+ newmod->target = target;
+ newmod->size = size;
+ newmod->next = 0;
+
+ if (modules_last)
+ modules_last->next = newmod;
+ else
+ modules = newmod;
+ modules_last = newmod;
+
+ return GRUB_ERR_NONE;
+}
+
+static void
+grub_slaunch_free (void)
+{
+ struct grub_slaunch_module *cur, *next;
+
+ for (cur = modules; cur; cur = next)
+ {
+ next = cur->next;
+ grub_free (cur);
+ }
+ modules = NULL;
+ modules_last = NULL;
+
+ grub_relocator_unload (relocator);
+ relocator = NULL;
+}
+
+static grub_err_t
+grub_cmd_slaunch (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_uint32_t manufacturer[3];
+ grub_uint32_t eax, edx, ebx, ecx;
+ grub_uint64_t msr_value;
+
+ if (argc == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("argument expected"));
+
+ /* Should be executing on the BSP */
+ msr_value = grub_rdmsr (GRUB_MSR_X86_APICBASE);
+ if (! (msr_value & GRUB_MSR_X86_APICBASE_BSP))
+ return grub_error (GRUB_ERR_BAD_DEVICE, N_("secure launch must run on BSP"));
+
+ if (! grub_cpu_is_cpuid_supported ())
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("CPUID not supported"));
+
+ grub_cpuid (0, eax, manufacturer[0], manufacturer[2], manufacturer[1]);
+
+ if (grub_memcmp (argv[0], "txt", 3) == 0)
+ {
+ if (grub_memcmp (manufacturer, "GenuineIntel", 12) != 0)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Intel platform required for TXT"));
+
+ grub_cpuid(GRUB_X86_CPUID_FEATURES, eax, ebx, ecx, edx);
+ if (! (ecx & GRUB_VMX_CPUID_FEATURE) || ! (ecx & GRUB_SMX_CPUID_FEATURE) )
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("CPU does not support Intel TXT"));
+
+ msr_value = grub_rdmsr (GRUB_MSR_X86_FEATURE_CONTROL);
+ if (! (msr_value & GRUB_MSR_X86_ENABLE_VMX_IN_SMX))
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Intel TXT is not enabled"));
+
+ grub_linux_slaunch_set (grub_slaunch_boot_txt);
+ }
+ else if (grub_memcmp (argv[0], "skinit", 6) == 0)
+ {
+ if (grub_memcmp (manufacturer, "AuthenticAMD", 12) != 0)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("AMD platform required for SKINIT"));
+
+ grub_cpuid (GRUB_AMD_CPUID_FEATURES, eax, ebx, ecx, edx);
+ if (! (ecx & GRUB_SVM_CPUID_FEATURE) )
+ return grub_error (GRUB_ERR_BAD_DEVICE, N_("CPU does not support AMD SVM"));
+
+ /* Check whether SVM feature is disabled in BIOS */
+ msr_value = grub_rdmsr (GRUB_MSR_AMD64_VM_CR);
+ if (msr_value & GRUB_MSR_SVM_VM_CR_SVM_DISABLE)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "BIOS has AMD SVM disabled");
+
+ grub_linux_slaunch_set (grub_slaunch_boot_skinit);
+ }
+ else
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_slaunch_module (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_file_t file;
+ grub_ssize_t size;
+ grub_err_t err;
+ grub_relocator_chunk_t ch;
+ void *addr = NULL;
+ grub_addr_t target;
+
+ if (argc == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+
+ if (! relocator)
+ {
+ relocator = grub_relocator_new ();
+ if (! relocator)
+ return grub_errno;
+ }
+
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_SLAUNCH_MODULE);
+ if (! file)
+ return grub_errno;
+
+ size = grub_file_size (file);
+ if (size == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("file size is zero"));
+
+ err = grub_relocator_alloc_chunk_align (relocator, &ch,
+ 0x4000000, (0xffffffff - size) + 1,
+ size, 0x1000,
+ GRUB_RELOCATOR_PREFERENCE_NONE, 1);
+ if (err)
+ {
+ grub_file_close (file);
+ return err;
+ }
+
+ addr = get_virtual_current_address (ch);
+ target = get_physical_target_address (ch);
+
+ err = grub_slaunch_add_module (addr, target, size);
+ if (err)
+ {
+ grub_file_close (file);
+ return err;
+ }
+
+
+ if (grub_file_read (file, addr, size) != size)
+ {
+ grub_file_close (file);
+ if (!grub_errno)
+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
+ argv[0]);
+ return grub_errno;
+ }
+
+ grub_file_close (file);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd_slaunch, cmd_slaunch_module;
+
+GRUB_MOD_INIT(slaunch)
+{
+ cmd_slaunch =
+ grub_register_command ("slaunch", grub_cmd_slaunch,
+ 0, N_("Launch Secure Loader"));
+ cmd_slaunch_module =
+ grub_register_command ("slaunch_module", grub_cmd_slaunch_module,
+ 0, N_("Secure Loader module command"));
+ my_mod = mod;
+}
+
+GRUB_MOD_FINI(slaunch)
+{
+ grub_slaunch_free ();
+ grub_unregister_command (cmd_slaunch_module);
+ grub_unregister_command (cmd_slaunch);
+}
diff --git a/grub-core/loader/i386/slaunch_skinit.c b/grub-core/loader/i386/slaunch_skinit.c
new file mode 100644
index 000000000..3c3f00f2b
--- /dev/null
+++ b/grub-core/loader/i386/slaunch_skinit.c
@@ -0,0 +1,34 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+grub_err_t
+grub_slaunch_boot_skinit (struct grub_slaunch_params *slparams)
+{
+ slparams = slparams;
+
+ return GRUB_ERR_NONE;
+}
diff --git a/grub-core/loader/i386/slaunch_txt.c b/grub-core/loader/i386/slaunch_txt.c
new file mode 100644
index 000000000..26fdd5306
--- /dev/null
+++ b/grub-core/loader/i386/slaunch_txt.c
@@ -0,0 +1,35 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+grub_err_t
+grub_slaunch_boot_txt (struct grub_slaunch_params *slparams)
+{
+ slparams = slparams;
+
+ return GRUB_ERR_NONE;
+}
diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
index 3073f64d5..1a99ca72c 100644
--- a/grub-core/loader/i386/xen.c
+++ b/grub-core/loader/i386/xen.c
@@ -40,6 +40,7 @@
#include
#include
#include
+#include
GRUB_MOD_LICENSE ("GPLv3+");
@@ -647,8 +648,11 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)),
grub_create_loader_cmdline (argc - 1, argv + 1,
(char *) xen_state.next_start.cmd_line,
sizeof (xen_state.next_start.cmd_line) - 1);
+ err = grub_verify_string (xen_state.next_start.cmd_line, GRUB_VERIFY_MODULE_CMDLINE);
+ if (err)
+ return err;
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
if (!file)
return grub_errno;
@@ -893,9 +897,8 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
xen_state.max_addr = ALIGN_UP (xen_state.max_addr, PAGE_SIZE);
- if (nounzip)
- grub_file_filter_disable_compression ();
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_INITRD |
+ (nounzip ? GRUB_FILE_TYPE_NO_DECOMPRESS : GRUB_FILE_TYPE_NONE));
if (!file)
return grub_errno;
size = grub_file_size (file);
@@ -909,6 +912,9 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
grub_create_loader_cmdline (argc - 1, argv + 1,
get_virtual_current_address (ch), cmdline_len);
+ err = grub_verify_string (get_virtual_current_address (ch), GRUB_VERIFY_MODULE_CMDLINE);
+ if (err)
+ goto fail;
xen_state.module_info_page[xen_state.n_modules].cmdline =
xen_state.max_addr - xen_state.modules_target_start;
diff --git a/grub-core/loader/i386/xen_file.c b/grub-core/loader/i386/xen_file.c
index 99fad4cad..52b75fad8 100644
--- a/grub-core/loader/i386/xen_file.c
+++ b/grub-core/loader/i386/xen_file.c
@@ -78,7 +78,7 @@ grub_xen_file (grub_file_t file)
Trim it. */
if (grub_memcmp (magic, XZ_MAGIC, sizeof (XZ_MAGIC) - 1) == 0)
payload_length -= 4;
- off_file = grub_file_offset_open (file, payload_offset,
+ off_file = grub_file_offset_open (file, GRUB_FILE_TYPE_LINUX_KERNEL, payload_offset,
payload_length);
if (!off_file)
goto fail;
diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c
index 59ef73a73..e64ed08f5 100644
--- a/grub-core/loader/i386/xnu.c
+++ b/grub-core/loader/i386/xnu.c
@@ -487,7 +487,7 @@ grub_cmd_devprop_load (grub_command_t cmd __attribute__ ((unused)),
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
- file = grub_file_open (args[0]);
+ file = grub_file_open (args[0], GRUB_FILE_XNU_DEVPROP);
if (! file)
return grub_errno;
size = grub_file_size (file);
diff --git a/grub-core/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c
index 750330d45..e325fe0ee 100644
--- a/grub-core/loader/ia64/efi/linux.c
+++ b/grub-core/loader/ia64/efi/linux.c
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
GRUB_MOD_LICENSE ("GPLv3+");
@@ -543,6 +544,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
p = grub_stpcpy (p, argv[i]);
}
cmdline[10] = '=';
+
+ *p = '\0';
+
+ err = grub_verify_string (cmdline, GRUB_VERIFY_KERNEL_CMDLINE);
+ if (err)
+ goto fail;
boot_param->command_line = (grub_uint64_t) cmdline;
boot_param->efi_systab = (grub_uint64_t) grub_efi_system_table;
diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
index be6fa0f4d..471b214d6 100644
--- a/grub-core/loader/linux.c
+++ b/grub-core/loader/linux.c
@@ -173,7 +173,6 @@ grub_initrd_init (int argc, char *argv[],
eptr = grub_strchr (ptr, ':');
if (eptr)
{
- grub_file_filter_disable_compression ();
initrd_ctx->components[i].newc_name = grub_strndup (ptr, eptr - ptr);
if (!initrd_ctx->components[i].newc_name)
{
@@ -198,8 +197,9 @@ grub_initrd_init (int argc, char *argv[],
root = 0;
newc = 0;
}
- grub_file_filter_disable_compression ();
- initrd_ctx->components[i].file = grub_file_open (fname);
+ initrd_ctx->components[i].file = grub_file_open (fname,
+ GRUB_FILE_TYPE_LINUX_INITRD
+ | GRUB_FILE_TYPE_NO_DECOMPRESS);
if (!initrd_ctx->components[i].file)
{
grub_initrd_close (initrd_ctx);
diff --git a/grub-core/loader/macho.c b/grub-core/loader/macho.c
index 59b195e27..085f9c689 100644
--- a/grub-core/loader/macho.c
+++ b/grub-core/loader/macho.c
@@ -188,12 +188,12 @@ grub_macho_file (grub_file_t file, const char *filename, int is_64bit)
}
grub_macho_t
-grub_macho_open (const char *name, int is_64bit)
+grub_macho_open (const char *name, enum grub_file_type type, int is_64bit)
{
grub_file_t file;
grub_macho_t macho;
- file = grub_file_open (name);
+ file = grub_file_open (name, type);
if (! file)
return 0;
diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c
index 5f383be3d..e256c440f 100644
--- a/grub-core/loader/mips/linux.c
+++ b/grub-core/loader/mips/linux.c
@@ -237,7 +237,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
- elf = grub_elf_open (argv[0]);
+ elf = grub_elf_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
if (! elf)
return grub_errno;
@@ -327,6 +327,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
linux_argv++;
linux_args += ALIGN_UP (sizeof ("a0"), 4);
+ char *params = linux_args;
+
#ifdef GRUB_MACHINE_MIPS_LOONGSON
{
unsigned mtype = grub_arch_machine;
@@ -352,6 +354,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
linux_args += ALIGN_UP (grub_strlen (argv[i]) + 1, 4);
}
+ *linux_args = '\0';
+
+ err = grub_verify_string (params, GRUB_VERIFY_KERNEL_CMDLINE);
+ if (err)
+ return err;
+
/* Reserve space for rd arguments. */
rd_addr_arg_off = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground;
linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4);
diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
index 40c67e824..4a98d7082 100644
--- a/grub-core/loader/multiboot.c
+++ b/grub-core/loader/multiboot.c
@@ -321,7 +321,7 @@ grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_MULTIBOOT_KERNEL);
if (! file)
return grub_errno;
@@ -387,10 +387,8 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("you need to load the kernel first"));
- if (nounzip)
- grub_file_filter_disable_compression ();
-
- file = grub_file_open (argv[0]);
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_MULTIBOOT_MODULE
+ | (nounzip ? GRUB_FILE_TYPE_NO_DECOMPRESS : GRUB_FILE_TYPE_NONE));
if (! file)
return grub_errno;
diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
index 4df659595..97ff6e324 100644
--- a/grub-core/loader/multiboot_mbi2.c
+++ b/grub-core/loader/multiboot_mbi2.c
@@ -1074,10 +1074,8 @@ grub_multiboot2_init_mbi (int argc, char *argv[])
return grub_errno;
cmdline_size = len;
- grub_create_loader_cmdline (argc, argv, cmdline,
- cmdline_size);
-
- return GRUB_ERR_NONE;
+ return grub_create_loader_cmdline (argc, argv, cmdline, cmdline_size,
+ GRUB_VERIFY_KERNEL_CMDLINE);
}
grub_err_t
@@ -1086,6 +1084,7 @@ grub_multiboot2_add_module (grub_addr_t start, grub_size_t size,
{
struct module *newmod;
grub_size_t len = 0;
+ grub_err_t err;
newmod = grub_malloc (sizeof (*newmod));
if (!newmod)
@@ -1104,8 +1103,10 @@ grub_multiboot2_add_module (grub_addr_t start, grub_size_t size,
newmod->cmdline_size = len;
total_modcmd += ALIGN_UP (len, MULTIBOOT_TAG_ALIGN);
- grub_create_loader_cmdline (argc, argv, newmod->cmdline,
- newmod->cmdline_size);
+ err = grub_create_loader_cmdline (argc, argv, newmod->cmdline,
+ newmod->cmdline_size, GRUB_VERIFY_MODULE_CMDLINE);
+ if (err)
+ return err;
if (modules_last)
modules_last->next = newmod;
diff --git a/grub-core/loader/powerpc/ieee1275/linux.c b/grub-core/loader/powerpc/ieee1275/linux.c
index 6e814649f..c114e7df4 100644
--- a/grub-core/loader/powerpc/ieee1275/linux.c
+++ b/grub-core/loader/powerpc/ieee1275/linux.c
@@ -302,8 +302,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* Create kernel command line. */
grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
- grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1,
- size);
+ if (grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1,
+ size))
+ goto out;
out:
diff --git a/grub-core/loader/sparc64/ieee1275/linux.c b/grub-core/loader/sparc64/ieee1275/linux.c
index 67ef04883..abe46faa0 100644
--- a/grub-core/loader/sparc64/ieee1275/linux.c
+++ b/grub-core/loader/sparc64/ieee1275/linux.c
@@ -340,8 +340,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* Create kernel command line. */
grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
- grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1,
- size);
+ if (grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1,
+ size, GRUB_VERIFY_KERNEL_CMDLINE))
+ goto out;
out:
if (elf)
diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
index c9885b1bc..ff66be4bf 100644
--- a/grub-core/loader/xnu.c
+++ b/grub-core/loader/xnu.c
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
GRUB_MOD_LICENSE ("GPLv3+");
@@ -351,7 +352,7 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)),
grub_xnu_unload ();
- macho = grub_macho_open (args[0], 0);
+ macho = grub_macho_open (args[0], GRUB_FILE_TYPE_XNU_KERNEL, 0);
if (! macho)
return grub_errno;
@@ -425,6 +426,10 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)),
if (ptr != grub_xnu_cmdline)
*(ptr - 1) = 0;
+ err = grub_verify_string (grub_xnu_cmdline, GRUB_VERIFY_KERNEL_CMDLINE);
+ if (err)
+ return err;
+
#if defined (__i386) && !defined (GRUB_MACHINE_EFI)
err = grub_efiemu_autocore ();
if (err)
@@ -456,7 +461,7 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)),
grub_xnu_unload ();
- macho = grub_macho_open (args[0], 1);
+ macho = grub_macho_open (args[0], GRUB_FILE_TYPE_XNU_KERNEL, 1);
if (! macho)
return grub_errno;
@@ -534,6 +539,10 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)),
if (ptr != grub_xnu_cmdline)
*(ptr - 1) = 0;
+ err = grub_verify_string (grub_xnu_cmdline, GRUB_VERIFY_KERNEL_CMDLINE);
+ if (err)
+ return err;
+
#if defined (__i386) && !defined (GRUB_MACHINE_EFI)
err = grub_efiemu_autocore ();
if (err)
@@ -674,7 +683,7 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile,
macho = 0;
if (infoplistname)
- infoplist = grub_file_open (infoplistname);
+ infoplist = grub_file_open (infoplistname, GRUB_FILE_TYPE_XNU_INFO_PLIST);
else
infoplist = 0;
grub_errno = GRUB_ERR_NONE;
@@ -771,7 +780,7 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)),
if (! grub_xnu_heap_size)
return grub_error (GRUB_ERR_BAD_OS, N_("you need to load the kernel first"));
- file = grub_file_open (args[0]);
+ file = grub_file_open (args[0], GRUB_FILE_TYPE_XNU_MKEXT);
if (! file)
return grub_errno;
@@ -885,7 +894,7 @@ grub_cmd_xnu_ramdisk (grub_command_t cmd __attribute__ ((unused)),
if (! grub_xnu_heap_size)
return grub_error (GRUB_ERR_BAD_OS, N_("you need to load the kernel first"));
- file = grub_file_open (args[0]);
+ file = grub_file_open (args[0], GRUB_FILE_TYPE_XNU_RAMDISK);
if (! file)
return grub_errno;
@@ -925,7 +934,7 @@ grub_xnu_check_os_bundle_required (char *plistname,
if (binname)
*binname = 0;
- file = grub_file_open (plistname);
+ file = grub_file_open (plistname, GRUB_FILE_TYPE_XNU_INFO_PLIST);
if (! file)
return 0;
@@ -1210,7 +1219,7 @@ grub_xnu_load_kext_from_dir (char *dirname, const char *osbundlerequired,
grub_strcpy (binname + grub_strlen (binname), "/");
grub_strcpy (binname + grub_strlen (binname), binsuffix);
grub_dprintf ("xnu", "%s:%s\n", ctx.plistname, binname);
- binfile = grub_file_open (binname);
+ binfile = grub_file_open (binname, GRUB_FILE_TYPE_XNU_KEXT);
if (! binfile)
grub_errno = GRUB_ERR_NONE;
@@ -1253,7 +1262,7 @@ grub_cmd_xnu_kext (grub_command_t cmd __attribute__ ((unused)),
/* User explicitly specified plist and binary. */
if (grub_strcmp (args[1], "-") != 0)
{
- binfile = grub_file_open (args[1]);
+ binfile = grub_file_open (args[1], GRUB_FILE_TYPE_XNU_KEXT);
if (! binfile)
return grub_errno;
}
diff --git a/grub-core/loader/xnu_resume.c b/grub-core/loader/xnu_resume.c
index 534a74438..8089804d4 100644
--- a/grub-core/loader/xnu_resume.c
+++ b/grub-core/loader/xnu_resume.c
@@ -53,8 +53,8 @@ grub_xnu_resume (char *imagename)
grub_addr_t target_image;
grub_err_t err;
- grub_file_filter_disable_compression ();
- file = grub_file_open (imagename);
+ file = grub_file_open (imagename, GRUB_FILE_TYPE_XNU_HIBERNATE_IMAGE
+ | GRUB_FILE_TYPE_NO_DECOMPRESS);
if (! file)
return 0;
diff --git a/grub-core/normal/autofs.c b/grub-core/normal/autofs.c
index 721b9c325..7a7cf2b0f 100644
--- a/grub-core/normal/autofs.c
+++ b/grub-core/normal/autofs.c
@@ -33,12 +33,6 @@ autoload_fs_module (void)
{
grub_named_list_t p;
int ret = 0;
- grub_file_filter_t grub_file_filters_was[GRUB_FILE_FILTER_MAX];
-
- grub_memcpy (grub_file_filters_was, grub_file_filters_enabled,
- sizeof (grub_file_filters_enabled));
- grub_memcpy (grub_file_filters_enabled, grub_file_filters_all,
- sizeof (grub_file_filters_enabled));
while ((p = fs_module_list) != NULL)
{
@@ -56,9 +50,6 @@ autoload_fs_module (void)
grub_free (p);
}
- grub_memcpy (grub_file_filters_enabled, grub_file_filters_was,
- sizeof (grub_file_filters_enabled));
-
return ret;
}
@@ -82,7 +73,7 @@ read_fs_list (const char *prefix)
tmp_autoload_hook = grub_fs_autoload_hook;
grub_fs_autoload_hook = NULL;
- file = grub_file_open (filename);
+ file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE_LIST);
if (file)
{
/* Override previous fs.lst. */
diff --git a/grub-core/normal/crypto.c b/grub-core/normal/crypto.c
index e6d345f33..d01e6f271 100644
--- a/grub-core/normal/crypto.c
+++ b/grub-core/normal/crypto.c
@@ -94,7 +94,7 @@ read_crypto_list (const char *prefix)
return;
}
- file = grub_file_open (filename);
+ file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE_LIST);
grub_free (filename);
if (!file)
{
diff --git a/grub-core/normal/dyncmd.c b/grub-core/normal/dyncmd.c
index 169c126f5..719ebf477 100644
--- a/grub-core/normal/dyncmd.c
+++ b/grub-core/normal/dyncmd.c
@@ -106,7 +106,7 @@ read_command_list (const char *prefix)
{
grub_file_t file;
- file = grub_file_open (filename);
+ file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE_LIST);
if (file)
{
char *buf = NULL;
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index 78a70a8bf..1b03dfd57 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -123,7 +123,7 @@ read_config_file (const char *config)
}
/* Try to open the config file. */
- rawfile = grub_file_open (config);
+ rawfile = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
if (! rawfile)
return 0;
diff --git a/grub-core/normal/term.c b/grub-core/normal/term.c
index ac5d69f0f..a1e5c5a0d 100644
--- a/grub-core/normal/term.c
+++ b/grub-core/normal/term.c
@@ -331,7 +331,7 @@ read_terminal_list (const char *prefix)
return;
}
- file = grub_file_open (filename);
+ file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE_LIST);
grub_free (filename);
if (!file)
{
diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
index 21b0d9ded..31359a4c9 100644
--- a/grub-core/video/readers/jpeg.c
+++ b/grub-core/video/readers/jpeg.c
@@ -772,7 +772,7 @@ grub_video_reader_jpeg (struct grub_video_bitmap **bitmap,
grub_file_t file;
struct grub_jpeg_data *data;
- file = grub_buffile_open (filename, 0);
+ file = grub_buffile_open (filename, GRUB_FILE_TYPE_PIXMAP, 0);
if (!file)
return grub_errno;
diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
index e1a01e99f..777e71334 100644
--- a/grub-core/video/readers/png.c
+++ b/grub-core/video/readers/png.c
@@ -1086,7 +1086,7 @@ grub_video_reader_png (struct grub_video_bitmap **bitmap,
grub_file_t file;
struct grub_png_data *data;
- file = grub_buffile_open (filename, 0);
+ file = grub_buffile_open (filename, GRUB_FILE_TYPE_PIXMAP, 0);
if (!file)
return grub_errno;
diff --git a/grub-core/video/readers/tga.c b/grub-core/video/readers/tga.c
index c7a16fa9c..7cb9d1d2a 100644
--- a/grub-core/video/readers/tga.c
+++ b/grub-core/video/readers/tga.c
@@ -297,7 +297,7 @@ grub_video_reader_tga (struct grub_video_bitmap **bitmap,
grub_memset (&data, 0, sizeof (data));
- data.file = grub_buffile_open (filename, 0);
+ data.file = grub_buffile_open (filename, GRUB_FILE_TYPE_PIXMAP, 0);
if (! data.file)
return grub_errno;
diff --git a/include/grub/bufio.h b/include/grub/bufio.h
index acdd0c882..0ff72d103 100644
--- a/include/grub/bufio.h
+++ b/include/grub/bufio.h
@@ -22,7 +22,9 @@
#include
-grub_file_t EXPORT_FUNC (grub_bufio_open) (grub_file_t io, int size);
-grub_file_t EXPORT_FUNC (grub_buffile_open) (const char *name, int size);
+grub_file_t EXPORT_FUNC (grub_bufio_open) (grub_file_t io, grub_size_t size);
+grub_file_t EXPORT_FUNC (grub_buffile_open) (const char *name,
+ enum grub_file_type type,
+ grub_size_t size);
#endif /* ! GRUB_BUFIO_H */
diff --git a/include/grub/dl.h b/include/grub/dl.h
index 2bca56ce0..fee27a14c 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -175,6 +175,7 @@ struct grub_dl
{
char *name;
int ref_count;
+ int persistent;
grub_dl_dep_t dep;
grub_dl_segment_t segment;
Elf_Sym *symtab;
@@ -240,6 +241,18 @@ grub_dl_get (const char *name)
return 0;
}
+static inline void
+grub_dl_set_persistent (grub_dl_t mod)
+{
+ mod->persistent = 1;
+}
+
+static inline int
+grub_dl_is_persistent (grub_dl_t mod)
+{
+ return mod->persistent;
+}
+
#endif
grub_err_t grub_dl_register_symbol (const char *name, void *addr,
diff --git a/include/grub/elfload.h b/include/grub/elfload.h
index 9a7ae4ebb..dbb609c9b 100644
--- a/include/grub/elfload.h
+++ b/include/grub/elfload.h
@@ -42,7 +42,7 @@ typedef int (*grub_elf32_phdr_iterate_hook_t)
typedef int (*grub_elf64_phdr_iterate_hook_t)
(grub_elf_t elf, Elf64_Phdr *phdr, void *arg);
-grub_elf_t grub_elf_open (const char *);
+grub_elf_t grub_elf_open (const char *, enum grub_file_type type);
grub_elf_t grub_elf_file (grub_file_t file, const char *filename);
grub_err_t grub_elf_close (grub_elf_t);
diff --git a/include/grub/file.h b/include/grub/file.h
index 739488cbe..c0a0c08ec 100644
--- a/include/grub/file.h
+++ b/include/grub/file.h
@@ -25,6 +25,112 @@
#include
#include
+enum grub_file_type
+ {
+ GRUB_FILE_TYPE_NONE = 0,
+ /* GRUB module to be loaded. */
+ GRUB_FILE_TYPE_GRUB_MODULE,
+ /* Loopback file to be represented as disk. */
+ GRUB_FILE_TYPE_LOOPBACK,
+ /* Linux kernel to be loaded. */
+ GRUB_FILE_TYPE_LINUX_KERNEL,
+ /* Linux initrd. */
+ GRUB_FILE_TYPE_LINUX_INITRD,
+
+ /* Multiboot kernel. */
+ GRUB_FILE_TYPE_MULTIBOOT_KERNEL,
+ /* Multiboot module. */
+ GRUB_FILE_TYPE_MULTIBOOT_MODULE,
+
+ GRUB_FILE_TYPE_BSD_KERNEL,
+ GRUB_FILE_TYPE_FREEBSD_ENV,
+ GRUB_FILE_TYPE_FREEBSD_MODULE,
+ GRUB_FILE_TYPE_FREEBSD_MODULE_ELF,
+ GRUB_FILE_TYPE_NETBSD_MODULE,
+ GRUB_FILE_TYPE_OPENBSD_RAMDISK,
+
+ GRUB_FILE_TYPE_XNU_INFO_PLIST,
+ GRUB_FILE_TYPE_XNU_MKEXT,
+ GRUB_FILE_TYPE_XNU_KEXT,
+ GRUB_FILE_TYPE_XNU_KERNEL,
+ GRUB_FILE_TYPE_XNU_RAMDISK,
+ GRUB_FILE_TYPE_XNU_HIBERNATE_IMAGE,
+ GRUB_FILE_XNU_DEVPROP,
+
+ GRUB_FILE_TYPE_PLAN9_KERNEL,
+
+ GRUB_FILE_TYPE_NTLDR,
+ GRUB_FILE_TYPE_TRUECRYPT,
+ GRUB_FILE_TYPE_FREEDOS,
+ GRUB_FILE_TYPE_PXECHAINLOADER,
+ GRUB_FILE_TYPE_PCCHAINLOADER,
+
+ GRUB_FILE_TYPE_COREBOOT_CHAINLOADER,
+
+ GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE,
+
+ /* File holding signature. */
+ GRUB_FILE_TYPE_SIGNATURE,
+ /* File holding public key to verify signature once. */
+ GRUB_FILE_TYPE_PUBLIC_KEY,
+ /* File holding public key to add to trused keys. */
+ GRUB_FILE_TYPE_PUBLIC_KEY_TRUST,
+ /* File of which we intend to print a blocklist to the user. */
+ GRUB_FILE_TYPE_PRINT_BLOCKLIST,
+ /* File we intend to use for test loading or testing speed. */
+ GRUB_FILE_TYPE_TESTLOAD,
+ /* File we open only to get its size. E.g. in ls output. */
+ GRUB_FILE_TYPE_GET_SIZE,
+ /* Font file. */
+ GRUB_FILE_TYPE_FONT,
+ /* File holding encryption key for encrypted ZFS. */
+ GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY,
+ /* File we open n grub-fstest. */
+ GRUB_FILE_TYPE_FSTEST,
+ /* File we open n grub-mount. */
+ GRUB_FILE_TYPE_MOUNT,
+ /* File which we attempt to identify the type of. */
+ GRUB_FILE_TYPE_FILE_ID,
+ /* File holding ACPI table. */
+ GRUB_FILE_TYPE_ACPI_TABLE,
+ /* File we intend show to user. */
+ GRUB_FILE_TYPE_CAT,
+ GRUB_FILE_TYPE_HEXCAT,
+ /* One of pair of files we intend to compare. */
+ GRUB_FILE_TYPE_CMP,
+ /* List of hashes for hashsum. */
+ GRUB_FILE_TYPE_HASHLIST,
+ /* File hashed by hashsum. */
+ GRUB_FILE_TYPE_TO_HASH,
+ /* Keyboard layout. */
+ GRUB_FILE_TYPE_KEYBOARD_LAYOUT,
+ /* Picture file. */
+ GRUB_FILE_TYPE_PIXMAP,
+ /* *.lst shipped by GRUB. */
+ GRUB_FILE_TYPE_GRUB_MODULE_LIST,
+ /* config file. */
+ GRUB_FILE_TYPE_CONFIG,
+ GRUB_FILE_TYPE_THEME,
+ GRUB_FILE_TYPE_GETTEXT_CATALOG,
+ GRUB_FILE_TYPE_FS_SEARCH,
+ GRUB_FILE_TYPE_AUDIO,
+ GRUB_FILE_TYPE_VBE_DUMP,
+
+ GRUB_FILE_TYPE_LOADENV,
+ GRUB_FILE_TYPE_SAVEENV,
+
+ GRUB_FILE_TYPE_VERIFY_SIGNATURE,
+
+ /* Secure Launch module. */
+ GRUB_FILE_TYPE_SLAUNCH_MODULE,
+
+ GRUB_FILE_TYPE_MASK = 0xffff,
+
+ /* --skip-sig is specified. */
+ GRUB_FILE_TYPE_SKIP_SIGNATURE = 0x10000,
+ GRUB_FILE_TYPE_NO_DECOMPRESS = 0x20000
+ };
+
/* File description. */
struct grub_file
{
@@ -68,7 +174,7 @@ extern grub_disk_read_hook_t EXPORT_VAR(grub_file_progress_hook);
/* Filters with lower ID are executed first. */
typedef enum grub_file_filter_id
{
- GRUB_FILE_FILTER_PUBKEY,
+ GRUB_FILE_FILTER_VERIFY,
GRUB_FILE_FILTER_GZIO,
GRUB_FILE_FILTER_XZIO,
GRUB_FILE_FILTER_LZOPIO,
@@ -77,61 +183,26 @@ typedef enum grub_file_filter_id
GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_LZOPIO,
} grub_file_filter_id_t;
-typedef grub_file_t (*grub_file_filter_t) (grub_file_t in, const char *filename);
+typedef grub_file_t (*grub_file_filter_t) (grub_file_t in, enum grub_file_type type);
-extern grub_file_filter_t EXPORT_VAR(grub_file_filters_all)[GRUB_FILE_FILTER_MAX];
-extern grub_file_filter_t EXPORT_VAR(grub_file_filters_enabled)[GRUB_FILE_FILTER_MAX];
+extern grub_file_filter_t EXPORT_VAR(grub_file_filters)[GRUB_FILE_FILTER_MAX];
static inline void
grub_file_filter_register (grub_file_filter_id_t id, grub_file_filter_t filter)
{
- grub_file_filters_all[id] = filter;
- grub_file_filters_enabled[id] = filter;
+ grub_file_filters[id] = filter;
}
static inline void
grub_file_filter_unregister (grub_file_filter_id_t id)
{
- grub_file_filters_all[id] = 0;
- grub_file_filters_enabled[id] = 0;
-}
-
-static inline void
-grub_file_filter_disable (grub_file_filter_id_t id)
-{
- grub_file_filters_enabled[id] = 0;
-}
-
-static inline void
-grub_file_filter_disable_compression (void)
-{
- grub_file_filter_id_t id;
-
- for (id = GRUB_FILE_FILTER_COMPRESSION_FIRST;
- id <= GRUB_FILE_FILTER_COMPRESSION_LAST; id++)
- grub_file_filters_enabled[id] = 0;
-}
-
-static inline void
-grub_file_filter_disable_all (void)
-{
- grub_file_filter_id_t id;
-
- for (id = 0;
- id < GRUB_FILE_FILTER_MAX; id++)
- grub_file_filters_enabled[id] = 0;
-}
-
-static inline void
-grub_file_filter_disable_pubkey (void)
-{
- grub_file_filters_enabled[GRUB_FILE_FILTER_PUBKEY] = 0;
+ grub_file_filters[id] = 0;
}
/* Get a device name from NAME. */
char *EXPORT_FUNC(grub_file_get_device_name) (const char *name);
-grub_file_t EXPORT_FUNC(grub_file_open) (const char *name);
+grub_file_t EXPORT_FUNC(grub_file_open) (const char *name, enum grub_file_type type);
grub_ssize_t EXPORT_FUNC(grub_file_read) (grub_file_t file, void *buf,
grub_size_t len);
grub_off_t EXPORT_FUNC(grub_file_seek) (grub_file_t file, grub_off_t offset);
@@ -159,8 +230,8 @@ grub_file_seekable (const grub_file_t file)
}
grub_file_t
-grub_file_offset_open (grub_file_t parent, grub_off_t start,
- grub_off_t size);
+grub_file_offset_open (grub_file_t parent, enum grub_file_type type,
+ grub_off_t start, grub_off_t size);
void
grub_file_offset_close (grub_file_t file);
diff --git a/include/grub/i386/cpuid.h b/include/grub/i386/cpuid.h
index f7ae4b0a4..8176e5d11 100644
--- a/include/grub/i386/cpuid.h
+++ b/include/grub/i386/cpuid.h
@@ -19,6 +19,19 @@
#ifndef GRUB_CPU_CPUID_HEADER
#define GRUB_CPU_CPUID_HEADER 1
+/* General */
+#define GRUB_X86_CPUID_VENDOR 0x00000000
+#define GRUB_X86_CPUID_FEATURES 0x00000001
+
+/* Intel */
+#define GRUB_VMX_CPUID_FEATURE (1<<5)
+#define GRUB_SMX_CPUID_FEATURE (1<<6)
+
+/* AMD */
+#define GRUB_AMD_CPUID_FEATURES 0x80000001
+#define GRUB_SVM_CPUID_FEATURE (1<<2)
+#define GRUB_AMD_CPUID_FUNC 0x8000000a
+
extern unsigned char grub_cpuid_has_longmode;
extern unsigned char grub_cpuid_has_pae;
diff --git a/include/grub/i386/mmio.h b/include/grub/i386/mmio.h
new file mode 100644
index 000000000..6a4c4946a
--- /dev/null
+++ b/include/grub/i386/mmio.h
@@ -0,0 +1,105 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef GRUB_MMIO_H
+#define GRUB_MMIO_H 1
+
+#include
+
+#define grub_mb() __asm__ __volatile__ ("mfence" : : : "memory")
+#define grub_rmb() __asm__ __volatile__ ("lfence" : : : "memory")
+#define grub_wmb() __asm__ __volatile__ ("sfence" : : : "memory")
+#define grub_barrier() __asm__ __volatile__ ("" : : : "memory")
+
+static __inline grub_uint8_t
+grub_readb (void *addr)
+{
+ grub_uint8_t _v;
+
+ grub_barrier();
+ _v = (*(volatile grub_uint8_t*)(addr));
+ grub_rmb();
+ return _v;
+}
+
+static __inline grub_uint16_t
+grub_readw (void *addr)
+{
+ grub_uint16_t _v;
+
+ grub_barrier();
+ _v = (*(volatile grub_uint16_t*)(addr));
+ grub_rmb();
+ return _v;
+}
+
+static __inline grub_uint32_t
+grub_readl (void *addr)
+{
+ grub_uint32_t _v;
+
+ grub_barrier();
+ _v = (*(volatile grub_uint32_t*)(addr));
+ grub_rmb();
+ return _v;
+}
+
+static __inline grub_uint64_t
+grub_readq (void *addr)
+{
+ grub_uint64_t _v;
+
+ grub_barrier();
+ _v = (*(volatile grub_uint64_t*)(addr));
+ grub_rmb();
+ return _v;
+}
+
+static __inline void
+grub_writeb (grub_uint8_t value, void *addr)
+{
+ grub_wmb();
+ (*(volatile grub_uint8_t *)(addr)) = value;
+ grub_barrier();
+}
+
+static __inline void
+grub_writew (grub_uint16_t value, void *addr)
+{
+ grub_wmb();
+ (*(volatile grub_uint16_t *)(addr)) = value;
+ grub_barrier();
+}
+
+static __inline void
+grub_writel (grub_uint32_t value, void *addr)
+{
+ grub_wmb();
+ (*(volatile grub_uint32_t *)(addr)) = value;
+ grub_barrier();
+}
+
+static __inline void
+grub_writeq (grub_uint64_t value, void *addr)
+{
+ grub_wmb();
+ (*(volatile grub_uint64_t *)(addr)) = value;
+ grub_barrier();
+}
+
+#endif
diff --git a/include/grub/i386/msr.h b/include/grub/i386/msr.h
new file mode 100644
index 000000000..a0c5d39e7
--- /dev/null
+++ b/include/grub/i386/msr.h
@@ -0,0 +1,82 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The definitions in this header are extracted from the Trusted Computing
+ * Group's "TPM Main Specification", Parts 1-3.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef GRUB_X86_MSR_H
+#define GRUB_X86_MSR_H 1
+
+/* General */
+
+#define GRUB_MSR_X86_APICBASE 0x0000001b
+#define GRUB_MSR_X86_APICBASE_BSP (1<<8)
+#define GRUB_MSR_X86_APICBASE_ENABLE (1<<11)
+#define GRUB_MSR_X86_APICBASE_BASE (0xfffff<<12)
+
+#define GRUB_MSR_X86_FEATURE_CONTROL 0x0000003a
+#define GRUB_MSR_X86_ENABLE_VMX_IN_SMX (1<<1)
+
+#define GRUB_MSR_X86_MCG_CAP 0x00000179
+#define GRUB_MSR_MCG_BANKCNT_MASK 0xff /* Number of banks */
+#define GRUB_MSR_X86_MCG_STATUS 0x0000017a
+#define GRUB_MSR_MCG_STATUS_MCIP (1ULL<<2) /* MC in progress */
+
+#define GRUB_MSR_X86_MC0_STATUS 0x00000401
+
+#define GRUB_MSR_X86_EFER 0xc0000080 /* Extended features */
+#define GRUB_MSR_EFER_SVME (1<<12) /* Enable virtualization */
+
+/* AMD Specific */
+
+#define GRUB_MSR_AMD64_PATCH_LEVEL 0x0000008b
+#define GRUB_MSR_AMD64_PATCH_CLEAR 0xc0010021 /* AMD-specific microcode
+ patch clear */
+#define GRUB_MSR_AMD64_VM_CR 0xc0010114
+#define GRUB_MSR_SVM_VM_CR_SVM_DISABLE 4
+
+static inline grub_uint64_t
+grub_rdmsr(grub_uint32_t msr)
+{
+ grub_uint64_t val = 0;
+
+#ifdef __x86_64__
+ asm volatile("rdmsr" : "=A" (val) : "c" (msr));
+#else
+ grub_uint32_t low, high;
+ asm volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
+ val = ((low) | (grub_uint64_t)(high) << 32);
+#endif
+
+ return val;
+}
+
+static inline void
+grub_wrmsr(grub_uint32_t msr, grub_uint64_t val)
+{
+#ifdef __x86_64__
+ asm volatile("wrmsr" : "=A" (val) : "c" (msr));
+#else
+ grub_uint32_t low, high;
+ high = (grub_uint32_t) ((val & 0xFFFFFFFF00000000LL) >> 32);
+ low = (grub_uint32_t) (val & 0xFFFFFFFFLL);
+ asm volatile("wrmsr" : "=a" (low), "=d" (high) : "c" (msr));
+#endif
+}
+
+#endif
diff --git a/include/grub/i386/txt.h b/include/grub/i386/txt.h
new file mode 100644
index 000000000..b9a392197
--- /dev/null
+++ b/include/grub/i386/txt.h
@@ -0,0 +1,475 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ *
+ * Intel TXT definitions header file.
+ */
+
+#ifndef GRUB_TXT_H
+#define GRUB_TXT_H 1
+
+#include
+#include
+
+/* Intel TXT Software Developers Guide */
+
+/* Appendix A TXT Execution Technology Authenticated Code Modules */
+/* A.1 Authenticated Code Module Format */
+
+#define GRUB_TXT_ACM_MODULE_TYPE 2
+
+#define GRUB_TXT_ACM_MODULE_SUB_TYPE_TXT_ACM 0
+#define GRUB_TXT_ACM_MODULE_SUB_TYPE_S_ACM 1
+
+#define GRUB_TXT_ACM_HEADER_LEN_0_0 161
+#define GRUB_TXT_ACM_HEADER_LEN_3_0 224
+
+#define GRUB_TXT_ACM_HEADER_VERSION_0_0 0x0000
+#define GRUB_TXT_ACM_HEADER_VERSION_3_0 0x0300
+
+#define GRUB_TXT_ACM_FLAG_PREPRODUCTION (1<<14)
+#define GRUB_TXT_ACM_FLAG_DEBUG_SIGNED (1<<15)
+
+#define GRUB_TXT_ACM_MODULE_VENDOR_INTEL 0x00008086
+
+struct grub_txt_acm_header
+{
+ grub_uint16_t module_type;
+ grub_uint16_t module_sub_type;
+ grub_uint32_t header_len;
+ grub_uint32_t header_version;
+ grub_uint16_t chipset_id;
+ grub_uint16_t flags;
+ grub_uint32_t module_vendor;
+ grub_uint32_t date; /* e.g 20131231H == December 31, 2013 */
+ grub_uint32_t size; /* multiples of 4 bytes */
+ grub_uint16_t txt_svn;
+ grub_uint16_t se_svn;
+ grub_uint32_t code_control;
+ grub_uint32_t error_entry_point;
+ grub_uint32_t gdt_limit;
+ grub_uint32_t gdt_base;
+ grub_uint32_t seg_sel;
+ grub_uint32_t entry_point;
+ grub_uint8_t reserved2[64];
+ grub_uint32_t key_size;
+ grub_uint32_t scratch_size;
+ /* RSA Pub Key and Signature */
+} GRUB_PACKED;
+
+/* Appendix B SMX Interaction with Platform */
+/* B.1 Intel Trusted Execution Technology Configuration Registers */
+
+#ifdef __x86_64__
+#define GRUB_TXT_PUB_CONFIG_REGS 0xfed30000ULL
+#define GRUB_TXT_PRIV_CONFIG_REGS 0xfed20000ULL
+#else
+#define GRUB_TXT_PUB_CONFIG_REGS 0xfed30000
+#define GRUB_TXT_PRIV_CONFIG_REGS 0xfed20000
+#endif
+
+#define GRUB_TXT_STS 0x0000
+#define GRUB_TXT_ESTS 0x0008
+#define GRUB_TXT_ERRORCODE 0x0030
+#define GRUB_TXT_CMD_RESET 0x0038
+#define GRUB_TXT_CMD_CLOSE_PRIVATE 0x0048
+#define GRUB_TXT_VER_FSBIF 0x0100
+#define GRUB_TXT_DIDVID 0x0110
+#define GRUB_TXT_VER_QPIIF 0x0200
+#define GRUB_TXT_CMD_UNLOCK_MEM_CONFIG 0x0218
+#define GRUB_TXT_SINIT_BASE 0x0270
+#define GRUB_TXT_SINIT_SIZE 0x0278
+#define GRUB_TXT_MLE_JOIN 0x0290
+#define GRUB_TXT_HEAP_BASE 0x0300
+#define GRUB_TXT_HEAP_SIZE 0x0308
+#define GRUB_TXT_MSEG_BASE 0x0310
+#define GRUB_TXT_MSEG_SIZE 0x0318
+#define GRUB_TXT_DPR 0x0330
+#define GRUB_TXT_CMD_OPEN_LOCALITY1 0x0380
+#define GRUB_TXT_CMD_CLOSE_LOCALITY1 0x0388
+#define GRUB_TXT_CMD_OPEN_LOCALITY2 0x0390
+#define GRUB_TXT_CMD_CLOSE_LOCALITY2 0x0398
+#define GRUB_TXT_PUBLIC_KEY 0x0400
+#define GRUB_TXT_CMD_SECRETS 0x08e0
+#define GRUB_TXT_CMD_NO_SECRETS 0x08e8
+#define GRUB_TXT_E2STS 0x08f0
+
+/* Appendix C Intel TXT Heap Memory */
+
+/* Ext Data Structs */
+
+struct grub_txt_heap_uuid
+{
+ grub_uint32_t data1;
+ grub_uint16_t data2;
+ grub_uint16_t data3;
+ grub_uint16_t data4;
+ grub_uint8_t data5[6];
+} GRUB_PACKED;
+
+struct grub_txt_heap_ext_data_element
+{
+ grub_uint32_t type;
+ grub_uint32_t size;
+ /* Data */
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_END 0
+
+struct grub_txt_heap_end_element
+{
+ grub_uint32_t type;
+ grub_uint32_t size;
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_BIOS_SPEC_VER 1
+
+struct grub_txt_heap_bios_spec_ver_element
+{
+ grub_uint16_t spec_ver_major;
+ grub_uint16_t spec_ver_minor;
+ grub_uint16_t spec_ver_revision;
+} HEAP_BIOS_SPEC_VER_ELEMENT;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_ACM 2
+
+struct grub_txt_heap_acm_element
+{
+ grub_uint32_t num_acms;
+ /* Array of num_acms grub_uint64_t addresses */
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_STM 3
+
+struct grub_txt_heap_stm_element
+{
+ /* STM specific BIOS properties */
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_CUSTOM 4
+
+struct grub_txt_heap_custom_element
+{
+ struct grub_txt_heap_uuid uuid;
+ /* Vendor Data */
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR 5
+
+struct grub_txt_heap_event_log_element
+{
+ grub_uint64_t event_log_phys_addr;
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_MADT 6
+
+struct grub_txt_heap_madt_element
+{
+ /* Copy of ACPI MADT table */
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1 8
+
+struct grub_txt_heap_event_log_pointer2_1_element
+{
+ grub_uint64_t phys_addr;
+ grub_uint32_t allocated_event_container_size;
+ grub_uint32_t first_record_offset;
+ grub_uint32_t next_record_offset;
+} GRUB_PACKED;
+
+#define GRUB_TXT_HEAP_EXTDATA_TYPE_MCFG 8
+
+struct grub_txt_heap_mcfg_element
+{
+ /* Copy of ACPI MCFG table */
+} GRUB_PACKED;
+
+/* TXT Heap Tables */
+
+struct grub_txt_bios_data
+{
+ grub_uint32_t version; /* Currently 5 for TPM 1.2 and 6 for TPM 2.0 */
+ grub_uint32_t bios_sinit_size;
+ grub_uint64_t reserved1;
+ grub_uint64_t reserved22;
+ grub_uint32_t num_logical_procs;
+ /* Versions >= 5 with updates in version 6 */
+ grub_uint32_t sinit_flags;
+ grub_uint32_t mle_flags;
+ /* Versions >= 4 */
+ /* Ext Data Elements */
+} GRUB_PACKED;
+
+#define GRUB_TXT_MAX_EVENT_LOG_SIZE 5*4*1024 /* 4k*5 */
+
+struct grub_txt_os_mle_data
+{
+ grub_uint32_t zero_page_addr;
+ grub_uint8_t event_log_buffer[GRUB_TXT_MAX_EVENT_LOG_SIZE];
+} GRUB_PACKED;
+
+struct grub_txt_os_sinit_data
+{
+ grub_uint32_t version; /* Currently 6 for TPM 1.2 and 7 for TPM 2.0 */
+ grub_uint32_t flags;
+ grub_uint64_t mle_ptab;
+ grub_uint64_t mle_size;
+ grub_uint64_t mle_hdr_base;
+ grub_uint64_t vtd_pmr_lo_base;
+ grub_uint64_t vtd_pmr_lo_size;
+ grub_uint64_t vtd_pmr_hi_base;
+ grub_uint64_t vtd_pmr_hi_size;
+ grub_uint64_t lcp_po_base;
+ grub_uint64_t lcp_po_size;
+ grub_uint32_t capabilities;
+ /* Version = 5 */
+ grub_uint64_t efi_rsdt_ptr;
+ /* Versions >= 6 */
+ /* Ext Data Elements */
+} GRUB_PACKED;
+
+struct grub_txt_sinit_mle_data
+{
+ grub_uint32_t version; /* Current values are 6 through 9 */
+ /* Versions <= 8 */
+ grub_uint8_t bios_acm_id[20];
+ grub_uint32_t edx_senter_flags;
+ grub_uint64_t mseg_valid;
+ grub_uint8_t sinit_hash[20];
+ grub_uint8_t mle_hash[20];
+ grub_uint8_t stm_hash[20];
+ grub_uint8_t lcp_policy_hash[20];
+ grub_uint32_t lcp_policy_control;
+ /* Versions >= 7 */
+ grub_uint32_t rlp_wakeup_addr;
+ grub_uint32_t reserved;
+ grub_uint32_t num_of_sinit_mdrs;
+ grub_uint32_t sinit_mdrs_table_offset;
+ grub_uint32_t sinit_vtd_dmar_table_size;
+ grub_uint32_t sinit_vtd_dmar_table_offset;
+ /* Versions >= 8 */
+ grub_uint32_t processor_scrtm_status;
+ /* Versions >= 9 */
+ /* Ext Data Elements */
+} GRUB_PACKED;
+
+struct grub_txt_sinit_memory_descriptor_records
+{
+ grub_uint64_t address;
+ grub_uint64_t length;
+ grub_uint8_t type;
+ grub_uint8_t reserved[7];
+} GRUB_PACKED;
+
+/* Section 2 Measured Launch Environment */
+/* 2.1 MLE Architecture Overview */
+/* Table 1. MLE Header structure */
+
+struct grub_txt_mle_header
+{
+ grub_uint8_t uuid[16];
+ grub_uint32_t header_len;
+ grub_uint32_t version;
+ grub_uint32_t entry_point;
+ grub_uint32_t first_valid_page;
+ grub_uint32_t mle_start;
+ grub_uint32_t mle_end;
+ grub_uint32_t capabilities;
+ grub_uint32_t cmdline_start;
+ grub_uint32_t cmdline_end;
+} GRUB_PACKED;
+
+/* TXT register and heap access */
+
+static inline grub_uint64_t
+grub_txt_read_reg (grub_uint32_t reg, grub_uint8_t read_public)
+{
+ grub_uint8_t *addr = (grub_uint8_t*)(read_public ? GRUB_TXT_PUB_CONFIG_REGS :
+ GRUB_TXT_PRIV_CONFIG_REGS);
+ return grub_readq(addr + reg);
+}
+
+static inline void
+grub_txt_write_reg (grub_uint32_t reg, grub_uint64_t val, grub_uint8_t read_public)
+{
+ grub_uint8_t *addr = (grub_uint8_t*)(read_public ? GRUB_TXT_PUB_CONFIG_REGS :
+ GRUB_TXT_PRIV_CONFIG_REGS);
+ grub_writeq(val, addr + reg);
+}
+
+static inline grub_uint8_t*
+grub_txt_get_heap (void)
+{
+#ifdef __x86_64__
+ return (grub_uint8_t*)grub_txt_read_reg (GRUB_TXT_HEAP_BASE, 1);
+#else
+ return (grub_uint8_t*)(grub_uint32_t)grub_txt_read_reg (GRUB_TXT_HEAP_BASE, 1);
+#endif
+}
+
+static inline grub_uint64_t
+grub_txt_bios_data_size (grub_uint8_t *heap)
+{
+ return *(grub_uint64_t *)heap;
+}
+
+static inline struct grub_txt_bios_data*
+grub_txt_bios_data_start (grub_uint8_t *heap)
+{
+ return (struct grub_txt_bios_data*)(heap + sizeof (grub_uint64_t));
+}
+
+static inline grub_uint64_t
+grub_txt_os_mle_data_size (grub_uint8_t *heap)
+{
+ return *(grub_uint64_t *)(heap + grub_txt_bios_data_size (heap));
+}
+
+static inline struct grub_txt_os_mle_data*
+grub_txt_os_mle_data_start (grub_uint8_t *heap)
+{
+ return (struct grub_txt_os_mle_data*)(heap + grub_txt_bios_data_size (heap) +
+ sizeof (grub_uint64_t));
+}
+
+static inline grub_uint64_t
+grub_txt_os_sinit_data_size (grub_uint8_t *heap)
+{
+ return *(grub_uint64_t *)(heap + grub_txt_bios_data_size (heap) +
+ grub_txt_os_mle_data_size (heap));
+}
+
+static inline struct grub_txt_os_sinit_data *
+grub_txt_os_sinit_data_start (grub_uint8_t *heap)
+{
+ return (struct grub_txt_os_sinit_data*)(heap +
+ grub_txt_bios_data_size (heap) +
+ grub_txt_os_mle_data_size (heap) + sizeof (grub_uint64_t));
+}
+
+static inline grub_uint64_t
+grub_txt_sinit_mle_data_size (grub_uint8_t *heap)
+{
+ return *(grub_uint64_t *)(heap + grub_txt_bios_data_size (heap) +
+ grub_txt_os_mle_data_size (heap) +
+ grub_txt_os_sinit_data_size (heap));
+}
+
+static inline struct grub_txt_sinit_mle_data*
+grub_txt_sinit_mle_data_start (grub_uint8_t *heap)
+{
+ return (struct grub_txt_sinit_mle_data*)(heap +
+ grub_txt_bios_data_size (heap) +
+ grub_txt_os_mle_data_size (heap) +
+ grub_txt_os_sinit_data_size (heap) +
+ sizeof (grub_uint64_t));
+}
+
+/* Intel 64 and IA-32 Architectures Software Developer’s Manual */
+/* Volume 2 (2A, 2B, 2C & 2D): Instruction Set Reference, A-Z */
+
+/* CHAPTER 6 SAFER MODE EXTENSIONS REFERENCE */
+
+#define GRUB_SMX_LEAF_CAPABILITIES 0
+#define GRUB_SMX_LEAF_UNDEFINED 1
+#define GRUB_SMX_LEAF_ENTERACCS 2
+#define GRUB_SMX_LEAF_EXITAC 3
+#define GRUB_SMX_LEAF_SENTER 4
+#define GRUB_SMX_LEAF_SEXIT 5
+#define GRUB_SMX_LEAF_PARAMETERS 6
+#define GRUB_SMX_LEAF_SMCTRL 7
+#define GRUB_SMX_LEAF_WAKEUP 8
+
+#define GRUB_SMX_CAPABILITY_CHIPSET_PRESENT (1<<0)
+#define GRUB_SMX_CAPABILITY_UNDEFINED (1<<1)
+#define GRUB_SMX_CAPABILITY_ENTERACCS (1<<2)
+#define GRUB_SMX_CAPABILITY_EXITAC (1<<3)
+#define GRUB_SMX_CAPABILITY_SENTER (1<<4)
+#define GRUB_SMX_CAPABILITY_SEXIT (1<<5)
+#define GRUB_SMX_CAPABILITY_PARAMETERS (1<<6)
+#define GRUB_SMX_CAPABILITY_SMCTRL (1<<7)
+#define GRUB_SMX_CAPABILITY_WAKEUP (1<<8)
+#define GRUB_SMX_CAPABILITY_EXTENDED_LEAFS (1<<31)
+
+static inline grub_uint32_t
+grub_txt_getsec_capabilities (grub_uint32_t index)
+{
+ grub_uint32_t caps;
+
+ __asm__ __volatile__ (".byte 0x0f,0x37\n"
+ : "=a" (caps)
+ : "a" (GRUB_SMX_LEAF_CAPABILITIES), "b" (index));
+ return caps;
+}
+
+static inline void
+grub_txt_getsec_enteraccs (grub_uint32_t acm_phys_addr, grub_uint32_t acm_size)
+{
+ __asm__ __volatile__ (".byte 0x0f,0x37\n" :
+ : "a" (GRUB_SMX_LEAF_ENTERACCS),
+ "b" (acm_phys_addr), "c" (acm_size));
+}
+
+static inline void
+grub_txt_getsec_exitac (grub_uint32_t near_jump)
+{
+ __asm__ __volatile__ (".byte 0x0f,0x37\n" :
+ : "a" (GRUB_SMX_LEAF_EXITAC), "b" (near_jump));
+}
+
+static inline void
+grub_txt_getsec_senter (grub_uint32_t acm_phys_addr, grub_uint32_t acm_size)
+{
+ __asm__ __volatile__ (".byte 0x0f,0x37\n" :
+ : "a" (GRUB_SMX_LEAF_SENTER),
+ "b" (acm_phys_addr), "c" (acm_size));
+}
+
+static inline void
+grub_txt_getsec_sexit (void)
+{
+ __asm__ __volatile__ (".byte 0x0f,0x37\n" : : "a" (GRUB_SMX_LEAF_SEXIT));
+}
+
+#define GRUB_SMX_PARAMETER_TYPE_MASK 0x1f
+
+static inline void
+grub_txt_getsec_parameters (grub_uint32_t index, grub_uint32_t *eax_out,
+ grub_uint32_t *ebx_out, grub_uint32_t *ecx_out)
+{
+ if (!eax_out || !ebx_out || !ecx_out)
+ return;
+
+ __asm__ __volatile__ (".byte 0x0f,0x37\n"
+ : "=a" (*eax_out), "=b" (*ebx_out), "=c" (*ecx_out)
+ : "a" (GRUB_SMX_LEAF_PARAMETERS), "b" (index));
+}
+
+static inline void
+grub_txt_getsec_smctrl (void)
+{
+ __asm__ __volatile__ (".byte 0x0f,0x37\n" :
+ : "a" (GRUB_SMX_LEAF_SMCTRL), "b" (0));
+}
+
+static inline void
+grub_txt_getsec_wakeup (void)
+{
+ __asm__ __volatile__ (".byte 0x0f,0x37\n" : : "a" (GRUB_SMX_LEAF_WAKEUP));
+}
+
+#endif
diff --git a/include/grub/lib/cmdline.h b/include/grub/lib/cmdline.h
index 1fe8d0179..cdca09b7a 100644
--- a/include/grub/lib/cmdline.h
+++ b/include/grub/lib/cmdline.h
@@ -21,11 +21,12 @@
#define GRUB_CMDLINE_HEADER 1
#include
+#include
#define LINUX_IMAGE "BOOT_IMAGE="
unsigned int grub_loader_cmdline_size (int argc, char *argv[]);
-int grub_create_loader_cmdline (int argc, char *argv[], char *buf,
- grub_size_t size);
+grub_err_t grub_create_loader_cmdline (int argc, char *argv[], char *buf,
+ grub_size_t size, enum grub_verify_string_type type);
#endif /* ! GRUB_CMDLINE_HEADER */
diff --git a/include/grub/list.h b/include/grub/list.h
index d170ff6da..b13acb962 100644
--- a/include/grub/list.h
+++ b/include/grub/list.h
@@ -35,6 +35,7 @@ void EXPORT_FUNC(grub_list_push) (grub_list_t *head, grub_list_t item);
void EXPORT_FUNC(grub_list_remove) (grub_list_t item);
#define FOR_LIST_ELEMENTS(var, list) for ((var) = (list); (var); (var) = (var)->next)
+#define FOR_LIST_ELEMENTS_NEXT(var, list) for ((var) = (var)->next; (var); (var) = (var)->next)
#define FOR_LIST_ELEMENTS_SAFE(var, nxt, list) for ((var) = (list), (nxt) = ((var) ? (var)->next : 0); (var); (var) = (nxt), ((nxt) = (var) ? (var)->next : 0))
static inline void *
diff --git a/include/grub/machoload.h b/include/grub/machoload.h
index 1eec118f1..f1157f410 100644
--- a/include/grub/machoload.h
+++ b/include/grub/machoload.h
@@ -49,7 +49,8 @@ struct grub_macho_file
};
typedef struct grub_macho_file *grub_macho_t;
-grub_macho_t grub_macho_open (const char *, int is_64bit);
+grub_macho_t grub_macho_open (const char *, enum grub_file_type type,
+ int is_64bit);
grub_macho_t grub_macho_file (grub_file_t file, const char *filename,
int is_64bit);
grub_err_t grub_macho_close (grub_macho_t);
diff --git a/include/grub/slaunch.h b/include/grub/slaunch.h
new file mode 100644
index 000000000..9d10926a1
--- /dev/null
+++ b/include/grub/slaunch.h
@@ -0,0 +1,60 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ *
+ * Main secure launch definitions header file.
+ */
+
+#ifndef GRUB_SLAUNCH_H
+#define GRUB_SLAUNCH_H 1
+
+#include
+#include
+
+#define GRUB_SL_BOOTPARAMS_OFFSET 0x12c
+
+struct grub_slaunch_info
+{
+ grub_uint32_t sl_version;
+ grub_uint32_t sl_entry; /* Field updated by boot build tool */
+ grub_uint32_t sl_mle_hdr; /* Field updated by boot build tool */
+ grub_uint32_t sl_flags;
+ grub_uint32_t sl_dev_map;
+} GRUB_PACKED;
+
+struct grub_slaunch_params
+{
+ struct linux_kernel_params *params;
+ grub_addr_t real_mode_target;
+ grub_addr_t prot_mode_target;
+};
+
+struct grub_slaunch_module
+{
+ struct grub_slaunch_module *next;
+ grub_uint8_t *addr;
+ grub_addr_t target;
+ grub_size_t size;
+};
+
+struct grub_slaunch_module *grub_slaunch_get_modules (void);
+
+grub_err_t grub_slaunch_boot_txt (struct grub_slaunch_params *slparams);
+grub_err_t grub_slaunch_boot_skinit (struct grub_slaunch_params *slparams);
+
+void grub_linux_slaunch_set (grub_err_t (*sfunc) (struct grub_slaunch_params*));
+
+#endif
diff --git a/include/grub/tis.h b/include/grub/tis.h
new file mode 100644
index 000000000..d25548ef1
--- /dev/null
+++ b/include/grub/tis.h
@@ -0,0 +1,156 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (c) 2018 Daniel P. Smith, Apertus Solutions, LLC
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ *
+ * The definitions in this header are extracted from the Trusted Computing
+ * Group's "TPM Main Specification", Parts 1-3.
+ */
+
+#ifndef GRUB_TIS_H
+#define GRUB_TIS_H 1
+
+#include
+
+/* Section 2.2.3 */
+#define TPM_AUTH_DATA_USAGE grub_uint8_t
+#define TPM_PAYLOAD_TYPE grub_uint8_t
+#define TPM_VERSION_BYTE grub_uint8_t
+#define TPM_TAG grub_uint16_t
+#define TPM_PROTOCOL_ID grub_uint16_t
+#define TPM_STARTUP_TYPE grub_uint16_t
+#define TPM_ENC_SCHEME grub_uint16_t
+#define TPM_SIG_SCHEME grub_uint16_t
+#define TPM_MIGRATE_SCHEME grub_uint16_t
+#define TPM_PHYSICAL_PRESENCE grub_uint16_t
+#define TPM_ENTITY_TYPE grub_uint16_t
+#define TPM_KEY_USAGE grub_uint16_t
+#define TPM_EK_TYPE grub_uint16_t
+#define TPM_STRUCTURE_TAG grub_uint16_t
+#define TPM_PLATFORM_SPECIFIC grub_uint16_t
+#define TPM_COMMAND_CODE grub_uint32_t
+#define TPM_CAPABILITY_AREA grub_uint32_t
+#define TPM_KEY_FLAGS grub_uint32_t
+#define TPM_ALGORITHM_ID grub_uint32_t
+#define TPM_MODIFIER_INDICATOR grub_uint32_t
+#define TPM_ACTUAL_COUNT grub_uint32_t
+#define TPM_TRANSPORT_ATTRIBUTES grub_uint32_t
+#define TPM_AUTHHANDLE grub_uint32_t
+#define TPM_DIRINDEX grub_uint32_t
+#define TPM_KEY_HANDLE grub_uint32_t
+#define TPM_PCRINDEX grub_uint32_t
+#define TPM_RESULT grub_uint32_t
+#define TPM_RESOURCE_TYPE grub_uint32_t
+#define TPM_KEY_CONTROL grub_uint32_t
+#define TPM_NV_INDEX grub_uint32_t The
+#define TPM_FAMILY_ID grub_uint32_t
+#define TPM_FAMILY_VERIFICATION grub_uint32_t
+#define TPM_STARTUP_EFFECTS grub_uint32_t
+#define TPM_SYM_MODE grub_uint32_t
+#define TPM_FAMILY_FLAGS grub_uint32_t
+#define TPM_DELEGATE_INDEX grub_uint32_t
+#define TPM_CMK_DELEGATE grub_uint32_t
+#define TPM_COUNT_ID grub_uint32_t
+#define TPM_REDIT_COMMAND grub_uint32_t
+#define TPM_TRANSHANDLE grub_uint32_t
+#define TPM_HANDLE grub_uint32_t
+#define TPM_FAMILY_OPERATION grub_uint32_t
+
+/* Section 6 */
+#define TPM_TAG_RQU_COMMAND 0x00C1
+#define TPM_TAG_RQU_AUTH1_COMMAND 0x00C2
+#define TPM_TAG_RQU_AUTH2_COMMAND 0x00C3
+#define TPM_TAG_RSP_COMMAND 0x00C4
+#define TPM_TAG_RSP_AUTH1_COMMAND 0x00C5
+#define TPM_TAG_RSP_AUTH2_COMMAND 0x00C6
+
+/* Section 16 */
+#define TPM_SUCCESS 0x0
+
+/* Section 17 */
+#define TPM_ORD_EXTEND 0x00000014
+
+#define SHA1_DIGEST_SIZE 20
+
+/* Section 5.4 */
+struct grub_tpm_sha1_digest
+{
+ grub_uint8_t digest[SHA1_DIGEST_SIZE];
+};
+
+struct grub_tpm_digest
+{
+ TPM_PCRINDEX pcr;
+ union
+ {
+ struct grub_tpm_sha1_digest sha1;
+ } digest;
+};
+
+#define TPM_DIGEST struct grub_tpm_digest
+#define TPM_CHOSENID_HASH TPM_DIGEST
+#define TPM_COMPOSITE_HASH TPM_DIGEST
+#define TPM_DIRVALUE TPM_DIGEST
+#define TPM_HMAC TPM_DIGEST
+#define TPM_PCRVALUE TPM_DIGEST
+#define TPM_AUDITDIGEST TPM_DIGEST
+#define TPM_DAA_TPM_SEED TPM_DIGEST
+#define TPM_DAA_CONTEXT_SEED TPM_DIGEST
+
+struct grub_tpm_extend_cmd
+{
+ TPM_COMMAND_CODE ordinal;
+ TPM_PCRINDEX pcr_num;
+ TPM_DIGEST digest;
+};
+
+struct grub_tpm_extend_resp
+{
+ TPM_COMMAND_CODE ordinal;
+ TPM_PCRVALUE digest;
+};
+
+struct grub_tpm_cmd_buf
+{
+ TPM_TAG tag;
+ grub_uint32_t size;
+ TPM_RESULT result;
+ union
+ {
+ struct grub_tpm_extend_cmd extend;
+ } cmd;
+};
+
+struct grub_tpm_resp_buf
+{
+ TPM_TAG tag;
+ grub_uint32_t size;
+ TPM_RESULT result;
+ union
+ {
+ struct grub_tpm_extend_resp extend;
+ } resp;
+};
+
+/* TPM Interface Specification functions */
+grub_uint8_t EXPORT_FUNC(grub_tis_request_locality) (grub_uint8_t l);
+grub_uint8_t EXPORT_FUNC(grub_tis_init) (void);
+grub_size_t EXPORT_FUNC(grub_tis_send) (struct grub_tpm_cmd_buf *buf);
+grub_size_t EXPORT_FUNC(grub_tis_recv) (struct grub_tpm_resp_buf *buf);
+
+/* TPM Commands */
+grub_uint8_t EXPORT_FUNC(grub_tpm_pcr_extend) (struct grub_tpm_digest *d);
+
+#endif
diff --git a/include/grub/verify.h b/include/grub/verify.h
new file mode 100644
index 000000000..79022b422
--- /dev/null
+++ b/include/grub/verify.h
@@ -0,0 +1,78 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2017 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+#include
+
+enum grub_verify_flags
+ {
+ GRUB_VERIFY_FLAGS_SKIP_VERIFICATION = 1,
+ GRUB_VERIFY_FLAGS_SINGLE_CHUNK = 2,
+ /* Defer verification to another authority. */
+ GRUB_VERIFY_FLAGS_DEFER_AUTH = 4
+ };
+
+enum grub_verify_string_type
+ {
+ GRUB_VERIFY_KERNEL_CMDLINE,
+ GRUB_VERIFY_MODULE_CMDLINE,
+ };
+
+struct grub_file_verifier
+{
+ struct grub_file_verifier *next;
+ struct grub_file_verifier **prev;
+
+ const char *name;
+
+ /*
+ * Check if file needs to be verified and set up context.
+ * init/read/fini is structured in the same way as hash interface.
+ */
+ grub_err_t (*init) (grub_file_t io, enum grub_file_type type,
+ void **context, enum grub_verify_flags *flags);
+
+ /*
+ * Right now we pass the whole file in one call but it may
+ * change in the future. If you insist on single buffer you
+ * need to set GRUB_VERIFY_FLAGS_SINGLE_CHUNK in verify_flags.
+ */
+ grub_err_t (*write) (void *context, void *buf, grub_size_t size);
+
+ grub_err_t (*fini) (void *context);
+ void (*close) (void *context);
+
+ grub_err_t (*verify_string) (char *str, enum grub_verify_string_type type);
+};
+
+extern struct grub_file_verifier *grub_file_verifiers;
+
+static inline void
+grub_verifier_register (struct grub_file_verifier *ver)
+{
+ grub_list_push (GRUB_AS_LIST_P (&grub_file_verifiers), GRUB_AS_LIST (ver));
+}
+
+static inline void
+grub_verifier_unregister (struct grub_file_verifier *ver)
+{
+ grub_list_remove (GRUB_AS_LIST (ver));
+}
+
+grub_err_t
+grub_verify_string (char *str, enum grub_verify_string_type type);
diff --git a/util/grub-fstest.c b/util/grub-fstest.c
index a358ae471..7074e8e41 100644
--- a/util/grub-fstest.c
+++ b/util/grub-fstest.c
@@ -120,9 +120,9 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len, void
return;
}
- if (uncompress == 0)
- grub_file_filter_disable_compression ();
- file = grub_file_open (pathname);
+ file = grub_file_open (pathname, ((uncompress == 0)
+ ? GRUB_FILE_TYPE_NO_DECOMPRESS : GRUB_FILE_TYPE_NONE)
+ | GRUB_FILE_TYPE_FSTEST);
if (!file)
{
grub_util_error (_("cannot open `%s': %s"), pathname,
diff --git a/util/grub-mount.c b/util/grub-mount.c
index a25db8a71..e32b502e7 100644
--- a/util/grub-mount.c
+++ b/util/grub-mount.c
@@ -208,7 +208,7 @@ fuse_getattr (const char *path, struct stat *st)
if (!ctx.file_info.dir)
{
grub_file_t file;
- file = grub_file_open (path);
+ file = grub_file_open (path, GRUB_FILE_TYPE_GET_SIZE);
if (! file && grub_errno == GRUB_ERR_BAD_FILE_TYPE)
{
grub_errno = GRUB_ERR_NONE;
@@ -244,7 +244,7 @@ static int
fuse_open (const char *path, struct fuse_file_info *fi __attribute__ ((unused)))
{
grub_file_t file;
- file = grub_file_open (path);
+ file = grub_file_open (path, GRUB_FILE_TYPE_MOUNT);
if (! file)
return translate_error ();
files[first_fd++] = file;
@@ -308,7 +308,7 @@ fuse_readdir_call_fill (const char *filename,
grub_file_t file;
char *tmp;
tmp = xasprintf ("%s/%s", ctx->path, filename);
- file = grub_file_open (tmp);
+ file = grub_file_open (tmp, GRUB_FILE_TYPE_GET_SIZE);
free (tmp);
/* Symlink to directory. */
if (! file && grub_errno == GRUB_ERR_BAD_FILE_TYPE)