Skip to content

feat(libkernel_sys): create symlink targets with parent-directory components - #10625

Open
Dom3005 wants to merge 2 commits into
boykopovar:mainfrom
Dom3005:feat/symlink-targets
Open

Dom3005 wants to merge 2 commits into
boykopovar:mainfrom
Dom3005:feat/symlink-targets

Conversation

@Dom3005

@Dom3005 Dom3005 commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

What

symlink threw parent-directory targets for any target with a .. component, such as ../file.txt or ... FreeBSD 11.4 stores the target unchanged and its namei resolves the .. later, from the directory that holds the link.

Here the link is a host symbolic link, so the host follows it, not the guest path resolver. A .. target is therefore created only when both reach the same place:

  • every directory a .. leaves must exist and not be a symbolic link, so the host's physical .. gives the same directory as the resolver's lexical one;
  • the target joined to the link's host directory, normalised, must equal the guest path it names (the link's guest directory joined with the target), resolved through the guest mounts.

Anything else still throws, with a message that names the reason: a .. that climbs out of a mount such as /savedata0, or a .. past a directory reached through a symbolic link. Absolute targets still throw as well; they would need a host path stored in the link and a translation back in readlink. The checks run after the existing EEXIST, ENOENT and ENOTDIR checks on the new name, so those errors come first, as in FreeBSD's kern_symlinkat.

A new symlink entry in docs/dev/debt/libkernel_sys.md describes the rule and what still throws.

Tested

Windows 11 26200, WinLibs MinGW-w64 GCC 15.2.0 r7, CMake + Ninja, Release, -DBUILD_TESTING=ON, Developer Mode on (so the link success cases run), on main 6cd36e6517.

  • guest_kernel_sys gets cases that:
    • create ../file.txt, deeper/../../file.txt and .., check readlink returns each target unchanged, and read the file through the link;
    • create a dangling ../missing/x;
    • throw for a link whose directory was reached through a symbolic link, without creating anything;
    • throw for ../file.txt in an aliased mount, where the guest path /file.txt and the host's parent directory differ;
    • create deeper/../up inside that mount and read through it.
      a/../b with a missing a, a/../../x and /abs still throw.
  • With this change, guest_kernel_sys passes 3 of 3, and the 82 tests matching kernel_sys|filesystem|symlink|readlink|lstat|stat|rename|link|chmod|access|open|path pass. The full build has 0 failed steps.
  • Control, main's Export.cpp with the new test: guest_kernel_sys aborts with symlink: parent-directory targets not implemented.
  • Not run on Linux locally; the Linux CI job covers it.
  • python tools/check_conventions.py --base upstream/main passes. tools/pr_overlap.py reports only feat(libkernel_sys): implement lchflags #9442, which adds a declaration on the same line of GuestKernelSys.cpp. None of the other open PRs that touch libkernel_sys/Export.cpp change symlink.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: feat(libkernel_sys): implement lchflags #9442
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

🤖 Generated with Claude Code

…ponents

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed exact head 69a7bd2c19dd68c1b269705ef33bfbf35609452c. The change permits relative .. targets only when the host’s physical traversal agrees with the guest path resolution: every directory being left exists and is not a symlink, and the resulting host path matches the resolved guest target. It keeps absolute targets and paths that escape mount aliases or traverse symlink directories unsupported. The added tests cover preserved readlink text, file reads through valid parent targets, dangling targets, a symlinked path component, mount escape, and an in-mount parent traversal. I checked the reported #9442 overlap: it only adds a separate declaration in the shared test file.

git diff --check upstream/main...HEAD and python3 tools/check_conventions.py --base upstream/main --head HEAD pass. Hosted eligibility, conventions, intake, labels, and report pass; hosted product jobs were skipped. The Windows 11 filesystem/CTest results in the PR description are author-reported; I did not independently run Windows. I found no blocking issue in this implementation.

@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 5021 core/libs/prx/libkernel_sys/Export.cpp
PR 7201 core/libs/prx/libkernel_sys/Export.cpp
PR 9097 core/libs/prx/libkernel_sys/Export.cpp
core/libs/tests/GuestKernelSys.cpp
PR 9297 docs/dev/debt/libkernel_sys.md
PR 9302 docs/dev/debt/libkernel_sys.md
PR 9826 core/libs/prx/libkernel_sys/Export.cpp
PR 10657 docs/dev/debt/libkernel_sys.md

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Follow-up on the new overlap warning at exact head 69a7bd2c19dd68c1b269705ef33bfbf35609452c: I manually compared #9442 and #10625. git merge-tree --write-tree upstream/pr/9442 upstream/pr/10625 reports a content conflict in core/libs/tests/GuestKernelSys.cpp at the adjacent prototype block: #9442 adds the lchflags_nid_postfix declaration, while this PR adds AddPathAlias_nid_no_patch and RemovePathAlias_nid_no_patch there. The declarations are independent and can be retained together, but the authors still need an agreed merge order and the dependent PR should record Depends on: #N per CONTRIBUTING. The current checklist says Depends on: none.

Please coordinate with #9442's author and update the dependency/order note. My earlier approval covered the symlink implementation; this follow-up requests changes only for the unresolved shared-file merge coordination.

@MarcZX10 MarcZX10 mentioned this pull request Oct 24, 2026
12 tasks done
@Dom3005

Dom3005 commented Oct 24, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for checking the overlap. I've proposed on #9442 that it merges first, and the checklist now says Depends on: #9442. Once #9442 lands I'll rebase onto main, keep both declaration blocks in GuestKernelSys.cpp, and force-push.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Re-reviewed exact head 69a7bd2c19dd68c1b269705ef33bfbf35609452c. The overlap issue is now handled: the author proposed #9442 first, updated the checklist to Depends on: #9442, and will retain both declaration blocks on rebase. The symlink path checks and test coverage remain as previously reviewed. Current git diff --check, repository conventions and merge-tree checks pass; hosted eligibility, intake, conventions, labels and report pass, while product jobs are skipped. The Windows test results are author-reported and were not independently reproduced here.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 24, 2026
@oneandonlydean oneandonlydean self-assigned this Oct 25, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

@Dom3005 Please drop the two newly added SymlinkTargetThrows cases for symlink-prefix traversal and mount escape (GuestKernelSys.cpp lines 340 and 344), together with any fixture/cleanup used only by those throw assertions. They pin currently unimplemented paths. Keep the successful parent targets, dangling target, unchanged readlink contents, actual reads and the in-mount success case. The new host/guest target checks otherwise look consistent; #9442 remains the declared integration prerequisite.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 25, 2026

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants