From aa9cca4019164120f0ce8b756c0cbb8751c7ac3d Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Mon, 30 Oct 2017 15:28:53 -0700 Subject: vboot: Use kernel max rollforward NV storage field Kernel verification will now roll forward the minimum allowable version in the TPM no farther than the kernel_max_rollforward setting. Note that CL:765573 changes chromeos-setgoodkernel so it always sets kernel_max_rollforward to 0xfffffffe when marking a kernel as good. That ensures that firmware with this setting will behave the same for now as existing firmware. BUG=chromium:783997 BRANCH=none CQ-DEPEND=CL:765573 TEST=make runtests Manual testing: crossystem tpm_kernvel --> print current kernel version in TPM - Resign the kernel with a higher version - Reboot - Wait a minute for chromeos-setgoodkernel to run crossystem kernel_max_rollforward=0 - Reboot crossystem tpm_kernvel --> has not changed - Wait a minute for chromeos-setgoodkernel to run crossystem kernel_max_rollforward -> 0xfffffffe - Reboot crossystem tpm_kernvel --> has changed to the higher version Change-Id: Ia32ecb7fa4078548cd311541ccbe120570cf1bc5 Reviewed-on: https://chromium-review.googlesource.com/765574 Commit-Ready: Randall Spangler Tested-by: Randall Spangler Reviewed-by: Julius Werner Reviewed-by: Stefan Reinauer Reviewed-on: https://chromium-review.googlesource.com/798127 Reviewed-by: Randall Spangler Commit-Queue: Shelley Chen Tested-by: Shelley Chen --- firmware/lib/vboot_api_kernel.c | 20 ++++++++++++++++++++ tests/vboot_api_kernel4_tests.c | 17 ++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c index 2cc1a88b..1879b845 100644 --- a/firmware/lib/vboot_api_kernel.c +++ b/firmware/lib/vboot_api_kernel.c @@ -188,6 +188,7 @@ VbError_t VbBootNormal(struct vb2_context *ctx, VbCommonParams *cparams) { VbSharedDataHeader *shared = (VbSharedDataHeader *)cparams->shared_data_blob; + uint32_t max_rollforward; /* Boot from fixed disk only */ VB2_DEBUG("Entering\n"); @@ -224,6 +225,25 @@ VbError_t VbBootNormal(struct vb2_context *ctx, VbCommonParams *cparams) return rv; } + /* Limit kernel version rollforward if needed */ + if (0 == VbNvGet(&vnc, VBNV_KERNEL_MAX_ROLLFORWARD, &max_rollforward)) { + /* + * Can't limit kernel version to less than the version + * currently in the TPM. That is, we're limiting rollforward, + * not allowing rollback. + */ + if (max_rollforward < shared->kernel_version_tpm_start) + max_rollforward = shared->kernel_version_tpm_start; + + if (shared->kernel_version_tpm > max_rollforward) { + VB2_DEBUG("Limiting TPM kernel version roll-forward " + "to 0x%x < 0x%x\n", + max_rollforward, shared->kernel_version_tpm); + + shared->kernel_version_tpm = max_rollforward; + } + } + if ((shared->kernel_version_tpm > shared->kernel_version_tpm_start) && RollbackKernelWrite(shared->kernel_version_tpm)) { VB2_DEBUG("Error writing kernel versions to TPM.\n"); diff --git a/tests/vboot_api_kernel4_tests.c b/tests/vboot_api_kernel4_tests.c index 59650701..e00c928a 100644 --- a/tests/vboot_api_kernel4_tests.c +++ b/tests/vboot_api_kernel4_tests.c @@ -53,6 +53,7 @@ static void ResetMocks(void) memset(&vnc, 0, sizeof(vnc)); VbNvSetup(&vnc); + VbNvSet(&vnc, VBNV_KERNEL_MAX_ROLLFORWARD, 0xffffffff); VbNvTeardown(&vnc); /* So CRC gets generated */ memset(&shared_data, 0, sizeof(shared_data)); @@ -88,7 +89,6 @@ uint32_t RollbackKernelRead(uint32_t *version) uint32_t RollbackKernelWrite(uint32_t version) { - TEST_EQ(version, new_version, "RollbackKernelWrite new version"); rkr_version = version; return rkw_retval; } @@ -150,6 +150,7 @@ static void VbSlkTest(void) { ResetMocks(); test_slk(0, 0, "Normal"); + TEST_EQ(rkr_version, 0x10002, " version"); /* * If shared->flags doesn't ask for software sync, we won't notice @@ -182,6 +183,20 @@ static void VbSlkTest(void) test_slk(0, 0, "Don't roll forward during try B"); TEST_EQ(rkr_version, 0x10002, " version"); + ResetMocks(); + VbNvSet(&vnc, VBNV_KERNEL_MAX_ROLLFORWARD, 0x30005); + VbNvTeardown(&vnc); + new_version = 0x40006; + test_slk(0, 0, "Limit max roll forward"); + TEST_EQ(rkr_version, 0x30005, " version"); + + ResetMocks(); + VbNvSet(&vnc, VBNV_KERNEL_MAX_ROLLFORWARD, 0x10001); + VbNvTeardown(&vnc); + new_version = 0x40006; + test_slk(0, 0, "Max roll forward can't rollback"); + TEST_EQ(rkr_version, 0x10002, " version"); + ResetMocks(); vbboot_retval = VBERROR_INVALID_KERNEL_FOUND; VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123); -- cgit v1.2.1