License cleanup: add SPDX GPL-2.0 license identifier to files with no license
Many source files in the tree are missing licensing information, which
makes it harder for compliance tools to determine the correct license.
By default all files without license information are under the default
license of the kernel, which is GPL version 2.
Update the files which contain no license information with the 'GPL-2.0'
SPDX license identifier. The SPDX identifier is a legally binding
shorthand, which can be used instead of the full boiler plate text.
This patch is based on work done by Thomas Gleixner and Kate Stewart and
Philippe Ombredanne.
How this work was done:
Patches were generated and checked against linux-4.14-rc6 for a subset of
the use cases:
- file had no licensing information it it.
- file was a */uapi/* one with no licensing information in it,
- file was a */uapi/* one with existing licensing information,
Further patches will be generated in subsequent months to fix up cases
where non-standard license headers were used, and references to license
had to be inferred by heuristics based on keywords.
The analysis to determine which SPDX License Identifier to be applied to
a file was done in a spreadsheet of side by side results from of the
output of two independent scanners (ScanCode & Windriver) producing SPDX
tag:value files created by Philippe Ombredanne. Philippe prepared the
base worksheet, and did an initial spot review of a few 1000 files.
The 4.13 kernel was the starting point of the analysis with 60,537 files
assessed. Kate Stewart did a file by file comparison of the scanner
results in the spreadsheet to determine which SPDX license identifier(s)
to be applied to the file. She confirmed any determination that was not
immediately clear with lawyers working with the Linux Foundation.
Criteria used to select files for SPDX license identifier tagging was:
- Files considered eligible had to be source code files.
- Make and config files were included as candidates if they contained >5
lines of source
- File already had some variant of a license header in it (even if <5
lines).
All documentation files were explicitly excluded.
The following heuristics were used to determine which SPDX license
identifiers to apply.
- when both scanners couldn't find any license traces, file was
considered to have no license information in it, and the top level
COPYING file license applied.
For non */uapi/* files that summary was:
SPDX license identifier # files
---------------------------------------------------|-------
GPL-2.0 11139
and resulted in the first patch in this series.
If that file was a */uapi/* path one, it was "GPL-2.0 WITH
Linux-syscall-note" otherwise it was "GPL-2.0". Results of that was:
SPDX license identifier # files
---------------------------------------------------|-------
GPL-2.0 WITH Linux-syscall-note 930
and resulted in the second patch in this series.
- if a file had some form of licensing information in it, and was one
of the */uapi/* ones, it was denoted with the Linux-syscall-note if
any GPL family license was found in the file or had no licensing in
it (per prior point). Results summary:
SPDX license identifier # files
---------------------------------------------------|------
GPL-2.0 WITH Linux-syscall-note 270
GPL-2.0+ WITH Linux-syscall-note 169
((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) 21
((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) 17
LGPL-2.1+ WITH Linux-syscall-note 15
GPL-1.0+ WITH Linux-syscall-note 14
((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause) 5
LGPL-2.0+ WITH Linux-syscall-note 4
LGPL-2.1 WITH Linux-syscall-note 3
((GPL-2.0 WITH Linux-syscall-note) OR MIT) 3
((GPL-2.0 WITH Linux-syscall-note) AND MIT) 1
and that resulted in the third patch in this series.
- when the two scanners agreed on the detected license(s), that became
the concluded license(s).
- when there was disagreement between the two scanners (one detected a
license but the other didn't, or they both detected different
licenses) a manual inspection of the file occurred.
- In most cases a manual inspection of the information in the file
resulted in a clear resolution of the license that should apply (and
which scanner probably needed to revisit its heuristics).
- When it was not immediately clear, the license identifier was
confirmed with lawyers working with the Linux Foundation.
- If there was any question as to the appropriate license identifier,
the file was flagged for further research and to be revisited later
in time.
In total, over 70 hours of logged manual review was done on the
spreadsheet to determine the SPDX license identifiers to apply to the
source files by Kate, Philippe, Thomas and, in some cases, confirmation
by lawyers working with the Linux Foundation.
Kate also obtained a third independent scan of the 4.13 code base from
FOSSology, and compared selected files where the other two scanners
disagreed against that SPDX file, to see if there was new insights. The
Windriver scanner is based on an older version of FOSSology in part, so
they are related.
Thomas did random spot checks in about 500 files from the spreadsheets
for the uapi headers and agreed with SPDX license identifier in the
files he inspected. For the non-uapi files Thomas did random spot checks
in about 15000 files.
In initial set of patches against 4.14-rc6, 3 files were found to have
copy/paste license identifier errors, and have been fixed to reflect the
correct identifier.
Additionally Philippe spent 10 hours this week doing a detailed manual
inspection and review of the 12,461 patched files from the initial patch
version early this week with:
- a full scancode scan run, collecting the matched texts, detected
license ids and scores
- reviewing anything where there was a license detected (about 500+
files) to ensure that the applied SPDX license was correct
- reviewing anything where there was no detection but the patch license
was not GPL-2.0 WITH Linux-syscall-note to ensure that the applied
SPDX license was correct
This produced a worksheet with 20 files needing minor correction. This
worksheet was then exported into 3 different .csv files for the
different types of files to be modified.
These .csv files were then reviewed by Greg. Thomas wrote a script to
parse the csv files and add the proper SPDX tag to the file, in the
format that the file expected. This script was further refined by Greg
based on the output to detect more types of files automatically and to
distinguish between header and source .c files (which need different
comment types.) Finally Greg ran the script using the .csv files to
generate the patches.
Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org>
Reviewed-by: Philippe Ombredanne <pombredanne@nexb.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2017-11-01 22:07:57 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
2012-07-11 23:08:12 +08:00
|
|
|
|
2017-09-20 16:13:36 +08:00
|
|
|
#ifndef __LINUX_TPM_EVENTLOG_H__
|
|
|
|
#define __LINUX_TPM_EVENTLOG_H__
|
2012-07-11 23:08:12 +08:00
|
|
|
|
2019-02-07 00:24:48 +08:00
|
|
|
#include <linux/tpm.h>
|
2017-01-23 15:26:27 +08:00
|
|
|
|
2012-07-11 23:08:12 +08:00
|
|
|
#define TCG_EVENT_NAME_LEN_MAX 255
|
|
|
|
#define MAX_TEXT_EVENT 1000 /* Max event string length */
|
|
|
|
#define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
|
|
|
|
|
2017-09-20 16:13:38 +08:00
|
|
|
#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 0x1
|
|
|
|
#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 0x2
|
|
|
|
|
2015-06-18 06:17:08 +08:00
|
|
|
#ifdef CONFIG_PPC64
|
|
|
|
#define do_endian_conversion(x) be32_to_cpu(x)
|
|
|
|
#else
|
|
|
|
#define do_endian_conversion(x) x
|
|
|
|
#endif
|
|
|
|
|
2012-07-11 23:08:12 +08:00
|
|
|
enum bios_platform_class {
|
|
|
|
BIOS_CLIENT = 0x00,
|
|
|
|
BIOS_SERVER = 0x01,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct tcpa_event {
|
|
|
|
u32 pcr_index;
|
|
|
|
u32 event_type;
|
|
|
|
u8 pcr_value[20]; /* SHA1 */
|
|
|
|
u32 event_size;
|
2020-03-24 08:38:18 +08:00
|
|
|
u8 event_data[];
|
2012-07-11 23:08:12 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
enum tcpa_event_types {
|
|
|
|
PREBOOT = 0,
|
|
|
|
POST_CODE,
|
|
|
|
UNUSED,
|
|
|
|
NO_ACTION,
|
|
|
|
SEPARATOR,
|
|
|
|
ACTION,
|
|
|
|
EVENT_TAG,
|
|
|
|
SCRTM_CONTENTS,
|
|
|
|
SCRTM_VERSION,
|
|
|
|
CPU_MICROCODE,
|
|
|
|
PLATFORM_CONFIG_FLAGS,
|
|
|
|
TABLE_OF_DEVICES,
|
|
|
|
COMPACT_HASH,
|
|
|
|
IPL,
|
|
|
|
IPL_PARTITION_DATA,
|
|
|
|
NONHOST_CODE,
|
|
|
|
NONHOST_CONFIG,
|
|
|
|
NONHOST_INFO,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct tcpa_pc_event {
|
|
|
|
u32 event_id;
|
|
|
|
u32 event_size;
|
2020-03-24 08:38:18 +08:00
|
|
|
u8 event_data[];
|
2012-07-11 23:08:12 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
enum tcpa_pc_event_ids {
|
|
|
|
SMBIOS = 1,
|
|
|
|
BIS_CERT,
|
|
|
|
POST_BIOS_ROM,
|
|
|
|
ESCD,
|
|
|
|
CMOS,
|
|
|
|
NVRAM,
|
|
|
|
OPTION_ROM_EXEC,
|
|
|
|
OPTION_ROM_CONFIG,
|
|
|
|
OPTION_ROM_MICROCODE = 10,
|
|
|
|
S_CRTM_VERSION,
|
|
|
|
S_CRTM_CONTENTS,
|
|
|
|
POST_CONTENTS,
|
|
|
|
HOST_TABLE_OF_DEVICES,
|
|
|
|
};
|
|
|
|
|
2017-01-23 15:26:27 +08:00
|
|
|
/* http://www.trustedcomputinggroup.org/tcg-efi-protocol-specification/ */
|
|
|
|
|
|
|
|
struct tcg_efi_specid_event_algs {
|
|
|
|
u16 alg_id;
|
|
|
|
u16 digest_size;
|
|
|
|
} __packed;
|
|
|
|
|
2020-06-15 15:16:36 +08:00
|
|
|
#define TCG_SPECID_SIG "Spec ID Event03"
|
|
|
|
|
2019-01-24 23:49:05 +08:00
|
|
|
struct tcg_efi_specid_event_head {
|
2017-01-23 15:26:27 +08:00
|
|
|
u8 signature[16];
|
|
|
|
u32 platform_class;
|
|
|
|
u8 spec_version_minor;
|
|
|
|
u8 spec_version_major;
|
|
|
|
u8 spec_errata;
|
|
|
|
u8 uintnsize;
|
|
|
|
u32 num_algs;
|
2019-01-24 23:49:05 +08:00
|
|
|
struct tcg_efi_specid_event_algs digest_sizes[];
|
2017-01-23 15:26:27 +08:00
|
|
|
} __packed;
|
|
|
|
|
|
|
|
struct tcg_pcr_event {
|
|
|
|
u32 pcr_idx;
|
|
|
|
u32 event_type;
|
|
|
|
u8 digest[20];
|
|
|
|
u32 event_size;
|
tpm: eventlog: Replace zero-length array with flexible-array member
The current codebase makes use of the zero-length array language
extension to the C90 standard, but the preferred mechanism to declare
variable-length types such as these ones is a flexible array member[1][2],
introduced in C99:
struct foo {
int stuff;
struct boo array[];
};
By making use of the mechanism above, we will get a compiler warning
in case the flexible array does not occur last in the structure, which
will help us prevent some kind of undefined behavior bugs from being
inadvertently introduced[3] to the codebase from now on.
Also, notice that, dynamic memory allocations won't be affected by
this change:
"Flexible array members have incomplete type, and so the sizeof operator
may not be applied. As a quirk of the original implementation of
zero-length arrays, sizeof evaluates to zero."[1]
sizeof(flexible-array-member) triggers a warning because flexible array
members have incomplete type[1]. There are some instances of code in
which the sizeof operator is being incorrectly/erroneously applied to
zero-length arrays and the result is zero. Such instances may be hiding
some bugs. So, this work (flexible-array member conversions) will also
help to get completely rid of those sorts of issues.
Also, the following issue shows up due to the flexible-array member
having incomplete type[4]:
drivers/char/tpm/eventlog/tpm2.c: In function ‘tpm2_bios_measurements_start’:
drivers/char/tpm/eventlog/tpm2.c:54:46: error: invalid application of ‘sizeof’ to incomplete type ‘u8[]’ {aka ‘unsigned char[]’}
54 | size = sizeof(struct tcg_pcr_event) - sizeof(event_header->event)
| ^
drivers/char/tpm/eventlog/tpm2.c: In function ‘tpm2_bios_measurements_next’:
drivers/char/tpm/eventlog/tpm2.c:102:10: error: invalid application of ‘sizeof’ to incomplete type ‘u8[]’ {aka ‘unsigned char[]’}
102 | sizeof(event_header->event) + event_header->event_size;
| ^
drivers/char/tpm/eventlog/tpm2.c: In function ‘tpm2_binary_bios_measurements_show’:
drivers/char/tpm/eventlog/tpm2.c:140:10: error: invalid application of ‘sizeof’ to incomplete type ‘u8[]’ {aka ‘unsigned char[]’}
140 | sizeof(event_header->event) + event_header->event_size;
| ^
scripts/Makefile.build:266: recipe for target 'drivers/char/tpm/eventlog/tpm2.o' failed
make[3]: *** [drivers/char/tpm/eventlog/tpm2.o] Error 1
As mentioned above: "Flexible array members have incomplete type, and
so the sizeof operator may not be applied. As a quirk of the original
implementation of zero-length arrays, sizeof evaluates to zero."[1] As
in "sizeof(event_header->event) always evaluated to 0, so removing it
has no effect".
Lastly, make use of the struct_size() helper to deal with the
flexible array member and its host structure.
This issue was found with the help of Coccinelle.
[1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
[2] https://github.com/KSPP/linux/issues/21
[3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour")
[4] https://github.com/KSPP/linux/issues/43
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
2020-05-09 00:38:26 +08:00
|
|
|
u8 event[];
|
2017-01-23 15:26:27 +08:00
|
|
|
} __packed;
|
|
|
|
|
|
|
|
struct tcg_event_field {
|
|
|
|
u32 event_size;
|
2020-03-24 08:38:18 +08:00
|
|
|
u8 event[];
|
2017-01-23 15:26:27 +08:00
|
|
|
} __packed;
|
|
|
|
|
2019-01-24 23:49:05 +08:00
|
|
|
struct tcg_pcr_event2_head {
|
2017-01-23 15:26:27 +08:00
|
|
|
u32 pcr_idx;
|
|
|
|
u32 event_type;
|
|
|
|
u32 count;
|
2019-02-07 00:24:48 +08:00
|
|
|
struct tpm_digest digests[];
|
2017-01-23 15:26:27 +08:00
|
|
|
} __packed;
|
|
|
|
|
2019-05-21 04:54:59 +08:00
|
|
|
struct tcg_algorithm_size {
|
|
|
|
u16 algorithm_id;
|
|
|
|
u16 algorithm_size;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct tcg_algorithm_info {
|
|
|
|
u8 signature[16];
|
|
|
|
u32 platform_class;
|
|
|
|
u8 spec_version_minor;
|
|
|
|
u8 spec_version_major;
|
|
|
|
u8 spec_errata;
|
|
|
|
u8 uintn_size;
|
|
|
|
u32 number_of_algorithms;
|
|
|
|
struct tcg_algorithm_size digest_sizes[];
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifndef TPM_MEMREMAP
|
|
|
|
#define TPM_MEMREMAP(start, size) NULL
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef TPM_MEMUNMAP
|
|
|
|
#define TPM_MEMUNMAP(start, size) do{} while(0)
|
|
|
|
#endif
|
|
|
|
|
2019-05-21 04:54:58 +08:00
|
|
|
/**
|
|
|
|
* __calc_tpm2_event_size - calculate the size of a TPM2 event log entry
|
|
|
|
* @event: Pointer to the event whose size should be calculated
|
|
|
|
* @event_header: Pointer to the initial event containing the digest lengths
|
2019-05-21 04:54:59 +08:00
|
|
|
* @do_mapping: Whether or not the event needs to be mapped
|
2019-05-21 04:54:58 +08:00
|
|
|
*
|
|
|
|
* The TPM2 event log format can contain multiple digests corresponding to
|
|
|
|
* separate PCR banks, and also contains a variable length of the data that
|
|
|
|
* was measured. This requires knowledge of how long each digest type is,
|
|
|
|
* and this information is contained within the first event in the log.
|
|
|
|
*
|
|
|
|
* We calculate the length by examining the number of events, and then looking
|
|
|
|
* at each event in turn to determine how much space is used for events in
|
|
|
|
* total. Once we've done this we know the offset of the data length field,
|
|
|
|
* and can calculate the total size of the event.
|
|
|
|
*
|
2019-10-03 00:59:02 +08:00
|
|
|
* Return: size of the event on success, 0 on failure
|
2019-05-21 04:54:58 +08:00
|
|
|
*/
|
|
|
|
|
2022-07-11 09:17:38 +08:00
|
|
|
static __always_inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
|
2019-05-21 04:54:59 +08:00
|
|
|
struct tcg_pcr_event *event_header,
|
|
|
|
bool do_mapping)
|
2019-05-21 04:54:58 +08:00
|
|
|
{
|
|
|
|
struct tcg_efi_specid_event_head *efispecid;
|
|
|
|
struct tcg_event_field *event_field;
|
2019-05-21 04:54:59 +08:00
|
|
|
void *mapping = NULL;
|
|
|
|
int mapping_size;
|
2019-05-21 04:54:58 +08:00
|
|
|
void *marker;
|
|
|
|
void *marker_start;
|
|
|
|
u32 halg_size;
|
|
|
|
size_t size;
|
|
|
|
u16 halg;
|
|
|
|
int i;
|
|
|
|
int j;
|
2019-10-03 00:59:00 +08:00
|
|
|
u32 count, event_type;
|
2020-06-15 15:16:36 +08:00
|
|
|
const u8 zero_digest[sizeof(event_header->digest)] = {0};
|
2019-05-21 04:54:58 +08:00
|
|
|
|
|
|
|
marker = event;
|
|
|
|
marker_start = marker;
|
|
|
|
marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type)
|
|
|
|
+ sizeof(event->count);
|
|
|
|
|
2019-05-21 04:54:59 +08:00
|
|
|
/* Map the event header */
|
|
|
|
if (do_mapping) {
|
|
|
|
mapping_size = marker - marker_start;
|
|
|
|
mapping = TPM_MEMREMAP((unsigned long)marker_start,
|
|
|
|
mapping_size);
|
|
|
|
if (!mapping) {
|
|
|
|
size = 0;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
mapping = marker_start;
|
|
|
|
}
|
|
|
|
|
|
|
|
event = (struct tcg_pcr_event2_head *)mapping;
|
2019-10-03 00:59:00 +08:00
|
|
|
/*
|
|
|
|
* The loop below will unmap these fields if the log is larger than
|
|
|
|
* one page, so save them here for reference:
|
|
|
|
*/
|
|
|
|
count = READ_ONCE(event->count);
|
|
|
|
event_type = READ_ONCE(event->event_type);
|
2019-05-21 04:54:59 +08:00
|
|
|
|
2020-06-15 15:16:36 +08:00
|
|
|
/* Verify that it's the log header */
|
|
|
|
if (event_header->pcr_idx != 0 ||
|
|
|
|
event_header->event_type != NO_ACTION ||
|
|
|
|
memcmp(event_header->digest, zero_digest, sizeof(zero_digest))) {
|
|
|
|
size = 0;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2019-05-21 04:54:58 +08:00
|
|
|
efispecid = (struct tcg_efi_specid_event_head *)event_header->event;
|
|
|
|
|
tpm: Require that all digests are present in TCG_PCR_EVENT2 structures
Require that the TCG_PCR_EVENT2.digests.count value strictly matches the
value of TCG_EfiSpecIdEvent.numberOfAlgorithms in the event field of the
TCG_PCClientPCREvent event log header. Also require that
TCG_EfiSpecIdEvent.numberOfAlgorithms is non-zero.
The TCG PC Client Platform Firmware Profile Specification section 9.1
(Family "2.0", Level 00 Revision 1.04) states:
For each Hash algorithm enumerated in the TCG_PCClientPCREvent entry,
there SHALL be a corresponding digest in all TCG_PCR_EVENT2 structures.
Note: This includes EV_NO_ACTION events which do not extend the PCR.
Section 9.4.5.1 provides this description of
TCG_EfiSpecIdEvent.numberOfAlgorithms:
The number of Hash algorithms in the digestSizes field. This field MUST
be set to a value of 0x01 or greater.
Enforce these restrictions, as required by the above specification, in
order to better identify and ignore invalid sequences of bytes at the
end of an otherwise valid TPM2 event log. Firmware doesn't always have
the means necessary to inform the kernel of the actual event log size so
the kernel's event log parsing code should be stringent when parsing the
event log for resiliency against firmware bugs. This is true, for
example, when firmware passes the event log to the kernel via a reserved
memory region described in device tree.
POWER and some ARM systems use the "linux,sml-base" and "linux,sml-size"
device tree properties to describe the memory region used to pass the
event log from firmware to the kernel. Unfortunately, the
"linux,sml-size" property describes the size of the entire reserved
memory region rather than the size of the event long within the memory
region and the event log format does not include information describing
the size of the event log.
tpm_read_log_of(), in drivers/char/tpm/eventlog/of.c, is where the
"linux,sml-size" property is used. At the end of that function,
log->bios_event_log_end is pointing at the end of the reserved memory
region. That's typically 0x10000 bytes offset from "linux,sml-base",
depending on what's defined in the device tree source.
The firmware event log only fills a portion of those 0x10000 bytes and
the rest of the memory region should be zeroed out by firmware. Even in
the case of a properly zeroed bytes in the remainder of the memory
region, the only thing allowing the kernel's event log parser to detect
the end of the event log is the following conditional in
__calc_tpm2_event_size():
if (event_type == 0 && event_field->event_size == 0)
size = 0;
If that wasn't there, __calc_tpm2_event_size() would think that a 16
byte sequence of zeroes, following an otherwise valid event log, was
a valid event.
However, problems can occur if a single bit is set in the offset
corresponding to either the TCG_PCR_EVENT2.eventType or
TCG_PCR_EVENT2.eventSize fields, after the last valid event log entry.
This could confuse the parser into thinking that an additional entry is
present in the event log and exposing this invalid entry to userspace in
the /sys/kernel/security/tpm0/binary_bios_measurements file. Such
problems have been seen if firmware does not fully zero the memory
region upon a warm reboot.
This patch significantly raises the bar on how difficult it is for
stale/invalid memory to confuse the kernel's event log parser but
there's still, ultimately, a reliance on firmware to properly initialize
the remainder of the memory region reserved for the event log as the
parser cannot be expected to detect a stale but otherwise properly
formatted firmware event log entry.
Fixes: fd5c78694f3f ("tpm: fix handling of the TPM 2.0 event logs")
Signed-off-by: Tyler Hicks <tyhicks@linux.microsoft.com>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
2020-07-11 03:29:55 +08:00
|
|
|
/*
|
|
|
|
* Perform validation of the event in order to identify malformed
|
|
|
|
* events. This function may be asked to parse arbitrary byte sequences
|
|
|
|
* immediately following a valid event log. The caller expects this
|
|
|
|
* function to recognize that the byte sequence is not a valid event
|
|
|
|
* and to return an event size of 0.
|
|
|
|
*/
|
2020-06-15 15:16:36 +08:00
|
|
|
if (memcmp(efispecid->signature, TCG_SPECID_SIG,
|
tpm: Require that all digests are present in TCG_PCR_EVENT2 structures
Require that the TCG_PCR_EVENT2.digests.count value strictly matches the
value of TCG_EfiSpecIdEvent.numberOfAlgorithms in the event field of the
TCG_PCClientPCREvent event log header. Also require that
TCG_EfiSpecIdEvent.numberOfAlgorithms is non-zero.
The TCG PC Client Platform Firmware Profile Specification section 9.1
(Family "2.0", Level 00 Revision 1.04) states:
For each Hash algorithm enumerated in the TCG_PCClientPCREvent entry,
there SHALL be a corresponding digest in all TCG_PCR_EVENT2 structures.
Note: This includes EV_NO_ACTION events which do not extend the PCR.
Section 9.4.5.1 provides this description of
TCG_EfiSpecIdEvent.numberOfAlgorithms:
The number of Hash algorithms in the digestSizes field. This field MUST
be set to a value of 0x01 or greater.
Enforce these restrictions, as required by the above specification, in
order to better identify and ignore invalid sequences of bytes at the
end of an otherwise valid TPM2 event log. Firmware doesn't always have
the means necessary to inform the kernel of the actual event log size so
the kernel's event log parsing code should be stringent when parsing the
event log for resiliency against firmware bugs. This is true, for
example, when firmware passes the event log to the kernel via a reserved
memory region described in device tree.
POWER and some ARM systems use the "linux,sml-base" and "linux,sml-size"
device tree properties to describe the memory region used to pass the
event log from firmware to the kernel. Unfortunately, the
"linux,sml-size" property describes the size of the entire reserved
memory region rather than the size of the event long within the memory
region and the event log format does not include information describing
the size of the event log.
tpm_read_log_of(), in drivers/char/tpm/eventlog/of.c, is where the
"linux,sml-size" property is used. At the end of that function,
log->bios_event_log_end is pointing at the end of the reserved memory
region. That's typically 0x10000 bytes offset from "linux,sml-base",
depending on what's defined in the device tree source.
The firmware event log only fills a portion of those 0x10000 bytes and
the rest of the memory region should be zeroed out by firmware. Even in
the case of a properly zeroed bytes in the remainder of the memory
region, the only thing allowing the kernel's event log parser to detect
the end of the event log is the following conditional in
__calc_tpm2_event_size():
if (event_type == 0 && event_field->event_size == 0)
size = 0;
If that wasn't there, __calc_tpm2_event_size() would think that a 16
byte sequence of zeroes, following an otherwise valid event log, was
a valid event.
However, problems can occur if a single bit is set in the offset
corresponding to either the TCG_PCR_EVENT2.eventType or
TCG_PCR_EVENT2.eventSize fields, after the last valid event log entry.
This could confuse the parser into thinking that an additional entry is
present in the event log and exposing this invalid entry to userspace in
the /sys/kernel/security/tpm0/binary_bios_measurements file. Such
problems have been seen if firmware does not fully zero the memory
region upon a warm reboot.
This patch significantly raises the bar on how difficult it is for
stale/invalid memory to confuse the kernel's event log parser but
there's still, ultimately, a reliance on firmware to properly initialize
the remainder of the memory region reserved for the event log as the
parser cannot be expected to detect a stale but otherwise properly
formatted firmware event log entry.
Fixes: fd5c78694f3f ("tpm: fix handling of the TPM 2.0 event logs")
Signed-off-by: Tyler Hicks <tyhicks@linux.microsoft.com>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
2020-07-11 03:29:55 +08:00
|
|
|
sizeof(TCG_SPECID_SIG)) ||
|
|
|
|
!efispecid->num_algs || count != efispecid->num_algs) {
|
2019-05-21 04:54:59 +08:00
|
|
|
size = 0;
|
|
|
|
goto out;
|
|
|
|
}
|
2019-05-21 04:54:58 +08:00
|
|
|
|
2019-10-03 00:59:00 +08:00
|
|
|
for (i = 0; i < count; i++) {
|
2019-05-21 04:54:58 +08:00
|
|
|
halg_size = sizeof(event->digests[i].alg_id);
|
2019-05-21 04:54:59 +08:00
|
|
|
|
|
|
|
/* Map the digest's algorithm identifier */
|
|
|
|
if (do_mapping) {
|
|
|
|
TPM_MEMUNMAP(mapping, mapping_size);
|
|
|
|
mapping_size = halg_size;
|
|
|
|
mapping = TPM_MEMREMAP((unsigned long)marker,
|
|
|
|
mapping_size);
|
|
|
|
if (!mapping) {
|
|
|
|
size = 0;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
mapping = marker;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&halg, mapping, halg_size);
|
2019-05-21 04:54:58 +08:00
|
|
|
marker = marker + halg_size;
|
2019-05-21 04:54:59 +08:00
|
|
|
|
2019-05-21 04:54:58 +08:00
|
|
|
for (j = 0; j < efispecid->num_algs; j++) {
|
|
|
|
if (halg == efispecid->digest_sizes[j].alg_id) {
|
|
|
|
marker +=
|
|
|
|
efispecid->digest_sizes[j].digest_size;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Algorithm without known length. Such event is unparseable. */
|
2019-05-21 04:54:59 +08:00
|
|
|
if (j == efispecid->num_algs) {
|
|
|
|
size = 0;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Map the event size - we don't read from the event itself, so
|
|
|
|
* we don't need to map it
|
|
|
|
*/
|
|
|
|
if (do_mapping) {
|
|
|
|
TPM_MEMUNMAP(mapping, mapping_size);
|
|
|
|
mapping_size += sizeof(event_field->event_size);
|
|
|
|
mapping = TPM_MEMREMAP((unsigned long)marker,
|
|
|
|
mapping_size);
|
|
|
|
if (!mapping) {
|
|
|
|
size = 0;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
mapping = marker;
|
2019-05-21 04:54:58 +08:00
|
|
|
}
|
|
|
|
|
2019-05-21 04:54:59 +08:00
|
|
|
event_field = (struct tcg_event_field *)mapping;
|
|
|
|
|
2019-05-21 04:54:58 +08:00
|
|
|
marker = marker + sizeof(event_field->event_size)
|
|
|
|
+ event_field->event_size;
|
|
|
|
size = marker - marker_start;
|
|
|
|
|
2019-10-03 00:59:00 +08:00
|
|
|
if (event_type == 0 && event_field->event_size == 0)
|
2019-05-21 04:54:59 +08:00
|
|
|
size = 0;
|
2019-10-03 00:59:00 +08:00
|
|
|
|
2019-05-21 04:54:59 +08:00
|
|
|
out:
|
|
|
|
if (do_mapping)
|
|
|
|
TPM_MEMUNMAP(mapping, mapping_size);
|
2019-05-21 04:54:58 +08:00
|
|
|
return size;
|
|
|
|
}
|
2019-05-21 04:54:59 +08:00
|
|
|
|
2012-07-11 23:08:12 +08:00
|
|
|
#endif
|