Skip to content

Commit b01d256

Browse files
ian-h-chamberlainMeziu
authored andcommitted
Update getrandom impl based on ctru error codes
1 parent e6a19e9 commit b01d256

File tree

1 file changed

+29
-17
lines changed

1 file changed

+29
-17
lines changed

src/lib.rs

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -74,26 +74,38 @@ unsafe extern "C" fn getrandom(
7474
mut buflen: libc::size_t,
7575
flags: libc::c_uint,
7676
) -> libc::ssize_t {
77-
// TODO: is this needed? Maybe just `buflen = buflen.min(libc::ssize_t::MAX)` ?
78-
buflen = buflen.min(0x1FFFFFF);
77+
// Based on https://man7.org/linux/man-pages/man2/getrandom.2.html
78+
// Technically we only have one source (no true /dev/random), but the
79+
// behavior should be more expected this way.
80+
let maxlen = if flags & libc::GRND_RANDOM != 0 {
81+
512
82+
} else {
83+
0x1FFFFFF
84+
};
85+
buflen = buflen.min(maxlen);
7986

80-
if flags != 0 {
81-
// no flags are supported on 3DS
82-
*__errno() = libc::EINVAL;
83-
return -1;
84-
}
87+
let ret = ctru_sys::PS_GenerateRandomBytes(buf, buflen as libc::c_uint);
8588

86-
let ret = ctru_sys::PS_GenerateRandomBytes(buf, buflen as libc::c_uint) as libc::ssize_t;
87-
if ret < 0 {
88-
// this is kind of a hack, but at least gives some visibility to the
89-
// error code returned by PS_GenerateRandomBytes I guess? Another option
90-
// might be to panic, which could use a payload of a specific error type
91-
// that the ctru panic handler could decode into 3DS-specific human-readable
92-
// errors.
93-
*__errno() = ret as libc::c_int;
94-
-1
95-
} else {
89+
// avoid conflicting a real POSIX errno by using a value < 0
90+
// should we define this in ctru-sys somewhere or something?
91+
const ECTRU: libc::c_int = -1;
92+
93+
if ctru_sys::R_SUCCEEDED(ret) {
9694
// safe because above ensures buflen < isize::MAX
9795
buflen as libc::ssize_t
96+
} else {
97+
// best-effort attempt at translating return codes
98+
*__errno() = match ctru_sys::R_SUMMARY(ret) as libc::c_uint {
99+
ctru_sys::RS_WOULDBLOCK => libc::EAGAIN,
100+
ctru_sys::RS_INVALIDARG | ctru_sys::RS_WRONGARG => {
101+
match ctru_sys::R_DESCRIPTION(ret) as libc::c_uint {
102+
// most likely user error, forgot to initialize PS module
103+
ctru_sys::RD_INVALID_HANDLE => ECTRU,
104+
_ => libc::EINVAL,
105+
}
106+
}
107+
_ => ECTRU,
108+
};
109+
-1
98110
}
99111
}

0 commit comments

Comments
 (0)