^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * mokvar-table.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2020 Red Hat
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Lenny Szubowicz <lszubowi@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This module contains the kernel support for the Linux EFI Machine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Owner Key (MOK) variable configuration table, which is identified by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * the LINUX_EFI_MOK_VARIABLE_TABLE_GUID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * This EFI configuration table provides a more robust alternative to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * EFI volatile variables by which an EFI boot loader can pass the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * contents of the Machine Owner Key (MOK) certificate stores to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * kernel during boot. If both the EFI MOK config table and corresponding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * EFI MOK variables are present, the table should be considered as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * more authoritative.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * This module includes code that validates and maps the EFI MOK table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * if it's presence was detected very early in boot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Kernel interface routines are provided to walk through all the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * entries in the MOK config table or to search for a specific named
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * The contents of the individual named MOK config table entries are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * made available to user space via read-only sysfs binary files under:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * /sys/firmware/efi/mok-variables/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define pr_fmt(fmt) "mokvar: " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/capability.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/efi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/kobject.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <asm/early_ioremap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * The LINUX_EFI_MOK_VARIABLE_TABLE_GUID config table is a packed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * sequence of struct efi_mokvar_table_entry, one for each named
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * MOK variable. The sequence is terminated by an entry with a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * completely NULL name and 0 data size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * efi_mokvar_table_size is set to the computed size of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * MOK config table by efi_mokvar_table_init(). This will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * non-zero if and only if the table if present and has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * validated by efi_mokvar_table_init().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static size_t efi_mokvar_table_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * efi_mokvar_table_va is the kernel virtual address at which the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * EFI MOK config table has been mapped by efi_mokvar_sysfs_init().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static struct efi_mokvar_table_entry *efi_mokvar_table_va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * Each /sys/firmware/efi/mok-variables/ sysfs file is represented by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * an instance of struct efi_mokvar_sysfs_attr on efi_mokvar_sysfs_list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * bin_attr.private points to the associated EFI MOK config table entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * This list is created during boot and then remains unchanged.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * So no synchronization is currently required to walk the list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct efi_mokvar_sysfs_attr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct bin_attribute bin_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct list_head node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static LIST_HEAD(efi_mokvar_sysfs_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static struct kobject *mokvar_kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * efi_mokvar_table_init() - Early boot validation of EFI MOK config table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * If present, validate and compute the size of the EFI MOK variable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * configuration table. This table may be provided by an EFI boot loader
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * as an alternative to ordinary EFI variables, due to platform-dependent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * limitations. The memory occupied by this table is marked as reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * This routine must be called before efi_free_boot_services() in order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * to guarantee that it can mark the table as reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * Implicit inputs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * efi.mokvar_table: Physical address of EFI MOK variable config table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * or special value that indicates no such table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * Implicit outputs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * efi_mokvar_table_size: Computed size of EFI MOK variable config table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * The table is considered present and valid if this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * is non-zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) void __init efi_mokvar_table_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) efi_memory_desc_t md;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) void *va = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) unsigned long cur_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) unsigned long offset_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) unsigned long map_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) unsigned long map_size_needed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) unsigned long size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct efi_mokvar_table_entry *mokvar_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!efi_enabled(EFI_MEMMAP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (efi.mokvar_table == EFI_INVALID_TABLE_ADDR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * The EFI MOK config table must fit within a single EFI memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * descriptor range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) err = efi_mem_desc_lookup(efi.mokvar_table, &md);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) pr_warn("EFI MOKvar config table is not within the EFI memory map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) offset_limit = efi_mem_desc_end(&md) - efi.mokvar_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * Validate the MOK config table. Since there is no table header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * from which we could get the total size of the MOK config table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * we compute the total size as we validate each variably sized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * entry, remapping as necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) while (cur_offset + sizeof(*mokvar_entry) <= offset_limit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) mokvar_entry = va + cur_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) map_size_needed = cur_offset + sizeof(*mokvar_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (map_size_needed > map_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (va)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) early_memunmap(va, map_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * Map a little more than the fixed size entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * header, anticipating some data. It's safe to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * do so as long as we stay within current memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * descriptor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) map_size = min(map_size_needed + 2*EFI_PAGE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) offset_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) va = early_memremap(efi.mokvar_table, map_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (!va) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) pr_err("Failed to map EFI MOKvar config table pa=0x%lx, size=%lu.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) efi.mokvar_table, map_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) mokvar_entry = va + cur_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* Check for last sentinel entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (mokvar_entry->name[0] == '\0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (mokvar_entry->data_size != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /* Sanity check that the name is null terminated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) size = strnlen(mokvar_entry->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) sizeof(mokvar_entry->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (size >= sizeof(mokvar_entry->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* Advance to the next entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) cur_offset = map_size_needed + mokvar_entry->data_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (va)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) early_memunmap(va, map_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) pr_err("EFI MOKvar config table is not valid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (md.type == EFI_BOOT_SERVICES_DATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) efi_mem_reserve(efi.mokvar_table, map_size_needed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) efi_mokvar_table_size = map_size_needed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * efi_mokvar_entry_next() - Get next entry in the EFI MOK config table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * mokvar_entry: Pointer to current EFI MOK config table entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * or null. Null indicates get first entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * Passed by reference. This is updated to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * same value as the return value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * Returns: Pointer to next EFI MOK config table entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * or null, if there are no more entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * Same value is returned in the mokvar_entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * This routine depends on the EFI MOK config table being entirely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * mapped with it's starting virtual address in efi_mokvar_table_va.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct efi_mokvar_table_entry *efi_mokvar_entry_next(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct efi_mokvar_table_entry **mokvar_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct efi_mokvar_table_entry *mokvar_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct efi_mokvar_table_entry *mokvar_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) size_t size_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) mokvar_cur = *mokvar_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) *mokvar_entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (efi_mokvar_table_va == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (mokvar_cur == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) mokvar_next = efi_mokvar_table_va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (mokvar_cur->name[0] == '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) size_cur = sizeof(*mokvar_cur) + mokvar_cur->data_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) mokvar_next = (void *)mokvar_cur + size_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (mokvar_next->name[0] == '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) *mokvar_entry = mokvar_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return mokvar_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * efi_mokvar_entry_find() - Find EFI MOK config entry by name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * name: Name of the entry to look for.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * Returns: Pointer to EFI MOK config table entry if found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * null otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * This routine depends on the EFI MOK config table being entirely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * mapped with it's starting virtual address in efi_mokvar_table_va.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct efi_mokvar_table_entry *efi_mokvar_entry_find(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct efi_mokvar_table_entry *mokvar_entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) while (efi_mokvar_entry_next(&mokvar_entry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (!strncmp(name, mokvar_entry->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) sizeof(mokvar_entry->name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return mokvar_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * efi_mokvar_sysfs_read() - sysfs binary file read routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * Returns: Count of bytes read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * Copy EFI MOK config table entry data for this mokvar sysfs binary file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * to the supplied buffer, starting at the specified offset into mokvar table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * entry data, for the specified count bytes. The copy is limited by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * amount of data in this mokvar config table entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static ssize_t efi_mokvar_sysfs_read(struct file *file, struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct bin_attribute *bin_attr, char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) loff_t off, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct efi_mokvar_table_entry *mokvar_entry = bin_attr->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (off >= mokvar_entry->data_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (count > mokvar_entry->data_size - off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) count = mokvar_entry->data_size - off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) memcpy(buf, mokvar_entry->data + off, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * efi_mokvar_sysfs_init() - Map EFI MOK config table and create sysfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * Map the EFI MOK variable config table for run-time use by the kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * and create the sysfs entries in /sys/firmware/efi/mok-variables/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * This routine just returns if a valid EFI MOK variable config table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * was not found earlier during boot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * This routine must be called during a "middle" initcall phase, i.e.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * after efi_mokvar_table_init() but before UEFI certs are loaded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * during late init.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * Implicit inputs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * efi.mokvar_table: Physical address of EFI MOK variable config table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * or special value that indicates no such table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * efi_mokvar_table_size: Computed size of EFI MOK variable config table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * The table is considered present and valid if this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * is non-zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * Implicit outputs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * efi_mokvar_table_va: Start virtual address of the EFI MOK config table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static int __init efi_mokvar_sysfs_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) void *config_va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct efi_mokvar_table_entry *mokvar_entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) struct efi_mokvar_sysfs_attr *mokvar_sysfs = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (efi_mokvar_table_size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) config_va = memremap(efi.mokvar_table, efi_mokvar_table_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) MEMREMAP_WB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (!config_va) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) pr_err("Failed to map EFI MOKvar config table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) efi_mokvar_table_va = config_va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) mokvar_kobj = kobject_create_and_add("mok-variables", efi_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (!mokvar_kobj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) pr_err("Failed to create EFI mok-variables sysfs entry\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) while (efi_mokvar_entry_next(&mokvar_entry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) mokvar_sysfs = kzalloc(sizeof(*mokvar_sysfs), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (!mokvar_sysfs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) sysfs_bin_attr_init(&mokvar_sysfs->bin_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) mokvar_sysfs->bin_attr.private = mokvar_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) mokvar_sysfs->bin_attr.attr.name = mokvar_entry->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) mokvar_sysfs->bin_attr.attr.mode = 0400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) mokvar_sysfs->bin_attr.size = mokvar_entry->data_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) mokvar_sysfs->bin_attr.read = efi_mokvar_sysfs_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) err = sysfs_create_bin_file(mokvar_kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) &mokvar_sysfs->bin_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) list_add_tail(&mokvar_sysfs->node, &efi_mokvar_sysfs_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) pr_err("Failed to create some EFI mok-variables sysfs entries\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) kfree(mokvar_sysfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) device_initcall(efi_mokvar_sysfs_init);