[−][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
/procmount, such that/proc/self/fd/operates correctly. libpathrs will explicitly verify that the/procmount is actually a bone-fideprocfsinstance (to avoid potential trickery) and abort if/procis not actuallyprocfs. - Native Backend:
openat2support.
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 |