Commit 5580b4a1 authored by James Morris's avatar James Morris
Browse files

Merge branch 'next-integrity' of...

Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity into next-integrity

From Mimi:

In Linux 4.19, a new LSM hook named security_kernel_load_data was
upstreamed, allowing LSMs and IMA to prevent the kexec_load
syscall.  Different signature verification methods exist for verifying
the kexec'ed kernel image.  This pull request adds additional support
in IMA to prevent loading unsigned kernel images via the kexec_load
syscall, independently of the IMA policy rules, based on the runtime
"secure boot" flag.  An initial IMA kselftest is included.

In addition, this pull request defines a new, separate keyring named
".platform" for storing the preboot/firmware keys needed for verifying
the kexec'ed kernel image's signature and includes the associated IMA
kexec usage of the ".platform" keyring.

(David Howell's and Josh Boyer's patches for reading the
preboot/firmware keys, which were previously posted for a different
use case scenario, are included here.)
parents 8bd8ea19 eed9de3b
Loading
Loading
Loading
Loading
+30 −1
Original line number Diff line number Diff line
@@ -18,10 +18,33 @@ integrity verifications match. A loaded Trusted Key can be updated with new
when the kernel and initramfs are updated.  The same key can have many saved
blobs under different PCR values, so multiple boots are easily supported.

TPM 1.2
-------

By default, trusted keys are sealed under the SRK, which has the default
authorization value (20 zeros).  This can be set at takeownership time with the
trouser's utility: "tpm_takeownership -u -z".

TPM 2.0
-------

The user must first create a storage key and make it persistent, so the key is
available after reboot. This can be done using the following commands.

With the IBM TSS 2 stack::

  #> tsscreateprimary -hi o -st
  Handle 80000000
  #> tssevictcontrol -hi o -ho 80000000 -hp 81000001

Or with the Intel TSS 2 stack::

  #> tpm2_createprimary --hierarchy o -G rsa2048 -o key.ctxt
  [...]
  handle: 0x800000FF
  #> tpm2_evictcontrol -c key.ctxt -p 0x81000001
  persistentHandle: 0x81000001

Usage::

    keyctl add trusted name "new keylen [options]" ring
@@ -30,7 +53,9 @@ Usage::
    keyctl print keyid

    options:
       keyhandle=    ascii hex value of sealing key default 0x40000000 (SRK)
       keyhandle=    ascii hex value of sealing key
                       TPM 1.2: default 0x40000000 (SRK)
                       TPM 2.0: no default; must be passed every time
       keyauth=	     ascii hex auth for sealing key default 0x00...i
                     (40 ascii zeros)
       blobauth=     ascii hex auth for sealed data default 0x00...
@@ -84,6 +109,10 @@ Examples of trusted and encrypted key usage:

Create and save a trusted key named "kmk" of length 32 bytes::

Note: When using a TPM 2.0 with a persistent key with handle 0x81000001,
append 'keyhandle=0x81000001' to statements between quotes, such as
"new 32 keyhandle=0x81000001".

    $ keyctl add trusted kmk "new 32" @u
    440502848

+4 −0
Original line number Diff line number Diff line
@@ -150,3 +150,7 @@ ifeq ($(CONFIG_X86_64),y)
	obj-$(CONFIG_MMCONF_FAM10H)	+= mmconf-fam10h_64.o
	obj-y				+= vsmp_64.o
endif

ifdef CONFIG_EFI
obj-$(CONFIG_IMA)			+= ima_arch.o
endif
+75 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (C) 2018 IBM Corporation
 */
#include <linux/efi.h>
#include <linux/ima.h>

extern struct boot_params boot_params;

static enum efi_secureboot_mode get_sb_mode(void)
{
	efi_char16_t efi_SecureBoot_name[] = L"SecureBoot";
	efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
	efi_status_t status;
	unsigned long size;
	u8 secboot;

	size = sizeof(secboot);

	/* Get variable contents into buffer */
	status = efi.get_variable(efi_SecureBoot_name, &efi_variable_guid,
				  NULL, &size, &secboot);
	if (status == EFI_NOT_FOUND) {
		pr_info("ima: secureboot mode disabled\n");
		return efi_secureboot_mode_disabled;
	}

