diff options
| author | Linus Färnstrand <faern@faern.net> | 2021-10-01 13:17:12 +0200 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2021-10-01 14:27:27 +0200 |
| commit | 7e716345c10255110fedab25d8a1e0dd7fa4e0a1 (patch) | |
| tree | f88875c4b0f3685c9c5002638ea14fe7b0d857bc | |
| parent | fd4dfa6d250d1351afaf8148a28927a7f2f978f8 (diff) | |
| download | mullvadvpn-7e716345c10255110fedab25d8a1e0dd7fa4e0a1.tar.xz mullvadvpn-7e716345c10255110fedab25d8a1e0dd7fa4e0a1.zip | |
Clarify safety around struct_as_slice function
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/wireguard_kernel/wg_message.rs | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/talpid-core/src/tunnel/wireguard/wireguard_kernel/wg_message.rs b/talpid-core/src/tunnel/wireguard/wireguard_kernel/wg_message.rs index 1e587712cc..b2687d9ffd 100644 --- a/talpid-core/src/tunnel/wireguard/wireguard_kernel/wg_message.rs +++ b/talpid-core/src/tunnel/wireguard/wireguard_kernel/wg_message.rs @@ -386,12 +386,13 @@ impl Nla for PeerNla { Flags(value) | ProtocolVersion(value) => NativeEndian::write_u32(buffer, *value), Endpoint(endpoint) => match &endpoint { InetAddr::V4(sockaddr_in) => { - let slice = unsafe { struct_as_slice(sockaddr_in) }; + // SAFETY: `sockaddr_in` has no padding bytes buffer - .write(slice) + .write(unsafe { struct_as_slice(sockaddr_in) }) .expect("Buffer too small for sockaddr_in"); } InetAddr::V6(sockaddr_in6) => { + // SAFETY: `sockaddr_in` has no padding bytes buffer .write(unsafe { struct_as_slice(sockaddr_in6) }) .expect("Buffer too small for sockaddr_in6"); @@ -402,6 +403,7 @@ impl Nla for PeerNla { } LastHandshakeTime(last_handshake) => { let timespec: &libc::timespec = last_handshake.as_ref(); + // SAFETY: `timespec` has no padding bytes buffer .write(unsafe { struct_as_slice(timespec) }) .expect("Buffer too small for timespec"); @@ -562,10 +564,19 @@ impl<'a, T: AsRef<[u8]> + 'a + ?Sized> Parseable<NlaBuffer<&'a T>> for AllowedIp } } +/// Returns a byte slice over the memory used by `t`. +/// +/// # Safety +/// +/// The returned slice includes any padding bytes of `t`. Padding bytes are uninitialized +/// data and it is undefined behavior for a `u8` to be uninitialized. Only call this method +/// on `T`s without padding. unsafe fn struct_as_slice<T: Sized>(t: &T) -> &[u8] { - let s = mem::size_of::<T>(); + let size = mem::size_of::<T>(); let ptr = t as *const T as *const u8; - std::slice::from_raw_parts(ptr, s) + // SAFETY: The memory from `ptr` and `size` bytes forward is always the same as the struct. + // The caller is responsible for not using this with structs containing padding. + std::slice::from_raw_parts(ptr, size) } fn ip_addr_to_bytes(addr: &IpAddr) -> Vec<u8> { |
