Skip to content

Fix TOCTOU race condition in file content probes - #2406

Open
Arden97 wants to merge 3 commits into
OpenSCAP:mainfrom
Arden97:toctou_symlink_following
Open

Fix TOCTOU race condition in file content probes#2406
Arden97 wants to merge 3 commits into
OpenSCAP:mainfrom
Arden97:toctou_symlink_following

Conversation

@Arden97

@Arden97 Arden97 commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

Description

  • Eliminate Time-Of-Check-To-Time-Of-Use race condition in three independent file content probes:
    • textfilecontent54
    • textfilecontent
    • yamlfilecontent
  • Prevent following and scanning blocked paths through symlinks

Rationale

  • The usage of stat() followed by open() in mentioned probes creates a tight vulnerability window, which attacker may use to switch paths during the file processing
  • in these changes, by using open() first we getting a file descriptor early, which prevents race condition
  • file descriptor is later passed to fstat() to confirm the presence of a valid scanning target
  • additional fixes:
    • Add O_NONBLOCK flag to open() calls to prevent FIFO-based denial-of-service (a named pipe without a writer would block the scanner indefinitely)
    • Replace fopen() with fdopen() in textfilecontent_probe.c and yamlfilecontent_probe.c to wrap the already-opened fd instead of performing a second path resolution
    • Add S_ISREG() check to yamlfilecontent_probe.c, which previously had none - it would attempt to parse directories, sockets, or other non-regular files as YAML
    • Add probe_fd_path_is_blocked() - a new helper in probe-api.c that resolves an open fd's real path via /proc/self/fd/<fd> and checks it against the blocked paths list
      • this change will ensure that blocked paths will not be followed and scanned through he symlinks
  • Fixes: OPENSCAP-6959

Testing

  • testing blocked paths scanning through symlinks
    • build oscap from source and then run ctest --test-dir build -R "textfilecontent|yamlfilecontent" -j$(nproc)
    • make sure that probes/textfilecontent54/test_symlinks.sh passed

goto cleanup;

fd = open(whole_path_with_prefix, O_RDONLY);
fd = open(whole_path_with_prefix, O_RDONLY | O_NONBLOCK);
*/
whole_path_with_prefix = oscap_path_join(prefix, whole_path);
if (stat(whole_path_with_prefix, &st) == -1)
tmp_fd = open(whole_path_with_prefix, O_RDONLY | O_NONBLOCK);

@Arden97 Arden97 Aug 27, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@jan-cerny, @Mab879, are these warnings from github-bot legit?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think they are legit. Any users can set the OSCAP_PROBE_ROOT environment variable to any string and this string will be used as a prefix prepended to the file path, which can potentionally lead to opening arbitrary or unwanted files in the open call. However, this is a pre-existing issue, and we haven't cared so far.

@jan-cerny jan-cerny self-assigned this Aug 27, 2026
}
if (fstat(tmp_fd, &st) == -1
|| !S_ISREG(st.st_mode)
|| probe_fd_path_is_blocked(tmp_fd, ctx->blocked_paths))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

IIUC if the prefix is used the probe_fd_path_is_blocked will check the path including the prefix, but we want to check the path without the prefix.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Correct, because blocked_paths are not prefixed. Updated

@Arden97
Arden97 marked this pull request as ready for review August 31, 2026 10:55
@Arden97
Arden97 force-pushed the toctou_symlink_following branch from 9bb95c6 to 147e453 Compare September 3, 2026 18:13
@sonarqubecloud

sonarqubecloud Bot commented Sep 3, 2026

Copy link
Copy Markdown

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants