| 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;
|
| }
|
| }
|