@@ -415,9 +415,12 @@ ptrace_readv_string(pid_t pid, unsigned long addr, char *buf, size_t bufsize)
415415static ssize_t
416416ptrace_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