Skip to content

Commit f096ea1

Browse files
authored
Merge pull request #67 from hyperlight-dev/fix/dns-pointer-loop
fix: add resource caps and DNS pointer-loop guard
2 parents 659686a + 4611c78 commit f096ea1

1 file changed

Lines changed: 47 additions & 1 deletion

File tree

host/src/lib.rs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,15 @@ const MAX_FS_READ: u64 = 16 * 1024 * 1024;
9696
/// Cap for `net_send`/`net_sendto` decoded payload (1 MiB).
9797
const MAX_NET_SEND: usize = 1024 * 1024;
9898

99+
/// Cap for `fs_write`/`fs_write_bytes` payload to prevent guest-triggered OOM (16 MiB).
100+
const MAX_FS_WRITE: usize = 16 * 1024 * 1024;
101+
102+
/// Cap for `fs_truncate` length to prevent disk exhaustion (1 GiB).
103+
const MAX_TRUNCATE_LEN: u64 = 1024 * 1024 * 1024;
104+
105+
/// Cap for incoming dispatch payload size (64 MiB).
106+
const MAX_DISPATCH_PAYLOAD: usize = 64 * 1024 * 1024;
107+
99108
/// Cap for `__hl_sleep` duration to prevent unbounded host-thread blocking (60 s).
100109
const MAX_SLEEP_NS: u64 = 60_000_000_000;
101110

@@ -674,6 +683,12 @@ impl ToolRegistry {
674683
/// payload and result to stderr — useful when diagnosing
675684
/// guest/host protocol mismatches.
676685
pub fn dispatch(&self, payload: &[u8]) -> Vec<u8> {
686+
if payload.len() > MAX_DISPATCH_PAYLOAD {
687+
return serde_json::to_vec(&serde_json::json!({
688+
"error": format!("payload too large: {} bytes (max {})", payload.len(), MAX_DISPATCH_PAYLOAD)
689+
}))
690+
.unwrap_or_default();
691+
}
677692
let debug = std::env::var("HL_DISPATCH_DEBUG")
678693
.ok()
679694
.map(|v| v == "1")
@@ -1122,6 +1137,7 @@ fn dns_read_name(data: &[u8], pos: &mut usize) -> Option<String> {
11221137
let mut p = *pos;
11231138
let mut jumped = false;
11241139
let mut jump_save = 0;
1140+
let mut hops = 0u8;
11251141
loop {
11261142
if p >= data.len() {
11271143
return None;
@@ -1132,10 +1148,13 @@ fn dns_read_name(data: &[u8], pos: &mut usize) -> Option<String> {
11321148
break;
11331149
}
11341150
if (len & 0xC0) == 0xC0 {
1135-
// Pointer
11361151
if p + 1 >= data.len() {
11371152
return None;
11381153
}
1154+
hops += 1;
1155+
if hops > 128 {
1156+
return None;
1157+
}
11391158
let offset = ((len & 0x3F) << 8) | data[p + 1] as usize;
11401159
if !jumped {
11411160
jump_save = p + 2;
@@ -1658,6 +1677,13 @@ impl FsRouter {
16581677
let text = args["text"]
16591678
.as_str()
16601679
.ok_or_else(|| anyhow!("fs_write: missing 'text'"))?;
1680+
if text.len() > MAX_FS_WRITE {
1681+
return Err(anyhow!(
1682+
"fs_write: payload too large ({} bytes, max {})",
1683+
text.len(),
1684+
MAX_FS_WRITE
1685+
));
1686+
}
16611687
let append = args["append"].as_bool().unwrap_or(false);
16621688
let (fs, rel) = r.route(path)?;
16631689
let target = fs.resolve(rel)?;
@@ -1764,9 +1790,22 @@ impl FsRouter {
17641790
let data_b64 = args["data"]
17651791
.as_str()
17661792
.ok_or_else(|| anyhow!("fs_write_bytes: missing 'data'"))?;
1793+
if data_b64.len() > MAX_FS_WRITE * 4 / 3 + 4 {
1794+
return Err(anyhow!(
1795+
"fs_write_bytes: payload too large (max {} decoded bytes)",
1796+
MAX_FS_WRITE
1797+
));
1798+
}
17671799
let data = base64::engine::general_purpose::STANDARD
17681800
.decode(data_b64)
17691801
.map_err(|e| anyhow!("fs_write_bytes: bad base64: {}", e))?;
1802+
if data.len() > MAX_FS_WRITE {
1803+
return Err(anyhow!(
1804+
"fs_write_bytes: decoded payload too large ({} bytes, max {})",
1805+
data.len(),
1806+
MAX_FS_WRITE
1807+
));
1808+
}
17701809
let offset = args["offset"].as_u64();
17711810
let append = args["append"].as_bool().unwrap_or(false);
17721811
let (fs, rel) = r.route(path)?;
@@ -1797,6 +1836,13 @@ impl FsRouter {
17971836
let length = args["length"]
17981837
.as_u64()
17991838
.ok_or_else(|| anyhow!("fs_truncate: missing 'length'"))?;
1839+
if length > MAX_TRUNCATE_LEN {
1840+
return Err(anyhow!(
1841+
"fs_truncate: length too large ({} bytes, max {})",
1842+
length,
1843+
MAX_TRUNCATE_LEN
1844+
));
1845+
}
18001846
let (fs, rel) = r.route(path)?;
18011847
let target = fs.resolve(rel)?;
18021848
let f = std::fs::OpenOptions::new()

0 commit comments

Comments
 (0)