Skip to content

fix: reject symlinks with sysopen O_EXCL|O_CREAT per POSIX#376

Draft
toddr-bot wants to merge 1 commit intocpan-authors:mainfrom
toddr-bot:koan.toddr.bot/fix-sysopen-excl-symlink
Draft

fix: reject symlinks with sysopen O_EXCL|O_CREAT per POSIX#376
toddr-bot wants to merge 1 commit intocpan-authors:mainfrom
toddr-bot:koan.toddr.bot/fix-sysopen-excl-symlink

Conversation

@toddr-bot
Copy link
Copy Markdown
Collaborator

@toddr-bot toddr-bot commented Apr 13, 2026

What

sysopen() with O_EXCL|O_CREAT now fails with EEXIST when the path is a symbolic link, matching POSIX open(2) semantics.

Why

POSIX mandates this behavior as a security measure against symlink race attacks (TOCTOU). Previously, O_EXCL|O_CREAT would follow the symlink and only check whether the resolved target existed — allowing exclusive-create through a symlink, which defeats the purpose of O_EXCL.

How

Added a pre-resolution check in __sysopen: before following symlinks, if both O_EXCL and O_CREAT are set, inspect the path directly via _get_file_object(). If it's a symlink, return EEXIST immediately.

Testing

7 new tests in t/sysopen.t covering:

  • Symlink to existing target → EEXIST
  • Broken symlink → EEXIST
  • Non-existent non-symlink → succeeds (no regression)
  • Existing regular file → EEXIST (existing behavior preserved)

Full test suite passes (pre-existing fh-ref-leak.t failure is an upstream Overload::FileCheck version issue, unrelated).

🤖 Generated with Claude Code


Quality Report

Changes: 2 files changed, 54 insertions(+)

Code scan: clean

Tests: failed (4 Failed, 94 test)

Branch hygiene: clean

Generated by Kōan post-mission quality pipeline

POSIX open(2) mandates that O_EXCL|O_CREAT must fail with EEXIST
when the final path component is a symbolic link, regardless of
where it points.  This is a security feature to prevent symlink
race attacks (TOCTOU).

Previously, sysopen with O_EXCL|O_CREAT would follow symlinks
and only check whether the resolved target existed, allowing
exclusive-create through a symlink — violating POSIX semantics.

Add a pre-resolution check: when both O_EXCL and O_CREAT are set,
inspect the path directly (without following) and fail immediately
if it is a symlink.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

1 participant