This library implements a set of C-friendly APIs (written in Rust) to make path resolution within a potentially-untrusted directory safe on GNU/Linux. There are countless examples of security vulnerabilities caused by bad handling of paths; this library provides an easy-to-use set of VFS APIs to avoid those kinds of issues.
Here is a toy example of using this library to open a path (/etc/passwd)
inside a root filesystem (/path/to/root) safely. More detailed examples can
be found in examples/ and tests/.
| Rust | C |
|---|---|
use std::fs::File;
use pathrs::{flags::OpenFlags, Root};
fn get_my_fd() -> Result<File, Error> {
const ROOT_PATH: &'static str = "/path/to/root";
const UNSAFE_PATH: &'static str = "/etc/passwd";
let root = Root::open(ROOT_PATH)?;
let handle = root.resolve(UNSAFE_PATH)?;
let file = handle.reopen(OpenFlags::O_RDONLY)?;
// The handle step can be skipped using root.open_subpath().
Ok(file)
} |
#define _GNU_SOURCE
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pathrs.h>
int get_my_fd(void)
{
const char *root_path = "/path/to/root";
const char *unsafe_path = "/etc/passwd";
int liberr = 0;
int root = -EBADF,
handle = -EBADF,
fd = -EBADF;
root = pathrs_open_root(root_path);
if (IS_PATHRS_ERR(root)) {
liberr = root;
goto err;
}
handle = pathrs_inroot_resolve(root, unsafe_path);
if (IS_PATHRS_ERR(handle)) {
liberr = handle;
goto err;
}
fd = pathrs_reopen(handle, O_RDONLY);
if (IS_PATHRS_ERR(fd)) {
liberr = fd;
goto err;
}
/* The handle step can be skipped using pathrs_inroot_open(). */
err:
if (IS_PATHRS_ERR(liberr)) {
pathrs_error_t *error = pathrs_errorinfo(liberr);
fprintf(stderr, "Uh-oh: %s (errno=%d)\n", error->description, error->saved_errno);
pathrs_errorinfo_free(error);
}
close(root);
close(handle);
return fd;
} |
On Linux, libpathrs also provides an API for safe procfs operations with
strict path safety in the procfs module. Click
here to see some concrete examples of its usage.
At the moment, libpathrs only works on Linux as it was designed around
Linux-only APIs that are necessary to provide safe path operations. In future,
we plan to expand support for other Unix-like operating systems.
While libpathrs will function on very old kernels (in theory back to Linux
2.6.39, though we do not currently test this) we strongly recommend using at
least Linux 5.6 to get a reasonable amount of protection against various
attacks. The oldest Linux kernel which currently supports all of the features
we use for hardening is Linux 6.8.
SPDX-License-Identifier: MPL-2.0 OR LGPL-3.0-or-later
libpathrs is licensed under the terms of the Mozilla Public License version
2.0 or the GNU Lesser General Public License version 3,
at your option.
Unless otherwise stated, by intentionally submitting any Contribution (as
defined by the Mozilla Public License version 2.0) for inclusion into the
libpathrs project, you are agreeing to dual-license your Contribution as
above, without any additional terms or conditions.
libpathrs: safe path resolution on Linux
Copyright (C) 2019-2025 SUSE LLC
Copyright (C) 2026 Aleksa Sarai <cyphar@cyphar.com>
== MPL-2.0 ==
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/.
Alternatively, this Source Code Form may also (at your option) be used
under the terms of the GNU Lesser General Public License Version 3, as
described below:
== LGPL-3.0-or-later ==
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
SPDX-License-Identifier: MPL-2.0
The language-specific bindings (the code in contrib/bindings/ and
go-pathrs/) are licensed under the Mozilla Public License version 2.0
(available in LICENSE.MPL-2.0).
NOTE: If you compile libpathrs.so into your binary statically, you still
need to abide by the license terms of the main libpathrs project.
libpathrs: safe path resolution on Linux
Copyright (C) 2019-2025 SUSE LLC
Copyright (C) 2026 Aleksa Sarai <cyphar@cyphar.com>
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/.
SPDX-License-Identifier: MPL-2.0
The example code in examples/ is licensed under the Mozilla Public License
version 2.0 (available in LICENSE.MPL-2.0).
libpathrs: safe path resolution on Linux
Copyright (C) 2019-2025 SUSE LLC
Copyright (C) 2026 Aleksa Sarai <cyphar@cyphar.com>
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/.