diff --git a/src/kernel/getdents.rs b/src/kernel/getdents.rs index ab7bac620..7ea76387c 100644 --- a/src/kernel/getdents.rs +++ b/src/kernel/getdents.rs @@ -79,9 +79,13 @@ pub(crate) fn sys_getdents64(request: UNotifyEventRequest) -> ScmpNotifResp { let mut seen_dotdot = false; let pid = req.pid(); let len = dir.len(); - let mut ret: u64 = 0; + let mut ret: usize = 0; while ret == 0 { - let mut entries = match getdents64(&fd, count) { + let siz = count.checked_sub(ret).ok_or(Errno::EOVERFLOW)?; + if siz == 0 { + break; + } + let mut entries = match getdents64(&fd, siz) { Ok(entries) => entries, Err(Errno::ECANCELED) => break, // EOF or empty directory Err(errno) => return Err(errno), @@ -144,11 +148,17 @@ pub(crate) fn sys_getdents64(request: UNotifyEventRequest) -> ScmpNotifResp { } // Access granted, write entry to sandbox process memory. - let addr = req.data.args[1].checked_add(ret).ok_or(Errno::EOVERFLOW)?; - match request.write_mem(entry.as_bytes(), addr) { + // Handle truncation as necessary. + let buf = entry.as_bytes(); + let siz = count.checked_sub(ret).ok_or(Errno::EOVERFLOW)?; + let siz = buf.len().min(siz); + let ptr = req.data.args[1] + .checked_add(ret as u64) + .ok_or(Errno::EOVERFLOW)?; + match request.write_mem(&buf[..siz], ptr) { Ok(n) => { - ret = ret.checked_add(n as u64).ok_or(Errno::EOVERFLOW)?; - if n != entry.size() { + ret = ret.checked_add(n).ok_or(Errno::EOVERFLOW)?; + if n != entry.size() || ret >= count { break; } }