2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-22 09:57:41 +00:00

ptrace_readv_string: properly handle reads of more than one page

When the "intercept" and "intercept_verify" options are enabled and
either argv[] or envp[] contains a string larger than the page size
(usually 4096), ptrace_readv_string() would fill the buffer with
mutiple copies of the same string.  Fixes GitHub issue #453.
This commit is contained in:
Todd C. Miller 2025-07-20 09:36:39 -06:00
parent fb208d383a
commit 2e93eabedf

View File

@ -387,8 +387,7 @@ ptrace_readv_string(pid_t pid, unsigned long addr, char *buf, size_t bufsize)
(unsigned long)remote.iov_base, remote.iov_len); (unsigned long)remote.iov_base, remote.iov_len);
debug_return_ssize_t(-1); debug_return_ssize_t(-1);
case 0: case 0:
sudo_debug_printf( sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"process_vm_readv(%d, [0x%lx, %zu], 1, [0x%lx, %zu], 1, 0): %s", "process_vm_readv(%d, [0x%lx, %zu], 1, [0x%lx, %zu], 1, 0): %s",
(int)pid, (unsigned long)local.iov_base, local.iov_len, (int)pid, (unsigned long)local.iov_base, local.iov_len,
(unsigned long)remote.iov_base, remote.iov_len, "premature EOF"); (unsigned long)remote.iov_base, remote.iov_len, "premature EOF");
@ -398,9 +397,17 @@ ptrace_readv_string(pid_t pid, unsigned long addr, char *buf, size_t bufsize)
cp = memchr(buf, '\0', (size_t)nread); cp = memchr(buf, '\0', (size_t)nread);
if (cp != NULL) if (cp != NULL)
debug_return_ssize_t((cp - buf0) + 1); /* includes NUL */ debug_return_ssize_t((cp - buf0) + 1); /* includes NUL */
/* No NUL terminator, we should have a full page. */
if (nread != page_size) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"process_vm_readv(%d, [0x%lx, %zu], 1, [0x%lx, %zu], 1, 0)"
" -> %zd",
(int)pid, (unsigned long)local.iov_base, local.iov_len,
(unsigned long)remote.iov_base, remote.iov_len, nread);
}
buf += nread; buf += nread;
bufsize -= (size_t)nread; bufsize -= (size_t)nread;
addr += sizeof(unsigned long); addr += (size_t)nread;
break; break;
} }
} }