RFC-0150: Update opt-out | |
---|---|
Status | Accepted |
Areas |
|
Description | Policy and features for product owners to allow users to opt out of software updates. |
Issues | |
Gerrit change | |
Authors | |
Reviewers | |
Date submitted (year-month-day) | 2022-01-14 |
Date reviewed (year-month-day) | 2022-01-31 |
Summary
We describe a new ability for product owners to allow users of their products to opt out of receiving software updates. We describe the policies associated with this mechanism, the ways in which it should be used, and the security mechanisms associated with storing the setting. Finally, we describe how other components on the system may observe whether the system is opted out of updates.
Motivation
We have a requirement from customers to allow users of Fuchsia devices to opt out of receiving updates. We must satisfy that requirement in a way that is as secure as possible for all users, regardless of their opt-out status.
Stakeholders
Facilitator:
pascallouis@google.com
Reviewers:
- kevinwells@google.com - Software Delivery (SWD)
- ampearce@google.com - Security
- pascallouis@google.com - Fuchsia Engineering Council (FEC)
Consulted:
- borthakur@google.com
- marvinpaul@google.com - Server implementation
- gtsai@google.com - Server implementation
- enoharemaien@google.com - Privacy
- hjfreyer@google.com - Component Platform / FEC
- Software Delivery team
Socialization:
This RFC went through a design phase with the Software Delivery team, the Security and Privacy teams, and customers.
Requirements
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in IETF RFC 2119.
- Product owners may allow users to opt out of updates, which means no updates are downloaded or installed to a user's device, except for critical updates designated by the product owner, including critical security updates.
- If a device is opted out of updates and has a Factory Data Reset (FDR) run, it should be opted back into updates.
- The setting must persist across reboots without having to be re-set on every boot by a product-level component (which would cause race conditions between the product-level component and update checks).
- The enablement and storage of the setting must be as secure as possible, to prevent an attacker finding a privilege escalation, opting the device out of updates, and persisting that vulnerability indefinitely.
- It must not be possible for someone to enable the opt-out option at runtime if the product owner has not decided to include it in a build (there must be a static compile-time flag to disable the feature entirely).
- We must have metrics on how many users (though not which specific users) are opted out of updates, to ensure that this option is not being exploited by attackers to persist vulnerabilities.
- If the system is in recovery mode, updates should always be allowed.
- If a user manually requests an update, even while updates are disabled, that update should be allowed.
- This feature should only be enabled on devices with tamper-resistant storage,
such as Replay Protected Memory Blocks (RPMB). We have no requirements to
enable this feature on devices without tamper-resistant storage, but we can
revisit this RFC if the need arises in future.
- Note: The proposed design does not limit us only to secure storage implementations, but removing tamper-resistant storage as a requirement would lead to security tradeoffs for the product owner.
Design
omaha-client
is our production system update checker. It communicates with an
Omaha server run by the product owner or a delegate. Together, the Omaha client
and server periodically negotiate a system or package version to install.
We propose that a product owner can enable the existence of this feature on a product by statically building in a flag in the Software Delivery configuration.
Reading and writing the opt-out option value
A new SWD component called update-settings-storage
will serve a FIDL API
called fuchsia.update.config.OptOut
to read this option and an API called
fuchsia.update.config.OptOutAdmin
to write this option. This API will need to
be exposed in the SDK to allow product-level components to toggle the option's
value on and off.
The fuchsia.update.config.OptOutAdmin
API must be strictly protected by
capability routing and Scrutiny verification, to ensure that no unauthorized
components gain access to it.
Reading the value of the opt-out setting using
fuchsia.update.config.OptOut
should be allowed to allowlisted components on
the system with looser controls than OptOutAdmin
. This will allow components
at the system and product level to make decisions based on whether the device is
opted out of updates, and provide settings and troubleshooting views of this
option.
Opt-out persistence and security
The component serving the OptOut
API, update-settings-storage
, must persist
the value of the opt-out setting across reboots, and must persist the setting in
integrity-protected storage. For instance, minfs
storage of this
setting without an accompanying hash and signature on the storage would be
insecure, and is disallowed.
We propose using hardware tamper-resistant storage (currently the only option on Fuchsia devices is RPMB) to store this opt-out setting. The property we desire from tamper-resistant storage is that it cannot be written to except by a signed Trusted Application, or rogue writes can be detected.
These storage APIs exist on the required products and should be exposed through the Verified Execution Trusted Application (VX TA) which is signed and authenticated via hardware measures at boot.
Update Checks
On each scheduled update check omaha-client
should read from
update-settings-storage
using the OptOut
FIDL API, and send the opt-out
value to Omaha using the existing updatedisabled
field
in the Omaha protocol.
If the system is running on the recovery partition, updatedisabled
should
always be false
. Similarly, if the update check was user-initiated,
updatedisabled
should always be false
.
If the Omaha server receives an update check with updatedisabled
equal to
true
, it should return NoUpdate
for that Omaha Application's response,
except for critical updates designated by the product owner.
There is an alternative here, which is to not send any Omaha update checks at
all if the device is opted out of updates. However, that alternative denies the
product owner metrics on how many users are opted out of updates, and denies the
product owner the ability to push critical updates (by overriding
updatedisabled
field if required, on the server).
The opt-out must apply to all applications for which omaha-client
is checking
for updates, including system updates and single packages.
Implementation
Implementation will take place between the SWD, firmware, security, and update server teams. The task breakdown is roughly as follows, and should correspond to CL chains to be submitted.
Software Delivery
- Create
fuchsia.update.config.OptOut
FIDL API - Implement
update-settings-storage
component - Read
fuchsia.update.config.OptOut
fromomaha-client
at update check time, forward to Omaha server asupdatedisabled
flag (unless the device is in recovery or the check was user-initiated) - Expose
fuchsia.update.config
in the SDK, and allowlist both protocols. - Add a Cobalt metric to
omaha-client
to count the number of opted-out devices - Expose the opt-out setting in Inspect data for
omaha-client
Firmware / Security
- Expose an API to RPMB via the Verified Execution Trusted Application (VX TA), statically include that API only on supported devices
- Modify the VX TA to clear the opt-out flag during Factory Data Reset (which it already mediates)
Update Server
- Modify generation of Omaha rules to return
NoUpdate
for all Application Update Check Requests ifupdatedisabled
is true for that Application.
Performance
There should be no noticeable impact on system or update check performance. Update checks are infrequent (on the order of hours), and not particularly latency sensitive.
Ergonomics
Our read API for this setting will help reduce possible developer or user confusion, as will Inspect and Cobalt logging of the opt-out state.
Backwards Compatibility
This RFC presents no backwards compatibility issues that we know of.
Security considerations
Updates are Fuchsia's most important security feature. Without updates, the Fuchsia team cannot patch vulnerabilities in the platform. More importantly, having this code exist on the device at all is a risk to all users whether or not they've opted out of updates: if an attacker gains sufficient privileges, they can change the update opt-out setting and increase their chances of persisting forever.
This design attempts to mitigate risk in the following ways:
- Storing the setting in tamper-resistant memory (RPMB)
- Only allowing a specific Verified Execution Trusted Application (TA) to
modify the setting
- TAs are only accessible when a device is in locked mode with an authenticated user logged in (after OOBE)
- The VX TA is much smaller and simpler than, e.g., minfs, and is almost exclusively modified by the security and firmware teams
- Auditing and allowlisting the routing of the TA
- Retaining the ability to push critical updates (as defined by the product
owner) to devices
- The criteria defining absolutely necessary updates are out of scope of this RFC
- We will continually know how many devices are opted out and can create alerts if that number becomes suspicious
The following risks still exist:
- We have no control over the product-level code which will call the opt-out API, and we must ensure that only highly-privileged components can access it
- An attacker who has gained sufficient kernel privileges could still take
control of
update-settings-storage
or the VX TA and ask them to modify the setting
The following security improvements are not scoped at this time, but could be considered for future iterations:
- Adding a physical presence requirement (user must interact with the device in some way, not just through a product-level component)
- Making the setting writeable from the bootloader only. This defends the setting against a kernel compromise at the expense of UX and cross-platform consistency
Privacy considerations
This design does not significantly impact user privacy, as all logging or propagation of opt-out status will go through a privacy-protected logging service: either our Crash database via Inspect, or Cobalt.
Testing
We'll integration test the update-settings-storage
component, its interaction
with omaha-client
, and the final requests to an Omaha server that
omaha-client
produces in various states of opt-out.
We'll integration test the RPMB API via the Verified Execution Trusted Application.
We'll also unit test the implementations in each of the components individually.
Finally, we'll engage with the testing teams to ensure that products which enable this feature have end to end testing of their entire integrations, similar to other update features.
Documentation
We'll need to add documentation to the new FIDL API, as well as to our OTA flow documentation.
Drawbacks, alternatives, and unknowns
'Tombstone' builds
We could implement an update-opt out by pushing a 'tombstone' build to devices which indicates that it will no longer update.
This has a notable upside:
- The opt-out setting would be stored in Verified Boot Metadata, which is immutable. This implies better security properties.
This also has some notable downsides:
- We'd need to generate a specific 'tombstone' build for every normal build we push, for every product which enables this feature.
- The actual application of the opt-out would require an OTA update, which violates our requirements.
Store the opt-out value in mutable storage
We could avoid some complexity by storing the opt-out value in minfs, which would allow this feature to be deployed to a greater range of products. However, this makes it trivial for an attacker with privilege escalation to persist their attacks indefinitely if they can gain write access to minfs. Gaining write access to minfs is likely substantially easier than modifying the Verified Execution Trusted Application's state, since the VX TA is much smaller than minfs in terms of surface area, and easier to audit.
If a user is opted out, omit update checks entirely
If a user is opted out, we could modify omaha-client
to not check for updates
at all. This has a couple of drawbacks: we can't get Omaha-based metrics on how
many users are opted out, and a
product owner
with
sufficient authorization can't ask devices to take critical updates.
Prior art and references
The Omaha protocol includes the updatedisabled
flag
for essentially this reason: a client device telling the server that it's
checking for an update, but that download and installation should not be
performed.
The Chrome browser supports disabling updates via enterprise policy. This may be a use case for potential Fuchsia devices, but we have no enterprise policy requirements at the moment.