Skip to content

[Comgr] Open time-statistics log with O_NOFOLLOW#3209

Open
lamb-j wants to merge 1 commit into
amd-stagingfrom
comgr/time-stat-nofollow
Open

[Comgr] Open time-statistics log with O_NOFOLLOW#3209
lamb-j wants to merge 1 commit into
amd-stagingfrom
comgr/time-stat-nofollow

Conversation

@lamb-j

@lamb-j lamb-j commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

The AMD_COMGR_TIME_STATISTICS perf log is opened with raw_fd_ostream(path, OF_Text) (i.e. O_CREAT|O_WRONLY|O_TRUNC, no O_NOFOLLOW). The path can be caller-influenced via AMD_COMGR_REDIRECT_LOGS, or defaults to a CWD-relative PerfStatsLog.txt. A symlink pre-planted at that path would be followed and the target truncated with the process's privileges.

This opens the file directly with O_NOFOLLOW on POSIX and wraps the descriptor in a raw_fd_ostream. Windows keeps the existing path-based open (O_NOFOLLOW has no equivalent there).

Note: this is an opt-in diagnostic feature (off unless the env var is set), so severity is low; this is defensive hardening. The sibling AMD_COMGR_SAVE_TEMPS path flagged by the same scan finding already uses fs::createUniqueDirectory (mkdtemp-equivalent) and needs no change.

ISSUE ID: ROCM-26581

The AMD_COMGR_TIME_STATISTICS log path can be caller-influenced via
AMD_COMGR_REDIRECT_LOGS, or default to a CWD-relative PerfStatsLog.txt.
Opening it without O_NOFOLLOW allows a pre-planted symlink at that path
to be followed and truncated with the process's privileges.

Open the file directly with O_NOFOLLOW on POSIX and wrap the descriptor
in a raw_fd_ostream. Windows retains the existing path-based open.

ISSUE ID: ROCM-26581
@lamb-j lamb-j requested a review from chinmaydd as a code owner July 6, 2026 00:51
@github-actions github-actions Bot added the comgr Related to Code Object Manager label Jul 6, 2026
// followed. The path may be caller-influenced (AMD_COMGR_REDIRECT_LOGS) or
// default to a CWD-relative file, so refuse to write through a symlink.
int FD = ::open(LogFile.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW,
0644);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not hardcode the file permissions ? Seems more permissive than the default

Comment on lines +50 to +54
if (FD < 0) {
EC = std::error_code(errno, std::generic_category());
} else {
LogF.reset(new (std::nothrow)
llvm::raw_fd_ostream(FD, /*shouldClose=*/true));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a test ?

Comment on lines +50 to +55
if (FD < 0) {
EC = std::error_code(errno, std::generic_category());
} else {
LogF.reset(new (std::nothrow)
llvm::raw_fd_ostream(FD, /*shouldClose=*/true));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (FD < 0) {
EC = std::error_code(errno, std::generic_category());
} else {
LogF.reset(new (std::nothrow)
llvm::raw_fd_ostream(FD, /*shouldClose=*/true));
}
if (FD < 0) {
EC = std::error_code(errno, std::generic_category());
} else {
LogF.reset(new (std::nothrow) llvm::raw_fd_ostream(FD, /*shouldClose=*/true));
if (!LogF) {
::close(FD);
EC = std::make_error_code(std::errc::not_enough_memory);
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we are at it, this fixes the FD leak if the new fails

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can also probably merge the #else block below into this one

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comgr Related to Code Object Manager

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants