cube(2): read the errno from the libc, not from the syscall return value

glibc's syscall() returns -1 for *any* negative kernel return and stores the real
errno separately, so `-ret` on the error path is always 1 — EPERM. KernelStore::call
was computing `from_raw_os_error(-ret)`, so an absent record (the kernel's -ENOENT)
came back as "Operation not permitted".

That is why it hid this long: it only fires on the error path, and every early gate
read records that existed. It is also what the sealer's EPERM was hours ago — not
Morton codes, not a stray probe write; this. The fix reads std::io::Error::last_os_error()
when the syscall returns -1, which is what libc left in errno.

Proven by the encryption gate, which exercises exactly the missing-record path
(keys reads an absent keystore cell first): PASS, with a sealed envelope on the
device and no plaintext.
This commit is contained in:
luulu
2026-09-19 14:32:30 -04:00
parent 41862194e9
commit bd5f3ccfb9
3 changed files with 9 additions and 2 deletions
+9 -2
View File
@@ -92,9 +92,16 @@ impl KernelStore {
// SAFETY: `syscall` is the libc entry point. The number is ours, there is exactly one
// argument, and it points at `args`, which outlives the call. The kernel copies
// everything it needs out of that structure and validates it.
//
// The errno is read from the libc, not from the return value: glibc's `syscall()` returns
// `-1` for *any* negative kernel return and stores the real errno in `errno`, so `-ret`
// here is always `1` (EPERM) on the error path. That mis-mapping turned an absent record
// (the kernel's `-ENOENT`) into "Operation not permitted" — which is how it stayed hidden
// this long: it only fires on the error path, and every early gate read records that
// existed.
let ret = unsafe { syscall(SYS_CUBE, args.op, args as *mut CubeArgs) };
if ret < 0 {
return Err(StoreError::Io(std::io::Error::from_raw_os_error((-ret) as i32)));
if ret == -1 {
return Err(StoreError::Io(std::io::Error::last_os_error()));
}
Ok(ret as u64)
}
Binary file not shown.
Binary file not shown.