Skip to content

Wrong time reported when launched with firecracker #2548

Description

@archevel

If I run the below hermit os based app with firecracker it prints out:

SystemTime UNIX epoch: 943920000.015268000 s
SystemTime UTC date: 1999-11-30

I expected it to be something along the lines of:

SystemTime UNIX epoch: 1783697396.421537000 s
SystemTime UTC date: 2026-07-10

I used somthing like this as my firecracker.json:

{
  "boot-source": {
    "kernel_image_path": "<some-path-to>/hermit-loader-x86_64-linux",
    "initrd_path": "target/x86_64-unknown-hermit/release/example",
    "boot_args": "console=ttyS0"
  },
  "machine-config": {
    "vcpu_count": 1,
    "mem_size_mib": 64,
    "smt": false
  },
  "drives": []
}

And launched it with:

$ firecracker --no-api --config-file firecracker.json

Running it in qemu produces the expected outuput. The root cause is that Firecracker (and other minimal microVM monitors) expose no CMOS RTC, so Hermit's RTC-based boot clock reads garbage and lands in ~1999. The main reason this is an issue for me where this actually came up is that it breaks anything that validates certificate/token validity windows inside the guest.

#[cfg(target_os = "hermit")]
use hermit as _;

use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};

use time::OffsetDateTime;

fn main() {
    println!("booted");

    match SystemTime::now().duration_since(UNIX_EPOCH) {
        Ok(dur) => {
            println!(
                "SystemTime UNIX epoch: {}.{:09} s",
                dur.as_secs(),
                dur.subsec_nanos(),
            );
            match OffsetDateTime::from_unix_timestamp(dur.as_secs() as i64) {
                Ok(dt) => println!(
                    "SystemTime UTC date: {}-{:02}-{:02}",
                    dt.year(),
                    dt.month() as u8,
                    dt.day(),
                ),
                Err(e) => println!("timestamp out of range: {e}"),
            }
        }
        Err(e) => {
            // A clock before 1970 means SystemTime is uninitialised/garbage.
            println!(
                "SystemTime is BEFORE the UNIX epoch by {:?} \
                 (wall clock not set correctly)",
                e.duration(),
            );
        }
    }
}

To get around it I added code in systemtime.rs for getting the time from the kvmclock, which is what firecracker exposes. Happy to share it if you'd like!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions