| {% set rfcid = "RFC-0008" %} |
| {% include "docs/contribute/governance/rfcs/_common/_rfc_header.md" %} |
| # {{ rfc.name }}: {{ rfc.title }} |
| <!-- SET the `rfcid` VAR ABOVE. DO NOT EDIT ANYTHING ELSE ABOVE THIS LINE. --> |
| |
| ## Summary |
| |
| We propose a five step process to deprecate the `zx_clock_get` and |
| `zx_clock_adjust` syscalls, migrate the remaining users to the replacement |
| syscalls that have been available since 2019, and finally remove the original |
| syscalls. |
| |
| |
| ## Motivation |
| |
| Fuchsia currently includes two independent sets of syscalls for interacting with |
| time: |
| |
| 1. The original design used `zx_clock_get` to read monotonic, UTC, and thread |
| clocks maintained by the kernel and used `zx_clock_adjust` to write to the |
| UTC clock. This design did not provide any way to slew clocks, define |
| additional clocks on different products, or communicate the status of clocks. |
| 2. In 2019 the `zx_clock_create`, `zx_clock_read`, `zx_clock_update` and |
| `zx_clock_get_details` syscalls were added to perform rich management of |
| clock objects, letting userspace define and maintain any number of clocks. |
| `zx_clock_get_monotonic` was also added to read the kernel's monotonic clock. |
| |
| Fuchsia currently defines two different UTC clocks; a kernel UTC clock that may |
| be read using `zx_clock_get` and a userspace UTC clock that may be read using |
| `zx_clock_read`. The time synchronization system attempts to keep these clocks |
| aligned, but since they offer different features some discrepancy is inevitable. |
| |
| This proposal defines the deprecation plan for the original time syscalls, |
| completing a migration that began in 2019 during the design of the replacement |
| syscalls were added. Removing these syscalls addresses the ongoing (and |
| increasing) operational and cognitive costs of maintaining two semi-compatible |
| ways to manage time. |
| |
| |
| ## Implementation |
| |
| `zx_clock_get` and `zx_clock_adjust` each accept a `clock_id` argument to |
| specify which of three possible timelines should be used. It is helpful to |
| consider these migration for these three timelines separately: |
| |
| * `ZX_CLOCK_MONOTONIC` - Calls to `zx_clock_get(ZX_CLOCK_MONOTONIC)` may be |
| directly replaced by a call to `zx_clock_get_monotonic`. This replacement |
| syscall is simpler to use and frequently offers better performance. |
| * `ZX_CLOCK_THREAD` - Calls to `zx_clock_get(ZX_CLOCK_THREAD)` may be replaced |
| by a call to `zx_object_get_info` using the topic `ZX_INFO_THREAD_STATS`. This |
| replacement provides more flexibility and better aligns with thread execution |
| time as a thread property. |
| * `ZX_CLOCK_UTC` - In the 2019 time syscalls UTC is managed in userspace by |
| the Fuchsia platform instead of directly by the kernel. Most language runtimes |
| have already been modified to read the userspace UTC clock so in most cases |
| calls to `zx_clock_get(ZX_CLOCK_UTC)` should be replaced by the standard UTC |
| calls in the language runtime. Where necessary the `zx_utc_reference_get` |
| function may be used to acquire a read only clock handle to pass into |
| `zx_clock_read`. Calls to `zx_clock_adjust(ZX_CLOCK_UTC)` may be replaced by a |
| call to `zx_clock_update` using a read/write clock handle acquired from |
| `fuchsia.time.Maintenance`. |
| |
| We propose a five step process for removing `zx_clock_get` and |
| `zx_clock_adjust`: |
| |
| 1. Update documentation to mark the syscalls as deprecated |
| 2. Migrate all known users to the replacement syscalls |
| 3. Stop maintaining kernel UTC clock and remove `zx_clock_adjust` |
| 4. Remove `zx_clock_get` declaration from the SDK |
| 5. Remove `zx_clock_get` implementation from Zircon |
| |
| ### Step 1 - Update documentation to mark the syscalls as deprecated |
| |
| This step is complete. The `zx_clock_get` and `zx_clock_adjust` calls are |
| clearly marked as deprecated and the documentation includes the alternative |
| solutions that we recommend above. |
| |
| ### Step 2 - Migrate all known users to the replacement syscalls |
| |
| This step is in progress. [fxr/433865](https://fxrev.dev/433865) recently moved |
| the standard language runtime UTC functions to the userspace UTC clock. This has |
| removed the majority of `zx_clock_get` usages but a long tail remains from a |
| wide range of different call sites across different repositories. |
| |
| We will burn down these remaining usages across stem and the petals in Global |
| Integration using code search to locate the calls and the |
| `syscalls_zx_clock_get_type_*` kcounters to track our progress. This will be a |
| lengthy process given the resources available and the fact that rolling an |
| upstream change to downstream repositories can often take weeks or months. |
| |
| Where a language runtime provides a wrapper around `zx_clock_get` or |
| `zx_clock_adjust` (for example the `fuchsia_zircon::Time::get` function |
| in Rust) we will remove each wrapper once no more clients are using it. |
| |
| ### Step 3 - Stop maintaining kernel UTC clock and remove `zx_clock_adjust` |
| |
| Maintaining an accurate time in `ZX_CLOCK_UTC` requires calls to `zx_clock_get` |
| and `zx_clock_adjust` from drivers and from several test components. These calls |
| will no longer be possible after step 4 so we cease maintaining kernel UTC as a |
| separate step. |
| |
| In step 3 we will remove the `ZX_CLOCK_UTC` synchronization, cause a crash |
| for any clients that attempt to read `ZX_CLOCK_UTC`, and remove the |
| `zx_clock_adjust` syscall entirely (this syscall is only used for setting UTC |
| and only invoked by a small number of privileged clients). |
| |
| After step 2 we should have already high confidence that there are no remaining |
| components using UTC in Global Integration, but causing a client crash on read |
| attempts lets us detect any omissions quickly. |
| |
| Specifically we will: |
| |
| 1. Remove all tests that verify `ZX_CLOCK_UTC`. |
| 2. Modify `zx_clock_get(ZX_CLOCK_UTC)` to flag the caller as a policy violator. |
| 2. Remove the calls to `zx_clock_adjust` from the real time clock drivers (and |
| remove the fallback RTC driver entirely since this was its only purpose) |
| 3. Remove `zx_clock_adjust` entirely. |
| |
| ### Step 4 - Remove `zx_clock_get` declaration from the SDK |
| |
| After step 3 we may have succeeded in removing all calls to `zx_clock_get` at |
| head but still need to support older prebuilt binaries that depend on |
| `zx_clock_get`. In this case we will remove the `zx_clock_get` declaration in |
| the SDK without removing the zircon implementation. At this stage any attempt to |
| compile code using the `zx_clock_get` will lead to a compilation failure. |
| |
| If no prebuilt binaries depend on `zx_clock_get` we will proceed directly to |
| step 5. |
| |
| ### Step 5 - Remove `zx_clock_get` implementation from Zircon |
| |
| Once no prebuilt binaries depend on `zx_clock_get` (as determined by their |
| symbol imports) we will remove `zx_clock_get` entirely, along with the |
| associated documentation. |
| |
| |
| ## Performance |
| |
| This proposal will lead to a negligible increase in overall system performance |
| by encouraging more widespread use of the more efficient |
| `zx_clock_get_monotonic` syscall and simplifying the operation the RTC drivers. |
| |
| |
| ## Security considerations |
| |
| This proposal does not impact the security of managing monotonic or thread time. |
| |
| In other operating systems UTC management vulnerabilities have been exploited to |
| perform various rollback attacks. This proposal improves the security of |
| managing UTC time by providing more fine grained access control. |
| |
| When using the `zx_clock_adjust` syscall the root resource is required to change |
| UTC time. This means a component that needs the ability to adjust time also |
| gains powerful unrelated capabilities and it means any component with the root |
| resource has the power to modify UTC whether it needs this power or not. |
| |
| Once this proposal is implemented, the only way to modify UTC will be through |
| the read/write clock handle distributed via `fuchsia.utc.Maintenance`. This |
| protocol is explicitly routed to only the components that need it and they |
| gain no additional capabilities along with this handle. |
| |
| |
| ## Privacy considerations |
| |
| This proposal does not impact privacy at the time of implementation. |
| |
| This proposal would enable the removal of UTC time as an ambient authority in |
| the future (a process could be launched without the userspace UTC clock handle |
| and would no longer have access to the kernel UTC clock). Potentially this could |
| be used to increase privacy for certain types of data processing. |
| |
| |
| ## Testing |
| |
| Each of the time management syscalls and the time synchronization infrastructure |
| that depends on them are covered by unit, integration, and end to end tests |
| today. These tests would be simplified somewhat by the removal of the two |
| syscalls and the second UTC clock. |
| |
| |
| ## Documentation |
| |
| Documentation updates are included in the implementation section above. |
| |
| |
| ## Drawbacks, alternatives, and unknowns |
| |
| The costs of this proposal are small - we estimate a few hours a week work from |
| 2-3 engineers in the component platform and kernel teams over a period of 1-3 |
| quarters. |
| |
| The alternatives mainly revolve around not cleaning up this technical debt or |
| cleaning up less of this technical debt; for example it would be possible to |
| stop maintaining the kernel UTC clock but not remove the associated syscalls. |
| These alternatives reduce cost in the short term but significantly increase it |
| in the long term. |
| |
| |
| ## Prior art and references |
| |
| [kernel_objects/clock](/docs/reference/kernel_objects/clock.md) provides a clear |
| overview of the operation of userspace clocks and is recommended reading. |