Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions abi/snapshot.json
Original file line number Diff line number Diff line change
Expand Up @@ -5123,6 +5123,10 @@
"name": "GetRobustList",
"number": 262
},
{
"name": "Times",
"number": 270
},
{
"name": "Mknod",
"number": 271
Expand Down
81 changes: 81 additions & 0 deletions crates/kernel/src/fork.rs
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,7 @@ pub fn serialize_fork_state(proc: &Process, buf: &mut [u8]) -> Result<usize, Err
SocketDomain::Unix => 0,
SocketDomain::Inet => 1,
SocketDomain::Inet6 => 2,
SocketDomain::Netlink => 3,
})?;
w.write_u32(match sock.sock_type {
SocketType::Stream => 0,
Expand Down Expand Up @@ -1046,6 +1047,7 @@ pub fn deserialize_fork_state(buf: &[u8], child_pid: u32) -> Result<Process, Err
0 => SocketDomain::Unix,
1 => SocketDomain::Inet,
2 => SocketDomain::Inet6,
3 => SocketDomain::Netlink,
_ => return Err(Errno::EINVAL),
};
let sock_type = match r.read_u32()? {
Expand Down Expand Up @@ -1497,6 +1499,85 @@ pub fn serialize_exec_state(proc: &Process, buf: &mut [u8]) -> Result<usize, Err
// ── Program break ──
w.write_u32(proc.memory.get_brk() as u32)?;

// ── Socket table ──
//
// POSIX exec replaces the program image, not the process's open file
// descriptions. Any socket fd that survives FD_CLOEXEC must still refer to
// its socket object after exec, including listener accept queues/options.
// Use the same wire shape as fork so socket indices encoded in socket OFDs
// (host_handle = -(idx + 1)) remain valid.
{
use crate::socket::{SocketDomain, SocketState, SocketType};
let mut sock_count = 0u32;
for idx in 0..proc.sockets.len() {
if proc.sockets.get(idx).is_some() {
sock_count += 1;
}
}
w.write_u32(proc.sockets.len() as u32)?;
w.write_u32(sock_count)?;
for idx in 0..proc.sockets.len() {
if let Some(sock) = proc.sockets.get(idx) {
w.write_u32(idx as u32)?;
w.write_u32(match sock.domain {
SocketDomain::Unix => 0,
SocketDomain::Inet => 1,
SocketDomain::Inet6 => 2,
SocketDomain::Netlink => 3,
})?;
w.write_u32(match sock.sock_type {
SocketType::Stream => 0,
SocketType::Dgram => 1,
})?;
w.write_u32(sock.protocol)?;
w.write_u32(match sock.state {
SocketState::Unbound => 0,
SocketState::Bound => 1,
SocketState::Listening => 2,
SocketState::Connected => 3,
SocketState::Closed => 4,
SocketState::Connecting => 4,
})?;
w.write_u32(sock.peer_idx.map(|v| v as u32).unwrap_or(0xFFFFFFFF))?;
w.write_u32(sock.recv_buf_idx.map(|v| v as u32).unwrap_or(0xFFFFFFFF))?;
w.write_u32(sock.send_buf_idx.map(|v| v as u32).unwrap_or(0xFFFFFFFF))?;
w.write_u32(if sock.shut_rd { 1 } else { 0 })?;
w.write_u32(if sock.shut_wr { 1 } else { 0 })?;
w.write_u32(sock.host_net_handle.map(|v| v as u32).unwrap_or(0xFFFFFFFF))?;
w.write_u32(sock.options.len() as u32)?;
for &(level, optname, value) in &sock.options {
w.write_u32(level)?;
w.write_u32(optname)?;
w.write_u32(value)?;
}
w.write_bytes(&sock.bind_addr)?;
w.write_u32(sock.bind_port as u32)?;
w.write_bytes(&sock.peer_addr)?;
w.write_u32(sock.peer_port as u32)?;
// Legacy per-process accept backlog is consume-once state.
// Shared listener backlog indices below preserve the actual
// POSIX accept queue for current stream listeners.
w.write_u32(0u32)?;
w.write_u32(if sock.global_pipes { 1 } else { 0 })?;
w.write_u32(
sock.shared_backlog_idx
.map(|v| v as u32)
.unwrap_or(0xFFFFFFFF),
)?;
match &sock.bind_path {
Some(p) => {
w.write_u32(p.len() as u32)?;
w.write_bytes(p)?;
}
None => {
w.write_u32(0xFFFFFFFF)?;
}
}
w.write_u32(sock.accept_wake_idx.unwrap_or(0xFFFFFFFF))?;
}
}
}

// ── Patch total_size ──
let total = w.pos as u32;
w.patch_u32(total_size_offset, total);
Expand Down
3 changes: 2 additions & 1 deletion crates/kernel/src/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub enum SocketDomain {
Unix,
Inet,
Inet6,
Netlink,
}

/// Socket type.
Expand Down Expand Up @@ -375,7 +376,6 @@ impl SocketInfo {
shared_backlog_idx: None,
accept_wake_idx: None,
dgram_queue: Vec::new(),
global_pipes: true,
ipv4_multicast_memberships: Vec::new(),
netlink_queue: Vec::new(),
global_pipes: true,
Expand Down Expand Up @@ -418,6 +418,7 @@ impl SocketInfo {
///
/// Discarded in the child:
/// * `dgram_queue` — buffered UDP datagrams.
/// * `netlink_queue` — buffered netlink replies.
/// * `oob_byte` — pending TCP out-of-band byte.
/// * `listen_backlog` — pre-accepted AF_UNIX same-process connections.
/// Indices reference other entries in this process's SocketTable; if
Expand Down
Loading
Loading