Skip to content

Commit 22f5707

Browse files
committed
host: add --port flag for inbound listen-port allowlist
Signed-off-by: danbugs <danilochiarlone@gmail.com>
1 parent 0eb9887 commit 22f5707

6 files changed

Lines changed: 275 additions & 30 deletions

File tree

examples/networking-py/Justfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ run-urllib:
2626
run-https:
2727
hyperlight-unikraft {{kernel}} --initrd {{initrd}} --memory {{memory}} --net -- /https_test.py
2828

29-
# Run echo server
29+
# Run echo server (--port implies --net)
3030
run-echo:
31-
hyperlight-unikraft {{kernel}} --initrd {{initrd}} --memory {{memory}} --net -- /echo_server.py
31+
hyperlight-unikraft {{kernel}} --initrd {{initrd}} --memory {{memory}} --port 8080 -- /echo_server.py
3232

3333
# Build rootfs via Docker (cross-platform)
3434
rootfs:

host/examples/pyhl_as_library.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn main() -> anyhow::Result<()> {
2222
// expose host directories via the guest's hostfs.
2323
let mounts: &[Preopen] = &[];
2424

25-
let mut rt = pyhl::Runtime::new(&home, mounts, None)?;
25+
let mut rt = pyhl::Runtime::new(&home, mounts, None, None)?;
2626

2727
eprintln!("-- first run (hermetic from loaded snapshot) --");
2828
let t1 = rt.run_code(&code)?;

host/src/bin/pyhl.rs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use hyperlight_unikraft::pyhl::{
2626
copy_replace, discover_source_artifacts, extract_from_ghcr, GHCR_INITRD_IMAGE,
2727
GHCR_KERNEL_IMAGE,
2828
};
29-
use hyperlight_unikraft::{AllowList, BlockList, NetworkPolicy, Preopen, Sandbox};
29+
use hyperlight_unikraft::{AllowList, BlockList, ListenPorts, NetworkPolicy, Preopen, Sandbox};
3030
use std::fs;
3131
use std::path::{Path, PathBuf};
3232
use std::time::Instant;
@@ -41,6 +41,7 @@ fn build_network_policy(
4141
net: bool,
4242
net_allow: &[String],
4343
net_block: &[String],
44+
has_ports: bool,
4445
) -> Result<Option<NetworkPolicy>> {
4546
if !net_allow.is_empty() {
4647
Ok(Some(NetworkPolicy::AllowList(AllowList::from_hosts(
@@ -50,13 +51,21 @@ fn build_network_policy(
5051
Ok(Some(NetworkPolicy::BlockList(BlockList::from_hosts(
5152
net_block,
5253
)?)))
53-
} else if net {
54+
} else if net || has_ports {
5455
Ok(Some(NetworkPolicy::AllowAll))
5556
} else {
5657
Ok(None)
5758
}
5859
}
5960

61+
fn build_listen_ports(ports: &[u16]) -> Option<ListenPorts> {
62+
if ports.is_empty() {
63+
None
64+
} else {
65+
Some(ListenPorts::from_ports(ports.iter().copied()))
66+
}
67+
}
68+
6069
/// Keep in sync with `py_initialize_once` in examples/python-agent-driver/
6170
/// hl_pydriver.c. These modules are imported during `pyhl setup`'s warmup
6271
/// so they're already in `sys.modules` in every `pyhl run` invocation —
@@ -187,6 +196,12 @@ struct SetupArgs {
187196
conflicts_with = "net_allow"
188197
)]
189198
net_block: Vec<String>,
199+
200+
/// Allow the guest to bind (listen) on the given port. Implies --net.
201+
/// Without this flag, `net_bind` is rejected (outbound-only).
202+
/// Repeatable: `--port 8080 --port 3000`.
203+
#[arg(long, value_name = "PORT")]
204+
port: Vec<u16>,
190205
}
191206

192207
#[derive(Args)]
@@ -236,6 +251,12 @@ struct RunArgs {
236251
)]
237252
net_block: Vec<String>,
238253

254+
/// Allow the guest to bind (listen) on the given port. Implies --net.
255+
/// Without this flag, `net_bind` is rejected (outbound-only).
256+
/// Repeatable: `--port 8080 --port 3000`.
257+
#[arg(long, value_name = "PORT")]
258+
port: Vec<u16>,
259+
239260
/// Print evolve/warmup/per-run timing to stderr. Off by default so the
240261
/// user's script output is clean.
241262
#[arg(short = 'v', long = "verbose")]
@@ -393,7 +414,13 @@ fn cmd_setup(args: SetupArgs) -> Result<()> {
393414
.iter()
394415
.map(|m| parse_mount(m))
395416
.collect::<Result<_>>()?;
396-
let network = build_network_policy(args.net, &args.net_allow, &args.net_block)?;
417+
let listen_ports = build_listen_ports(&args.port);
418+
let network = build_network_policy(
419+
args.net,
420+
&args.net_allow,
421+
&args.net_block,
422+
listen_ports.is_some(),
423+
)?;
397424

398425
eprintln!("pyhl: warming up Python and persisting snapshot…");
399426
let t_warm = Instant::now();
@@ -407,6 +434,9 @@ fn cmd_setup(args: SetupArgs) -> Result<()> {
407434
if let Some(ref policy) = network {
408435
builder = builder.network(policy.clone());
409436
}
437+
if let Some(ref lp) = listen_ports {
438+
builder = builder.listen_ports(lp.clone());
439+
}
410440
let mut sbox = builder.build()?;
411441
sbox.restore()?;
412442
let _: () = sbox.call_named("run", "pass".to_string())?;
@@ -531,7 +561,13 @@ fn cmd_run(args: RunArgs) -> Result<()> {
531561
.iter()
532562
.map(|m| parse_mount(m))
533563
.collect::<Result<_>>()?;
534-
let network = build_network_policy(args.net, &args.net_allow, &args.net_block)?;
564+
let listen_ports = build_listen_ports(&args.port);
565+
let network = build_network_policy(
566+
args.net,
567+
&args.net_allow,
568+
&args.net_block,
569+
listen_ports.is_some(),
570+
)?;
535571

536572
let initrd = home.join(INITRD_FILE);
537573

@@ -546,6 +582,7 @@ fn cmd_run(args: RunArgs) -> Result<()> {
546582
&run_preopens,
547583
initrd_ref,
548584
network.as_ref(),
585+
listen_ports.as_ref(),
549586
)?;
550587
if args.verbose {
551588
eprintln!(

0 commit comments

Comments
 (0)