cyphar/libpathrs
GitHub: cyphar/libpathrs
一个用 Rust 编写的 Linux 路径解析安全库,通过提供对 C 友好的 VFS API 来防止在不受信任目录中的路径处理漏洞。
Stars: 135 | Forks: 12
## `libpathrs`
[](https://docs.rs/pathrs/)
[](https://pkg.go.dev/cyphar.com/go-pathrs)
[](https://pypi.org/project/pathrs/)
[](Cargo.toml)
[](https://deps.rs/repo/github/cyphar/libpathrs)
[](https://codecov.io/github/cyphar/libpathrs)
[](https://github.com/cyphar/libpathrs/actions/workflows/rust.yml)
[](https://github.com/cyphar/libpathrs/actions/workflows/bindings-c.yml)
[](https://github.com/cyphar/libpathrs/actions/workflows/bindings-go.yml)
[](https://github.com/cyphar/libpathrs/actions/workflows/bindings-python.yml)
本库实现了一组对 C 友好的 API(使用 Rust 编写),旨在使在潜在不受信任的目录中进行路径解析在 GNU/Linux 上变得安全。[有无数因不当处理路径而导致安全漏洞的例子][avoidable-issues];本库提供了一组易于使用的 VFS API 来避免此类问题。
### 示例
以下是一个使用本库在根文件系统(`/path/to/root`)中安全打开路径(`/etc/passwd`)的简单示例。更详细的示例可以在 `examples/` 和 `tests/` 中找到。
#### Rust
```
use std::fs::File;
use pathrs::{flags::OpenFlags, Root};
fn get_my_fd() -> Result {
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)
}
```
#### C
```
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
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;
}
```
#### Go
```
package main
import (
"os"
"cyphar.com/go-pathrs"
)
func getMyFD() (*os.File, error) {
const rootPath = "/path/to/root"
const unsafePath = "/etc/passwd"
root, err := pathrs.OpenRoot(rootPath)
if err != nil {
return nil, err
}
defer root.Close()
handle, err := root.Resolve(unsafePath)
if err != nil {
return nil, err
}
defer handle.Close()
// The handle step can be skipped using root.Open().
return handle.Open()
}
```
在 Linux 上,libpathrs 还提供了一个用于安全 `procfs` 操作的 API,并在 [`procfs` 模块][docs.rs-procfs]中实现了严格的路径安全。[点击这里][procfs-api]查看其用法的具体示例。
### 内核支持
目前,`libpathrs` 仅适用于 Linux,因为它是围绕提供安全路径操作所必需的 Linux 专有 API 设计的。未来,我们计划扩展对其他类 Unix 操作系统的支持。
尽管 `libpathrs` 可以在非常旧的内核上运行(理论上可追溯至 Linux 2.6.39,尽管我们目前未对此进行测试),但我们*强烈*建议至少使用 Linux 5.6,以获得针对各种攻击的合理保护。目前支持[我们用于强化的所有功能][kernel-feature-list]的最低 Linux 内核版本是 Linux 6.8。
### 许可证
`SPDX-License-Identifier: MPL-2.0 OR LGPL-3.0-or-later`
`libpathrs` 根据您的选择,采用 [Mozilla Public License version 2.0][MPL-2.0] 或 [GNU Lesser General Public License version 3][LGPL-3.0] 的条款进行许可。
除非另有说明,否则通过有意提交任何贡献(定义见 Mozilla Public License version 2.0)以包含在 `libpathrs` 项目中,即表示您同意按上述方式对您的贡献进行双重许可,且不附带任何额外的条款或条件。
```
libpathrs: safe path resolution on Linux
Copyright (C) 2019-2025 SUSE LLC
Copyright (C) 2026 Aleksa Sarai
== 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 .
```
#### 绑定
`SPDX-License-Identifier: MPL-2.0`
特定语言的绑定(`contrib/bindings/` 和 `go-pathrs/` 中的代码)采用 Mozilla Public License version 2.0(详见 [`LICENSE.MPL-2.0`][MPL-2.0])进行许可。
**注意**:如果您将 `libpathrs.so` 静态编译到您的二进制文件中,您仍需遵守主要 `libpathrs` 项目的许可条款。
```
libpathrs: safe path resolution on Linux
Copyright (C) 2019-2025 SUSE LLC
Copyright (C) 2026 Aleksa Sarai
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`
`examples/` 中的示例代码采用 Mozilla Public License version 2.0(详见 [`LICENSE.MPL-2.0`][MPL-2.0])进行许可。
```
libpathrs: safe path resolution on Linux
Copyright (C) 2019-2025 SUSE LLC
Copyright (C) 2026 Aleksa Sarai
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/.
```
标签:Rust, 可视化界面, 安全防护, 日志审计, 系统开发, 网络流量审计, 路径解析, 逆向工具, 通知系统