From b6887d70ace63d7b3a146d6981bbdf423c31ca5b Mon Sep 17 00:00:00 2001 From: Kunal Mehta Date: Thu, 14 Nov 2024 18:58:29 -0500 Subject: [PATCH] WIP: Script to upgrade from focal to noble The script is split into various stages where progress is tracked on-disk. The script is able to resume where it was at any point, and needs to, given multiple reboots in the middle. The new noble-upgrade.json file shipped in the securedrop-config package is used to control the upgrade process. Fixes #7332. --- Cargo.lock | 92 +++- noble-migration/Cargo.toml | 3 + noble-migration/files/apt_freedom_press.list | 1 + noble-migration/files/sources.list | 13 + noble-migration/files/ubuntu.sources | 11 + noble-migration/src/bin/upgrade.rs | 470 ++++++++++++++++++ .../usr/share/securedrop/noble-upgrade.json | 10 + securedrop/debian/rules | 3 +- supply-chain/audits.toml | 14 + supply-chain/imports.lock | 114 ++++- 10 files changed, 718 insertions(+), 13 deletions(-) create mode 100644 noble-migration/files/apt_freedom_press.list create mode 100644 noble-migration/files/sources.list create mode 100644 noble-migration/files/ubuntu.sources create mode 100644 noble-migration/src/bin/upgrade.rs create mode 100644 securedrop/debian/config/usr/share/securedrop/noble-upgrade.json diff --git a/Cargo.lock b/Cargo.lock index 3e6b176c92..36251fb17b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -113,6 +113,12 @@ version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bzip2" version = "0.4.4" @@ -263,6 +269,25 @@ dependencies = [ "log", ] +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "env_filter", + "log", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -637,9 +662,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "memchr" @@ -682,6 +707,9 @@ name = "noble-migration" version = "0.1.0" dependencies = [ "anyhow", + "env_logger", + "log", + "rand", "rustix", "serde", "serde_json", @@ -796,6 +824,15 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + [[package]] name = "precomputed-hash" version = "0.1.1" @@ -880,6 +917,36 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -1550,6 +1617,27 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "zerofrom" version = "0.1.4" diff --git a/noble-migration/Cargo.toml b/noble-migration/Cargo.toml index 23b92fd926..1a11fd4893 100644 --- a/noble-migration/Cargo.toml +++ b/noble-migration/Cargo.toml @@ -5,6 +5,9 @@ edition = "2021" [dependencies] anyhow = "1.0.93" +env_logger = { version = "0.11.5", default-features = false } +log = "0.4.22" +rand = "0.8.5" rustix = { version = "0.38.40", features = ["process"] } serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.132" diff --git a/noble-migration/files/apt_freedom_press.list b/noble-migration/files/apt_freedom_press.list new file mode 100644 index 0000000000..12e72a6778 --- /dev/null +++ b/noble-migration/files/apt_freedom_press.list @@ -0,0 +1 @@ +deb [arch=amd64] https://apt.freedom.press noble main diff --git a/noble-migration/files/sources.list b/noble-migration/files/sources.list new file mode 100644 index 0000000000..df96219dc8 --- /dev/null +++ b/noble-migration/files/sources.list @@ -0,0 +1,13 @@ +## newer versions of the distribution. +deb http://archive.ubuntu.com/ubuntu/ noble main + +## newer versions of the distribution. +deb http://archive.ubuntu.com/ubuntu/ noble universe + +## Major bug fix updates produced after the final release of the +## distribution. +deb http://archive.ubuntu.com/ubuntu/ noble-updates main + +### Security fixes for distribution packages +deb http://security.ubuntu.com/ubuntu noble-security main +deb http://security.ubuntu.com/ubuntu noble-security universe diff --git a/noble-migration/files/ubuntu.sources b/noble-migration/files/ubuntu.sources new file mode 100644 index 0000000000..bcd1f501fe --- /dev/null +++ b/noble-migration/files/ubuntu.sources @@ -0,0 +1,11 @@ +Types: deb +URIs: http://archive.ubuntu.com/ubuntu/ +Suites: noble noble-updates +Components: main universe restricted multiverse +Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg + +Types: deb +URIs: http://security.ubuntu.com/ubuntu/ +Suites: noble-security +Components: main universe restricted multiverse +Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg diff --git a/noble-migration/src/bin/upgrade.rs b/noble-migration/src/bin/upgrade.rs new file mode 100644 index 0000000000..377bf324e7 --- /dev/null +++ b/noble-migration/src/bin/upgrade.rs @@ -0,0 +1,470 @@ +//! Migrate a SecureDrop server from focal to noble +//! +//! This script should never be run directly, only via the +//! systemd service. +use anyhow::{bail, Context, Result}; +use log::{debug, error, info}; +use rand::{thread_rng, Rng}; +use rustix::process::geteuid; +use serde::{Deserialize, Serialize}; +use std::{ + collections::HashMap, + fs::{self, Permissions}, + os::unix::{fs::PermissionsExt, process::ExitStatusExt}, + path::Path, + process::{self, Command, ExitCode}, + thread::sleep, + time::Duration, +}; + +const CONFIG_PATH: &str = "/usr/share/securedrop/noble-upgrade.json"; +const STATE_PATH: &str = "/etc/securedrop-noble-migration.json"; +const MON_OSSEC_CONFIG: &str = "/var/ossec/etc/ossec.conf"; + +#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)] +enum Stage { + None, + PendingUpdates, + MigrationCheck, + DisableApache2, + Backup, + Marker, + SuspendOSSEC, + DisableUnattendedUpdates, + ChangeAptSources, + AptGetUpdate, + AptGetUpgradeNoNew, + AptGetFullUpgrade, + ReenableUnattendedUpdates, + ReenableOSSEC, + Reboot, + SwitchUbuntuSources, + IntegrityCheck, + ReenableApache2, + RemoveBackup, + Done, +} + +#[derive(Serialize, Deserialize)] +struct State { + finished: Stage, + bucket: usize, +} + +impl State { + fn load() -> Result { + if !Path::new(STATE_PATH).exists() { + debug!("State file, {}, doesn't exist; state=None", STATE_PATH); + let mut rng = thread_rng(); + let state = State { + finished: Stage::None, + bucket: rng.gen_range(1..=5), + }; + // Persist the randomly selected bucket + state.save()?; + return Ok(state); + } + debug!("Loading state from {}", STATE_PATH); + // FIXME: what if this fails? + serde_json::from_str( + &fs::read_to_string(STATE_PATH) + .context("Unable to read STATE_PATH")?, + ) + .context("Deserializing STATE_PATH failed") + } + + fn set(&mut self, stage: Stage) -> Result<()> { + debug!("Finished stage {stage:?}"); + self.finished = stage; + self.save() + } + + fn save(&self) -> Result<()> { + fs::write( + STATE_PATH, + serde_json::to_string(self).context("Failed to serialize state")?, + ) + .context("Failed to write state") + } +} + +fn run_next_stage(state: &mut State) -> Result<()> { + match state.finished { + Stage::None => { + pending_updates(state)?; + // n.b. this is unreachable because we've already rebooted + state.set(Stage::PendingUpdates)?; + } + Stage::PendingUpdates => { + migration_check()?; + state.set(Stage::MigrationCheck)?; + } + Stage::MigrationCheck => { + disable_apache2()?; + state.set(Stage::DisableApache2)?; + } + Stage::DisableApache2 => { + backup()?; + state.set(Stage::Backup)?; + } + Stage::Backup => { + suspend_ossec()?; + state.set(Stage::Marker)?; + } + Stage::Marker => { + marker()?; + state.set(Stage::SuspendOSSEC)?; + } + Stage::SuspendOSSEC => { + disable_unattended_updates()?; + state.set(Stage::DisableUnattendedUpdates)?; + } + Stage::DisableUnattendedUpdates => { + change_apt_sources()?; + state.set(Stage::ChangeAptSources)?; + } + Stage::ChangeAptSources => { + apt_get_update()?; + state.set(Stage::AptGetUpdate)?; + } + Stage::AptGetUpdate => { + apt_get_upgrade_no_new()?; + state.set(Stage::AptGetUpgradeNoNew)?; + } + Stage::AptGetUpgradeNoNew => { + apt_get_full_upgrade()?; + state.set(Stage::AptGetFullUpgrade)?; + } + Stage::AptGetFullUpgrade => { + reenable_unattended_updates()?; + state.set(Stage::ReenableUnattendedUpdates)?; + } + Stage::ReenableUnattendedUpdates => { + reenable_ossec()?; + state.set(Stage::ReenableOSSEC)?; + } + Stage::ReenableOSSEC => { + reboot(state)?; + // n.b. this is unreachable because we've already rebooted + state.set(Stage::Reboot)?; + } + Stage::Reboot => { + switch_ubuntu_sources()?; + state.set(Stage::SwitchUbuntuSources)?; + } + Stage::SwitchUbuntuSources => { + integrity_check()?; + state.set(Stage::IntegrityCheck)?; + } + Stage::IntegrityCheck => { + reenable_apache2()?; + state.set(Stage::ReenableApache2)?; + } + Stage::ReenableApache2 => { + remove_backup()?; + state.set(Stage::RemoveBackup)?; + } + Stage::RemoveBackup => { + state.set(Stage::Done)?; + } + Stage::Done => {} + } + Ok(()) +} + +/// A wrapper to roughly implement Python's subprocess.check_call/check_output +fn check_call(binary: &str, args: &[&str]) -> Result { + debug!("Running: {binary} {}", args.join(" ")); + let output = Command::new(binary) + .args(args) + .env("DEBIAN_FRONTEND", "noninteractive") + .output() + .context(format!("failed to spawn/execute '{binary}'"))?; + if output.status.success() { + debug!("Finished running: {binary} {}", args.join(" ")); + // FIXME: should we use from_utf8_lossy here? + let stdout = String::from_utf8(output.stdout) + .context("stdout contains non-utf8 bytes")?; + debug!("{stdout}"); + Ok(stdout) + } else { + debug!("Errored running: {binary} {}", args.join(" ")); + // Figure out why it failed by looking at the exit code, and if none, + // look at if it was a signal + let exit = match output.status.code() { + Some(code) => format!("exit code {code}"), + None => match output.status.signal() { + Some(signal) => format!("terminated by signal {signal}"), + None => "for an unknown reason".to_string(), + }, + }; + error!("{}", String::from_utf8_lossy(&output.stderr)); + bail!("running '{binary}' failed; {exit}") + } +} + +/// Check if the current server is the mon server by +/// looking for the securedrop-ossec-server package +fn is_mon_server() -> bool { + Path::new("/usr/share/doc/securedrop-ossec-server/copyright").exists() +} + +fn pending_updates(state: &mut State) -> Result<()> { + info!("Applying any pending updates..."); + check_call("apt-get", &["update"])?; + check_call("unattended-upgrade", &[])?; + state.set(Stage::PendingUpdates)?; + check_call("systemctl", &["reboot"])?; + // Because we've initiated the reboot, do a hard stop here to ensure that + // we don't keep moving forward if the reboot doesn't happen instantly + process::exit(0); +} + +fn migration_check() -> Result<()> { + info!("Checking pre-migration steps..."); + // TODO: consider just invoking the Rust code directly + check_call("systemctl", &["start", "securedrop-noble-migration-check"])?; + loop { + // Wait for the service to finish + let output = check_call( + "systemctl", + &["is-active", "securedrop-noble-migration-check"], + )?; + if output == "active" { + sleep(Duration::from_secs(1)); + } else { + break; + } + } + let data: HashMap = serde_json::from_str( + &fs::read_to_string("/etc/securedrop-noble-migration-check.json")?, + )?; + if data.contains_key("error") { + bail!("Migration check errored") + } else if data.values().any(|val| val == &false) { + bail!("Migration check failed") + } + + Ok(()) +} + +fn disable_apache2() -> Result<()> { + if is_mon_server() { + return Ok(()); + } + info!("Stopping web server for duration of upgrade..."); + check_call("systemctl", &["mask", "apache2"])?; + Ok(()) +} + +fn backup() -> Result<()> { + info!("Taking a backup..."); + // Create a root-only directory to store the backup + fs::create_dir("/var/lib/securedrop-backups")?; + let permissions = Permissions::from_mode(0o700); + fs::set_permissions("/var/lib/securedrop-backups", permissions)?; + check_call( + "/usr/bin/securedrop-app-backup.py", + &["--dest", "/var/lib/securedrop-backups"], + )?; + Ok(()) +} + +fn marker() -> Result<()> { + info!("Writing upgrade marker file..."); + fs::write("/etc/securedrop-upgraded-from-focal", "yes") + .context("failed to write upgrade marker file") +} + +fn suspend_ossec() -> Result<()> { + if !is_mon_server() { + return Ok(()); + } + info!("Temporarily suspending most OSSEC notifications..."); + let current = fs::read_to_string(MON_OSSEC_CONFIG)?; + let new = current.replace( + "7", + "15", + ); + fs::write(MON_OSSEC_CONFIG, new)?; + check_call("systemctl", &["restart", "ossec"])?; + Ok(()) +} + +fn disable_unattended_updates() -> Result<()> { + info!("Temporarily disabling background updates..."); + check_call("systemctl", &["mask", "unattended-upgrades"])?; + check_call("systemctl", &["mask", "apt-daily"])?; + check_call("systemctl", &["mask", "apt-daily-upgrade"])?; + Ok(()) +} + +fn change_apt_sources() -> Result<()> { + info!("Switching APT sources to noble..."); + fs::write( + "/etc/apt/sources.list", + include_str!("../../files/sources.list"), + )?; + fs::write( + "/etc/apt/sources.list.d/apt_freedom_press.list", + include_str!("../../files/apt_freedom_press.list"), + )?; + Ok(()) +} + +fn apt_get_update() -> Result<()> { + info!("Updating APT cache..."); + check_call("apt-get", &["update"])?; + Ok(()) +} + +fn apt_get_upgrade_no_new() -> Result<()> { + info!("Upgrading APT packages (first pass)..."); + check_call( + "apt-get", + &[ + "upgrade", + "--without-new-pkgs", + "--force-confold", + "--force-confdef", + ], + )?; + Ok(()) +} + +fn apt_get_full_upgrade() -> Result<()> { + info!("Upgrading APT packages (second pass)..."); + check_call( + "apt-get", + &["full-upgrade", "--force-confold", "--force-confdef"], + )?; + Ok(()) +} + +fn reenable_unattended_updates() -> Result<()> { + info!("Re-enabling background updates..."); + check_call("systemctl", &["unmask", "unattended-upgrades"])?; + check_call("systemctl", &["unmask", "apt-daily"])?; + check_call("systemctl", &["unmask", "apt-daily-upgrade"])?; + Ok(()) +} + +fn reenable_ossec() -> Result<()> { + if !is_mon_server() { + return Ok(()); + } + info!("Re-enabling OSSEC notifications..."); + let current = fs::read_to_string(MON_OSSEC_CONFIG)?; + let new = current.replace( + "15", + "7", + ); + fs::write(MON_OSSEC_CONFIG, new)?; + check_call("systemctl", &["restart", "ossec"])?; + Ok(()) +} + +fn reboot(state: &mut State) -> Result<()> { + info!("Rebooting!"); + state.set(Stage::Reboot)?; + check_call("systemctl", &["reboot"])?; + // Because we've initiated the reboot, do a hard stop here to ensure that + // we don't keep moving forward if the reboot doesn't happen instantly + process::exit(0); +} + +fn switch_ubuntu_sources() -> Result<()> { + info!("Switching APT sources format..."); + fs::write( + "/etc/apt/sources.list.d/ubuntu.sources", + include_str!("../../files/ubuntu.sources"), + ) + .context("failed to write ubuntu.sources")?; + fs::remove_file("/etc/apt/sources.list") + .context("failed to remove sources.list")?; + Ok(()) +} + +fn integrity_check() -> Result<()> { + info!("Running integrity check post-upgrade..."); + // FIXME: do something here + // FIXME: check no failing systemd units + // FIXME: check firewall is up + Ok(()) +} + +fn reenable_apache2() -> Result<()> { + if is_mon_server() { + return Ok(()); + } + info!("Starting web server..."); + check_call("systemctl", &["unmask", "apache2"])?; + Ok(()) +} + +fn remove_backup() -> Result<()> { + info!("Deleting backup..."); + fs::remove_dir_all("/var/lib/securedrop-backups")?; + Ok(()) +} + +#[derive(Deserialize)] +struct UpgradeConfig { + app: HostUpgradeConfig, + mon: HostUpgradeConfig, +} + +#[derive(Deserialize)] +struct HostUpgradeConfig { + enabled: bool, + bucket: usize, +} + +fn should_upgrade(state: &State) -> Result { + let config: UpgradeConfig = serde_json::from_str( + &fs::read_to_string(CONFIG_PATH) + .context("failed to read CONFIG_PATH")?, + ) + .context("failed to deserialize CONFIG_PATH")?; + let for_host = if is_mon_server() { + &config.mon + } else { + &config.app + }; + if !for_host.enabled { + info!("Auto-upgrades are disabled"); + return Ok(false); + } + if for_host.bucket > state.bucket { + info!( + "Auto-upgrades are enabled, but our bucket hasn't been enabled yet" + ); + return Ok(false); + } + + Ok(true) +} + +fn main() -> Result { + // TODO: set a format here, default to info + env_logger::init(); + + if !geteuid().is_root() { + error!("This script must be run as root"); + return Ok(ExitCode::FAILURE); + } + + let mut state = State::load()?; + if !should_upgrade(&state)? { + return Ok(ExitCode::SUCCESS); + } + info!("Starting migration from state: {:?}", state.finished); + loop { + run_next_stage(&mut state)?; + if state.finished == Stage::Done { + break; + } + } + + Ok(ExitCode::SUCCESS) +} diff --git a/securedrop/debian/config/usr/share/securedrop/noble-upgrade.json b/securedrop/debian/config/usr/share/securedrop/noble-upgrade.json new file mode 100644 index 0000000000..4c0a630183 --- /dev/null +++ b/securedrop/debian/config/usr/share/securedrop/noble-upgrade.json @@ -0,0 +1,10 @@ +{ + "app": { + "enabled": false, + "bucket": 0 + }, + "mon": { + "enabled": false, + "bucket": 0 + } +} diff --git a/securedrop/debian/rules b/securedrop/debian/rules index 548660c328..ef980b230b 100755 --- a/securedrop/debian/rules +++ b/securedrop/debian/rules @@ -22,7 +22,8 @@ override_dh_auto_install: cd /srv/rust/noble-migration && cargo build --release --locked && \ cd /srv/securedrop && \ mkdir -p ./debian/securedrop-config/usr/bin && \ - mv /srv/rust/target/release/check ./debian/securedrop-config/usr/bin/securedrop-noble-migration-check + mv /srv/rust/target/release/check ./debian/securedrop-config/usr/bin/securedrop-noble-migration-check && \ + mv /srv/rust/target/release/upgrade ./debian/securedrop-config/usr/bin/securedrop-noble-upgrade # Build redwood wheel python3 /srv/rust/redwood/build-wheel.py --release --redwood /srv/rust/redwood --target /srv/rust/target # Set up virtualenv and install dependencies diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml index a420308c26..876a482cca 100644 --- a/supply-chain/audits.toml +++ b/supply-chain/audits.toml @@ -300,6 +300,20 @@ start = "2019-03-19" end = "2024-05-02" notes = "Rust Project member" +[[trusted.env_filter]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2024-01-19" +end = "2025-06-02" +notes = "Rust Project member" + +[[trusted.env_logger]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2022-11-24" +end = "2025-06-02" +notes = "Rust Project member" + [[trusted.equivalent]] criteria = "safe-to-deploy" user-id = 539 # Josh Stone (cuviper) diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index ce168f3c3e..ccf9910087 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -64,6 +64,20 @@ user-id = 539 user-login = "cuviper" user-name = "Josh Stone" +[[publisher.env_filter]] +version = "0.1.2" +when = "2024-07-25" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + +[[publisher.env_logger]] +version = "0.11.5" +when = "2024-07-25" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + [[publisher.equivalent]] version = "1.0.1" when = "2023-07-10" @@ -448,6 +462,13 @@ criteria = "safe-to-run" delta = "2.3.2 -> 2.4.0" aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" +[[audits.google.audits.byteorder]] +who = "danakj " +criteria = "safe-to-deploy" +version = "1.5.0" +notes = "Unsafe review in https://crrev.com/c/5838022" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + [[audits.google.audits.cc]] who = "George Burgess IV " criteria = "safe-to-run" @@ -562,16 +583,16 @@ version = "1.4.0" aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" [[audits.google.audits.log]] -who = "ChromeOS" -criteria = "safe-to-run" -version = "0.4.17" -aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" +who = "danakj " +criteria = "safe-to-deploy" +version = "0.4.22" +notes = """ +Unsafe review in https://docs.google.com/document/d/1IXQbD1GhTRqNHIGxq6yy7qHqxeO4CwN5noMFXnqyDIM/edit?usp=sharing -[[audits.google.audits.log]] -who = "George Burgess IV " -criteria = "safe-to-run" -delta = "0.4.17 -> 0.4.20" -aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" +Unsafety is generally very well-documented, with one exception, which we +describe in the review doc. +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" [[audits.google.audits.memoffset]] who = "Dennis Kempin " @@ -609,6 +630,24 @@ criteria = "safe-to-run" version = "0.3.26" aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" +[[audits.google.audits.ppv-lite86]] +who = "danakj@chromium.org" +criteria = "safe-to-run" +version = "0.2.17" +notes = """ +Reviewed in https://crrev.com/c/5171063 + +Previously reviewed during security review and the audit is grandparented in. +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.ppv-lite86]] +who = "danakj " +criteria = "safe-to-run" +delta = "0.2.17 -> 0.2.20" +notes = "Using zerocopy to reduce unsafe usage." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + [[audits.google.audits.proc-macro2]] who = "Adrian Taylor " criteria = "safe-to-deploy" @@ -704,6 +743,29 @@ The delta just 1) inlines/expands `impl ToTokens` that used to be handled via """ aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" +[[audits.google.audits.rand]] +who = "danakj@chromium.org" +criteria = "safe-to-run" +version = "0.8.5" +notes = """ +Reviewed in https://crrev.com/c/5171063 + +Previously reviewed during security review and the audit is grandparented in. +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.rand_chacha]] +who = "Android Legacy" +criteria = "safe-to-run" +version = "0.3.1" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.rand_core]] +who = "Android Legacy" +criteria = "safe-to-run" +version = "0.6.4" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + [[audits.google.audits.same-file]] who = "Android Legacy" criteria = "safe-to-run" @@ -1421,7 +1483,7 @@ aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-ch [[audits.mozilla.audits.url]] who = "Valentin Gosu " criteria = "safe-to-deploy" -delta = "2.5.1 -> 2.5.3" +delta = "2.5.1 -> 2.5.4" aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" [[audits.mozilla.audits.utf16_iter]] @@ -1488,6 +1550,26 @@ criteria = "safe-to-deploy" delta = "0.7.3 -> 0.7.4" aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" +[[audits.mozilla.audits.zerocopy]] +who = "Alex Franchuk " +criteria = "safe-to-deploy" +version = "0.7.32" +notes = """ +This crate is `no_std` so doesn't use any side-effectful std functions. It +contains quite a lot of `unsafe` code, however. I verified portions of this. It +also has a large, thorough test suite. The project claims to run tests with +Miri to have stronger soundness checks, and also claims to use formal +verification tools to prove correctness. +""" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.zerocopy-derive]] +who = "Alex Franchuk " +criteria = "safe-to-deploy" +version = "0.7.32" +notes = "Clean, safe macros for zerocopy." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + [[audits.mozilla.audits.zerofrom]] who = "Makoto Kato " criteria = "safe-to-deploy" @@ -1580,3 +1662,15 @@ who = "Jack Grigg " criteria = "safe-to-deploy" delta = "1.16.0 -> 1.17.0" aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.zerocopy]] +who = "Daira-Emma Hopwood " +criteria = "safe-to-deploy" +delta = "0.7.32 -> 0.7.34" +aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" + +[[audits.zcash.audits.zerocopy-derive]] +who = "Daira-Emma Hopwood " +criteria = "safe-to-deploy" +delta = "0.7.32 -> 0.7.34" +aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml"