Skip to content

Commit 7afe8d6

Browse files
committed
Fix potential UB issues
Ensure buffer is the right size. Ensure correct alignment and no UB
1 parent ff3c218 commit 7afe8d6

File tree

1 file changed

+32
-15
lines changed

1 file changed

+32
-15
lines changed

src/exec_ptrace.c

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -415,9 +415,12 @@ ptrace_readv_string(pid_t pid, unsigned long addr, char *buf, size_t bufsize)
415415
static ssize_t
416416
ptrace_read_string(pid_t pid, unsigned long addr, char *buf, size_t bufsize)
417417
{
418-
const char *cp, *buf0 = buf;
419-
unsigned long word;
418+
const char *buf0 = buf;
420419
size_t i;
420+
union {
421+
unsigned long word;
422+
char buf[sizeof(unsigned long)];
423+
} u;
421424
debug_decl(ptrace_read_string, SUDO_DEBUG_EXEC);
422425

423426
#ifdef HAVE_PROCESS_VM_READV
@@ -432,28 +435,27 @@ ptrace_read_string(pid_t pid, unsigned long addr, char *buf, size_t bufsize)
432435
* is the unit ptrace(2) uses.
433436
*/
434437
for (;;) {
435-
word = ptrace(PTRACE_PEEKDATA, pid, addr, NULL);
436-
if (word == (unsigned long)-1) {
438+
u.word = ptrace(PTRACE_PEEKDATA, pid, addr, NULL);
439+
if (u.word == (unsigned long)-1) {
437440
sudo_debug_printf(
438441
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
439442
"ptrace(PTRACE_PEEKDATA, %d, 0x%lx, NULL)", (int)pid, addr);
440443
debug_return_ssize_t(-1);
441444
}
442445

443-
cp = (char *)&word;
444-
for (i = 0; i < sizeof(unsigned long); i++) {
446+
for (i = 0; i < sizeof(u.buf); i++) {
445447
if (bufsize == 0) {
446448
sudo_debug_printf(SUDO_DEBUG_ERROR,
447449
"%s: %d: out of space reading string", __func__, (int)pid);
448450
errno = ENOSPC;
449451
debug_return_ssize_t(-1);
450452
}
451-
*buf = cp[i];
453+
*buf = u.buf[i];
452454
if (*buf++ == '\0')
453455
debug_return_ssize_t(buf - buf0);
454456
bufsize--;
455457
}
456-
addr += sizeof(unsigned long);
458+
addr += sizeof(u.word);
457459
}
458460
}
459461

@@ -469,6 +471,12 @@ growbuf(char **bufp, size_t *bufsizep, char **curp, size_t *remp)
469471
char *newbuf;
470472
debug_decl(growbuf, SUDO_DEBUG_EXEC);
471473

474+
/* Check for overflow when doubling the size of the buffer. */
475+
if (oldsize > SIZE_MAX / 2) {
476+
sudo_warnx(U_("%s: %s"), __func__, U_("buffer size overflow"));
477+
debug_return_bool(false);
478+
}
479+
472480
/* Double the size of the buffer. */
473481
newbuf = reallocarray(*bufp, 2, oldsize);
474482
if (newbuf == NULL) {
@@ -952,14 +960,23 @@ proc_read_link(pid_t pid, const char *name, char *buf, size_t bufsize)
952960
char path[PATH_MAX];
953961
debug_decl(proc_read_link, SUDO_DEBUG_EXEC);
954962

963+
/* Ensure minimum buffer size and termination */
964+
if (bufsize < 2) {
965+
errno = EOVERFLOW;
966+
debug_return_bool(false);
967+
}
968+
955969
len = snprintf(path, sizeof(path), "/proc/%d/%s", (int)pid, name);
956-
if (len > 0 && len < ssizeof(path)) {
957-
len = readlink(path, buf, bufsize - 1);
958-
if (len != -1) {
959-
/* readlink(2) does not add the NUL for us. */
960-
buf[len] = '\0';
961-
debug_return_bool(true);
962-
}
970+
if (len < 0 || len >= ssizeof(path)) {
971+
errno = ENAMETOOLONG;
972+
debug_return_bool(false);
973+
}
974+
975+
len = readlink(path, buf, bufsize - 1);
976+
if (len != -1) {
977+
/* readlink(2) does not add the NUL for us. */
978+
buf[len] = '\0';
979+
debug_return_bool(true);
963980
}
964981
debug_return_bool(false);
965982
}

0 commit comments

Comments
 (0)