Skip to content

Commit 4c7356f

Browse files
committed
feat(sandbox): Landlock TCP port restriction in Platform mode
Add Landlock ABI v4 TCP connect restriction for Platform mode. When the kernel supports ABI v4, only the proxy port (default 3128) is allowed for outbound TCP connections. On older kernels, BestEffort compat level silently degrades -- the rule has no effect but the proxy still works cooperatively. Both handle_access(ConnectTcp) and add_rule(NetPort) use the ? operator since BestEffort guarantees they succeed on all kernel versions. Signed-off-by: Ladislav Smola <lsmola@redhat.com>
1 parent 42158f3 commit 4c7356f

1 file changed

Lines changed: 35 additions & 3 deletions

File tree

crates/openshell-sandbox/src/sandbox/linux/landlock.rs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
66
use crate::policy::{LandlockCompatibility, NetworkMode, SandboxPolicy};
77
use landlock::{
8-
ABI, Access, AccessFs, CompatLevel, Compatible, PathBeneath, PathFd, PathFdError, Ruleset,
9-
RulesetAttr, RulesetCreatedAttr, Scope,
8+
ABI, Access, AccessFs, AccessNet, CompatLevel, Compatible, NetPort, PathBeneath, PathFd,
9+
PathFdError, Ruleset, RulesetAttr, RulesetCreatedAttr, Scope,
1010
};
1111
use miette::{IntoDiagnostic, Result};
1212
use std::path::{Path, PathBuf};
@@ -184,6 +184,7 @@ pub fn prepare(policy: &SandboxPolicy, workdir: Option<&str>) -> Result<Option<P
184184
.handle_access(access_all)
185185
.into_diagnostic()?;
186186

187+
<<<<<<< HEAD
187188
// Platform mode: restrict abstract Unix sockets and signals.
188189
// Without a network namespace, abstract Unix sockets in the pod
189190
// are visible to the agent. This scope prevents connecting to
@@ -195,6 +196,15 @@ pub fn prepare(policy: &SandboxPolicy, workdir: Option<&str>) -> Result<Option<P
195196
.scope(Scope::AbstractUnixSocket)
196197
.into_diagnostic()?;
197198
ruleset = ruleset.scope(Scope::Signal).into_diagnostic()?;
199+
=======
200+
// Platform mode: declare intent to handle TCP connect access.
201+
// BestEffort compat level: silently succeeds on kernels without
202+
// ABI v4 (restriction has no effect but doesn't break anything).
203+
if matches!(policy.network.mode, NetworkMode::Platform) {
204+
ruleset = ruleset
205+
.handle_access(AccessNet::ConnectTcp)
206+
.into_diagnostic()?;
207+
>>>>>>> 5c72320 (feat(sandbox): Landlock TCP port restriction in Platform mode)
198208
}
199209

200210
let mut ruleset = ruleset.create().into_diagnostic()?;
@@ -220,6 +230,28 @@ pub fn prepare(policy: &SandboxPolicy, workdir: Option<&str>) -> Result<Option<P
220230
}
221231
}
222232

233+
if matches!(policy.network.mode, NetworkMode::Platform) {
234+
let proxy_port = policy
235+
.network
236+
.proxy
237+
.as_ref()
238+
.and_then(|p| p.http_addr)
239+
.map_or(3128_u16, |addr| addr.port());
240+
241+
// BestEffort compat level: add_rule silently succeeds even if
242+
// ABI v4 is unavailable. The rule has no effect on older kernels,
243+
// but the proxy still works cooperatively.
244+
ruleset = ruleset
245+
.add_rule(NetPort::new(proxy_port, AccessNet::ConnectTcp))
246+
.into_diagnostic()?;
247+
debug!(
248+
port = proxy_port,
249+
"Landlock TCP connect rule added (proxy port only, \
250+
effective on kernels with ABI v4+)"
251+
);
252+
rules_applied += 1;
253+
}
254+
223255
if rules_applied == 0 {
224256
return Err(miette::miette!(
225257
"Landlock ruleset has zero valid paths — all {} path(s) failed to open. \
@@ -228,7 +260,7 @@ pub fn prepare(policy: &SandboxPolicy, workdir: Option<&str>) -> Result<Option<P
228260
));
229261
}
230262

231-
let skipped = total_paths - rules_applied;
263+
let skipped = total_paths.saturating_sub(rules_applied);
232264
openshell_ocsf::ocsf_emit!(
233265
openshell_ocsf::ConfigStateChangeBuilder::new(crate::ocsf_ctx())
234266
.severity(openshell_ocsf::SeverityId::Informational)

0 commit comments

Comments
 (0)