[−][src]Crate pathrs
libpathrs provides a series of primitives for Linux programs to safely handle path operations inside an untrusted directory tree.
The idea is that a Root
handle is like a handle for resolution inside a
chroot(2)
, with Handle
being an O_PATH
descriptor which you can
"upgrade" to a proper File
. However this library acts far more
efficiently than spawning a new process and doing a full chroot(2)
for
every operation.
In order to ensure the maximum possible number of people can make us of this library to increase the overall security of Linux tooling, it is written in Rust (to be memory-safe) and produces C dylibs for usage with any language that supports C-based FFI.
Assumptions
This library assumes that the kernel supports all of the needed features for at least one libpathrs backend. At time of writing, those are:
- A working
/proc
mount, such that/proc/self/fd/
operates correctly. libpathrs will explicitly verify that the/proc
mount is actually a bone-fideprocfs
instance (to avoid potential trickery) and abort if/proc
is not actuallyprocfs
. - Native Backend:
openat2
support.
Examples
The recommended usage of libpathrs looks something like this:
let (root_path, unsafe_path) = ("/path/to/root", "/etc/passwd"); // Get a root handle for resolution. let root = Root::open(root_path)?; // Resolve the path. let handle = root.resolve(unsafe_path)?; // Upgrade the handle to a full std::fs::File. let file = handle.reopen(libc::O_RDONLY)?; // Or, in one line: let file = root.resolve(unsafe_path)? .reopen(libc::O_RDONLY)?;
The corresponding C example would be:
#include <pathrs.h>
int get_my_fd(void)
{
const char *root_path = "/path/to/root";
const char *unsafe_path = "/etc/passwd";
int fd = -1;
pathrs_root_t *root = NULL;
pathrs_handle_t *handle = NULL;
pathrs_error_t *error = NULL;
root = pathrs_open(root_path);
error = pathrs_error(PATHRS_ROOT, root);
if (error)
goto err;
handle = pathrs_resolve(root, unsafe_path);
error = pathrs_error(PATHRS_ROOT, root);
if (error) /* or (!handle) */
goto err;
fd = pathrs_reopen(handle, O_RDONLY);
error = pathrs_error(PATHRS_HANDLE, handle);
if (error) /* or (fd < 0) */
goto err;
err:
if (error)
fprintf(stderr, "Uh-oh: %s (errno=%d)\n", error->description, error->saved_errno);
pathrs_free(PATHRS_ROOT, root);
pathrs_free(PATHRS_HANDLE, handle);
pathrs_free(PATHRS_ERROR, error);
return fd;
}
Modules
error | Error types for libpathrs. |
Structs
Handle | A handle to an existing inode within a |
OpenFlags | Wrapper for the underlying |
RenameFlags | Wrapper for the underlying |
Resolver | Resolover backend and its associated flags. |
ResolverFlags | Optional flags to modify the resolution of paths inside a |
Root | A handle to the root of a directory tree. |
Enums
InodeType | An inode type to be created with |
ResolverBackend | The backend used for path resolution within a |