syswonder / ruxos

Rust Unikernel OS
https://ruxos.syswonder.org
Other
59 stars 19 forks source link

A wrong implement for `sys_getrandom`'s flags #140

Open ken4647 opened 1 month ago

ken4647 commented 1 month ago

In api/ruxos_posix_api/src/imp/getrandom.rs, it is implemented as:

/// Fills the buffer pointed to by buf with up to buflen random bytes.
pub unsafe extern "C" fn sys_getrandom(buf: *mut c_void, buflen: size_t, flags: c_int) -> ssize_t {
    info!(
        "sys_getrandom <= buf: {:?}, buflen: {}, flags: {}",
        buf, buflen, flags
    );
    syscall_body!(sys_getrandom, {
        if buf.is_null() {
            return Err(LinuxError::EFAULT);
        }

        // BUG: flags are implemented wrongly, flags should be checks bit by bit
        match flags as _ {
            crate::ctypes::GRND_NONBLOCK => {}
            crate::ctypes::GRND_RANDOM => {}
            _ => return Err(LinuxError::EINVAL),
        }
        // fill the buffer 8 bytes at a time first, then fill the remaining bytes
        let buflen_mod = buflen % (core::mem::size_of::<i64>() / core::mem::size_of::<u8>());
        let buflen_div = buflen / (core::mem::size_of::<i64>() / core::mem::size_of::<u8>());
        for i in 0..buflen_div {
            *((buf as *mut u8 as *mut i64).add(i)) = sys_random() as i64;
        }
        for i in 0..buflen_mod {
            *((buf as *mut u8).add(buflen - buflen_mod + i)) = sys_rand() as u8;
        }
        Ok(buflen as ssize_t)
    })
}

Obviously, the flag is checked as:

        match flags as _ {
            crate::ctypes::GRND_NONBLOCK => {}
            crate::ctypes::GRND_RANDOM => {}
            _ => return Err(LinuxError::EINVAL),
        }

This will make errors like below happens:

[1727161820.746064 0:1 ruxos_posix_api::imp::getrandom:152] sys_getrandom <= buf: 0xffff8000009d5ef0, buflen: 32, flags: 0
[1727161820.746318 0:1 ruxos_posix_api::imp::getrandom:156] sys_getrandom => Err(EINVAL)