Skip to content

Commit dfc2465

Browse files
committed
Fix memfd alignment
1 parent d1901f4 commit dfc2465

File tree

4 files changed

+40
-14
lines changed

4 files changed

+40
-14
lines changed

crates/bitwarden-crypto/src/store/backend/implementation/custom_alloc/linux_memfd_secret.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,24 @@ pub(crate) struct LinuxMemfdSecretAlloc;
66

77
impl LinuxMemfdSecretAlloc {
88
pub fn new() -> Option<Self> {
9-
// To test if memfd_secret is supported, we try to allocate a 1 byte and see if that succeeds.
9+
// To test if memfd_secret is supported, we try to allocate a 1 byte and see if that
10+
// succeeds.
1011
static IS_SUPPORTED: LazyLock<bool> = LazyLock::new(|| {
11-
let Some(ptr) = (unsafe { memsec::memfd_secret_sized(1) }) else {
12+
let Some(ptr): Option<NonNull<[u8]>> = (unsafe { memsec::memfd_secret_sized(1) })
13+
else {
1214
return false;
1315
};
16+
17+
// Check that the pointer is readable and writable
18+
let result = unsafe {
19+
let ptr = ptr.as_ptr() as *mut u8;
20+
*ptr = 30;
21+
*ptr += 107;
22+
*ptr == 137
23+
};
24+
1425
unsafe { memsec::free_memfd_secret(ptr) };
15-
true
26+
result
1627
});
1728

1829
(*IS_SUPPORTED).then_some(Self)
@@ -34,8 +45,23 @@ unsafe impl Allocator for LinuxMemfdSecretAlloc {
3445
});
3546
}
3647

37-
let ptr: NonNull<[u8]> = unsafe { memsec::memfd_secret_sized(layout.size()) }
38-
.expect("memfd_secret_sized failed");
48+
// Ensure the size we want to allocate is a multiple of the alignment,
49+
// so that both the start and end of the allocation are aligned.
50+
let layout = layout.pad_to_align();
51+
52+
let Some(ptr): Option<NonNull<[u8]>> =
53+
(unsafe { memsec::memfd_secret_sized(layout.size()) })
54+
else {
55+
return Err(AllocError);
56+
};
57+
58+
// Check that the pointer is aligned to the requested alignment.
59+
// This should never happen, but just in case, we free the memory and return an allocation
60+
// error.
61+
if (ptr.as_ptr() as *mut u8).align_offset(layout.align()) != 0 {
62+
unsafe { memsec::free_memfd_secret(ptr.as_ptr() as *mut u8) };
63+
return Err(AllocError);
64+
}
3965

4066
Ok(ptr)
4167
}

crates/bitwarden-crypto/src/store/backend/implementation/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ mod tests {
5959
let basic_store: Box<dyn StoreBackendDebug<TestSymmKey>> =
6060
Box::new(basic::BasicBackend::new());
6161

62-
let mlock_store: Box<dyn StoreBackendDebug<TestSymmKey>> =
62+
let memfd_store: Box<dyn StoreBackendDebug<TestSymmKey>> =
6363
Box::new(custom_alloc::CustomAllocBackend::new(
6464
custom_alloc::LinuxMemfdSecretAlloc::new().unwrap(),
6565
));
66-
compare_stores(100_000, basic_store, mlock_store);
66+
compare_stores(100_000, basic_store, memfd_store);
6767
}
6868

6969
/// This function will perform a number of random operations on two stores,
@@ -88,11 +88,11 @@ mod tests {
8888
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Operation {
8989
match rng.gen_range(0..=4) {
9090
0 => Operation::Upsert(
91-
TestSymmKey::A(rng.gen_range(0..=10)),
91+
TestSymmKey::A(rng.gen_range(0..=1000)),
9292
SymmetricCryptoKey::generate(rng),
9393
),
94-
1 => Operation::Get(TestSymmKey::A(rng.gen_range(0..=10))),
95-
2 => Operation::Remove(TestSymmKey::A(rng.gen_range(0..=10))),
94+
1 => Operation::Get(TestSymmKey::A(rng.gen_range(0..=1000))),
95+
2 => Operation::Remove(TestSymmKey::A(rng.gen_range(0..=1000))),
9696
3 => Operation::Clear,
9797
// This one has to be constant as we can't capture variables
9898
4 => Operation::Retain(|key| match key {

crates/bitwarden-crypto/src/store/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ pub(crate) mod tests {
360360

361361
// Create some test data
362362
let data: Vec<_> = (0..300usize)
363-
.map(|n| DataView(format!("Test {}", n), TestSymmKey::A((n % 15) as u8)))
363+
.map(|n| DataView(format!("Test {}", n), TestSymmKey::A((n % 15) as u32)))
364364
.collect();
365365

366366
// Encrypt the data

crates/bitwarden-crypto/src/traits/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@ pub(crate) mod tests {
1818
key_ids! {
1919
#[symmetric]
2020
pub enum TestSymmKey {
21-
A(u8),
21+
A(u32),
2222

2323
// We only support one variant value,
2424
// but that value can be a tuple
2525
B((u8, u8)),
2626

2727
#[local]
28-
C(u8),
28+
C(u16),
2929
}
3030

3131
#[asymmetric]
3232
pub enum TestAsymmKey {
33-
A(u8),
33+
A(u16),
3434
B,
3535
#[local]
3636
C(&'static str),

0 commit comments

Comments
 (0)