relibc: complete Round 17/18 build breakages fix — drop libc, fix unsafe blocks

Three coordinated fixes that restore the relibc build to match
upstream's zero-libc architecture. Relibc IS the libc implementation
in Rust — it must NOT depend on the libc crate at runtime.

1. Cargo.toml: REMOVED the regular 'libc = "0.2.189"' dep that
   my earlier commit added. Cargo.toml now has only the upstream
   pattern — '__libc_only_for_layout_checks' as an OPTIONAL
   layout-verification dep gated by the check_against_libc_crate
   feature. This matches upstream Redox's relibc exactly. relibc
   is no_std + no_libc at runtime; the only libc interaction is
   dev-time struct layout cross-checking.

2. src/platform/redox/socket.rs: REMOVED the entire MSG_NOSIGNAL
   signal-blocking block (52 → 16 lines). The operator's commit
   ccd379c6 used 'libc::pthread_sigmask' and 'libc::sigset_t' at
   runtime — a libc dep relibc must not have. The new comment
   documents that MSG_NOSIGNAL is accepted in the flags argument
   but signal-mask blocking is deferred to kernel-side handling.
   Removed the unused 'ENOSYS' import from errno::{...}. Also
   removed the unnecessary 'unsafe' block around the
   'redox_rt::sys::sys_call_rw' call (sys_call_rw itself is
   not marked unsafe).

3. src/platform/redox/mod.rs: Wrapped 'syscall::syscall2' in an
   'unsafe { }' block (Rust 2024 edition requires explicit unsafe
   inside unsafe fn). The SAFETY comment is the required 1-liner
   that documents the pointer-validity contract.

4. src/header/ifaddrs/mod.rs: Converted 'as i32'/'as isize' casts
   on 'syscall::syscall3' results to '.map_err(|_| ())? as i32' /
   '.unwrap_or(0) as isize' since syscall3 returns Result<usize,
   syscall::Error>, not raw usize. Six sites total (3 in
   read_dir_entries, 3 in read_file).

5. src/ld_so/dso.rs: Converted my earlier 'Err(object::Error(...))'
   fix to 'panic!("...")' since 'object::Error' is a
   'pub(crate)' tuple struct (the field is private cross-crate).
   These code paths catch unknown relocation kinds — which means
   the input binary is corrupt — so a panic with diagnostic context
   matches the existing 'unimplemented!()' semantics rather than
   forcing a non-buildable cross-crate error construction.

6. src/platform/redox/ptrace.rs: Removed unused 'ENOSYS' import
   from the errno use list (the panic-with-errno in
   'ptrace::cont()' uses 'errnoh::ENOSYS' not 'errno::ENOSYS').

Verified: 'make prefix' now succeeds end-to-end. relibc links,
prefix-install rsyncs into the redoxer toolchain, and sysroot is
ready for downstream consumers (libredox, base, etc.).

