New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 900002 link

Starred by 4 users

Issue metadata

Status: Fixed
Owner:
Closed: Jan 13
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Chrome
Pri: 1
Type: Bug



Sign in to add a comment

firmware_TPMVersionCheck got broken by max-rollforward feature

Project Member Reported by jwer...@chromium.org, Oct 29

Issue description

firmware_TPMVersionCheck is a simple FAFT test that confirms crossystem tpm_fwver and tpm_kernver are both 0x10001. This should be true for devices running FAFT since they're usually always dev-keyed.

On recent bring-up boards that come straight out of the factory, this only succeeds in developer mode but not in normal mode. In developer mode tpm_kernver is 0x10001 as expected, but in normal mode it is 0x0.

Investigation brought up that the actual rollback protection version in the kernel TPM space is 0x0, as it was from TPM factory setup. This is somewhat expected because booting in developer mode doesn't (and never has) roll forward this version, and devices straight out of the factory may never have booted in normal mode. The weird thing about developer mode is that tpm_kernver doesn't actually report the version in the TPM -- it reports the version of the kernel that was booted, regardless of whether that version was actually written back to the TPM or not.

In normal mode it reports the correct version in the TPM because it gets corrected back to that by VbBootNormal() after the decision not to roll forward. That decision is made after checking VB2_NV_KERNEL_MAX_ROLLFORWARD, which is still 0 on these boards. I'm not sure why it is 0... it is supposed to get set to 0xfffffffe for unenrolled devices, but that doesn't happen for me even though I do have a process called update_engine running in userland. I've attached one update_engine.log from the device in question. Maybe the code that's supposed to set this not run on devices using test images (because they also don't run auto-update)?

So there are possibly two bugs here:

a) update_engine should always set kernel_max_rollforward, even on devices with an unofficial or test image.

b) crossystem tpm_kernver doesn't actually return the version currently in the TPM in all cases. This has always been this way, but it feels wrong. Should we fix that?
 
update_engine.log
4.5 KB View Download
Cc: hunyadym@chromium.org
Owner: ahass...@chromium.org
Status: Assigned (was: Untriaged)
Owner: zentaro@chromium.org
Yeah, that'd explain it.  If you set kernel_max_rollforward=0 and the TPM version is 0, then it doesn't roll forward.  That's working as intended.

There are a total of 4 numbers now:
1) Kernel version in TPM at start
2) Max rollforward
3) Kernel version in TPM at end
4) Kernel version actually booted

tpm_kernver is now an unholy hybrid of (3) and (4), at least in developer mode.

We should really just be passing the contents of secdata and secdatak down from vboot to the OS in the shared data blob, and separately reporting the versions we booted.
rspangler@ - So is there something to do on the client side here? Or is this something that needs to be fixed in firmware?
@zentaro: Yes, the main bug is still as I explained in the initial post (under 'a)'). update_engine needs to reasonably initialize kernel_max_rollforward on all devices, including devices with test images or early prerelease devices for which Omaha stuff hasn't been set up yet. I assume there's something pretty early in update_engine that just causes it to abort and do nothing in those cases, but it still needs to initialize this NVRAM value (to 0xfffffffe, i.e. assume that all these "unofficial" builds are normal consumer devices).

We're discussing some separate smaller issues that we may want to clean up in firmware here as well, but those are not directly related to the update_engine bug and will not directly solve the problem.
Cc: maxkirsch@chromium.org
Labels: ReleaseBlock-Beta M-73
*ping*

This has been open for close to a month and is affecting firmware testing for multiple bring-up teams. Is anyone actively working on this? Can we please get an ETA?
Sorry I've been working on other rollback features recently. I didn't realize this was actively blocking people.

I'll take a look tomorrow and Thursday. I'm going on vacation on Friday for a week, so if I don't have a solution on Thursday, I think Amin might be able to work on this also.
Looking at this bug, when SetMaxKernelKeyVersionForRollback() is called (and it is always called after an update check)
https://chromium.git.corp.google.com/aosp/platform/system/update_engine/+/72b80edb1ef2db08564929549eb8d7a1e0b24542/omaha_request_action.cc#1216

It should eventually sets the kernel_max_rollforward=0xffffffe for devices that don't have rollback enabled. This includes all the test and devices coming out of factory I guess. 

So, there are either two problems:
1) The devices mentioned in #1 have not been forced update checked. So just a simple update check might resolve their issue.
   - This has a caveat though, the device should actually get a response from omaha or devserver as setting the kernel_max_rollforward happens only after a response is received.

2) These devices in question are being detected as non-consumer devices (per https://chromium.git.corp.google.com/chromiumos/platform2/+/9f429a148a2feceb0ad94fcacb6a5f8940edb74a/libbrillo/policy/libpolicy.cc#53)

jwerner@ can you see if the value is set after a successful update check? That happens when I do this check on my test device.

The reason I'm asking is to figure out if the IsConsumerDevice() is working correctly on the aforementioned device, then we can add a hook somewhere in the update engine initialization to set the kernel_max_rollforward to its proper value. This will solve the problem for when the device is not explicitly called update check or even it is called, no response has received. WDYT?
How do I force an update check? (Keep in mind that this is a bare bring-up board on my desk, I don't have a screen and can't click around in menus.)

I'm pretty sure that enterprise policy shouldn't be a problem, it's probably that the device just never does that update check (or never succeeds). Do devices with test images even do update checks? (Because they don't actually update, right? Does that determination get made before or after it queries Omaha?) We also often don't have a network hooked up during bring-up.

So yeah, a hook that just always initializes it on boot should solve it. You can also only run that when IsOfficialBuild() is false if you want, in case there's some good reason to wait for the update check in production builds.
Test devices don't run periodic updates, but each cros flash or provisioning is basically an update. So you can just do a cros flash if possible.
We don't have a builder that makes working images for this board yet, and I don't have the whole system compiled on my workstation atm, so I don't think I can cros flash. Anyway, let's assume the consumer device check work for now and implement the fix for when there are no update checks. We need to add that anyway, right? We can see if that's enough to get it working afterwards.
Status: Started (was: Assigned)
Owner: ahass...@chromium.org
Project Member

Comment 16 by bugdroid1@chromium.org, Jan 13

The following revision refers to this bug:
  https://chromium.googlesource.com/aosp/platform/system/update_engine/+/ef13c92c549fee1a73118c32315e4472a5c4ffa3

commit ef13c92c549fee1a73118c32315e4472a5c4ffa3
Author: Amin Hassani <ahassani@chromium.org>
Date: Sun Jan 13 21:52:16 2019

update_engine: Initialize kernel_max_rollforward to infinity on init

Currently the value of kernel_max_rollforward is set only after a successful
update check, but if the update is not successful or there was never an explicit
update check (test devices or bring up devices), this value is not set and it
can case incorrect firmware behavior. This CL initializes the value to infinity,
if the device is detected to be a consumer device, on update_engine
initialization.

BUG= chromium:900002 
TEST=unittests
TEST=changed the value of kernel_max_rollforward and restart update_engine, the
value changed to infinity.

Change-Id: I1a2c905b5f5d5c10e71d055e31896f2838320fc0
Reviewed-on: https://chromium-review.googlesource.com/1405456
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Amin Hassani <ahassani@chromium.org>
Reviewed-by: Zentaro Kavanagh <zentaro@chromium.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Reviewed-by: Sen Jiang <senj@chromium.org>

[modify] https://crrev.com/ef13c92c549fee1a73118c32315e4472a5c4ffa3/real_system_state.cc

Status: Fixed (was: Started)

Sign in to add a comment