Skip to content

Commit

Permalink
Improve wtmp record mangling.
Browse files Browse the repository at this point in the history
This fixes two problems with the current wtmp/utmp record mangling.
First it is not idempotent, the system's notion of boot time is
set to the current time of day whenever sled agent confirms that
time is synchronised. Secondly, this is only approximate even for the
first sled agent start, but it's plain wrong if sled agent restarts
later.

In conjunction with changes to stlouis, the `tmpx` utility is now
able to process all zones itself, and uses the true system boot
time for each zone when updating records.

Fixes: #3514
  • Loading branch information
citrus-it committed Nov 17, 2023
1 parent ca9d90a commit 72054fe
Showing 1 changed file with 10 additions and 35 deletions.
45 changes: 10 additions & 35 deletions sled-agent/src/services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,11 @@ use sled_storage::manager::StorageHandle;
use slog::Logger;
use std::collections::BTreeMap;
use std::collections::HashSet;
use std::iter;
use std::iter::FromIterator;
use std::net::{IpAddr, Ipv6Addr, SocketAddr};
use std::str::FromStr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};
use tokio::io::AsyncWriteExt;
use tokio::sync::oneshot;
use tokio::sync::Mutex;
Expand Down Expand Up @@ -2384,10 +2382,7 @@ impl ServiceManager {
Ok(())
}

pub fn boottime_rewrite<'a>(
&self,
zones: impl Iterator<Item = &'a RunningZone>,
) {
pub fn boottime_rewrite(&self) {
if self
.inner
.time_synced
Expand All @@ -2398,33 +2393,13 @@ impl ServiceManager {
return;
}

let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("SystemTime before UNIX EPOCH");

info!(self.inner.log, "Setting boot time to {:?}", now);

let files: Vec<Utf8PathBuf> = zones
.map(|z| z.root())
.chain(iter::once(Utf8PathBuf::from("/")))
.flat_map(|r| [r.join("var/adm/utmpx"), r.join("var/adm/wtmpx")])
.collect();

for file in files {
let mut command = std::process::Command::new(PFEXEC);
let cmd = command.args(&[
"/usr/platform/oxide/bin/tmpx",
&format!("{}", now.as_secs()),
&file.as_str(),
]);
match execute(cmd) {
Err(e) => {
warn!(self.inner.log, "Updating {} failed: {}", &file, e);
}
Ok(_) => {
info!(self.inner.log, "Updated {}", &file);
}
}
// Call out to the 'tmpx' utility program which will rewrite the wtmpx
// and utmpx databases in every zone, including the global zone, to
// reflect the adjusted system boot time.
let mut command = std::process::Command::new(PFEXEC);
let cmd = command.args(&["/usr/platform/oxide/bin/tmpx", "-Z"]);
if let Err(e) = execute(cmd) {
warn!(self.inner.log, "Updating [wu]tmpx databases failed: {}", e);
}
}

Expand All @@ -2433,7 +2408,7 @@ impl ServiceManager {

if let Some(true) = self.inner.skip_timesync {
info!(self.inner.log, "Configured to skip timesync checks");
self.boottime_rewrite(existing_zones.values());
self.boottime_rewrite();
return Ok(TimeSync {
sync: true,
ref_id: 0,
Expand Down Expand Up @@ -2487,7 +2462,7 @@ impl ServiceManager {
&& correction.abs() <= 0.05;

if sync {
self.boottime_rewrite(existing_zones.values());
self.boottime_rewrite();
}

Ok(TimeSync {
Expand Down

0 comments on commit 72054fe

Please sign in to comment.