	if (status != EFI_SUCCESS) {
		pr_info("ima: secureboot mode unknown\n");
		return efi_secureboot_mode_unknown;
	}

	if (secboot == 0) {
		pr_info("ima: secureboot mode disabled\n");
		return efi_secureboot_mode_disabled;
	}

	pr_info("ima: secureboot mode enabled\n");
	return efi_secureboot_mode_enabled;
}

bool arch_ima_get_secureboot(void)
{
	static enum efi_secureboot_mode sb_mode;
	static bool initialized;

	if (!initialized && efi_enabled(EFI_BOOT)) {
		sb_mode = boot_params.secure_boot;

		if (sb_mode == efi_secureboot_mode_unset)
			sb_mode = get_sb_mode();
		initialized = true;
	}

	if (sb_mode == efi_secureboot_mode_enabled)
		return true;
	else
		return false;
}

/* secureboot arch rules */
static const char * const sb_arch_rules[] = {
#if !IS_ENABLED(CONFIG_KEXEC_VERIFY_SIG)
	"appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig",
#endif /* CONFIG_KEXEC_VERIFY_SIG */
	"measure func=KEXEC_KERNEL_CHECK",
	NULL
};

const char * const *arch_get_ima_policy(void)
{
	if (IS_ENABLED(CONFIG_IMA_ARCH_POLICY) && arch_ima_get_secureboot())
		return sb_arch_rules;
	return NULL;
}
+34 −0
Original line number Diff line number Diff line
@@ -663,6 +663,10 @@ void efi_native_runtime_setup(void);
#define EFI_IMAGE_SECURITY_DATABASE_GUID	EFI_GUID(0xd719b2cb, 0x3d3a, 0x4596,  0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f)
#define EFI_SHIM_LOCK_GUID			EFI_GUID(0x605dab50, 0xe046, 0x4300,  0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23)

#define EFI_CERT_SHA256_GUID			EFI_GUID(0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28)
#define EFI_CERT_X509_GUID			EFI_GUID(0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72)
#define EFI_CERT_X509_SHA256_GUID		EFI_GUID(0x3bd2a492, 0x96c0, 0x4079, 0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed)

/*
 * This GUID is used to pass to the kernel proper the struct screen_info
 * structure that was populated by the stub based on the GOP protocol instance
@@ -934,6 +938,27 @@ typedef struct {
	efi_memory_desc_t entry[0];
} efi_memory_attributes_table_t;

typedef struct {
	efi_guid_t signature_owner;
	u8 signature_data[];
} efi_signature_data_t;

typedef struct {
	efi_guid_t signature_type;
	u32 signature_list_size;
	u32 signature_header_size;
	u32 signature_size;
	u8 signature_header[];
	/* efi_signature_data_t signatures[][] */
} efi_signature_list_t;

typedef u8 efi_sha256_hash_t[32];

typedef struct {
	efi_sha256_hash_t to_be_signed_hash;
	efi_time_t time_of_revocation;
} efi_cert_x509_sha256_t;

/*
 * All runtime access to EFI goes through this structure:
 */
@@ -1116,6 +1141,15 @@ extern int efi_memattr_apply_permissions(struct mm_struct *mm,
char * __init efi_md_typeattr_format(char *buf, size_t size,
				     const efi_memory_desc_t *md);


typedef void (*efi_element_handler_t)(const char *source,
				      const void *element_data,
				      size_t element_size);
extern int __init parse_efi_signature_list(
	const char *source,
	const void *data, size_t size,
	efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *));

/**
 * efi_range_is_wc - check the WC bit on an address range
 * @start: starting kvirt address
+15 −0
Original line number Diff line number Diff line
@@ -30,6 +30,21 @@ extern void ima_post_path_mknod(struct dentry *dentry);
extern void ima_add_kexec_buffer(struct kimage *image);
#endif

#if defined(CONFIG_X86) && defined(CONFIG_EFI)
extern bool arch_ima_get_secureboot(void);
extern const char * const *arch_get_ima_policy(void);
#else
static inline bool arch_ima_get_secureboot(void)
{
	return false;
}

static inline const char * const *arch_get_ima_policy(void)
{
	return NULL;
}
#endif

#else
static inline int ima_bprm_check(struct linux_binprm *bprm)
{
Loading