Skip to content

Commit

Permalink
utils: Fix TOCTOU in get_pid_exe()
Browse files Browse the repository at this point in the history
This fixes a classic TOCTOU. The problem is that if `pid` exits between
the exists() check and read_symlink() we will eat a ENOENT exception.
Fix by checking result of read_symlink() operation itself.

Discovered in a flakey test run in another PR:

[  FAILED  ] builtin.func_uprobe_elf_symtable
	Command: /home/runner/work/bpftrace/bpftrace/build-ci/src/bpftrace -e 'uprobe:./testprogs/uprobe_symres_exited_process:test { print(func); exit(); }'
	Unclean exit code: -6
	Output: Attaching 1 probe...\n__BPFTRACE_NOTIFY_PROBES_ATTACHED\nterminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error'\n  what():  filesystem error: read_symlink: No such file or directory [/proc/13255/exe]\n
  • Loading branch information
danobi authored and viktormalik committed Nov 14, 2023
1 parent 5630750 commit 51d9fbe
Showing 1 changed file with 12 additions and 5 deletions.
17 changes: 12 additions & 5 deletions src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,11 +274,18 @@ std::string get_pid_exe(const std::string &pid)
proc_path /= pid;
proc_path /= "exe";

if (!std_filesystem::exists(proc_path, ec) ||
!std_filesystem::is_symlink(proc_path, ec))
return "";

return std_filesystem::read_symlink(proc_path).string();
try
{
return std_filesystem::read_symlink(proc_path).string();
}
catch (const std_filesystem::filesystem_error &e)
{
auto err = e.code().value();
if (err == ENOENT || err == EINVAL)
return {};
else
throw e;
}
}

std::string get_pid_exe(pid_t pid)
Expand Down

0 comments on commit 51d9fbe

Please sign in to comment.