Skip to content

Commit 87b30fa

Browse files
committed
Flush PF states when transitioning to secured states
1 parent dd475d1 commit 87b30fa

File tree

1 file changed

+29
-1
lines changed

1 file changed

+29
-1
lines changed

talpid-core/src/firewall/macos.rs

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::{FirewallArguments, FirewallPolicy};
22
use ipnetwork::IpNetwork;
33
use pfctl::{DropAction, FilterRuleAction, Uid};
4+
use std::process::Stdio;
45
use std::{
56
env,
67
net::{IpAddr, Ipv4Addr},
@@ -49,7 +50,13 @@ impl Firewall {
4950
pub fn apply_policy(&mut self, policy: FirewallPolicy) -> Result<()> {
5051
self.enable()?;
5152
self.add_anchor()?;
52-
self.set_rules(policy)
53+
self.set_rules(policy)?;
54+
55+
// When entering a secured state, clear connection states
56+
// Otherwise, an existing connection may be approved by some other anchor, and leak
57+
clear_all_states();
58+
59+
Ok(())
5360
}
5461

5562
pub fn reset_policy(&mut self) -> Result<()> {
@@ -668,3 +675,24 @@ enum RuleLogging {
668675
Drop,
669676
All,
670677
}
678+
679+
/// Clear all PF connection states by calling 'pfctl -F rules'. This could be done more nicely
680+
/// using the `DIOCKILLSTATES` or `DIOCCLRSTATES` ioctl.
681+
///
682+
/// See http://man.openbsd.org/pf.4, `DIOCKILLSTATES`, and `DIOCCLRSTATES` for more info.
683+
fn clear_all_states() {
684+
let status = std::process::Command::new("/sbin/pfctl")
685+
.args(["-F", "states"])
686+
.stdout(Stdio::null())
687+
.stderr(Stdio::null())
688+
.status();
689+
match status {
690+
Ok(status) if status.success() => (),
691+
Ok(status) => {
692+
log::error!("Failed to clear PF states. pfctl failed: {status}");
693+
}
694+
Err(error) => {
695+
log::error!("Failed to clear PF states: {error}");
696+
}
697+
}
698+
}

0 commit comments

Comments
 (0)