@@ -951,9 +951,10 @@ ptrace_write_vec(pid_t pid, struct sudo_ptrace_regs *regs, char **vec,
951951/*
952952 * Read a link from /proc/PID and store the result in buf.
953953 * Used to read the cwd and exe links in /proc/PID.
954- * Returns true on success, else false.
954+ * Returns the number of bytes written to buf on success, else -1.
955+ * Note: name and buf _may_ overlap.
955956 */
956- static bool
957+ static ssize_t
957958proc_read_link (pid_t pid , const char * name , char * buf , size_t bufsize )
958959{
959960 ssize_t len ;
@@ -962,14 +963,14 @@ proc_read_link(pid_t pid, const char *name, char *buf, size_t bufsize)
962963
963964 len = snprintf (path , sizeof (path ), "/proc/%d/%s" , (int )pid , name );
964965 if (len > 0 && len < ssizeof (path )) {
965- len = readlink (path , buf , bufsize - 1 );
966- if (len != -1 ) {
966+ len = readlink (path , buf , bufsize );
967+ if (len != -1 && ( size_t ) len != bufsize ) {
967968 /* readlink(2) does not add the NUL for us. */
968969 buf [len ] = '\0' ;
969- debug_return_bool (true );
970+ debug_return_ssize_t ( len + 1 );
970971 }
971972 }
972- debug_return_bool (false );
973+ debug_return_ssize_t ( -1 );
973974}
974975
975976/*
@@ -1011,6 +1012,20 @@ get_execve_info(pid_t pid, struct sudo_ptrace_regs *regs, char **pathname_out,
10111012 "unable to read execve pathname for process %d" , (int )pid );
10121013 goto bad ;
10131014 }
1015+
1016+ /* For fexecve() the path may be in the form /proc/self/fd/N */
1017+ if (strncmp (argbuf , "/proc/self/fd/" , 14 ) == 0 ) {
1018+ const char * errstr ;
1019+ const char * fdstr = argbuf + 14 ;
1020+ (void )sudo_strtonum (fdstr , 0 , INT_MAX , & errstr );
1021+ if (errstr == NULL ) {
1022+ /* Rewrite argbuf with link target (if it is one). */
1023+ ssize_t len = proc_read_link (pid , fdstr , argbuf , bufsize );
1024+ if (len != -1 )
1025+ nread = len ;
1026+ }
1027+ }
1028+
10141029 /* Defer setting pathname until after all reallocations are done. */
10151030 off = (size_t )nread ;
10161031 }
@@ -1626,7 +1641,7 @@ ptrace_verify_post_exec(pid_t pid, struct sudo_ptrace_regs *regs,
16261641 }
16271642
16281643 /* Get the executable path. */
1629- if (! proc_read_link (pid , "exe" , pathname , sizeof (pathname ))) {
1644+ if (proc_read_link (pid , "exe" , pathname , sizeof (pathname )) == -1 ) {
16301645 /* Missing /proc file system is not a fatal error. */
16311646 sudo_debug_printf (SUDO_DEBUG_ERROR , "%s: unable to read /proc/%d/exe" ,
16321647 __func__ , (int )pid );
@@ -1768,7 +1783,7 @@ ptrace_intercept_execve(pid_t pid, struct intercept_closure *closure)
17681783 }
17691784
17701785 /* Get the current working directory and execve info. */
1771- if (! proc_read_link (pid , "cwd" , cwd , sizeof (cwd )))
1786+ if (proc_read_link (pid , "cwd" , cwd , sizeof (cwd )) == -1 )
17721787 (void )strlcpy (cwd , "unknown" , sizeof (cwd ));
17731788 buf = get_execve_info (pid , & regs , & pathname , & argc , & argv ,
17741789 & envc , & envp );
0 commit comments