Skip to content

fix(storage): unescape /proc/self/mountinfo paths in getMountInfo - #868

Open
Anand-240 wants to merge 1 commit into
urunc-dev:mainfrom
Anand-240:fix/mountinfo-octal-unescape
Open

fix(storage): unescape /proc/self/mountinfo paths in getMountInfo#868
Anand-240 wants to merge 1 commit into
urunc-dev:mainfrom
Anand-240:fix/mountinfo-octal-unescape

Conversation

@Anand-240

Copy link
Copy Markdown
Contributor

Description

getMountInfo() in pkg/unikontainers/block.go figures out whether a bind-mount source is itself a mount point by scanning /proc/self/mountinfo and comparing the mount point field against the given path with a plain string comparison (preDash[4] == path).

The kernel octal-escapes spaces, tabs, newlines and backslashes in the root and mount point fields of that file (e.g. a space becomes \040). The old code read those fields straight off the file and never unescaped them, so a mount whose path contained any of those characters could never match, getMountInfo returned ErrMountpoint, and getBlockVolumes() silently skipped attaching it as a block device with no error surfaced anywhere.

This switches getMountInfo to use moby/sys/mountinfo.GetMounts, which is already a dependency and already used elsewhere in this file (mountinfo.Mounted in restoreBlockVolumes). That library decodes the escaping while parsing, so the comparison works correctly. The actual matching logic is pulled out into findMountInfo(mounts []*mountinfo.Info, path string) so it can be tested against synthetic mount entries instead of depending on the real /proc/self/mountinfo of whatever process runs the tests.

Related issues

How was this tested?

  • go build ./... and go vet ./... on Linux (cross-compiled from macOS, then verified inside a golang container since the affected code and unix/loop-device syscalls it depends on are Linux-only).
  • go test ./pkg/unikontainers/... in a Linux container: existing TestGetBlockDevice still passes (it exercises getMountInfo("/proc") against the real mountinfo of the test process).
  • Added TestFindMountInfoEscapedPath, which builds a synthetic mountinfo line with a mount point escaped the way the kernel would escape it (space, tab, backslash), parses it with mountinfo.GetMountsFromReader, and checks findMountInfo matches it against the real, unescaped path. This reproduces the bug and fails on the old code path, passes with the fix.
  • Confirmed two other test failures in the same package (TestCopyFile, TestMoveFile) are pre-existing and unrelated — they fail identically on unmodified main when run as root inside the container (permission-denied checks don't trigger for root).
  • I did not have a working golangci-lint/hypervisor e2e setup available in this environment, so make lint and the e2e suites were not run locally; flagging that here rather than checking those boxes.

LLM usage

Claude (Anthropic, model: claude-sonnet-5) was used to investigate the bug, write the fix, and write this description. All changes were reviewed and tested by me before opening this PR, per the project's LLM policy.

Checklist

  • I have read the contribution guide.
  • The linter passes locally (make lint) — not run locally, see note above.
  • The e2e tests of at least one tool pass locally (make test_ctr, make test_nerdctl, make test_docker, make test_crictl) — not run locally, see note above.
  • If LLMs were used: I have read the llm policy.

@netlify

netlify Bot commented Jul 31, 2026

Copy link
Copy Markdown

Deploy Preview for urunc canceled.

Name Link
🔨 Latest commit 2386752
🔍 Latest deploy log https://app.netlify.com/projects/urunc/deploys/6a6c974c3f8ba30008ee671f

The kernel octal-escapes spaces, tabs, newlines and backslashes in the
root and mount point fields of /proc/self/mountinfo. getMountInfo was
comparing the raw, still-escaped mount point field against the caller's
real path, so any bind-mount source containing one of those characters
never matched and getBlockVolumes silently skipped it instead of
attaching it as a block device.

Switch to moby/sys/mountinfo.GetMounts, which already decodes the
escaping, instead of hand-splitting the mountinfo lines. The matching
logic is split into findMountInfo so it can be exercised with synthetic
mountinfo entries in a test.

Fixes: urunc-dev#867
Signed-off-by: Anand-240 <anandprakashsrivastava68@gmail.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

1 participant