Skip to content

Commit eec74e4

Browse files
authored
refactor: FreeBSD platform support cleanup (#205)
* refactor: FreeBSD platform support cleanup#205
1 parent 66c420f commit eec74e4

5 files changed

Lines changed: 35 additions & 24 deletions

File tree

ROADMAP.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ This document outlines the planned features and improvements for RustNet.
1919
- BPF device access and permissions setup
2020
- Native libpcap packet capture
2121
- Cross-compilation support from Linux
22+
- [ ] **FreeBSD Capsicum Full Sandbox** (`cap_enter()`): Replace per-FD `cap_rights_limit()` with full capability mode to prevent file access and data exfiltration. Requires:
23+
- Switch from `sockstat` subprocess to `libprocstat(3)` library calls for process lookup (eliminates `fork()`/`execve()` dependency)
24+
- Integrate `libcasper` for privileged sysctl access from inside capability mode (`kern.proc.filedesc` is blocked in `cap_enter()`)
25+
- Architecture: pre-fork a Casper service before `cap_enter()`, communicate over socket pair at runtime
26+
- Write FFI bindings for `libprocstat` and `libcasper` (no Rust crate exists)
27+
- Link against `-lprocstat -lcasper -lcap_sysctl` (system libraries on FreeBSD 10+)
2228
- [ ] **OpenBSD and NetBSD Support**: Future platforms to support
2329
- [x] **Linux Process Identification**: **Experimental eBPF Support Implemented** - Basic eBPF-based process identification now available with `--features ebpf`. Provides efficient kernel-level process-to-connection mapping with lower overhead than procfs. Currently has limitations (see eBPF Improvements section below).
2430

SECURITY.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ RustNet processes untrusted network data, making defense-in-depth security criti
66

77
- [Landlock Sandboxing (Linux)](#landlock-sandboxing-linux)
88
- [Seatbelt Sandboxing (macOS)](#seatbelt-sandboxing-macos)
9+
- [FreeBSD Sandboxing](#freebsd-sandboxing)
910
- [Privilege Requirements](#privilege-requirements)
1011
- [Read-Only Operation](#read-only-operation)
1112
- [No External Communication](#no-external-communication)
@@ -116,6 +117,10 @@ Unlike Linux Landlock, clipboard copy (`c` key) works normally under Seatbelt. m
116117

117118
On Linux, clipboard requires access to Wayland sockets (`/run/user/UID/wayland-0`) or X11 sockets (`/tmp/.X11-unix/`). Landlock's deny-default model blocks these because they are not in the write-path allowlist, so clipboard is unavailable when Landlock is active.
118119

120+
## FreeBSD Sandboxing
121+
122+
FreeBSD does not currently have sandboxing enabled. A full Capsicum sandbox using `cap_enter()` with `libcasper` for privileged process lookup is planned — see [ROADMAP.md](ROADMAP.md) for details.
123+
119124
## Privilege Requirements
120125

121126
RustNet requires privileged access for packet capture:

src/network/platform/freebsd/interface_stats.rs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,28 @@ impl InterfaceStatsProvider for FreeBSDStatsProvider {
2323

2424
while let Some(ifa) = current.as_ref() {
2525
// Only process AF_LINK entries (data link layer)
26-
if let Some(addr) = ifa.ifa_addr.as_ref() {
27-
if addr.sa_family as i32 == libc::AF_LINK {
28-
let name = CStr::from_ptr(ifa.ifa_name).to_string_lossy().to_string();
26+
if let Some(addr) = ifa.ifa_addr.as_ref()
27+
&& addr.sa_family as i32 == libc::AF_LINK
28+
{
29+
let name = CStr::from_ptr(ifa.ifa_name).to_string_lossy().to_string();
2930

30-
// Get if_data from ifa_data
31-
#[cfg(target_os = "freebsd")]
32-
{
33-
if let Some(if_data) = (ifa.ifa_data as *const libc::if_data).as_ref() {
34-
stats.push(InterfaceStats {
35-
interface_name: name,
36-
rx_bytes: if_data.ifi_ibytes,
37-
tx_bytes: if_data.ifi_obytes,
38-
rx_packets: if_data.ifi_ipackets,
39-
tx_packets: if_data.ifi_opackets,
40-
rx_errors: if_data.ifi_ierrors,
41-
tx_errors: if_data.ifi_oerrors,
42-
rx_dropped: if_data.ifi_iqdrops,
43-
tx_dropped: 0, // Not typically available on FreeBSD
44-
collisions: if_data.ifi_collisions,
45-
timestamp: SystemTime::now(),
46-
});
47-
}
31+
// Get if_data from ifa_data
32+
#[cfg(target_os = "freebsd")]
33+
{
34+
if let Some(if_data) = (ifa.ifa_data as *const libc::if_data).as_ref() {
35+
stats.push(InterfaceStats {
36+
interface_name: name,
37+
rx_bytes: if_data.ifi_ibytes,
38+
tx_bytes: if_data.ifi_obytes,
39+
rx_packets: if_data.ifi_ipackets,
40+
tx_packets: if_data.ifi_opackets,
41+
rx_errors: if_data.ifi_ierrors,
42+
tx_errors: if_data.ifi_oerrors,
43+
rx_dropped: if_data.ifi_iqdrops,
44+
tx_dropped: 0, // Not typically available on FreeBSD
45+
collisions: if_data.ifi_collisions,
46+
timestamp: SystemTime::now(),
47+
});
4848
}
4949
}
5050
}

src/network/platform/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ mod windows;
105105

106106
// Re-export factory functions and types from platform modules
107107
#[cfg(target_os = "freebsd")]
108-
pub use freebsd::{FreeBSDProcessLookup, FreeBSDStatsProvider, create_process_lookup};
108+
pub use freebsd::{FreeBSDStatsProvider, create_process_lookup};
109109
#[cfg(all(target_os = "linux", feature = "landlock"))]
110110
pub use linux::sandbox;
111111
#[cfg(target_os = "linux")]

src/ui.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2010,8 +2010,8 @@ fn draw_stats_panel(
20102010
]
20112011
};
20122012

2013-
// Non-Linux/non-macOS unix (FreeBSD) or macOS without macos-sandbox feature:
2014-
// show privilege info
2013+
// Other unix platforms (FreeBSD, macOS without macos-sandbox feature, etc.):
2014+
// show privilege info only
20152015
#[cfg(all(
20162016
unix,
20172017
not(target_os = "linux"),

0 commit comments

Comments
 (0)