mirror of
				https://git.proxmox.com/git/grub2
				synced 2025-11-04 14:51:07 +00:00 
			
		
		
		
	In order to be able to read from and write to model-specific registers, two new modules are added. They are i386 specific, as the cpuid module. rdmsr module registers the command rdmsr that allows reading from a MSR. wrmsr module registers the command wrmsr that allows writing to a MSR. wrmsr module is disabled if UEFI secure boot is enabled. Please note that on SMP systems, interacting with a MSR that has a scope per hardware thread, implies that the value only applies to the particular cpu/core/thread that ran the command. Also, if you specify a reserved or unimplemented MSR address, it will cause a general protection exception (which is not currently being handled) and the system will reboot. Signed-off-by: Jesús Diéguez Fernández <jesusdf@gmail.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
		
			
				
	
	
		
			143 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 *  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 <http://www.gnu.org/licenses/>.
 | 
						|
 *
 | 
						|
 *  EFI shim lock verifier.
 | 
						|
 */
 | 
						|
 | 
						|
#include <grub/dl.h>
 | 
						|
#include <grub/efi/efi.h>
 | 
						|
#include <grub/err.h>
 | 
						|
#include <grub/file.h>
 | 
						|
#include <grub/misc.h>
 | 
						|
#include <grub/verify.h>
 | 
						|
 | 
						|
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", "wrmsr", 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:
 | 
						|
    case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE:
 | 
						|
      *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);
 | 
						|
}
 |