relibc: pass level via SocketCall wire format for set/get sockopt
DEF-P0-11 (Finding 1.7: option collision) from NETWORKING-AND-DRIVERS-CODE-ASSESSMENT-2026-07-27.md §3.4: the previous relibc->netstack wire format was [SocketCall::SetSockOpt, option_name]. The netstack dispatched on option only, with no level. Options that share a numeric value across levels collided silently: - option 4: TCP_KEEPIDLE (SOL_SOCKET) vs IP_TOS (IPPROTO_IP) - option 2: TCP_MAXSEG (IPPROTO_TCP) vs IP_TTL (IPPROTO_IP) vs SO_REUSEADDR (SOL_SOCKET) Wire format fix: [SocketCall::Set/GetSockOpt, level, option_name]. The netstack trait SocketT now takes (level, name) separately so each impl can dispatch on both. The stale 'TODO convert back to match when we support more levels' comment in setsockopt is removed (the level is now passed in the wire format directly). Also matches the netstack scheme/socket.rs dispatch which already reads metadata[1] as level and metadata[2] as option.
This commit is contained in:
@@ -860,7 +860,14 @@ unsafe { *option_len_ptr = mem::size_of::<c_int>() as socklen_t };
|
||||
return Ok(());
|
||||
}
|
||||
_ => {
|
||||
let metadata = [SocketCall::GetSockOpt as u64, option_name as u64];
|
||||
// Wire format: [SocketCall::GetSockOpt, level, option]
|
||||
// Level disambiguates option 4 (TCP_KEEPIDLE at SOL_SOCKET)
|
||||
// from option 4 (IP_TOS at IPPROTO_IP) etc.
|
||||
let metadata = [
|
||||
SocketCall::GetSockOpt as u64,
|
||||
level as u64,
|
||||
option_name as u64,
|
||||
];
|
||||
let payload =
|
||||
// SAFETY: caller guarantees ptr is aligned for T and len is exact; no alias
|
||||
unsafe { slice::from_raw_parts_mut(option_value.cast::<u8>(), option_len) };
|
||||
@@ -1206,18 +1213,26 @@ unsafe { &*option_value.cast::<timeval>() };
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// TODO convert back to match when we support more levels
|
||||
// Wire format: [SocketCall::SetSockOpt, level, option]
|
||||
// The netstack dispatches on level + option together. Without
|
||||
// level in the wire format, option 4 (TCP_KEEPIDLE at SOL_SOCKET)
|
||||
// reads as IP_TOS (also option 4) at IPPROTO_IP. See
|
||||
// NETWORKING-AND-DRIVERS-CODE-ASSESSMENT-2026-07-27.md §3.4
|
||||
// (Finding 1.7: option collision).
|
||||
if level == SOL_SOCKET {
|
||||
match option_name {
|
||||
SO_RCVTIMEO => return set_timeout(b"read_timeout"),
|
||||
SO_SNDTIMEO => return set_timeout(b"write_timeout"),
|
||||
_ => {
|
||||
let metadata = [SocketCall::SetSockOpt as u64, option_name as u64];
|
||||
let metadata = [
|
||||
SocketCall::SetSockOpt as u64,
|
||||
level as u64,
|
||||
option_name as u64,
|
||||
];
|
||||
let payload = // SAFETY: caller must verify the safety contract for this operation
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(option_value as *mut u8, option_len as usize)
|
||||
};
|
||||
let call_flags = CallFlags::empty();
|
||||
redox_rt::sys::sys_call_rw(
|
||||
socket as usize,
|
||||
payload,
|
||||
|
||||
Reference in New Issue
Block a user