Skip to content

Commit 52a28ce

Browse files
authored
Merge pull request #68 from hyperlight-dev/fix/re-audit-round2
fix: harden fs and net handlers
2 parents 4c053f6 + 0dcbe53 commit 52a28ce

1 file changed

Lines changed: 33 additions & 0 deletions

File tree

host/src/lib.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ const MAX_DISPATCH_PAYLOAD: usize = 64 * 1024 * 1024;
108108
/// Cap for `__hl_sleep` duration to prevent unbounded host-thread blocking (60 s).
109109
const MAX_SLEEP_NS: u64 = 60_000_000_000;
110110

111+
/// Cap for `fs_list` directory entries to prevent host OOM on huge directories.
112+
const MAX_DIR_ENTRIES: usize = 100_000;
113+
111114
/// Default socket timeout for read/write/connect operations (30 s).
112115
const SOCKET_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30);
113116

@@ -1290,6 +1293,8 @@ fn handle_net_accept(
12901293
let st = tbl.get_sock_type(fd)?;
12911294
(s, p, st)
12921295
};
1296+
new_sock.set_read_timeout(Some(SOCKET_TIMEOUT))?;
1297+
new_sock.set_write_timeout(Some(SOCKET_TIMEOUT))?;
12931298
let peer_addr: Option<SocketAddr> = peer.as_socket();
12941299
let new_fd = table.lock().unwrap().insert(HostSocket {
12951300
socket: new_sock,
@@ -1716,6 +1721,13 @@ impl FsRouter {
17161721
for entry in
17171722
std::fs::read_dir(&target).map_err(|e| anyhow!("fs_list {:?}: {}", path, e))?
17181723
{
1724+
if entries.len() >= MAX_DIR_ENTRIES {
1725+
return Err(anyhow!(
1726+
"fs_list {:?}: too many entries (max {})",
1727+
path,
1728+
MAX_DIR_ENTRIES
1729+
));
1730+
}
17191731
let entry = entry?;
17201732
let ft = entry.file_type()?;
17211733
entries.push(json!({
@@ -1814,6 +1826,13 @@ impl FsRouter {
18141826
));
18151827
}
18161828
let offset = args["offset"].as_u64();
1829+
if let Some(off) = offset {
1830+
if off > MAX_TRUNCATE_LEN {
1831+
return Err(anyhow!(
1832+
"fs_write_bytes: offset too large ({off}, max {MAX_TRUNCATE_LEN})"
1833+
));
1834+
}
1835+
}
18171836
let append = args["append"].as_bool().unwrap_or(false);
18181837
let (fs, rel) = r.route(path)?;
18191838
let target = fs.resolve(rel)?;
@@ -1885,6 +1904,9 @@ impl FsRouter {
18851904
.ok_or_else(|| anyhow!("fs_unlink: missing 'path'"))?;
18861905
let (fs, rel) = r.route(path)?;
18871906
let target = fs.resolve(rel)?;
1907+
if target == *fs.root() {
1908+
return Err(anyhow!("fs_unlink: cannot remove mount root"));
1909+
}
18881910
let md =
18891911
std::fs::metadata(&target).map_err(|e| anyhow!("fs_unlink {:?}: {}", path, e))?;
18901912
if md.is_dir() {
@@ -3465,4 +3487,15 @@ mod tests {
34653487
assert_eq!(sock.read_timeout().unwrap(), Some(SOCKET_TIMEOUT));
34663488
assert_eq!(sock.write_timeout().unwrap(), Some(SOCKET_TIMEOUT));
34673489
}
3490+
3491+
#[test]
3492+
fn dns_read_name_rejects_circular_pointer() {
3493+
// Two compression pointers pointing at each other: offset 0 → 2, offset 2 → 0
3494+
let data = [0xC0, 0x02, 0xC0, 0x00];
3495+
let mut pos = 0usize;
3496+
assert!(
3497+
dns_read_name(&data, &mut pos).is_none(),
3498+
"circular DNS compression pointers should be rejected"
3499+
);
3500+
}
34683501
}

0 commit comments

Comments
 (0)