Skip to content

Commit 0a8b037

Browse files
committed
fix: address Copilot review feedback on net_poll and hl_sleep
Clamp timeout_ms before i64→c_int cast, validate events range, handle poll() errors and EINTR, report POLLNVAL for unknown fds, add argument check to patch_interp.py. Signed-off-by: danbugs <danilochiarlone@gmail.com>
1 parent 7e9881b commit 0a8b037

3 files changed

Lines changed: 37 additions & 5 deletions

File tree

examples/go-http/patch_interp.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
import struct
1010
import sys
1111

12+
if len(sys.argv) != 2:
13+
print(f"Usage: {sys.argv[0]} <elf-binary>", file=sys.stderr)
14+
sys.exit(1)
15+
1216
path = sys.argv[1]
1317
with open(path, "rb") as f:
1418
data = bytearray(f.read())

examples/go/patch_interp.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
import struct
1010
import sys
1111

12+
if len(sys.argv) != 2:
13+
print(f"Usage: {sys.argv[0]} <elf-binary>", file=sys.stderr)
14+
sys.exit(1)
15+
1216
path = sys.argv[1]
1317
with open(path, "rb") as f:
1418
data = bytearray(f.read())

host/src/lib.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,42 +1635,59 @@ fn handle_net_poll(
16351635
.get("fds")
16361636
.and_then(|v| v.as_array())
16371637
.ok_or_else(|| anyhow!("net_poll: missing 'fds' array"))?;
1638-
let timeout_ms = args.get("timeout_ms").and_then(|v| v.as_i64()).unwrap_or(0) as libc::c_int;
1638+
let timeout_ms = args
1639+
.get("timeout_ms")
1640+
.and_then(|v| v.as_i64())
1641+
.unwrap_or(0)
1642+
.clamp(0, libc::c_int::MAX as i64) as libc::c_int;
16391643

16401644
let tbl = table.lock().unwrap();
16411645
let mut pollfds: Vec<libc::pollfd> = Vec::new();
16421646
let mut guest_fds: Vec<u64> = Vec::new();
1647+
let mut ready = Vec::new();
16431648

16441649
for entry in fds_val {
16451650
let fd = entry
16461651
.get("fd")
16471652
.and_then(|v| v.as_u64())
16481653
.ok_or_else(|| anyhow!("net_poll: entry missing 'fd'"))?;
1649-
let events = entry.get("events").and_then(|v| v.as_i64()).unwrap_or(0) as i16;
1654+
let raw_events = entry.get("events").and_then(|v| v.as_i64()).unwrap_or(0);
1655+
if !(0..=i16::MAX as i64).contains(&raw_events) {
1656+
return Err(anyhow!("net_poll: events {raw_events} out of i16 range"));
1657+
}
1658+
let events = raw_events as i16;
16501659
if let Ok(sock) = tbl.get_socket(fd) {
16511660
pollfds.push(libc::pollfd {
16521661
fd: sock.as_raw_fd(),
16531662
events,
16541663
revents: 0,
16551664
});
16561665
guest_fds.push(fd);
1666+
} else {
1667+
ready.push(json!({ "fd": fd, "revents": libc::POLLNVAL as i64 }));
16571668
}
16581669
}
16591670
drop(tbl);
16601671

16611672
if pollfds.is_empty() {
1662-
return Ok(json!({"ready": []}));
1673+
return Ok(json!({"ready": ready}));
16631674
}
16641675

1665-
let _ret = unsafe {
1676+
let ret = unsafe {
16661677
libc::poll(
16671678
pollfds.as_mut_ptr(),
16681679
pollfds.len() as libc::nfds_t,
16691680
timeout_ms,
16701681
)
16711682
};
16721683

1673-
let mut ready = Vec::new();
1684+
if ret < 0 {
1685+
let err = std::io::Error::last_os_error();
1686+
if err.raw_os_error() != Some(libc::EINTR) {
1687+
return Err(anyhow!("net_poll: poll() failed: {err}"));
1688+
}
1689+
}
1690+
16741691
for (i, pfd) in pollfds.iter().enumerate() {
16751692
if pfd.revents != 0 {
16761693
ready.push(json!({
@@ -1719,6 +1736,13 @@ fn hl_sleep_poll_sockets(
17191736
)
17201737
};
17211738

1739+
if ret < 0 {
1740+
let err = std::io::Error::last_os_error();
1741+
if err.raw_os_error() != Some(libc::EINTR) {
1742+
return Err(anyhow!("hl_sleep poll failed: {err}"));
1743+
}
1744+
}
1745+
17221746
Ok(json!({"socket_ready": ret > 0}))
17231747
}
17241748

0 commit comments

Comments
 (0)