pathrs

package
v0.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 19, 2025 License: BSD-3-Clause, MPL-2.0 Imports: 4 Imported by: 5

README

pathrs-lite

github.com/cyphar/filepath-securejoin/pathrs-lite provides a minimal pure Go implementation of the core bits of libpathrs. This is not intended to be a complete replacement for libpathrs, instead it is mainly intended to be useful as a transition tool for existing Go projects.

pathrs-lite also provides a very easy way to switch to libpathrs (even for downstreams where pathrs-lite is being used in a third-party package and is not interested in using CGo). At build time, if you use the libpathrs build tag then pathrs-lite will use libpathrs directly instead of the pure Go implementation. The two backends are functionally equivalent (and we have integration tests to verify this), so this migration should be very easy with no user-visible impact.

License

Most of this subpackage is licensed under the Mozilla Public License (version 2.0). For more information, see the top-level COPYING.md and LICENSE.MPL-2.0 files, as well as the individual license headers for each file.

Copyright (C) 2024-2025 Aleksa Sarai <cyphar@cyphar.com>
Copyright (C) 2024-2025 SUSE LLC

This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.

Documentation

Overview

Package pathrs (pathrs-lite) is a less complete pure Go implementation of some of the APIs provided by libpathrs.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MkdirAll

func MkdirAll(root, unsafePath string, mode os.FileMode) error

MkdirAll is a race-safe alternative to the os.MkdirAll function, where the new directory is guaranteed to be within the root directory (if an attacker can move directories from inside the root to outside the root, the created directory tree might be outside of the root but the key constraint is that at no point will we walk outside of the directory tree we are creating).

Effectively, MkdirAll(root, unsafePath, mode) is equivalent to

path, _ := securejoin.SecureJoin(root, unsafePath)
err := os.MkdirAll(path, mode)

But is much safer. The above implementation is unsafe because if an attacker can modify the filesystem tree between SecureJoin and os.MkdirAll, it is possible for MkdirAll to resolve unsafe symlink components and create directories outside of the root.

If you plan to open the directory after you have created it or want to use an open directory handle as the root, you should use MkdirAllHandle instead. This function is a wrapper around MkdirAllHandle.

func MkdirAllHandle

func MkdirAllHandle(root *os.File, unsafePath string, mode os.FileMode) (*os.File, error)

MkdirAllHandle is equivalent to MkdirAll, except that it is safer to use in two respects:

  • The caller provides the root directory as an *os.File (preferably O_PATH) handle. This means that the caller can be sure which root directory is being used. Note that this can be emulated by using /proc/self/fd/... as the root path with os.MkdirAll.

  • Once all of the directories have been created, an *os.File O_PATH handle to the directory at unsafePath is returned to the caller. This is done in an effectively-race-free way (an attacker would only be able to swap the final directory component), which is not possible to emulate with MkdirAll.

In addition, the returned handle is obtained far more efficiently than doing a brand new lookup of unsafePath (such as with SecureJoin or openat2) after doing MkdirAll. If you intend to open the directory after creating it, you should use MkdirAllHandle.

func OpenInRoot

func OpenInRoot(root, unsafePath string) (*os.File, error)

OpenInRoot safely opens the provided unsafePath within the root. Effectively, OpenInRoot(root, unsafePath) is equivalent to

path, _ := securejoin.SecureJoin(root, unsafePath)
handle, err := os.OpenFile(path, unix.O_PATH|unix.O_CLOEXEC)

But is much safer. The above implementation is unsafe because if an attacker can modify the filesystem tree between SecureJoin and os.OpenFile, it is possible for the returned file to be outside of the root.

Note that the returned handle is an O_PATH handle, meaning that only a very limited set of operations will work on the handle. This is done to avoid accidentally opening an untrusted file that could cause issues (such as a disconnected TTY that could cause a DoS, or some other issue). In order to use the returned handle, you can "upgrade" it to a proper handle using Reopen.

func OpenatInRoot

func OpenatInRoot(root *os.File, unsafePath string) (*os.File, error)

OpenatInRoot is equivalent to OpenInRoot, except that the root is provided using an *os.File handle, to ensure that the correct root directory is used.

func Reopen

func Reopen(handle *os.File, flags int) (*os.File, error)

Reopen takes an *os.File handle and re-opens it through /proc/self/fd. Reopen(file, flags) is effectively equivalent to

fdPath := fmt.Sprintf("/proc/self/fd/%d", file.Fd())
os.OpenFile(fdPath, flags|unix.O_CLOEXEC)

But with some extra hardenings to ensure that we are not tricked by a maliciously-configured /proc mount. While this attack scenario is not common, in container runtimes it is possible for higher-level runtimes to be tricked into configuring an unsafe /proc that can be used to attack file operations. See CVE-2019-19921 for more details.

Types

This section is empty.

Directories

Path Synopsis
Package internal contains unexported common code for filepath-securejoin.
Package internal contains unexported common code for filepath-securejoin.
assert
Package assert provides some basic assertion helpers for Go.
Package assert provides some basic assertion helpers for Go.
fd
Package fd provides a drop-in interface-based replacement of *os.File that allows for things like noop-Close wrappers to be used.
Package fd provides a drop-in interface-based replacement of *os.File that allows for things like noop-Close wrappers to be used.
gocompat
Package gocompat includes compatibility shims (backported from future Go stdlib versions) to permit filepath-securejoin to be used with older Go versions (often filepath-securejoin is added in security patches for old releases, so avoiding the need to bump Go compiler requirements is a huge plus to downstreams).
Package gocompat includes compatibility shims (backported from future Go stdlib versions) to permit filepath-securejoin to be used with older Go versions (often filepath-securejoin is added in security patches for old releases, so avoiding the need to bump Go compiler requirements is a huge plus to downstreams).
gopathrs
Package gopathrs is a less complete pure Go implementation of some of the APIs provided by [libpathrs].
Package gopathrs is a less complete pure Go implementation of some of the APIs provided by [libpathrs].
kernelversion
Package kernelversion provides a simple mechanism for checking whether the running kernel is at least as new as some baseline kernel version.
Package kernelversion provides a simple mechanism for checking whether the running kernel is at least as new as some baseline kernel version.
linux
Package linux returns information about what features are supported on the running kernel.
Package linux returns information about what features are supported on the running kernel.
procfs
Package procfs provides a safe API for operating on /proc on Linux.
Package procfs provides a safe API for operating on /proc on Linux.
testutils
Package testutils provides some internal helpers for tests.
Package testutils provides some internal helpers for tests.
Package procfs provides a safe API for operating on /proc on Linux.
Package procfs provides a safe API for operating on /proc on Linux.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL