fix(backends): copy links when the filesystem rejects symlinks (CIFS/SMB) (#10890)#10893
Open
localai-bot wants to merge 4 commits into
Open
fix(backends): copy links when the filesystem rejects symlinks (CIFS/SMB) (#10890)#10893localai-bot wants to merge 4 commits into
localai-bot wants to merge 4 commits into
Conversation
… symlinks (#10890) Backend installation extracts the OCI image tar via containerd's archive.Apply, which calls os.Symlink directly. On filesystems that do not support symlinks (notably CIFS/SMB mounts, commonly used to back the /backends volume) the syscall fails with "operation not supported" and the whole install aborts, leaving an empty backend directory. The CUDA llama.cpp image trips this on the libcublas.so -> libcublas.so.12.x symlink. When archive.Apply fails with a link-unsupported error, reset the staging directory and re-extract with a pure-Go walker that still attempts real symlinks/hardlinks first and degrades to copying the link target's contents in place when the filesystem rejects them. mutate.Extract already flattened the layers, so the tar carries no whiteouts to interpret. Link copies are deferred to a second pass so forward references resolve. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:opus-4.8 [Claude Code]
Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:opus-4.8 [Claude Code]
safeJoin sanitized "../.." entries by clamping them under root instead of rejecting them, so a malicious entry was silently redirected rather than refused. Join without the leading-slash trick and reject any entry whose cleaned path resolves outside root; absolute link targets are still mapped under root (image-root relative) rather than escaping. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:opus-4.8 [Claude Code]
Use hdr.FileInfo().Mode() instead of converting the int64 tar mode to os.FileMode (removes two G115 overflow findings), and annotate the tar extraction file operations with justified #nosec comments: every path is validated by safeJoin against the extraction root before use (G304/G305). Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude:opus-4.8 [Claude Code]
Owner
|
@localai-bot this is not right, OCI images have layers and this as-is its not unpacking layers. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes #10890.
Backend installation on a CIFS/SMB-backed
/backendsvolume fails for every backend with:The OCI image tar is extracted via containerd's
archive.Apply, which creates symlinks withos.Symlink. CIFS/SMB mounts (a common way to store/backendson a NAS) do not support symlinks and reject the syscall withoperation not supported, aborting the whole install and leaving an empty backend directory. The CUDA llama.cpp image trips on thelibcublas.so -> libcublas.so.12.xsymlink.Fix
When
archive.Applyfails with a link-unsupported error (ENOTSUP/EOPNOTSUPP/EPERM, or the matching "operation not supported/permitted" text), the staging directory is reset and re-extracted with a pure-Go tar walker that:mutate.Extractalready flattens the layers before this point, so the tar carries no whiteouts to interpret; a plain walker is sufficient. The primaryarchive.Applypath is unchanged, so this only affects filesystems that were already failing 100% of installs. The staging directory is the ephemeral, per-install*.install-tmpdir, so wiping it before the fallback pass is safe.Tests
Added
pkg/oci/extract_internal_test.go(Ginkgo/Gomega):isLinkUnsupportedErrortruth table (syscall errnos + wrapped*os.LinkError+ negatives).safeJoinkeeps entries in-root and rejects traversal.extractTarCopyingLinkspreserves symlinks on a symlink-capable FS, and, withsymlink()stubbed to returnENOTSUP, materialises the target as a real regular file copy with the right bytes.Note
Built and verified via CI (no Go toolchain in the authoring sandbox).
Assisted-by: Claude:opus-4.8 [Claude Code]