{"id":16921394,"url":"https://github.com/thediveo/procfsroot","last_synced_at":"2026-02-20T21:03:13.624Z","repository":{"id":57587322,"uuid":"372055491","full_name":"thediveo/procfsroot","owner":"thediveo","description":"Making /proc/[PID]/root wormholes more accessible.","archived":false,"fork":false,"pushed_at":"2025-01-05T17:49:05.000Z","size":74,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-05T18:27:47.230Z","etag":null,"topics":["filesystem","golang","linux","procfs"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thediveo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-29T19:31:23.000Z","updated_at":"2025-01-05T17:49:08.000Z","dependencies_parsed_at":"2024-06-20T05:54:48.213Z","dependency_job_id":null,"html_url":"https://github.com/thediveo/procfsroot","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thediveo%2Fprocfsroot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thediveo%2Fprocfsroot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thediveo%2Fprocfsroot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thediveo%2Fprocfsroot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thediveo","download_url":"https://codeload.github.com/thediveo/procfsroot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235639224,"owners_count":19022269,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["filesystem","golang","linux","procfs"],"created_at":"2024-10-13T19:51:37.953Z","updated_at":"2025-10-07T15:30:22.083Z","avatar_url":"https://github.com/thediveo.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ProcfsRoot\n\n[![PkgGoDev](https://pkg.go.dev/badge/github.com/thediveo/procfsroot)](https://pkg.go.dev/github.com/thediveo/procfsroot)\n[![GitHub](https://img.shields.io/github/license/thediveo/procfsroot)](https://img.shields.io/github/license/thediveo/procfsroot)\n![build and test](https://github.com/thediveo/procfsroot/actions/workflows/buildandtest.yaml/badge.svg?branch=master)\n[![Go Report Card](https://goreportcard.com/badge/github.com/thediveo/procfsroot)](https://goreportcard.com/report/github.com/thediveo/procfsroot)\n![Coverage](https://img.shields.io/badge/Coverage-96.9%25-brightgreen)\n\n`procfsroot` is a small Go module that helps with accessing file system paths\ncontaining absolute symbolic links that are to be taken relative (sic!) to a\nparticular root path. A good example is accessing paths inside\n`/proc/[PID]/root` \"wormholes\" in the [proc file\nsystem](https://man7.org/linux/man-pages/man5/proc.5.html). Symbolic links are\nproperly resolved and kept inside a given root path, prohibiting rogue relative\nsymbolic links from breaking out of a procfs root wormhole.\n\nFor devcontainer instructions, please see the [section \"DevContainer\"\nbelow](#devcontainer).\n\n## Usage\n\n`procfsroot.EvalSymlinks()` mirrors Golang's\n[`filepath.EvalSymlinks`](https://golang.org/pkg/path/filepath/#EvalSymlinks),\nbut works only on paths using \"`/`\" forward slashes and enforces symbolic link\nchasing relative to an enforced root path.\n\nIn the following example, the \"absolute\" path `/var/run/docker.sock` (which\nmight be in a different mount namespace) is correctly resolved in the root\ncontext of `/proc/1/root` – even in case of absolute symbolic links, such as\n`/var/run` usually being an absolute symlink pointing to `/run`. Trying to\ndirectly use `/proc/1/root/var/run/docker.sock` will fail in case of different\nmount namespaces between the accessing process and the initial mount namespace\nof the init process PID 1, as this would be resolved by the Linux kernel into\n`/run/docker.sock` in the current mount namespace(*).\n\n```go\nimport (\n    \"os\"\n    \"github.com/thediveo/procfsroot\"\n)\n\nconst root := \"/proc/1/root\"\n\nfunc main() {\n    p, err := procfsroot.EvalSymlinks(\"/var/run/docker.sock\", root, procfsroot.EvalFullPath)\n    if err != nil {\n        panic(err)\n    }\n    f, err := os.Open(root + p)\n    defer f.Close()\n}\n```\n\nFor illustrational purposes, simply run this as an \"incontinentainer\" to show\nthat absolute symbolic path access will fail when done through a wormhole:\n\n```bash\n$ docker run -it --rm --pid=host --privileged busybox ls -l /proc/1/root/var/run/docker.socket\nls: /proc/1/root/var/run/docker.socket: No such file or directory\n```\n\n## Mount Namespace Wormholes\n\nIn case you have either never noticed the special `/proc/[PID]/root` links or\nhave ever wondered what they're good for: they're kind of \"wormholes\" into\narbitrary [mount\nnamespaces](https://man7.org/linux/man-pages/man7/mount_namespaces.7.html) given\na suitable process ID (PID). They simplify accessing directories and files in\nother mount namespaces because they do not require switching the accessing\nprocess first into the target mount namespace (which can only be done while\nsingle threaded).\n\n| Access Method | Required Capabilites |\n| :--- | :--- |\n| `setns()` | `CAP_SYS_ADMIN`, `CAP_SYS_CHROOT`, as well as typically also `CAP_SYS_PTRACE` in order to access a mount namespace reference in `/proc/[PID]/ns/mnt`\u003c/li\u003e\u003c/ul\u003e |\n| `/proc/[PID]/root` | `CAP_SYS_PTRACE` (so convenient 😀) |\n\nOf course, the usual file system DAC (discretionary access control) still\napplies as usual – including UID 0 access rules.\n\nAlso, for access to `/proc/[PID]` the current process needs to be in a suitable\n[PID namespace](https://man7.org/linux/man-pages/man7/pid_namespaces.7.html)\nthat includes the PID of a \"target\" process of interest. Of course, the initial\nPID namespace is \"gold standard\".\n\n## DevContainer\n\n\u003e [!CAUTION]\n\u003e\n\u003e Do **not** use VSCode's \"~~Dev Containers: Clone Repository in Container\n\u003e Volume~~\" command, as it is utterly broken by design, ignoring\n\u003e `.devcontainer/devcontainer.json`.\n\n1. `git clone https://github.com/thediveo/procfsroot`\n2. in VSCode: Ctrl+Shift+P, \"Dev Containers: Open Workspace in Container...\"\n3. select `enumflag.code-workspace` and off you go...\n\n## VSCode Tasks\n\nThe included `procfsroot.code-workspace` defines the following tasks:\n\n- **Build workspace** task: builds all, including the shared library test\n  plugin.\n\n- **Run all tests with coverage** task: does what it says on the tin and runs\n  all tests with coverage.\n\n## Make Targets\n\n- `make`: lists available targets.\n- `make test`: runs all tests.\n- `make coverage`: deprecated, use the `gocover` CLI command in the devcontainer\n  instead.\n- `make report`: deprecated, use the `goreportcard-cli` CLI command in the\n  devcontainer instead.\n\n## Copyright and License\n\nCopyright 2021, 2025 Harald Albrecht, licensed under the Apache License, Version 2.0.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthediveo%2Fprocfsroot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthediveo%2Fprocfsroot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthediveo%2Fprocfsroot/lists"}