From 479e6ad5c6a4c954553cad08a4b12c00a518b1f2 Mon Sep 17 00:00:00 2001 From: edef Date: Mon, 24 Mar 2025 20:32:12 +0000 Subject: [PATCH] fix(snix/castore/import): don't allocate parent repeatedly We use hashbrown directly (instead of through std::collections::HashMap) so that we can use HashMap::entry_ref, which only allocates if the entry is not yet occupied. This implicitly switches our hash to a less long-term DoS-resistant one (foldhash rather than SipHash), but we don't usually face HashDoS risks when ingesting archives. Change-Id: I3e7fc2cd08d96380cd9fd62bfcfe6cd24698bc9a Reviewed-on: https://cl.snix.dev/c/snix/+/30277 Reviewed-by: Florian Klink Tested-by: besadii --- snix/Cargo.lock | 1 + snix/Cargo.nix | 4 ++++ snix/castore/Cargo.toml | 1 + snix/castore/src/import/mod.rs | 4 ++-- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/snix/Cargo.lock b/snix/Cargo.lock index ebb3dec78..6b911776f 100644 --- a/snix/Cargo.lock +++ b/snix/Cargo.lock @@ -4186,6 +4186,7 @@ dependencies = [ "fastcdc", "fuse-backend-rs", "futures", + "hashbrown 0.15.2", "hex-literal", "hyper-util", "libc", diff --git a/snix/Cargo.nix b/snix/Cargo.nix index bd8003e82..5daabfeaf 100644 --- a/snix/Cargo.nix +++ b/snix/Cargo.nix @@ -13640,6 +13640,10 @@ rec { name = "futures"; packageId = "futures"; } + { + name = "hashbrown"; + packageId = "hashbrown 0.15.2"; + } { name = "hyper-util"; packageId = "hyper-util"; diff --git a/snix/castore/Cargo.toml b/snix/castore/Cargo.toml index 805ea8369..ea7ac56a3 100644 --- a/snix/castore/Cargo.toml +++ b/snix/castore/Cargo.toml @@ -55,6 +55,7 @@ vmm-sys-util = { workspace = true, optional = true } virtio-bindings = { workspace = true, optional = true } wu-manber.workspace = true auto_impl = "1.2.0" +hashbrown = "0.15.2" [build-dependencies] prost-build.workspace = true diff --git a/snix/castore/src/import/mod.rs b/snix/castore/src/import/mod.rs index 6b5e4e6bd..dac422c11 100644 --- a/snix/castore/src/import/mod.rs +++ b/snix/castore/src/import/mod.rs @@ -10,7 +10,7 @@ use crate::{B3Digest, Directory, Node}; use futures::{Stream, StreamExt}; use tracing::Level; -use std::collections::HashMap; +use hashbrown::HashMap; use tracing::instrument; mod error; @@ -131,7 +131,7 @@ where // record node in parent directory, creating a new [Directory] if not there yet. directories - .entry(parent.to_owned()) + .entry_ref(parent) .or_default() .add(name, node) .map_err(|e| {