Skip to content

Sync symlink/ownership hardening from upstream - #85

Merged
artursarlo merged 1 commit into
masterfrom
cve-sync-from-upstream-2
Oct 1, 2026
Merged

artursarlo merged 1 commit into
masterfrom
cve-sync-from-upstream-2

Conversation

@artursarlo

Copy link
Copy Markdown

Summary

This PR continues our upstream CVE/security sync. Our previous sync (#80) backported dependency fixes up to intel/gprofiler#1046, but two code-level security fixes had already landed upstream (intel/gprofiler) before then and were intentionally out of scope for that dependency-focused PR. A fresh scan of upstream master confirms these are still the only security fixes missing from our fork. Each change below mirrors upstream, reconciled against our fork's divergence.

Changes & rationale

1. Restore ownership validation + add symlink checks in mkdir_owned_root

Backports intel/gprofiler#1047.

  • Adds is_owned_by_current_user() and, in mkdir_owned_root_wrapper() (non-root path), validates the directory is owned by the current user instead of merely writable.
  • Adds symlink checks (reject, don't follow) to both mkdir_owned_root() and mkdir_owned_root_wrapper(), before and after creation, to prevent symlink attacks.
  • Upstream's PR primarily removed an erroneous unconditional return that made the ownership check dead code (introduced in 5285bef7). Our fork had already fixed that dead-code bug via an assert is_root() rewrite of mkdir_owned_root(), so this change layers in only the missing symlink/ownership hardening while preserving our fork's assert is_root() design and shutil.rmtree-and-recreate behavior.

2. Fix symlink escape vulnerabilities in safe_copy and log reading (CWE-59)

Backports intel/gprofiler#1050.

  • safe_copy(): uses O_EXCL for atomic temp-file creation (defeats symlink redirection of writes), adds a defense-in-depth dst symlink check before rename, and fixes an fd leak if os.fdopen() fails.
  • Adds safe_read_text(): reads files with O_NOFOLLOW so the kernel atomically rejects symlinks at open time; fixes an fd leak on os.fdopen() failure. Adds _O_NOFOLLOW with a getattr fallback for portability.
  • gprofiler/profilers/java.py: _read_ap_log() now uses safe_read_text() for the async-profiler log path.

These close two container-escape vectors:

  1. Write escape — attacker plants a symlink at the libasyncProfiler.so copy destination to overwrite arbitrary host files.
  2. Read escape — attacker plants a symlink at the async-profiler log path to exfiltrate host file contents into gProfiler logs.

Notes

Test plan

Backports two security fixes merged upstream (intel/gprofiler) after our
last CVE sync (origin #80, which covered up to intel#1046):

- intel#1047: restore ownership validation in mkdir_owned_root and add
  symlink checks to both mkdir_owned_root and mkdir_owned_root_wrapper.
  Our fork had already removed the erroneous dead-code 'return' via an
  assert-is-root rewrite; this layers in the missing symlink/ownership
  hardening while preserving that customization.
- intel#1050: harden safe_copy (O_EXCL atomic temp creation + dst symlink
  check + fd-leak fix) and add safe_read_text (O_NOFOLLOW) to prevent
  symlink escape (CWE-59); use safe_read_text in java _read_ap_log.

Co-authored-by: Cursor <cursoragent@cursor.com>
@artursarlo
artursarlo merged commit 6b85d68 into master Oct 1, 2026
14 of 19 checks passed
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.

2 participants