Files
RedBear-OS/local/patches/relibc/P5-named-semaphores.patch
vasilito b9874d0941 feat: USB storage read/write proof + full Red Bear OS tree sync
Add redbear-usb-storage-check in-guest binary that validates USB mass
storage read and write I/O: discovers /scheme/disk/ devices, writes a
test pattern to sector 2048, reads it back, verifies match, restores
original content. Updates test-usb-storage-qemu.sh with write-proof
verification step.

Includes all accumulated Red Bear OS work: kernel patches, relibc
patches, driver infrastructure, DRM/GPU, KDE recipes, firmware,
validation tooling, build system hardening, and documentation.
2026-05-03 23:03:24 +01:00

250 lines
7.6 KiB
Diff

diff --git a/src/header/semaphore/cbindgen.toml b/src/header/semaphore/cbindgen.toml
index be8f845..a96854c 100644
--- a/src/header/semaphore/cbindgen.toml
+++ b/src/header/semaphore/cbindgen.toml
@@ -3,6 +3,9 @@ include_guard = "_RELIBC_SEMAPHORE_H"
after_includes = """
#include <bits/timespec.h> // for timespec
"""
+trailer = """
+#define SEM_FAILED ((sem_t *) -1)
+"""
language = "C"
style = "Type"
no_includes = true
diff --git a/src/header/semaphore/mod.rs b/src/header/semaphore/mod.rs
index 0ca2fa9..2dd1bc2 100644
--- a/src/header/semaphore/mod.rs
+++ b/src/header/semaphore/mod.rs
@@ -2,111 +2,183 @@
//!
//! See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/semaphore.h.html>.
+use core::mem::size_of;
+
use crate::{
+ c_str::CStr,
header::{
bits_timespec::timespec,
+ errno::{EEXIST, EAGAIN, EINVAL, ETIMEDOUT},
+ fcntl::{O_CREAT, O_EXCL, O_RDWR},
+ sys_mman::{
+ mmap, munmap, shm_open, shm_unlink, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE,
+ },
time::{CLOCK_MONOTONIC, CLOCK_REALTIME},
+ unistd::{close, ftruncate},
+ },
+ platform::{
+ ERRNO,
+ types::{c_char, c_int, c_long, c_uint, clockid_t, c_void, mode_t, off_t},
},
- platform::types::{c_char, c_int, c_long, c_uint, clockid_t},
};
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/semaphore.h.html>.
-// TODO: Statically verify size and align
#[repr(C)]
#[derive(Clone, Copy)]
pub union sem_t {
pub size: [c_char; 4],
pub align: c_long,
}
+
+pub const SEM_FAILED: *mut sem_t = usize::MAX as *mut sem_t;
+
pub type RlctSempahore = crate::sync::Semaphore;
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_close.html>.
-// #[unsafe(no_mangle)]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn sem_close(sem: *mut sem_t) -> c_int {
- todo!("named semaphores")
+ unsafe { munmap(sem.cast::<c_void>(), size_of::<sem_t>()) }
}
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_destroy.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sem_destroy(sem: *mut sem_t) -> c_int {
unsafe { core::ptr::drop_in_place(sem.cast::<RlctSempahore>()) };
0
}
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_getvalue.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int {
unsafe { sval.write(get(sem).value() as c_int) };
-
0
}
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_init.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sem_init(sem: *mut sem_t, _pshared: c_int, value: c_uint) -> c_int {
unsafe { sem.cast::<RlctSempahore>().write(RlctSempahore::new(value)) };
-
0
}
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_open.html>.
-// TODO: va_list
-// #[unsafe(no_mangle)]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn sem_open(
name: *const c_char,
- oflag: c_int, /* (va_list) value: c_uint */
+ oflag: c_int,
+ mut __valist: ...
) -> *mut sem_t {
- todo!("named semaphores")
+ if name.is_null() {
+ ERRNO.set(EINVAL);
+ return SEM_FAILED;
+ }
+ let name_c = unsafe { CStr::from_ptr(name) };
+ let name_bytes = name_c.to_bytes();
+ if name_bytes.is_empty() || name_bytes[0] != b'/' {
+ ERRNO.set(EINVAL);
+ return SEM_FAILED;
+ }
+ if name_bytes[1..].iter().any(|&b| b == b'/') {
+ ERRNO.set(EINVAL);
+ return SEM_FAILED;
+ }
+ let creat = oflag & O_CREAT == O_CREAT;
+ let excl = oflag & O_EXCL == O_EXCL;
+ let (mode, value): (mode_t, c_uint) = if creat {
+ (
+ unsafe { __valist.arg::<mode_t>() },
+ unsafe { __valist.arg::<c_uint>() },
+ )
+ } else {
+ (0, 0)
+ };
+ let (fd, created) = if creat && excl {
+ let fd = unsafe { shm_open(name, O_CREAT | O_EXCL | O_RDWR, mode) };
+ if fd < 0 { return SEM_FAILED; }
+ (fd, true)
+ } else if creat {
+ let fd = unsafe { shm_open(name, O_CREAT | O_EXCL | O_RDWR, mode) };
+ if fd >= 0 {
+ (fd, true)
+ } else if ERRNO.get() == EEXIST {
+ let fd = unsafe { shm_open(name, O_RDWR, 0) };
+ if fd < 0 { return SEM_FAILED; }
+ (fd, false)
+ } else {
+ return SEM_FAILED;
+ }
+ } else {
+ let fd = unsafe { shm_open(name, O_RDWR, 0) };
+ if fd < 0 { return SEM_FAILED; }
+ (fd, false)
+ };
+ if created {
+ if ftruncate(fd, size_of::<sem_t>() as off_t) < 0 {
+ let _ = close(fd);
+ return SEM_FAILED;
+ }
+ }
+ let ptr = unsafe {
+ mmap(
+ core::ptr::null_mut(),
+ size_of::<sem_t>(),
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ fd,
+ 0,
+ )
+ };
+ let _ = close(fd);
+ if ptr == MAP_FAILED { return SEM_FAILED; }
+ let sem_ptr = ptr.cast::<sem_t>();
+ if created {
+ unsafe { sem_ptr.cast::<RlctSempahore>().write(RlctSempahore::new(value)) };
+ }
+ sem_ptr
}
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_post.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sem_post(sem: *mut sem_t) -> c_int {
unsafe { get(sem) }.post(1);
-
0
}
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_trywait.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int {
- unsafe { get(sem) }.try_wait();
-
+ if unsafe { get(sem) }.try_wait() == 0 {
+ ERRNO.set(EAGAIN);
+ return -1;
+ }
0
}
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_unlink.html>.
-// #[unsafe(no_mangle)]
+#[unsafe(no_mangle)]
pub unsafe extern "C" fn sem_unlink(name: *const c_char) -> c_int {
- todo!("named semaphores")
+ unsafe { shm_unlink(name) }
}
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_trywait.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sem_wait(sem: *mut sem_t) -> c_int {
- if let Ok(()) = unsafe { get(sem) }.wait(None, CLOCK_MONOTONIC) {}; // TODO handle error
-
+ if let Err(()) = unsafe { get(sem) }.wait(None, CLOCK_MONOTONIC) {
+ ERRNO.set(EINVAL);
+ return -1;
+ }
0
}
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_clockwait.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sem_clockwait(
sem: *mut sem_t,
clock_id: clockid_t,
abstime: *const timespec,
) -> c_int {
- if let Ok(()) = unsafe { get(sem) }.wait(Some(&unsafe { (*abstime).clone() }), clock_id) {}; // TODO handle error
-
+ if let Err(()) = unsafe { get(sem) }.wait(Some(&unsafe { (*abstime).clone() }), clock_id) {
+ ERRNO.set(ETIMEDOUT);
+ return -1;
+ }
0
}
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_timedwait.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn sem_timedwait(sem: *mut sem_t, abstime: *const timespec) -> c_int {
- if let Ok(()) = unsafe { get(sem) }.wait(Some(&unsafe { (*abstime).clone() }), CLOCK_REALTIME) {
- }; // TODO handle error
-
+ if let Err(()) = unsafe { get(sem) }.wait(Some(&unsafe { (*abstime).clone() }), CLOCK_REALTIME) {
+ ERRNO.set(ETIMEDOUT);
+ return -1;
+ }
0
}
diff --git a/src/sync/semaphore.rs b/src/sync/semaphore.rs
index ce14961..0c280d9 100644
--- a/src/sync/semaphore.rs
+++ b/src/sync/semaphore.rs
@@ -58,7 +58,7 @@ impl Semaphore {
loop {
let value = self.try_wait();
- if value == 0 {
+ if value > 0 {
return Ok(());
}