Avoid potentially overwriting string table when writing argv.
In compat mode, if argc is odd, writing the last pointer of argv will overlap with the address of argv[0], so leave an extra word in between. Also remove incorrect comments about PTRACE_PEEKDATA unaligned access.
This commit is contained in:
@@ -320,7 +320,6 @@ ptrace_read_string(pid_t pid, long addr, char *buf, size_t bufsize)
|
|||||||
debug_return_ssize_t(-1);
|
debug_return_ssize_t(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX - this could be optimized. */
|
|
||||||
cp = (char *)&word;
|
cp = (char *)&word;
|
||||||
for (i = 0; i < sizeof(long); i++) {
|
for (i = 0; i < sizeof(long); i++) {
|
||||||
if (bufsize == 0) {
|
if (bufsize == 0) {
|
||||||
@@ -353,7 +352,6 @@ ptrace_read_vec(pid_t pid, struct sudo_ptrace_regs *regs, long addr,
|
|||||||
|
|
||||||
/* Fill in vector. */
|
/* Fill in vector. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* XXX - unaligned access for compat binaries */
|
|
||||||
long word = ptrace(PTRACE_PEEKDATA, pid, addr, NULL);
|
long word = ptrace(PTRACE_PEEKDATA, pid, addr, NULL);
|
||||||
word &= regs->addrmask;
|
word &= regs->addrmask;
|
||||||
switch (word) {
|
switch (word) {
|
||||||
@@ -393,7 +391,6 @@ ptrace_get_vec_len(pid_t pid, struct sudo_ptrace_regs *regs, long addr)
|
|||||||
debug_decl(ptrace_get_vec_len, SUDO_DEBUG_EXEC);
|
debug_decl(ptrace_get_vec_len, SUDO_DEBUG_EXEC);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* XXX - unaligned access for compat binaries */
|
|
||||||
long word = ptrace(PTRACE_PEEKDATA, pid, addr, NULL);
|
long word = ptrace(PTRACE_PEEKDATA, pid, addr, NULL);
|
||||||
word &= regs->addrmask;
|
word &= regs->addrmask;
|
||||||
switch (word) {
|
switch (word) {
|
||||||
@@ -900,12 +897,15 @@ ptrace_intercept_execve(pid_t pid, struct intercept_closure *closure)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate the amount of space required for pointers + strings.
|
* Calculate the amount of space required for pointers + strings.
|
||||||
* We align everything on a word boundary to simplify writes,
|
* We align everything on a word boundary to avoid overlapping
|
||||||
* ptrace(2) may not be able to write to unaligned addresses.
|
* writes since ptrace(2) does everything in native word units.
|
||||||
|
*
|
||||||
|
* In compat mode, if argc is odd, writing the last pointer will
|
||||||
|
* overlap the first string so leave an extra word in between.
|
||||||
*/
|
*/
|
||||||
if (argv_mismatch) {
|
if (argv_mismatch) {
|
||||||
/* argv pointers */
|
/* argv pointers */
|
||||||
len = (argc + 1) * regs.wordsize;
|
len = (argc + 1 + regs.compat) * regs.wordsize;
|
||||||
space += WORDALIGN(len);
|
space += WORDALIGN(len);
|
||||||
|
|
||||||
/* argv strings */
|
/* argv strings */
|
||||||
@@ -929,12 +929,11 @@ ptrace_intercept_execve(pid_t pid, struct intercept_closure *closure)
|
|||||||
set_sc_arg2(®s, sp);
|
set_sc_arg2(®s, sp);
|
||||||
|
|
||||||
/* Skip over argv pointers (plus NULL) for string table. */
|
/* Skip over argv pointers (plus NULL) for string table. */
|
||||||
strtab += WORDALIGN((argc + 1) * regs.wordsize);
|
strtab += WORDALIGN((argc + 1 + regs.compat) * regs.wordsize);
|
||||||
|
|
||||||
/* Copy new argv (+ NULL) into tracee one word at a time. */
|
/* Copy new argv (+ NULL) into tracee one word at a time. */
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
/* Store string address as new argv[i]. */
|
/* Store string address as new argv[i]. */
|
||||||
/* XXX - unaligned access for compat binaries */
|
|
||||||
if (ptrace(PTRACE_POKEDATA, pid, sp, strtab) == -1) {
|
if (ptrace(PTRACE_POKEDATA, pid, sp, strtab) == -1) {
|
||||||
sudo_warn("ptrace(PTRACE_POKEDATA, %d, 0x%lx, 0x%lx)",
|
sudo_warn("ptrace(PTRACE_POKEDATA, %d, 0x%lx, 0x%lx)",
|
||||||
(int)pid, sp, strtab);
|
(int)pid, sp, strtab);
|
||||||
@@ -948,7 +947,6 @@ ptrace_intercept_execve(pid_t pid, struct intercept_closure *closure)
|
|||||||
goto done;
|
goto done;
|
||||||
strtab += len;
|
strtab += len;
|
||||||
}
|
}
|
||||||
/* XXX - unaligned access for compat binaries */
|
|
||||||
if (ptrace(PTRACE_POKEDATA, pid, sp, NULL) == -1) {
|
if (ptrace(PTRACE_POKEDATA, pid, sp, NULL) == -1) {
|
||||||
sudo_warn("ptrace(PTRACE_POKEDATA, %d, 0x%lx, NULL)",
|
sudo_warn("ptrace(PTRACE_POKEDATA, %d, 0x%lx, NULL)",
|
||||||
(int)pid, sp);
|
(int)pid, sp);
|
||||||
|
Reference in New Issue
Block a user