Merge branch 'x86-txt-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-txt-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: x86, intel_txt: clean up the impact on generic code, unbreak non-x86 x86, intel_txt: Handle ACPI_SLEEP without X86_TRAMPOLINE x86, intel_txt: Fix typos in Kconfig help x86, intel_txt: Factor out the code for S3 setup x86, intel_txt: tboot.c needs <asm/fixmap.h> intel_txt: Force IOMMU on for Intel TXT launch x86, intel_txt: Intel TXT Sx shutdown support x86, intel_txt: Intel TXT reboot/halt shutdown support x86, intel_txt: Intel TXT boot support
This commit is contained in:
commit
1aaf2e5913
|
@ -0,0 +1,210 @@
|
|||
Intel(R) TXT Overview:
|
||||
=====================
|
||||
|
||||
Intel's technology for safer computing, Intel(R) Trusted Execution
|
||||
Technology (Intel(R) TXT), defines platform-level enhancements that
|
||||
provide the building blocks for creating trusted platforms.
|
||||
|
||||
Intel TXT was formerly known by the code name LaGrande Technology (LT).
|
||||
|
||||
Intel TXT in Brief:
|
||||
o Provides dynamic root of trust for measurement (DRTM)
|
||||
o Data protection in case of improper shutdown
|
||||
o Measurement and verification of launched environment
|
||||
|
||||
Intel TXT is part of the vPro(TM) brand and is also available some
|
||||
non-vPro systems. It is currently available on desktop systems
|
||||
based on the Q35, X38, Q45, and Q43 Express chipsets (e.g. Dell
|
||||
Optiplex 755, HP dc7800, etc.) and mobile systems based on the GM45,
|
||||
PM45, and GS45 Express chipsets.
|
||||
|
||||
For more information, see http://www.intel.com/technology/security/.
|
||||
This site also has a link to the Intel TXT MLE Developers Manual,
|
||||
which has been updated for the new released platforms.
|
||||
|
||||
Intel TXT has been presented at various events over the past few
|
||||
years, some of which are:
|
||||
LinuxTAG 2008:
|
||||
http://www.linuxtag.org/2008/en/conf/events/vp-donnerstag/
|
||||
details.html?talkid=110
|
||||
TRUST2008:
|
||||
http://www.trust2008.eu/downloads/Keynote-Speakers/
|
||||
3_David-Grawrock_The-Front-Door-of-Trusted-Computing.pdf
|
||||
IDF 2008, Shanghai:
|
||||
http://inteldeveloperforum.com.edgesuite.net/shanghai_2008/
|
||||
aep/PROS003/index.html
|
||||
IDFs 2006, 2007 (I'm not sure if/where they are online)
|
||||
|
||||
Trusted Boot Project Overview:
|
||||
=============================
|
||||
|
||||
Trusted Boot (tboot) is an open source, pre- kernel/VMM module that
|
||||
uses Intel TXT to perform a measured and verified launch of an OS
|
||||
kernel/VMM.
|
||||
|
||||
It is hosted on SourceForge at http://sourceforge.net/projects/tboot.
|
||||
The mercurial source repo is available at http://www.bughost.org/
|
||||
repos.hg/tboot.hg.
|
||||
|
||||
Tboot currently supports launching Xen (open source VMM/hypervisor
|
||||
w/ TXT support since v3.2), and now Linux kernels.
|
||||
|
||||
|
||||
Value Proposition for Linux or "Why should you care?"
|
||||
=====================================================
|
||||
|
||||
While there are many products and technologies that attempt to
|
||||
measure or protect the integrity of a running kernel, they all
|
||||
assume the kernel is "good" to begin with. The Integrity
|
||||
Measurement Architecture (IMA) and Linux Integrity Module interface
|
||||
are examples of such solutions.
|
||||
|
||||
To get trust in the initial kernel without using Intel TXT, a
|
||||
static root of trust must be used. This bases trust in BIOS
|
||||
starting at system reset and requires measurement of all code
|
||||
executed between system reset through the completion of the kernel
|
||||
boot as well as data objects used by that code. In the case of a
|
||||
Linux kernel, this means all of BIOS, any option ROMs, the
|
||||
bootloader and the boot config. In practice, this is a lot of
|
||||
code/data, much of which is subject to change from boot to boot
|
||||
(e.g. changing NICs may change option ROMs). Without reference
|
||||
hashes, these measurement changes are difficult to assess or
|
||||
confirm as benign. This process also does not provide DMA
|
||||
protection, memory configuration/alias checks and locks, crash
|
||||
protection, or policy support.
|
||||
|
||||
By using the hardware-based root of trust that Intel TXT provides,
|
||||
many of these issues can be mitigated. Specifically: many
|
||||
pre-launch components can be removed from the trust chain, DMA
|
||||
protection is provided to all launched components, a large number
|
||||
of platform configuration checks are performed and values locked,
|
||||
protection is provided for any data in the event of an improper
|
||||
shutdown, and there is support for policy-based execution/verification.
|
||||
This provides a more stable measurement and a higher assurance of
|
||||
system configuration and initial state than would be otherwise
|
||||
possible. Since the tboot project is open source, source code for
|
||||
almost all parts of the trust chain is available (excepting SMM and
|
||||
Intel-provided firmware).
|
||||
|
||||
How Does it Work?
|
||||
=================
|
||||
|
||||
o Tboot is an executable that is launched by the bootloader as
|
||||
the "kernel" (the binary the bootloader executes).
|
||||
o It performs all of the work necessary to determine if the
|
||||
platform supports Intel TXT and, if so, executes the GETSEC[SENTER]
|
||||
processor instruction that initiates the dynamic root of trust.
|
||||
- If tboot determines that the system does not support Intel TXT
|
||||
or is not configured correctly (e.g. the SINIT AC Module was
|
||||
incorrect), it will directly launch the kernel with no changes
|
||||
to any state.
|
||||
- Tboot will output various information about its progress to the
|
||||
terminal, serial port, and/or an in-memory log; the output
|
||||
locations can be configured with a command line switch.
|
||||
o The GETSEC[SENTER] instruction will return control to tboot and
|
||||
tboot then verifies certain aspects of the environment (e.g. TPM NV
|
||||
lock, e820 table does not have invalid entries, etc.).
|
||||
o It will wake the APs from the special sleep state the GETSEC[SENTER]
|
||||
instruction had put them in and place them into a wait-for-SIPI
|
||||
state.
|
||||
- Because the processors will not respond to an INIT or SIPI when
|
||||
in the TXT environment, it is necessary to create a small VT-x
|
||||
guest for the APs. When they run in this guest, they will
|
||||
simply wait for the INIT-SIPI-SIPI sequence, which will cause
|
||||
VMEXITs, and then disable VT and jump to the SIPI vector. This
|
||||
approach seemed like a better choice than having to insert
|
||||
special code into the kernel's MP wakeup sequence.
|
||||
o Tboot then applies an (optional) user-defined launch policy to
|
||||
verify the kernel and initrd.
|
||||
- This policy is rooted in TPM NV and is described in the tboot
|
||||
project. The tboot project also contains code for tools to
|
||||
create and provision the policy.
|
||||
- Policies are completely under user control and if not present
|
||||
then any kernel will be launched.
|
||||
- Policy action is flexible and can include halting on failures
|
||||
or simply logging them and continuing.
|
||||
o Tboot adjusts the e820 table provided by the bootloader to reserve
|
||||
its own location in memory as well as to reserve certain other
|
||||
TXT-related regions.
|
||||
o As part of it's launch, tboot DMA protects all of RAM (using the
|
||||
VT-d PMRs). Thus, the kernel must be booted with 'intel_iommu=on'
|
||||
in order to remove this blanket protection and use VT-d's
|
||||
page-level protection.
|
||||
o Tboot will populate a shared page with some data about itself and
|
||||
pass this to the Linux kernel as it transfers control.
|
||||
- The location of the shared page is passed via the boot_params
|
||||
struct as a physical address.
|
||||
o The kernel will look for the tboot shared page address and, if it
|
||||
exists, map it.
|
||||
o As one of the checks/protections provided by TXT, it makes a copy
|
||||
of the VT-d DMARs in a DMA-protected region of memory and verifies
|
||||
them for correctness. The VT-d code will detect if the kernel was
|
||||
launched with tboot and use this copy instead of the one in the
|
||||
ACPI table.
|
||||
o At this point, tboot and TXT are out of the picture until a
|
||||
shutdown (S<n>)
|
||||
o In order to put a system into any of the sleep states after a TXT
|
||||
launch, TXT must first be exited. This is to prevent attacks that
|
||||
attempt to crash the system to gain control on reboot and steal
|
||||
data left in memory.
|
||||
- The kernel will perform all of its sleep preparation and
|
||||
populate the shared page with the ACPI data needed to put the
|
||||
platform in the desired sleep state.
|
||||
- Then the kernel jumps into tboot via the vector specified in the
|
||||
shared page.
|
||||
- Tboot will clean up the environment and disable TXT, then use the
|
||||
kernel-provided ACPI information to actually place the platform
|
||||
into the desired sleep state.
|
||||
- In the case of S3, tboot will also register itself as the resume
|
||||
vector. This is necessary because it must re-establish the
|
||||
measured environment upon resume. Once the TXT environment
|
||||
has been restored, it will restore the TPM PCRs and then
|
||||
transfer control back to the kernel's S3 resume vector.
|
||||
In order to preserve system integrity across S3, the kernel
|
||||
provides tboot with a set of memory ranges (kernel
|
||||
code/data/bss, S3 resume code, and AP trampoline) that tboot
|
||||
will calculate a MAC (message authentication code) over and then
|
||||
seal with the TPM. On resume and once the measured environment
|
||||
has been re-established, tboot will re-calculate the MAC and
|
||||
verify it against the sealed value. Tboot's policy determines
|
||||
what happens if the verification fails.
|
||||
|
||||
That's pretty much it for TXT support.
|
||||
|
||||
|
||||
Configuring the System:
|
||||
======================
|
||||
|
||||
This code works with 32bit, 32bit PAE, and 64bit (x86_64) kernels.
|
||||
|
||||
In BIOS, the user must enable: TPM, TXT, VT-x, VT-d. Not all BIOSes
|
||||
allow these to be individually enabled/disabled and the screens in
|
||||
which to find them are BIOS-specific.
|
||||
|
||||
grub.conf needs to be modified as follows:
|
||||
title Linux 2.6.29-tip w/ tboot
|
||||
root (hd0,0)
|
||||
kernel /tboot.gz logging=serial,vga,memory
|
||||
module /vmlinuz-2.6.29-tip intel_iommu=on ro
|
||||
root=LABEL=/ rhgb console=ttyS0,115200 3
|
||||
module /initrd-2.6.29-tip.img
|
||||
module /Q35_SINIT_17.BIN
|
||||
|
||||
The kernel option for enabling Intel TXT support is found under the
|
||||
Security top-level menu and is called "Enable Intel(R) Trusted
|
||||
Execution Technology (TXT)". It is marked as EXPERIMENTAL and
|
||||
depends on the generic x86 support (to allow maximum flexibility in
|
||||
kernel build options), since the tboot code will detect whether the
|
||||
platform actually supports Intel TXT and thus whether any of the
|
||||
kernel code is executed.
|
||||
|
||||
The Q35_SINIT_17.BIN file is what Intel TXT refers to as an
|
||||
Authenticated Code Module. It is specific to the chipset in the
|
||||
system and can also be found on the Trusted Boot site. It is an
|
||||
(unencrypted) module signed by Intel that is used as part of the
|
||||
DRTM process to verify and configure the system. It is signed
|
||||
because it operates at a higher privilege level in the system than
|
||||
any other macrocode and its correct operation is critical to the
|
||||
establishment of the DRTM. The process for determining the correct
|
||||
SINIT ACM for a system is documented in the SINIT-guide.txt file
|
||||
that is on the tboot SourceForge site under the SINIT ACM downloads.
|
|
@ -12,6 +12,7 @@ Offset Proto Name Meaning
|
|||
000/040 ALL screen_info Text mode or frame buffer information
|
||||
(struct screen_info)
|
||||
040/014 ALL apm_bios_info APM BIOS information (struct apm_bios_info)
|
||||
058/008 ALL tboot_addr Physical address of tboot shared page
|
||||
060/010 ALL ist_info Intel SpeedStep (IST) BIOS support information
|
||||
(struct ist_info)
|
||||
080/010 ALL hd0_info hd0 disk parameter, OBSOLETE!!
|
||||
|
|
|
@ -179,6 +179,10 @@ config ARCH_SUPPORTS_OPTIMIZED_INLINING
|
|||
config ARCH_SUPPORTS_DEBUG_PAGEALLOC
|
||||
def_bool y
|
||||
|
||||
config HAVE_INTEL_TXT
|
||||
def_bool y
|
||||
depends on EXPERIMENTAL && DMAR && ACPI
|
||||
|
||||
# Use the generic interrupt handling code in kernel/irq/:
|
||||
config GENERIC_HARDIRQS
|
||||
bool
|
||||
|
|
|
@ -85,7 +85,8 @@ struct efi_info {
|
|||
struct boot_params {
|
||||
struct screen_info screen_info; /* 0x000 */
|
||||
struct apm_bios_info apm_bios_info; /* 0x040 */
|
||||
__u8 _pad2[12]; /* 0x054 */
|
||||
__u8 _pad2[4]; /* 0x054 */
|
||||
__u64 tboot_addr; /* 0x058 */
|
||||
struct ist_info ist_info; /* 0x060 */
|
||||
__u8 _pad3[16]; /* 0x070 */
|
||||
__u8 hd0_info[16]; /* obsolete! */ /* 0x080 */
|
||||
|
|
|
@ -131,6 +131,9 @@ enum fixed_addresses {
|
|||
#endif
|
||||
#ifdef CONFIG_X86_32
|
||||
FIX_WP_TEST,
|
||||
#endif
|
||||
#ifdef CONFIG_INTEL_TXT
|
||||
FIX_TBOOT_BASE,
|
||||
#endif
|
||||
__end_of_fixed_addresses
|
||||
};
|
||||
|
|
|
@ -52,6 +52,7 @@ obj-$(CONFIG_X86_DS_SELFTEST) += ds_selftest.o
|
|||
obj-$(CONFIG_X86_32) += tls.o
|
||||
obj-$(CONFIG_IA32_EMULATION) += tls.o
|
||||
obj-y += step.o
|
||||
obj-$(CONFIG_INTEL_TXT) += tboot.o
|
||||
obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
||||
obj-y += cpu/
|
||||
obj-y += acpi/
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <linux/pm.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/tboot.h>
|
||||
#include <acpi/reboot.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/apic.h>
|
||||
|
@ -508,6 +509,8 @@ static void native_machine_emergency_restart(void)
|
|||
if (reboot_emergency)
|
||||
emergency_vmx_disable_all();
|
||||
|
||||
tboot_shutdown(TB_SHUTDOWN_REBOOT);
|
||||
|
||||
/* Tell the BIOS if we want cold or warm reboot */
|
||||
*((unsigned short *)__va(0x472)) = reboot_mode;
|
||||
|
||||
|
@ -634,6 +637,8 @@ static void native_machine_halt(void)
|
|||
/* stop other cpus and apics */
|
||||
machine_shutdown();
|
||||
|
||||
tboot_shutdown(TB_SHUTDOWN_HALT);
|
||||
|
||||
/* stop this cpu */
|
||||
stop_this_cpu(NULL);
|
||||
}
|
||||
|
@ -645,6 +650,8 @@ static void native_machine_power_off(void)
|
|||
machine_shutdown();
|
||||
pm_power_off();
|
||||
}
|
||||
/* a fallback in case there is no PM info available */
|
||||
tboot_shutdown(TB_SHUTDOWN_HALT);
|
||||
}
|
||||
|
||||
struct machine_ops machine_ops = {
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/crash_dump.h>
|
||||
#include <linux/tboot.h>
|
||||
|
||||
#include <video/edid.h>
|
||||
|
||||
|
@ -977,6 +978,8 @@ void __init setup_arch(char **cmdline_p)
|
|||
paravirt_pagetable_setup_done(swapper_pg_dir);
|
||||
paravirt_post_allocator_init();
|
||||
|
||||
tboot_probe();
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
map_vsyscall();
|
||||
#endif
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include <linux/bootmem.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/nmi.h>
|
||||
#include <linux/tboot.h>
|
||||
|
||||
#include <asm/acpi.h>
|
||||
#include <asm/desc.h>
|
||||
|
@ -1318,6 +1319,7 @@ void play_dead_common(void)
|
|||
void native_play_dead(void)
|
||||
{
|
||||
play_dead_common();
|
||||
tboot_shutdown(TB_SHUTDOWN_WFS);
|
||||
wbinvd_halt();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,447 @@
|
|||
/*
|
||||
* tboot.c: main implementation of helper functions used by kernel for
|
||||
* runtime support of Intel(R) Trusted Execution Technology
|
||||
*
|
||||
* Copyright (c) 2006-2009, Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/dma_remapping.h>
|
||||
#include <linux/init_task.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/dmar.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/pfn.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/tboot.h>
|
||||
|
||||
#include <asm/trampoline.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/bootparam.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/fixmap.h>
|
||||
#include <asm/proto.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/e820.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "acpi/realmode/wakeup.h"
|
||||
|
||||
/* Global pointer to shared data; NULL means no measured launch. */
|
||||
struct tboot *tboot __read_mostly;
|
||||
|
||||
/* timeout for APs (in secs) to enter wait-for-SIPI state during shutdown */
|
||||
#define AP_WAIT_TIMEOUT 1
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "tboot: " fmt
|
||||
|
||||
static u8 tboot_uuid[16] __initdata = TBOOT_UUID;
|
||||
|
||||
void __init tboot_probe(void)
|
||||
{
|
||||
/* Look for valid page-aligned address for shared page. */
|
||||
if (!boot_params.tboot_addr)
|
||||
return;
|
||||
/*
|
||||
* also verify that it is mapped as we expect it before calling
|
||||
* set_fixmap(), to reduce chance of garbage value causing crash
|
||||
*/
|
||||
if (!e820_any_mapped(boot_params.tboot_addr,
|
||||
boot_params.tboot_addr, E820_RESERVED)) {
|
||||
pr_warning("non-0 tboot_addr but it is not of type E820_RESERVED\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* only a natively booted kernel should be using TXT */
|
||||
if (paravirt_enabled()) {
|
||||
pr_warning("non-0 tboot_addr but pv_ops is enabled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Map and check for tboot UUID. */
|
||||
set_fixmap(FIX_TBOOT_BASE, boot_params.tboot_addr);
|
||||
tboot = (struct tboot *)fix_to_virt(FIX_TBOOT_BASE);
|
||||
if (memcmp(&tboot_uuid, &tboot->uuid, sizeof(tboot->uuid))) {
|
||||
pr_warning("tboot at 0x%llx is invalid\n",
|
||||
boot_params.tboot_addr);
|
||||
tboot = NULL;
|
||||
return;
|
||||
}
|
||||
if (tboot->version < 5) {
|
||||
pr_warning("tboot version is invalid: %u\n", tboot->version);
|
||||
tboot = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
pr_info("found shared page at phys addr 0x%llx:\n",
|
||||
boot_params.tboot_addr);
|
||||
pr_debug("version: %d\n", tboot->version);
|
||||
pr_debug("log_addr: 0x%08x\n", tboot->log_addr);
|
||||
pr_debug("shutdown_entry: 0x%x\n", tboot->shutdown_entry);
|
||||
pr_debug("tboot_base: 0x%08x\n", tboot->tboot_base);
|
||||
pr_debug("tboot_size: 0x%x\n", tboot->tboot_size);
|
||||
}
|
||||
|
||||
static pgd_t *tboot_pg_dir;
|
||||
static struct mm_struct tboot_mm = {
|
||||
.mm_rb = RB_ROOT,
|
||||
.pgd = swapper_pg_dir,
|
||||
.mm_users = ATOMIC_INIT(2),
|
||||
.mm_count = ATOMIC_INIT(1),
|
||||
.mmap_sem = __RWSEM_INITIALIZER(init_mm.mmap_sem),
|
||||
.page_table_lock = __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock),
|
||||
.mmlist = LIST_HEAD_INIT(init_mm.mmlist),
|
||||
.cpu_vm_mask = CPU_MASK_ALL,
|
||||
};
|
||||
|
||||
static inline void switch_to_tboot_pt(void)
|
||||
{
|
||||
write_cr3(virt_to_phys(tboot_pg_dir));
|
||||
}
|
||||
|
||||
static int map_tboot_page(unsigned long vaddr, unsigned long pfn,
|
||||
pgprot_t prot)
|
||||
{
|
||||
pgd_t *pgd;
|
||||
pud_t *pud;
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
|
||||
pgd = pgd_offset(&tboot_mm, vaddr);
|
||||
pud = pud_alloc(&tboot_mm, pgd, vaddr);
|
||||
if (!pud)
|
||||
return -1;
|
||||
pmd = pmd_alloc(&tboot_mm, pud, vaddr);
|
||||
if (!pmd)
|
||||
return -1;
|
||||
pte = pte_alloc_map(&tboot_mm, pmd, vaddr);
|
||||
if (!pte)
|
||||
return -1;
|
||||
set_pte_at(&tboot_mm, vaddr, pte, pfn_pte(pfn, prot));
|
||||
pte_unmap(pte);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int map_tboot_pages(unsigned long vaddr, unsigned long start_pfn,
|
||||
unsigned long nr)
|
||||
{
|
||||
/* Reuse the original kernel mapping */
|
||||
tboot_pg_dir = pgd_alloc(&tboot_mm);
|
||||
if (!tboot_pg_dir)
|
||||
return -1;
|
||||
|
||||
for (; nr > 0; nr--, vaddr += PAGE_SIZE, start_pfn++) {
|
||||
if (map_tboot_page(vaddr, start_pfn, PAGE_KERNEL_EXEC))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tboot_create_trampoline(void)
|
||||
{
|
||||
u32 map_base, map_size;
|
||||
|
||||
/* Create identity map for tboot shutdown code. */
|
||||
map_base = PFN_DOWN(tboot->tboot_base);
|
||||
map_size = PFN_UP(tboot->tboot_size);
|
||||
if (map_tboot_pages(map_base << PAGE_SHIFT, map_base, map_size))
|
||||
panic("tboot: Error mapping tboot pages (mfns) @ 0x%x, 0x%x\n",
|
||||
map_base, map_size);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI_SLEEP
|
||||
|
||||
static void add_mac_region(phys_addr_t start, unsigned long size)
|
||||
{
|
||||
struct tboot_mac_region *mr;
|
||||
phys_addr_t end = start + size;
|
||||
|
||||
if (start && size) {
|
||||
mr = &tboot->mac_regions[tboot->num_mac_regions++];
|
||||
mr->start = round_down(start, PAGE_SIZE);
|
||||
mr->size = round_up(end, PAGE_SIZE) - mr->start;
|
||||
}
|
||||
}
|
||||
|
||||
static int tboot_setup_sleep(void)
|
||||
{
|
||||
tboot->num_mac_regions = 0;
|
||||
|
||||
/* S3 resume code */
|
||||
add_mac_region(acpi_wakeup_address, WAKEUP_SIZE);
|
||||
|
||||
#ifdef CONFIG_X86_TRAMPOLINE
|
||||
/* AP trampoline code */
|
||||
add_mac_region(virt_to_phys(trampoline_base), TRAMPOLINE_SIZE);
|
||||
#endif
|
||||
|
||||
/* kernel code + data + bss */
|
||||
add_mac_region(virt_to_phys(_text), _end - _text);
|
||||
|
||||
tboot->acpi_sinfo.kernel_s3_resume_vector = acpi_wakeup_address;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* no CONFIG_ACPI_SLEEP */
|
||||
|
||||
static int tboot_setup_sleep(void)
|
||||
{
|
||||
/* S3 shutdown requested, but S3 not supported by the kernel... */
|
||||
BUG();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void tboot_shutdown(u32 shutdown_type)
|
||||
{
|
||||
void (*shutdown)(void);
|
||||
|
||||
if (!tboot_enabled())
|
||||
return;
|
||||
|
||||
/*
|
||||
* if we're being called before the 1:1 mapping is set up then just
|
||||
* return and let the normal shutdown happen; this should only be
|
||||
* due to very early panic()
|
||||
*/
|
||||
if (!tboot_pg_dir)
|
||||
return;
|
||||
|
||||
/* if this is S3 then set regions to MAC */
|
||||
if (shutdown_type == TB_SHUTDOWN_S3)
|
||||
if (tboot_setup_sleep())
|
||||
return;
|
||||
|
||||
tboot->shutdown_type = shutdown_type;
|
||||
|
||||
switch_to_tboot_pt();
|
||||
|
||||
shutdown = (void(*)(void))(unsigned long)tboot->shutdown_entry;
|
||||
shutdown();
|
||||
|
||||
/* should not reach here */
|
||||
while (1)
|
||||
halt();
|
||||
}
|
||||
|
||||
static void tboot_copy_fadt(const struct acpi_table_fadt *fadt)
|
||||
{
|
||||
#define TB_COPY_GAS(tbg, g) \
|
||||
tbg.space_id = g.space_id; \
|
||||
tbg.bit_width = g.bit_width; \
|
||||
tbg.bit_offset = g.bit_offset; \
|
||||
tbg.access_width = g.access_width; \
|
||||
tbg.address = g.address;
|
||||
|
||||
TB_COPY_GAS(tboot->acpi_sinfo.pm1a_cnt_blk, fadt->xpm1a_control_block);
|
||||
TB_COPY_GAS(tboot->acpi_sinfo.pm1b_cnt_blk, fadt->xpm1b_control_block);
|
||||
TB_COPY_GAS(tboot->acpi_sinfo.pm1a_evt_blk, fadt->xpm1a_event_block);
|
||||
TB_COPY_GAS(tboot->acpi_sinfo.pm1b_evt_blk, fadt->xpm1b_event_block);
|
||||
|
||||
/*
|
||||
* We need phys addr of waking vector, but can't use virt_to_phys() on
|
||||
* &acpi_gbl_FACS because it is ioremap'ed, so calc from FACS phys
|
||||
* addr.
|
||||
*/
|
||||
tboot->acpi_sinfo.wakeup_vector = fadt->facs +
|
||||
offsetof(struct acpi_table_facs, firmware_waking_vector);
|
||||
}
|
||||
|
||||
void tboot_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control)
|
||||
{
|
||||
static u32 acpi_shutdown_map[ACPI_S_STATE_COUNT] = {
|
||||
/* S0,1,2: */ -1, -1, -1,
|
||||
/* S3: */ TB_SHUTDOWN_S3,
|
||||
/* S4: */ TB_SHUTDOWN_S4,
|
||||
/* S5: */ TB_SHUTDOWN_S5 };
|
||||
|
||||
if (!tboot_enabled())
|
||||
return;
|
||||
|
||||
tboot_copy_fadt(&acpi_gbl_FADT);
|
||||
tboot->acpi_sinfo.pm1a_cnt_val = pm1a_control;
|
||||
tboot->acpi_sinfo.pm1b_cnt_val = pm1b_control;
|
||||
/* we always use the 32b wakeup vector */
|
||||
tboot->acpi_sinfo.vector_width = 32;
|
||||
|
||||
if (sleep_state >= ACPI_S_STATE_COUNT ||
|
||||
acpi_shutdown_map[sleep_state] == -1) {
|
||||
pr_warning("unsupported sleep state 0x%x\n", sleep_state);
|
||||
return;
|
||||
}
|
||||
|
||||
tboot_shutdown(acpi_shutdown_map[sleep_state]);
|
||||
}
|
||||
|
||||
static atomic_t ap_wfs_count;
|
||||
|
||||
static int tboot_wait_for_aps(int num_aps)
|
||||
{
|
||||
unsigned long timeout;
|
||||
|
||||
timeout = AP_WAIT_TIMEOUT*HZ;
|
||||
while (atomic_read((atomic_t *)&tboot->num_in_wfs) != num_aps &&
|
||||
timeout) {
|
||||
mdelay(1);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
if (timeout)
|
||||
pr_warning("tboot wait for APs timeout\n");
|
||||
|
||||
return !(atomic_read((atomic_t *)&tboot->num_in_wfs) == num_aps);
|
||||
}
|
||||
|
||||
static int __cpuinit tboot_cpu_callback(struct notifier_block *nfb,
|
||||
unsigned long action, void *hcpu)
|
||||
{
|
||||
switch (action) {
|
||||
case CPU_DYING:
|
||||
atomic_inc(&ap_wfs_count);
|
||||
if (num_online_cpus() == 1)
|
||||
if (tboot_wait_for_aps(atomic_read(&ap_wfs_count)))
|
||||
return NOTIFY_BAD;
|
||||
break;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block tboot_cpu_notifier __cpuinitdata =
|
||||
{
|
||||
.notifier_call = tboot_cpu_callback,
|
||||
};
|
||||
|
||||
static __init int tboot_late_init(void)
|
||||
{
|
||||
if (!tboot_enabled())
|
||||
return 0;
|
||||
|
||||
tboot_create_trampoline();
|
||||
|
||||
atomic_set(&ap_wfs_count, 0);
|
||||
register_hotcpu_notifier(&tboot_cpu_notifier);
|
||||
return 0;
|
||||
}
|
||||
|
||||
late_initcall(tboot_late_init);
|
||||
|
||||
/*
|
||||
* TXT configuration registers (offsets from TXT_{PUB, PRIV}_CONFIG_REGS_BASE)
|
||||
*/
|
||||
|
||||
#define TXT_PUB_CONFIG_REGS_BASE 0xfed30000
|
||||
#define TXT_PRIV_CONFIG_REGS_BASE 0xfed20000
|
||||
|
||||
/* # pages for each config regs space - used by fixmap */
|
||||
#define NR_TXT_CONFIG_PAGES ((TXT_PUB_CONFIG_REGS_BASE - \
|
||||
TXT_PRIV_CONFIG_REGS_BASE) >> PAGE_SHIFT)
|
||||
|
||||
/* offsets from pub/priv config space */
|
||||
#define TXTCR_HEAP_BASE 0x0300
|
||||
#define TXTCR_HEAP_SIZE 0x0308
|
||||
|
||||
#define SHA1_SIZE 20
|
||||
|
||||
struct sha1_hash {
|
||||
u8 hash[SHA1_SIZE];
|
||||
};
|
||||
|
||||
struct sinit_mle_data {
|
||||
u32 version; /* currently 6 */
|
||||
struct sha1_hash bios_acm_id;
|
||||
u32 edx_senter_flags;
|
||||
u64 mseg_valid;
|
||||
struct sha1_hash sinit_hash;
|
||||
struct sha1_hash mle_hash;
|
||||
struct sha1_hash stm_hash;
|
||||
struct sha1_hash lcp_policy_hash;
|
||||
u32 lcp_policy_control;
|
||||
u32 rlp_wakeup_addr;
|
||||
u32 reserved;
|
||||
u32 num_mdrs;
|
||||
u32 mdrs_off;
|
||||
u32 num_vtd_dmars;
|
||||
u32 vtd_dmars_off;
|
||||
} __packed;
|
||||
|
||||
struct acpi_table_header *tboot_get_dmar_table(struct acpi_table_header *dmar_tbl)
|
||||
{
|
||||
void *heap_base, *heap_ptr, *config;
|
||||
|
||||
if (!tboot_enabled())
|
||||
return dmar_tbl;
|
||||
|
||||
/*
|
||||
* ACPI tables may not be DMA protected by tboot, so use DMAR copy
|
||||
* SINIT saved in SinitMleData in TXT heap (which is DMA protected)
|
||||
*/
|
||||
|
||||
/* map config space in order to get heap addr */
|
||||
config = ioremap(TXT_PUB_CONFIG_REGS_BASE, NR_TXT_CONFIG_PAGES *
|
||||
PAGE_SIZE);
|
||||
if (!config)
|
||||
return NULL;
|
||||
|
||||
/* now map TXT heap */
|
||||
heap_base = ioremap(*(u64 *)(config + TXTCR_HEAP_BASE),
|
||||
*(u64 *)(config + TXTCR_HEAP_SIZE));
|
||||
iounmap(config);
|
||||
if (!heap_base)
|
||||
return NULL;
|
||||
|
||||
/* walk heap to SinitMleData */
|
||||
/* skip BiosData */
|
||||
heap_ptr = heap_base + *(u64 *)heap_base;
|
||||
/* skip OsMleData */
|
||||
heap_ptr += *(u64 *)heap_ptr;
|
||||
/* skip OsSinitData */
|
||||
heap_ptr += *(u64 *)heap_ptr;
|
||||
/* now points to SinitMleDataSize; set to SinitMleData */
|
||||
heap_ptr += sizeof(u64);
|
||||
/* get addr of DMAR table */
|
||||
dmar_tbl = (struct acpi_table_header *)(heap_ptr +
|
||||
((struct sinit_mle_data *)heap_ptr)->vtd_dmars_off -
|
||||
sizeof(u64));
|
||||
|
||||
/* don't unmap heap because dmar.c needs access to this */
|
||||
|
||||
return dmar_tbl;
|
||||
}
|
||||
|
||||
int tboot_force_iommu(void)
|
||||
{
|
||||
if (!tboot_enabled())
|
||||
return 0;
|
||||
|
||||
if (no_iommu || swiotlb || dmar_disabled)
|
||||
pr_warning("Forcing Intel-IOMMU to enabled\n");
|
||||
|
||||
dmar_disabled = 0;
|
||||
#ifdef CONFIG_SWIOTLB
|
||||
swiotlb = 0;
|
||||
#endif
|
||||
no_iommu = 0;
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -45,6 +45,7 @@
|
|||
#include <acpi/acpi.h>
|
||||
#include "accommon.h"
|
||||
#include "actables.h"
|
||||
#include <linux/tboot.h>
|
||||
|
||||
#define _COMPONENT ACPI_HARDWARE
|
||||
ACPI_MODULE_NAME("hwsleep")
|
||||
|
@ -342,6 +343,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
|
|||
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
|
||||
tboot_sleep(sleep_state, pm1a_control, pm1b_control);
|
||||
|
||||
/* Write #2: Write both SLP_TYP + SLP_EN */
|
||||
|
||||
status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/timer.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/tboot.h>
|
||||
|
||||
#undef PREFIX
|
||||
#define PREFIX "DMAR:"
|
||||
|
@ -413,6 +414,12 @@ parse_dmar_table(void)
|
|||
*/
|
||||
dmar_table_detect();
|
||||
|
||||
/*
|
||||
* ACPI tables may not be DMA protected by tboot, so use DMAR copy
|
||||
* SINIT saved in SinitMleData in TXT heap (which is DMA protected)
|
||||
*/
|
||||
dmar_tbl = tboot_get_dmar_table(dmar_tbl);
|
||||
|
||||
dmar = (struct acpi_table_dmar *)dmar_tbl;
|
||||
if (!dmar)
|
||||
return -ENODEV;
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <linux/iommu.h>
|
||||
#include <linux/intel-iommu.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/tboot.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/iommu.h>
|
||||
#include "pci.h"
|
||||
|
@ -3183,12 +3184,22 @@ static int __init init_iommu_sysfs(void)
|
|||
int __init intel_iommu_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int force_on = 0;
|
||||
|
||||
if (dmar_table_init())
|
||||
return -ENODEV;
|
||||
/* VT-d is required for a TXT/tboot launch, so enforce that */
|
||||
force_on = tboot_force_iommu();
|
||||
|
||||
if (dmar_dev_scope_init())
|
||||
if (dmar_table_init()) {
|
||||
if (force_on)
|
||||
panic("tboot: Failed to initialize DMAR table\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (dmar_dev_scope_init()) {
|
||||
if (force_on)
|
||||
panic("tboot: Failed to initialize DMAR device scope\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the need for DMA-remapping initialization now.
|
||||
|
@ -3204,6 +3215,8 @@ int __init intel_iommu_init(void)
|
|||
|
||||
ret = init_dmars();
|
||||
if (ret) {
|
||||
if (force_on)
|
||||
panic("tboot: Failed to initialize DMARs\n");
|
||||
printk(KERN_ERR "IOMMU: dmar init failed\n");
|
||||
put_iova_domain(&reserved_iova_list);
|
||||
iommu_exit_mempool();
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* tboot.h: shared data structure with tboot and kernel and functions
|
||||
* used by kernel for runtime support of Intel(R) Trusted
|
||||
* Execution Technology
|
||||
*
|
||||
* Copyright (c) 2006-2009, Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_TBOOT_H
|
||||
#define _LINUX_TBOOT_H
|
||||
|
||||
/* these must have the values from 0-5 in this order */
|
||||
enum {
|
||||
TB_SHUTDOWN_REBOOT = 0,
|
||||
TB_SHUTDOWN_S5,
|
||||
TB_SHUTDOWN_S4,
|
||||
TB_SHUTDOWN_S3,
|
||||
TB_SHUTDOWN_HALT,
|
||||
TB_SHUTDOWN_WFS
|
||||
};
|
||||
|
||||
#ifdef CONFIG_INTEL_TXT
|
||||
#include <acpi/acpi.h>
|
||||
/* used to communicate between tboot and the launched kernel */
|
||||
|
||||
#define TB_KEY_SIZE 64 /* 512 bits */
|
||||
|
||||
#define MAX_TB_MAC_REGIONS 32
|
||||
|
||||
struct tboot_mac_region {
|
||||
u64 start; /* must be 64 byte -aligned */
|
||||
u32 size; /* must be 64 byte -granular */
|
||||
} __packed;
|
||||
|
||||
/* GAS - Generic Address Structure (ACPI 2.0+) */
|
||||
struct tboot_acpi_generic_address {
|
||||
u8 space_id;
|
||||
u8 bit_width;
|
||||
u8 bit_offset;
|
||||
u8 access_width;
|
||||
u64 address;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* combines Sx info from FADT and FACS tables per ACPI 2.0+ spec
|
||||
* (http://www.acpi.info/)
|
||||
*/
|
||||
struct tboot_acpi_sleep_info {
|
||||
struct tboot_acpi_generic_address pm1a_cnt_blk;
|
||||
struct tboot_acpi_generic_address pm1b_cnt_blk;
|
||||
struct tboot_acpi_generic_address pm1a_evt_blk;
|
||||
struct tboot_acpi_generic_address pm1b_evt_blk;
|
||||
u16 pm1a_cnt_val;
|
||||
u16 pm1b_cnt_val;
|
||||
u64 wakeup_vector;
|
||||
u32 vector_width;
|
||||
u64 kernel_s3_resume_vector;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* shared memory page used for communication between tboot and kernel
|
||||
*/
|
||||
struct tboot {
|
||||
/*
|
||||
* version 3+ fields:
|
||||
*/
|
||||
|
||||
/* TBOOT_UUID */
|
||||
u8 uuid[16];
|
||||
|
||||
/* version number: 5 is current */
|
||||
u32 version;
|
||||
|
||||
/* physical addr of tb_log_t log */
|
||||
u32 log_addr;
|
||||
|
||||
/*
|
||||
* physical addr of entry point for tboot shutdown and
|
||||
* type of shutdown (TB_SHUTDOWN_*) being requested
|
||||
*/
|
||||
u32 shutdown_entry;
|
||||
u32 shutdown_type;
|
||||
|
||||
/* kernel-specified ACPI info for Sx shutdown */
|
||||
struct tboot_acpi_sleep_info acpi_sinfo;
|
||||
|
||||
/* tboot location in memory (physical) */
|
||||
u32 tboot_base;
|
||||
u32 tboot_size;
|
||||
|
||||
/* memory regions (phys addrs) for tboot to MAC on S3 */
|
||||
u8 num_mac_regions;
|
||||
struct tboot_mac_region mac_regions[MAX_TB_MAC_REGIONS];
|
||||
|
||||
|
||||
/*
|
||||
* version 4+ fields:
|
||||
*/
|
||||
|
||||
/* symmetric key for use by kernel; will be encrypted on S3 */
|
||||
u8 s3_key[TB_KEY_SIZE];
|
||||
|
||||
|
||||
/*
|
||||
* version 5+ fields:
|
||||
*/
|
||||
|
||||
/* used to 4byte-align num_in_wfs */
|
||||
u8 reserved_align[3];
|
||||
|
||||
/* number of processors in wait-for-SIPI */
|
||||
u32 num_in_wfs;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* UUID for tboot data struct to facilitate matching
|
||||
* defined as {663C8DFF-E8B3-4b82-AABF-19EA4D057A08} by tboot, which is
|
||||
* represented as {} in the char array used here
|
||||
*/
|
||||
#define TBOOT_UUID {0xff, 0x8d, 0x3c, 0x66, 0xb3, 0xe8, 0x82, 0x4b, 0xbf,\
|
||||
0xaa, 0x19, 0xea, 0x4d, 0x5, 0x7a, 0x8}
|
||||
|
||||
extern struct tboot *tboot;
|
||||
|
||||
static inline int tboot_enabled(void)
|
||||
{
|
||||
return tboot != NULL;
|
||||
}
|
||||
|
||||
extern void tboot_probe(void);
|
||||
extern void tboot_shutdown(u32 shutdown_type);
|
||||
extern void tboot_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control);
|
||||
extern struct acpi_table_header *tboot_get_dmar_table(
|
||||
struct acpi_table_header *dmar_tbl);
|
||||
extern int tboot_force_iommu(void);
|
||||
|
||||
#else
|
||||
|
||||
#define tboot_probe() do { } while (0)
|
||||
#define tboot_shutdown(shutdown_type) do { } while (0)
|
||||
#define tboot_sleep(sleep_state, pm1a_control, pm1b_control) \
|
||||
do { } while (0)
|
||||
#define tboot_get_dmar_table(dmar_tbl) (dmar_tbl)
|
||||
#define tboot_force_iommu() 0
|
||||
|
||||
#endif /* !CONFIG_INTEL_TXT */
|
||||
|
||||
#endif /* _LINUX_TBOOT_H */
|
|
@ -401,6 +401,7 @@ int disable_nonboot_cpus(void)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
BUG_ON(num_online_cpus() > 1);
|
||||
/* Make sure the CPUs won't be enabled by someone else */
|
||||
|
|
|
@ -113,6 +113,36 @@ config SECURITY_ROOTPLUG
|
|||
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
config INTEL_TXT
|
||||
bool "Enable Intel(R) Trusted Execution Technology (Intel(R) TXT)"
|
||||
depends on HAVE_INTEL_TXT
|
||||
help
|
||||
This option enables support for booting the kernel with the
|
||||
Trusted Boot (tboot) module. This will utilize
|
||||
Intel(R) Trusted Execution Technology to perform a measured launch
|
||||
of the kernel. If the system does not support Intel(R) TXT, this
|
||||
will have no effect.
|
||||
|
||||
Intel TXT will provide higher assurance of system configuration and
|
||||
initial state as well as data reset protection. This is used to
|
||||
create a robust initial kernel measurement and verification, which
|
||||
helps to ensure that kernel security mechanisms are functioning
|
||||
correctly. This level of protection requires a root of trust outside
|
||||
of the kernel itself.
|
||||
|
||||
Intel TXT also helps solve real end user concerns about having
|
||||
confidence that their hardware is running the VMM or kernel that
|
||||
it was configured with, especially since they may be responsible for
|
||||
providing such assurances to VMs and services running on it.
|
||||
|
||||
See <http://www.intel.com/technology/security/> for more information
|
||||
about Intel(R) TXT.
|
||||
See <http://tboot.sourceforge.net> for more information about tboot.
|
||||
See Documentation/intel_txt.txt for a description of how to enable
|
||||
Intel TXT support in a kernel boot.
|
||||
|
||||
If you are unsure as to whether this is required, answer N.
|
||||
|
||||
config LSM_MMAP_MIN_ADDR
|
||||
int "Low address space for LSM to protect from user allocation"
|
||||
depends on SECURITY && SECURITY_SELINUX
|
||||
|
|
Loading…
Reference in New Issue