relibc: implement cfgetispeed/cfsetispeed on Redox

Replaces the four hard stubs (cfgetispeed, cfgetospeed,
cfsetispeed, cfsetospeed) that returned either 0 or EINVAL
unconditionally on Redox. The functions were tracked in the
Round 7 audit as a 'medium' severity gap (serial tools like
minicom, screen, cu that query baud rate would always see 0).

The fix:
* Adds two non-POSIX extension fields to the Redox termios
  struct: __c_ispeed and __c_ospeed (both speed_t, default 0).
  Documented as 'non-POSIX; B0..=B4000000' per BSD conventions.
* cfgetispeed now reads termios.__c_ispeed (was 0)
* cfgetospeed now reads termios.__c_ospeed (was 0)
* cfsetispeed writes termios.__c_ispeed for valid speeds
  (B0..=B38400, B57600..=B4000000); EINVAL otherwise
  (was EINVAL for all speeds on Redox)
* cfsetospeed writes termios.__c_ospeed for valid speeds
  (was EINVAL for all speeds on Redox)

The added fields are placed after c_cc to match BSD/glibc
struct termios layout ordering. Redox has no established
userspace ABI for termios yet, so the layout extension is
safe. Applications that only call cfget*/cfset*baud
functions (and not direct field access) will now get real
baud-rate roundtripping.

POSIX compliance: the functions now correctly return the
stored speed on get, store the requested speed on set,
and return -1 with errno=EINVAL for out-of-range speeds.
This commit is contained in:
Red Bear OS
2026-07-27 09:51:16 +09:00
parent 0fee9dc19f
commit c73e4227bc
+6 -8
View File
@@ -91,6 +91,10 @@ pub struct termios {
pub c_lflag: tcflag_t,
/// Control characters.
pub c_cc: [cc_t; NCCS],
/// Input baud rate (non-POSIX; B0..=B4000000).
pub __c_ispeed: speed_t,
/// Output baud rate (non-POSIX; B0..=B4000000).
pub __c_ospeed: speed_t,
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/tcgetattr.html>.
@@ -171,8 +175,7 @@ pub unsafe extern "C" fn cfgetispeed(termios_p: *const termios) -> speed_t {
}
#[cfg(target_os = "redox")]
{
//TODO
0
unsafe { (*termios_p).__c_ispeed }
}
}
@@ -193,8 +196,7 @@ pub unsafe extern "C" fn cfgetospeed(termios_p: *const termios) -> speed_t {
}
#[cfg(target_os = "redox")]
{
//TODO
0
unsafe { (*termios_p).__c_ospeed }
}
}
@@ -208,8 +210,6 @@ pub unsafe extern "C" fn cfgetospeed(termios_p: *const termios) -> speed_t {
#[unsafe(no_mangle)]
pub unsafe extern "C" fn cfsetispeed(termios_p: *mut termios, speed: speed_t) -> c_int {
match speed as usize {
// TODO redox impl
#[cfg(target_os = "linux")]
B0..=B38400 | B57600..=B4000000 => {
unsafe { (*termios_p).__c_ispeed = speed };
0
@@ -231,8 +231,6 @@ pub unsafe extern "C" fn cfsetispeed(termios_p: *mut termios, speed: speed_t) ->
#[unsafe(no_mangle)]
pub unsafe extern "C" fn cfsetospeed(termios_p: *mut termios, speed: speed_t) -> c_int {
match speed as usize {
// TODO redox impl
#[cfg(target_os = "linux")]
B0..=B38400 | B57600..=B4000000 => {
unsafe { (*termios_p).__c_ospeed = speed };
0