diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml index dd6ef304c..15586f880 100644 --- a/.github/actions/setup-rust/action.yml +++ b/.github/actions/setup-rust/action.yml @@ -64,7 +64,7 @@ runs: - name: Install nightly Rust id: nightly run: | - NIGHTLY="nightly-2024-12-13" + NIGHTLY="nightly-2025-05-30" rustup toolchain install $NIGHTLY rustup component add rust-src --toolchain $NIGHTLY diff --git a/rust/apple-client-ffi/build.rs b/rust/apple-client-ffi/build.rs index 117a2b5ba..d7744c202 100644 --- a/rust/apple-client-ffi/build.rs +++ b/rust/apple-client-ffi/build.rs @@ -5,9 +5,9 @@ fn main() { let bridges = vec!["src/lib.rs"]; for path in &bridges { - println!("cargo:rerun-if-changed={}", path); + println!("cargo:rerun-if-changed={path}"); } - println!("cargo:rerun-if-env-changed={}", XCODE_CONFIGURATION_ENV); + println!("cargo:rerun-if-env-changed={XCODE_CONFIGURATION_ENV}"); swift_bridge_build::parse_bridges(bridges) .write_all_concatenated(out_dir, env!("CARGO_PKG_NAME")); diff --git a/rust/bin-shared/src/known_dirs/macos.rs b/rust/bin-shared/src/known_dirs/macos.rs index 7b9d9b7f3..f5dcd1658 100644 --- a/rust/bin-shared/src/known_dirs/macos.rs +++ b/rust/bin-shared/src/known_dirs/macos.rs @@ -35,7 +35,7 @@ pub fn logs() -> Option { /// Runtime directory for temporary files pub fn runtime() -> Option { let user = std::env::var("USER").ok()?; - Some(PathBuf::from("/tmp").join(format!("{}-{}", BUNDLE_ID, user))) + Some(PathBuf::from("/tmp").join(format!("{BUNDLE_ID}-{user}"))) } /// User session data directory diff --git a/rust/clippy.toml b/rust/clippy.toml index 30d4edfea..ba5dd243e 100644 --- a/rust/clippy.toml +++ b/rust/clippy.toml @@ -3,8 +3,5 @@ disallowed-methods = [ { path = "std::collections::HashMap::iter", reason = "HashMap has non-deterministic iteration order, use BTreeMap instead" }, { path = "std::collections::HashSet::iter", reason = "HashSet has non-deterministic iteration order, use BTreeSet instead" }, { path = "std::collections::HashMap::iter_mut", reason = "HashMap has non-deterministic iteration order, use BTreeMap instead" }, - { path = "std::collections::HashSet::iter_mut", reason = "HashSet has non-deterministic iteration order, use BTreeSet instead" }, - { path = "std::collections::HashMap::into_iter", reason = "HashMap has non-deterministic iteration order, use BTreeMap instead" }, - { path = "std::collections::HashSet::into_iter", reason = "HashSet has non-deterministic iteration order, use BTreeSet instead" }, { path = "tracing::subscriber::set_global_default", reason = "Does not init `LogTracer`, use `firezone_logging::init` instead." }, ] diff --git a/rust/connlib/l4-tcp-dns-server/lib.rs b/rust/connlib/l4-tcp-dns-server/lib.rs index 3dcc122bc..86cb09a51 100644 --- a/rust/connlib/l4-tcp-dns-server/lib.rs +++ b/rust/connlib/l4-tcp-dns-server/lib.rs @@ -136,20 +136,20 @@ impl Server { })); } - if let Some(tcp_v4) = self.tcp_v4.as_mut() { - if let Poll::Ready((stream, from)) = tcp_v4.poll_accept(cx)? { - self.reading_tcp_queries - .push(read_tcp_query(stream, from).boxed()); - continue; - } + if let Some(tcp_v4) = self.tcp_v4.as_mut() + && let Poll::Ready((stream, from)) = tcp_v4.poll_accept(cx)? + { + self.reading_tcp_queries + .push(read_tcp_query(stream, from).boxed()); + continue; } - if let Some(tcp_v6) = self.tcp_v6.as_mut() { - if let Poll::Ready((stream, from)) = tcp_v6.poll_accept(cx)? { - self.reading_tcp_queries - .push(read_tcp_query(stream, from).boxed()); - continue; - } + if let Some(tcp_v6) = self.tcp_v6.as_mut() + && let Poll::Ready((stream, from)) = tcp_v6.poll_accept(cx)? + { + self.reading_tcp_queries + .push(read_tcp_query(stream, from).boxed()); + continue; } self.waker.register(cx.waker()); diff --git a/rust/connlib/tunnel/src/client.rs b/rust/connlib/tunnel/src/client.rs index 837064cf9..b19f9ed5f 100644 --- a/rust/connlib/tunnel/src/client.rs +++ b/rust/connlib/tunnel/src/client.rs @@ -622,13 +622,13 @@ impl ClientState { return Ok(Ok(())); }; - if let Some(old_gateway_id) = self.resources_gateways.insert(resource_id, gateway_id) { - if self.peers.get(&old_gateway_id).is_some() { - assert_eq!( - old_gateway_id, gateway_id, - "Resources are not expected to change gateways without a previous message, resource_id = {resource_id}" - ); - } + if let Some(old_gateway_id) = self.resources_gateways.insert(resource_id, gateway_id) + && self.peers.get(&old_gateway_id).is_some() + { + assert_eq!( + old_gateway_id, gateway_id, + "Resources are not expected to change gateways without a previous message, resource_id = {resource_id}" + ) } match self.node.upsert_connection( diff --git a/rust/connlib/tunnel/src/peer/nat_table.rs b/rust/connlib/tunnel/src/peer/nat_table.rs index 8a3c79a67..dc648e6ac 100644 --- a/rust/connlib/tunnel/src/peer/nat_table.rs +++ b/rust/connlib/tunnel/src/peer/nat_table.rs @@ -36,11 +36,11 @@ impl NatTable { Protocol::Icmp(_) => ICMP_TTL, }; - if now.duration_since(*e) >= ttl { - if let Some((inside, _)) = self.table.remove_by_right(outside) { - tracing::debug!(?inside, ?outside, ?ttl, "NAT session expired"); - self.expired.insert(*outside); - } + if now.duration_since(*e) >= ttl + && let Some((inside, _)) = self.table.remove_by_right(outside) + { + tracing::debug!(?inside, ?outside, ?ttl, "NAT session expired"); + self.expired.insert(*outside); } } } diff --git a/rust/connlib/tunnel/src/tests/reference.rs b/rust/connlib/tunnel/src/tests/reference.rs index ecb16d118..7029ab7fb 100644 --- a/rust/connlib/tunnel/src/tests/reference.rs +++ b/rust/connlib/tunnel/src/tests/reference.rs @@ -168,8 +168,8 @@ impl ReferenceState { "private keys must be unique", |(c, gateways, _, _, _, _, _, _, _)| { let different_keys = gateways - .iter() - .map(|(_, g)| g.inner().key) + .values() + .map(|g| g.inner().key) .chain(iter::once(c.inner().key)) .collect::>(); diff --git a/rust/connlib/tunnel/src/tests/sim_client.rs b/rust/connlib/tunnel/src/tests/sim_client.rs index c8e2f0993..e678658f3 100644 --- a/rust/connlib/tunnel/src/tests/sim_client.rs +++ b/rust/connlib/tunnel/src/tests/sim_client.rs @@ -204,20 +204,20 @@ impl SimClient { } fn update_sent_requests(&mut self, packet: &IpPacket) { - if let Some(icmp) = packet.as_icmpv4() { - if let Icmpv4Type::EchoRequest(echo) = icmp.icmp_type() { - self.sent_icmp_requests - .insert((Seq(echo.seq), Identifier(echo.id)), packet.clone()); - return; - } + if let Some(icmp) = packet.as_icmpv4() + && let Icmpv4Type::EchoRequest(echo) = icmp.icmp_type() + { + self.sent_icmp_requests + .insert((Seq(echo.seq), Identifier(echo.id)), packet.clone()); + return; } - if let Some(icmp) = packet.as_icmpv6() { - if let Icmpv6Type::EchoRequest(echo) = icmp.icmp_type() { - self.sent_icmp_requests - .insert((Seq(echo.seq), Identifier(echo.id)), packet.clone()); - return; - } + if let Some(icmp) = packet.as_icmpv6() + && let Icmpv6Type::EchoRequest(echo) = icmp.icmp_type() + { + self.sent_icmp_requests + .insert((Seq(echo.seq), Identifier(echo.id)), packet.clone()); + return; } if let Some(udp) = packet.as_udp() { @@ -311,20 +311,20 @@ impl SimClient { return; } - if let Some(icmp) = packet.as_icmpv4() { - if let Icmpv4Type::EchoReply(echo) = icmp.icmp_type() { - self.received_icmp_replies - .insert((Seq(echo.seq), Identifier(echo.id)), packet.clone()); - return; - } + if let Some(icmp) = packet.as_icmpv4() + && let Icmpv4Type::EchoReply(echo) = icmp.icmp_type() + { + self.received_icmp_replies + .insert((Seq(echo.seq), Identifier(echo.id)), packet.clone()); + return; } - if let Some(icmp) = packet.as_icmpv6() { - if let Icmpv6Type::EchoReply(echo) = icmp.icmp_type() { - self.received_icmp_replies - .insert((Seq(echo.seq), Identifier(echo.id)), packet.clone()); - return; - } + if let Some(icmp) = packet.as_icmpv6() + && let Icmpv6Type::EchoReply(echo) = icmp.icmp_type() + { + self.received_icmp_replies + .insert((Seq(echo.seq), Identifier(echo.id)), packet.clone()); + return; } tracing::error!(?packet, "Unhandled packet"); @@ -521,12 +521,12 @@ impl RefClient { continue; } - if let Some(overlapping_resource) = table.exact_match(resource.address) { - if self.is_connected_to_internet_or_cidr(*overlapping_resource) { - tracing::debug!(%overlapping_resource, resource = %resource.id, address = %resource.address, "Already connected to resource with this exact address, retaining existing route"); + if let Some(overlapping_resource) = table.exact_match(resource.address) + && self.is_connected_to_internet_or_cidr(*overlapping_resource) + { + tracing::debug!(%overlapping_resource, resource = %resource.id, address = %resource.address, "Already connected to resource with this exact address, retaining existing route"); - continue; - } + continue; } tracing::debug!(resource = %resource.id, address = %resource.address, "Adding CIDR route"); diff --git a/rust/connlib/tunnel/src/tests/sim_gateway.rs b/rust/connlib/tunnel/src/tests/sim_gateway.rs index b701d00ec..5fd00d6e9 100644 --- a/rust/connlib/tunnel/src/tests/sim_gateway.rs +++ b/rust/connlib/tunnel/src/tests/sim_gateway.rs @@ -187,24 +187,24 @@ impl SimGateway { .icmp_error_for_ip(dst_ip) .map(|icmp_error| icmp_error_reply(&packet, icmp_error).unwrap()); - if let Some(icmp) = packet.as_icmpv4() { - if let Icmpv4Type::EchoRequest(echo) = icmp.icmp_type() { - let packet_id = u64::from_be_bytes(*icmp.payload().first_chunk().unwrap()); - tracing::debug!(%packet_id, "Received ICMP request"); - self.received_icmp_requests - .insert(packet_id, packet.clone()); - return self.handle_icmp_request(&packet, echo, icmp.payload(), icmp_error, now); - } + if let Some(icmp) = packet.as_icmpv4() + && let Icmpv4Type::EchoRequest(echo) = icmp.icmp_type() + { + let packet_id = u64::from_be_bytes(*icmp.payload().first_chunk().unwrap()); + tracing::debug!(%packet_id, "Received ICMP request"); + self.received_icmp_requests + .insert(packet_id, packet.clone()); + return self.handle_icmp_request(&packet, echo, icmp.payload(), icmp_error, now); } - if let Some(icmp) = packet.as_icmpv6() { - if let Icmpv6Type::EchoRequest(echo) = icmp.icmp_type() { - let packet_id = u64::from_be_bytes(*icmp.payload().first_chunk().unwrap()); - tracing::debug!(%packet_id, "Received ICMP request"); - self.received_icmp_requests - .insert(packet_id, packet.clone()); - return self.handle_icmp_request(&packet, echo, icmp.payload(), icmp_error, now); - } + if let Some(icmp) = packet.as_icmpv6() + && let Icmpv6Type::EchoRequest(echo) = icmp.icmp_type() + { + let packet_id = u64::from_be_bytes(*icmp.payload().first_chunk().unwrap()); + tracing::debug!(%packet_id, "Received ICMP request"); + self.received_icmp_requests + .insert(packet_id, packet.clone()); + return self.handle_icmp_request(&packet, echo, icmp.payload(), icmp_error, now); } if let Some(udp) = packet.as_udp() { diff --git a/rust/gateway/src/main.rs b/rust/gateway/src/main.rs index a09a43487..f20dcf79b 100644 --- a/rust/gateway/src/main.rs +++ b/rust/gateway/src/main.rs @@ -200,16 +200,16 @@ async fn try_main(cli: Cli, telemetry: &mut Telemetry) -> Result<()> { } async fn get_firezone_id(env_id: Option) -> Result { - if let Some(id) = env_id { - if !id.is_empty() { - return Ok(id); - } + if let Some(id) = env_id + && !id.is_empty() + { + return Ok(id); } - if let Ok(id) = tokio::fs::read_to_string(ID_PATH).await { - if !id.is_empty() { - return Ok(id); - } + if let Ok(id) = tokio::fs::read_to_string(ID_PATH).await + && !id.is_empty() + { + return Ok(id); } let device_id = device_id::get_or_create_at(Path::new(ID_PATH))?; diff --git a/rust/gui-client/src-admx-macro/lib.rs b/rust/gui-client/src-admx-macro/lib.rs index 86ba56d0d..c1d6c0557 100644 --- a/rust/gui-client/src-admx-macro/lib.rs +++ b/rust/gui-client/src-admx-macro/lib.rs @@ -54,8 +54,7 @@ fn try_admx(attr: TokenStream, item: TokenStream) -> syn::Result Result<(), io::Error> { let base = Path::new("Software").join("Classes").join(FZ_SCHEME); let (key, _) = hkcu.create_subkey(&base)?; - key.set_value("", &format!("URL:{}", id))?; + key.set_value("", &format!("URL:{id}"))?; key.set_value("URL Protocol", &"")?; let (icon, _) = hkcu.create_subkey(base.join("DefaultIcon"))?; - icon.set_value("", &format!("{},0", &exe))?; + icon.set_value("", &format!("{exe},0"))?; let (cmd, _) = hkcu.create_subkey(base.join("shell").join("open").join("command"))?; - cmd.set_value("", &format!("{} open-deep-link \"%1\"", &exe))?; + cmd.set_value("", &format!("{exe} open-deep-link \"%1\""))?; Ok(()) } diff --git a/rust/gui-client/src-tauri/src/ipc/windows.rs b/rust/gui-client/src-tauri/src/ipc/windows.rs index 88b7cb195..e12c5ca43 100644 --- a/rust/gui-client/src-tauri/src/ipc/windows.rs +++ b/rust/gui-client/src-tauri/src/ipc/windows.rs @@ -169,7 +169,7 @@ fn ipc_path(id: SocketId) -> String { /// Public because the GUI Client reuses this for deep links. Eventually that code /// will be de-duped into this code. pub fn named_pipe_path(id: &str) -> String { - format!(r"\\.\pipe\{}", id) + format!(r"\\.\pipe\{id}") } #[cfg(test)] diff --git a/rust/logging/src/err_with_sources.rs b/rust/logging/src/err_with_sources.rs index 6882448de..a15c010d4 100644 --- a/rust/logging/src/err_with_sources.rs +++ b/rust/logging/src/err_with_sources.rs @@ -15,7 +15,7 @@ impl fmt::Display for ErrorWithSources<'_> { write!(f, "{}", self.e)?; for cause in anyhow::Chain::new(self.e).skip(1) { - write!(f, ": {}", cause)?; + write!(f, ": {cause}")?; } Ok(()) diff --git a/rust/logging/src/format.rs b/rust/logging/src/format.rs index acebd44f1..3d8bd76d3 100644 --- a/rust/logging/src/format.rs +++ b/rust/logging/src/format.rs @@ -109,7 +109,7 @@ where if self.level { let fmt_level = FmtLevel::new(meta.level(), writer.has_ansi_escapes()); - write!(writer, "{} ", fmt_level)?; + write!(writer, "{fmt_level} ")?; } let dimmed = if writer.has_ansi_escapes() { diff --git a/rust/relay/ebpf-turn-router/src/channel_data.rs b/rust/relay/ebpf-turn-router/src/channel_data.rs index 71979167e..565210826 100644 --- a/rust/relay/ebpf-turn-router/src/channel_data.rs +++ b/rust/relay/ebpf-turn-router/src/channel_data.rs @@ -10,9 +10,14 @@ pub struct ChannelData<'a> { } impl<'a> ChannelData<'a> { + /// # SAFETY + /// + /// You must not create multiple [`ChannelData`] structs at same time. #[inline(always)] - pub fn parse(ctx: &'a XdpContext, ip_header_length: usize) -> Result { - let hdr = ref_mut_at::(ctx, EthHdr::LEN + ip_header_length + UdpHdr::LEN)?; + pub unsafe fn parse(ctx: &'a XdpContext, ip_header_length: usize) -> Result { + // Safety: We are forwarding the constraint. + let hdr = + unsafe { ref_mut_at::(ctx, EthHdr::LEN + ip_header_length + UdpHdr::LEN) }?; if !(0x4000..0x4FFF).contains(&u16::from_be_bytes(hdr.number)) { return Err(Error::NotAChannelDataMessage); diff --git a/rust/relay/ebpf-turn-router/src/eth.rs b/rust/relay/ebpf-turn-router/src/eth.rs index 3008130d7..30f5fb4d2 100644 --- a/rust/relay/ebpf-turn-router/src/eth.rs +++ b/rust/relay/ebpf-turn-router/src/eth.rs @@ -15,10 +15,14 @@ pub struct Eth<'a> { } impl<'a> Eth<'a> { + /// # SAFETY + /// + /// You must not create multiple [`Eth`] structs at same time. #[inline(always)] - pub fn parse(ctx: &'a XdpContext) -> Result { + pub unsafe fn parse(ctx: &'a XdpContext) -> Result { Ok(Self { - inner: ref_mut_at::(ctx, 0)?, + // Safety: We are forwarding the constraint. + inner: unsafe { ref_mut_at::(ctx, 0) }?, ctx, }) } diff --git a/rust/relay/ebpf-turn-router/src/ip4.rs b/rust/relay/ebpf-turn-router/src/ip4.rs index c1e7eaf5f..fb8f4bfeb 100644 --- a/rust/relay/ebpf-turn-router/src/ip4.rs +++ b/rust/relay/ebpf-turn-router/src/ip4.rs @@ -15,9 +15,13 @@ pub struct Ip4<'a> { } impl<'a> Ip4<'a> { + /// # SAFETY + /// + /// You must not create multiple [`Ip4`] structs at same time. #[inline(always)] - pub fn parse(ctx: &'a XdpContext) -> Result { - let ip4_hdr = ref_mut_at::(ctx, EthHdr::LEN)?; + pub unsafe fn parse(ctx: &'a XdpContext) -> Result { + // Safety: We are forwarding the constraint. + let ip4_hdr = unsafe { ref_mut_at::(ctx, EthHdr::LEN) }?; // IPv4 packets with options are handled in user-space. if usize::from(ip4_hdr.ihl()) * 4 != Ipv4Hdr::LEN { diff --git a/rust/relay/ebpf-turn-router/src/ip6.rs b/rust/relay/ebpf-turn-router/src/ip6.rs index 80e19f6d1..7c96a5706 100644 --- a/rust/relay/ebpf-turn-router/src/ip6.rs +++ b/rust/relay/ebpf-turn-router/src/ip6.rs @@ -15,11 +15,15 @@ pub struct Ip6<'a> { } impl<'a> Ip6<'a> { + /// # SAFETY + /// + /// You must not create multiple [`Ip6`] structs at same time. #[inline(always)] - pub fn parse(ctx: &'a XdpContext) -> Result { + pub unsafe fn parse(ctx: &'a XdpContext) -> Result { Ok(Self { ctx, - inner: ref_mut_at::(ctx, EthHdr::LEN)?, + // Safety: We are forwarding the constraint. + inner: unsafe { ref_mut_at::(ctx, EthHdr::LEN) }?, }) } diff --git a/rust/relay/ebpf-turn-router/src/main.rs b/rust/relay/ebpf-turn-router/src/main.rs index bbdf387a8..7e6768df2 100644 --- a/rust/relay/ebpf-turn-router/src/main.rs +++ b/rust/relay/ebpf-turn-router/src/main.rs @@ -109,7 +109,8 @@ pub fn handle_turn(ctx: XdpContext) -> u32 { #[inline(always)] fn try_handle_turn(ctx: &XdpContext) -> Result { - let eth = Eth::parse(ctx)?; + // Safety: This is the only instance of `Eth`. + let eth = unsafe { Eth::parse(ctx) }?; match eth.ether_type() { EtherType::Ipv4 => try_handle_turn_ipv4(ctx, eth)?, @@ -124,7 +125,8 @@ fn try_handle_turn(ctx: &XdpContext) -> Result { #[inline(always)] fn try_handle_turn_ipv4(ctx: &XdpContext, eth: Eth) -> Result<(), Error> { - let ipv4 = Ip4::parse(ctx)?; + // Safety: This is the only instance of `Ip4`. + let ipv4 = unsafe { Ip4::parse(ctx) }?; eth::save_mac_for_ipv4(ipv4.src(), eth.src()); eth::save_mac_for_ipv4(ipv4.dst(), eth.dst()); @@ -133,7 +135,8 @@ fn try_handle_turn_ipv4(ctx: &XdpContext, eth: Eth) -> Result<(), Error> { return Err(Error::NotUdp); } - let udp = Udp::parse(ctx, Ipv4Hdr::LEN)?; // TODO: Change the API so we parse the UDP header _from_ the ipv4 struct? + // Safety: This is the only instance of `Udp` in this scope. + let udp = unsafe { Udp::parse(ctx, Ipv4Hdr::LEN) }?; // TODO: Change the API so we parse the UDP header _from_ the ipv4 struct? let udp_payload_len = udp.payload_len(); trace!( @@ -170,7 +173,8 @@ fn try_handle_ipv4_channel_data_to_udp( ipv4: Ip4, udp: Udp, ) -> Result<(), Error> { - let cd = ChannelData::parse(ctx, Ipv4Hdr::LEN)?; + // Safety: This is the only instance of `Udp` in this scope. + let cd = unsafe { ChannelData::parse(ctx, Ipv4Hdr::LEN) }?; let key = ClientAndChannelV4::new(ipv4.src(), udp.src(), cd.number()); @@ -259,7 +263,8 @@ fn try_handle_ipv4_udp_to_channel_data( #[inline(always)] fn try_handle_turn_ipv6(ctx: &XdpContext, eth: Eth) -> Result<(), Error> { - let ipv6 = Ip6::parse(ctx)?; + // Safety: This is the only instance of `Ip6` in this scope. + let ipv6 = unsafe { Ip6::parse(ctx) }?; eth::save_mac_for_ipv6(ipv6.src(), eth.src()); eth::save_mac_for_ipv6(ipv6.dst(), eth.dst()); @@ -268,7 +273,8 @@ fn try_handle_turn_ipv6(ctx: &XdpContext, eth: Eth) -> Result<(), Error> { return Err(Error::NotUdp); } - let udp = Udp::parse(ctx, Ipv6Hdr::LEN)?; // TODO: Change the API so we parse the UDP header _from_ the ipv6 struct? + // Safety: This is the only instance of `Udp` in this scope. + let udp = unsafe { Udp::parse(ctx, Ipv6Hdr::LEN) }?; // TODO: Change the API so we parse the UDP header _from_ the ipv6 struct? let udp_payload_len = udp.payload_len(); trace!( @@ -354,7 +360,8 @@ fn try_handle_ipv6_channel_data_to_udp( ipv6: Ip6, udp: Udp, ) -> Result<(), Error> { - let cd = ChannelData::parse(ctx, Ipv6Hdr::LEN)?; + // Safety: This is the only instance of `ChannelData` in this scope. + let cd = unsafe { ChannelData::parse(ctx, Ipv6Hdr::LEN) }?; let key = ClientAndChannelV6::new(ipv6.src(), udp.src(), cd.number()); diff --git a/rust/relay/ebpf-turn-router/src/ref_mut_at.rs b/rust/relay/ebpf-turn-router/src/ref_mut_at.rs index cbefeeaed..5e37b0c40 100644 --- a/rust/relay/ebpf-turn-router/src/ref_mut_at.rs +++ b/rust/relay/ebpf-turn-router/src/ref_mut_at.rs @@ -6,8 +6,13 @@ use crate::error::Error; /// /// The length is based on the size of `T` and the bytes at the specified offset will simply be cast into `T`. /// `T` should therefore most definitely be `repr(C)`. +/// +/// # SAFETY +/// +/// You must not obtain overlapping mutable references from the context. #[inline(always)] -pub(crate) fn ref_mut_at(ctx: &XdpContext, offset: usize) -> Result<&mut T, Error> { +#[expect(clippy::mut_from_ref, reason = "The function is unsafe.")] +pub(crate) unsafe fn ref_mut_at(ctx: &XdpContext, offset: usize) -> Result<&mut T, Error> { let start = ctx.data(); let end = ctx.data_end(); let len = core::mem::size_of::(); diff --git a/rust/relay/ebpf-turn-router/src/udp.rs b/rust/relay/ebpf-turn-router/src/udp.rs index 712058757..18ad19ef7 100644 --- a/rust/relay/ebpf-turn-router/src/udp.rs +++ b/rust/relay/ebpf-turn-router/src/udp.rs @@ -10,11 +10,15 @@ pub struct Udp<'a> { } impl<'a> Udp<'a> { + /// # SAFETY + /// + /// You must not create multiple [`Udp`] structs at same time. #[inline(always)] - pub fn parse(ctx: &'a XdpContext, ip_header_length: usize) -> Result { + pub unsafe fn parse(ctx: &'a XdpContext, ip_header_length: usize) -> Result { Ok(Self { ctx, - inner: ref_mut_at::(ctx, EthHdr::LEN + ip_header_length)?, + // Safety: We are forwarding the constraint. + inner: unsafe { ref_mut_at::(ctx, EthHdr::LEN + ip_header_length) }?, }) } diff --git a/rust/relay/server/build.rs b/rust/relay/server/build.rs index d51a2dc6e..348a22aca 100644 --- a/rust/relay/server/build.rs +++ b/rust/relay/server/build.rs @@ -14,7 +14,7 @@ fn main() -> anyhow::Result<()> { aya_build::build_ebpf( [package], - aya_build::Toolchain::Custom("nightly-2024-12-13"), + aya_build::Toolchain::Custom("nightly-2025-05-30"), )?; Ok(()) diff --git a/rust/relay/server/src/auth.rs b/rust/relay/server/src/auth.rs index f15f58de1..e3875c245 100644 --- a/rust/relay/server/src/auth.rs +++ b/rust/relay/server/src/auth.rs @@ -80,7 +80,7 @@ impl MessageIntegrityExt for MessageIntegrity { let password = generate_password(relay_secret, expired, salt); self.check_long_term_credential( - &Username::new(format!("{}:{}", expiry_unix_timestamp, salt)) + &Username::new(format!("{expiry_unix_timestamp}:{salt}")) .map_err(|_| Error::InvalidUsername)?, &FIREZONE, &password, @@ -109,7 +109,7 @@ impl AuthenticatedMessage { let (expiry_unix_timestamp, salt) = split_username(username)?; let expired = systemtime_from_unix(expiry_unix_timestamp); - let username = Username::new(format!("{}:{}", expiry_unix_timestamp, salt)) + let username = Username::new(format!("{expiry_unix_timestamp}:{salt}")) .map_err(|_| Error::InvalidUsername)?; let password = generate_password(relay_secret, expired, salt); diff --git a/rust/relay/server/tests/regression.rs b/rust/relay/server/tests/regression.rs index 8fee057ff..7004fe244 100644 --- a/rust/relay/server/tests/regression.rs +++ b/rust/relay/server/tests/regression.rs @@ -753,7 +753,7 @@ impl TestServer { let Some(actual_output) = self.server.next_command() else { let msg = match expected_output { Output::SendMessage((recipient, msg)) => { - format!("to send message {:?} to {recipient}", msg) + format!("to send message {msg:?} to {recipient}") } CreateAllocation(port, family) => { format!("to create allocation on port {port} for address family {family}") @@ -793,8 +793,8 @@ impl TestServer { .unwrap(); if expected_bytes != payload { - let expected_message = format!("{:?}", message); - let actual_message = format!("{:?}", sent_message); + let expected_message = format!("{message:?}"); + let actual_message = format!("{sent_message:?}"); difference::assert_diff!(&expected_message, &actual_message, "\n", 0); } diff --git a/rust/rust-toolchain.toml b/rust/rust-toolchain.toml index ec5737980..6a0e04e65 100644 --- a/rust/rust-toolchain.toml +++ b/rust/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.87.0" +channel = "1.88.0" components = ["rust-src", "rust-analyzer", "clippy"] targets = ["x86_64-unknown-linux-musl"]