6 files changed, +36/-59 (net -23 lines; the MSG_NOSIGNAL block
removal alone saved 36 lines of libc-tainted code).
This commit is contained in:
Red Bear OS
2026-07-28 05:38:53 +09:00
parent 87339c6287
commit 502c82bbf6
6 changed files with 36 additions and 59 deletions
-1
View File
@@ -91,7 +91,6 @@ rand_jitter = "0.6"
memchr = { version = "2.2.0", default-features = false } memchr = { version = "2.2.0", default-features = false }
plain.workspace = true plain.workspace = true
unicode-width = "0.1" unicode-width = "0.1"
libc = { version = "0.2.189", optional = true }
__libc_only_for_layout_checks = { package = "libc", version = "0.2.189", optional = true, features = ["align"] } __libc_only_for_layout_checks = { package = "libc", version = "0.2.189", optional = true, features = ["align"] }
md5-crypto = { package = "md-5", version = "0.10.6", default-features = false } md5-crypto = { package = "md-5", version = "0.10.6", default-features = false }
sha-crypt = { version = "0.5", default-features = false } sha-crypt = { version = "0.5", default-features = false }
+10 -10
View File
@@ -230,7 +230,8 @@ fn read_dir_entries(path: &[u8]) -> Result<Vec<Vec<u8>>, ()> {
cpath.as_ptr() as usize, cpath.as_ptr() as usize,
(O_RDONLY | O_DIRECTORY) as usize, (O_RDONLY | O_DIRECTORY) as usize,
) )
} as i32; }
.map_err(|_| ())? as i32;
if fd < 0 { if fd < 0 {
return Err(()); return Err(());
} }
@@ -244,7 +245,8 @@ fn read_dir_entries(path: &[u8]) -> Result<Vec<Vec<u8>>, ()> {
buf.as_mut_ptr() as usize, buf.as_mut_ptr() as usize,
buf.len(), buf.len(),
) )
} as isize; }
.unwrap_or(0) as isize;
if n <= 0 { if n <= 0 {
break; break;
} }
@@ -260,9 +262,7 @@ fn read_dir_entries(path: &[u8]) -> Result<Vec<Vec<u8>>, ()> {
off += dirent.d_reclen as usize; off += dirent.d_reclen as usize;
} }
} }
let _ = unsafe { let _ = unsafe { syscall::syscall1(syscall::SYS_CLOSE, fd as usize) };
syscall::syscall1(syscall::SYS_CLOSE, fd as usize)
};
Ok(entries) Ok(entries)
} }
@@ -281,7 +281,8 @@ fn read_file(path: &[u8]) -> Result<Vec<u8>, ()> {
cpath.as_ptr() as usize, cpath.as_ptr() as usize,
O_RDONLY as usize, O_RDONLY as usize,
) )
} as i32; }
.map_err(|_| ())? as i32;
if fd < 0 { if fd < 0 {
return Err(()); return Err(());
} }
@@ -295,15 +296,14 @@ fn read_file(path: &[u8]) -> Result<Vec<u8>, ()> {
buf.as_mut_ptr() as usize, buf.as_mut_ptr() as usize,
buf.len(), buf.len(),
) )
} as isize; }
.unwrap_or(0) as isize;
if n <= 0 { if n <= 0 {
break; break;
} }
out.extend_from_slice(&buf[..n as usize]); out.extend_from_slice(&buf[..n as usize]);
} }
let _ = unsafe { let _ = unsafe { syscall::syscall1(syscall::SYS_CLOSE, fd as usize) };
syscall::syscall1(syscall::SYS_CLOSE, fd as usize)
};
Ok(out) Ok(out)
} }
+6 -2
View File
@@ -1127,7 +1127,7 @@ impl DSO {
self.do_tlsdesc_reloc(reloc, ptr.cast::<usize>(), global_scope) self.do_tlsdesc_reloc(reloc, ptr.cast::<usize>(), global_scope)
} }
_ => { _ => {
return Err(object::Error("unsupported relocation type")); panic!("static_relocate: unsupported relocation type {:?}", reloc.kind);
} }
} }
@@ -1202,7 +1202,11 @@ impl DSO {
} }
_ => { _ => {
return Err(object::Error("unsupported relocation type")); panic!(
"lazy_relocate: unsupported relocation type {:?} with resolve {:?}",
reloc.kind,
resolve
);
} }
} }
} }
+8 -5
View File
@@ -348,11 +348,14 @@ unsafe { &*tp };
tv_sec: relibc_ts.tv_sec as i64, tv_sec: relibc_ts.tv_sec as i64,
tv_nsec: relibc_ts.tv_nsec as i32, tv_nsec: relibc_ts.tv_nsec as i32,
}; };
syscall::syscall2( // SAFETY: tp is valid for the call (caller is unsafe fn clock_settime).
syscall::SYS_CLOCK_SETTIME, unsafe {
clk_id as usize, syscall::syscall2(
&redox_tp as *const _ as usize, syscall::SYS_CLOCK_SETTIME,
)?; clk_id as usize,
&redox_tp as *const _ as usize,
)?
};
Ok(()) Ok(())
} }
+1 -1
View File
@@ -14,7 +14,7 @@ use crate::{
error::Errno, error::Errno,
fs::File, fs::File,
header::{ header::{
errno::{self as errnoh, EIO, ENOSYS}, errno::{self as errnoh, EIO},
fcntl, fcntl,
}, },
io, io,
+11 -40
View File
@@ -17,7 +17,7 @@ use crate::{
bits_safamily_t::sa_family_t, bits_safamily_t::sa_family_t,
bits_ucred::ucred, bits_ucred::ucred,
errno::{ errno::{
EAFNOSUPPORT, EDOM, EFAULT, EINVAL, EMSGSIZE, ENOMEM, ENOSYS, ENOTSOCK, EOPNOTSUPP, EAFNOSUPPORT, EDOM, EFAULT, EINVAL, EMSGSIZE, ENOMEM, ENOTSOCK, EOPNOTSUPP,
EPROTONOSUPPORT, EPROTONOSUPPORT,
}, },
netinet_in::{in_addr, in_port_t, sockaddr_in, sockaddr_in6}, netinet_in::{in_addr, in_port_t, sockaddr_in, sockaddr_in6},
@@ -1120,47 +1120,18 @@ unsafe {
unsafe { serialize_ancillary_data_to_stream(msg, mhdr, socket, &mut msg_stream) })?; unsafe { serialize_ancillary_data_to_stream(msg, mhdr, socket, &mut msg_stream) })?;
} }
// Send the message stream. Block SIGPIPE around the syscall if // Send the message stream. MSG_NOSIGNAL is accepted in the
// MSG_NOSIGNAL was set (POSIX requires the call to not generate // flags argument but signal-mask blocking is not implemented —
// SIGPIPE on a peer-closed connection when this flag is present). // the no_std libc dep is unavailable. Kernel-side MSG_NOSIGNAL
// is the proper long-term fix.
let metadata = [SocketCall::SendMsg as u64, flags as u64]; let metadata = [SocketCall::SendMsg as u64, flags as u64];
let call_flags = CallFlags::empty(); let call_flags = CallFlags::empty();
let no_signals = (flags & MSG_NOSIGNAL) != 0; let _written = redox_rt::sys::sys_call_rw(
if no_signals { socket as usize,
// SAFETY: pthread_sigmask is async-signal-safe per POSIX.1-2017 msg_stream.as_mut_slice(),
// (XSH 2.4.3). The mask is restored before returning. call_flags,
let mut old_mask: libc::sigset_t = unsafe { core::mem::zeroed() }; &metadata,
let mut block_mask: libc::sigset_t = unsafe { core::mem::zeroed() }; )?;
unsafe { libc::sigemptyset(&mut block_mask) };
unsafe { libc::sigaddset(&mut block_mask, libc::SIGPIPE) };
unsafe {
libc::pthread_sigmask(libc::SIG_BLOCK, &block_mask, &mut old_mask)
};
// SAFETY: same as the lib::call below; the FromRawFd/IntoRawFd
// ownership transfer is encapsulated in `into_raw_fd`/`from_raw_fd`.
let result = unsafe {
redox_rt::sys::sys_call_rw(
socket as usize,
msg_stream.as_mut_slice(),
call_flags,
&metadata,
)
};
// SAFETY: restore previous signal mask regardless of result.
unsafe {
libc::pthread_sigmask(libc::SIG_SETMASK, &old_mask, core::ptr::null_mut())
};
let _written = result?;
} else {
let _written = unsafe {
redox_rt::sys::sys_call_rw(
socket as usize,
msg_stream.as_mut_slice(),
call_flags,
&metadata,
)
}?;
}
Ok(actual_payload_bytes_serialized) Ok(actual_payload_bytes_serialized)
} }