陶泥儿产物读取改用 no-follow 打开
- read_package_bytes 用 OpenOptions + O_NOFOLLOW / FILE_FLAG_OPEN_REPARSE_POINT,关掉 symlink_metadata 检查后到打开之间被换成符号链接的 TOCTOU 窗口
This commit is contained in:
@@ -262,7 +262,23 @@ pub(crate) fn read_artifact_package(root: &Path) -> Result<TaonierArtifactPackag
|
||||
/// 调用方已经确认过 `expected_bytes` 在上限内,按它预分配容量即可,避免接近 200 MiB 的包在
|
||||
/// 反复扩容时多复制约一倍数据。
|
||||
fn read_package_bytes(path: &Path, expected_bytes: u64) -> Result<(Vec<u8>, String), String> {
|
||||
let mut file = std::fs::File::open(path)
|
||||
// 不跟随符号链接打开:`read_artifact_package` 先做了 symlink_metadata 检查,这里用
|
||||
// no-follow 打开关掉「检查后、打开前被换成同长度链接」的 TOCTOU 窗口。
|
||||
let mut options = std::fs::OpenOptions::new();
|
||||
options.read(true);
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
options.custom_flags(libc::O_CLOEXEC | libc::O_NOFOLLOW);
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
use std::os::windows::fs::OpenOptionsExt;
|
||||
const FILE_FLAG_OPEN_REPARSE_POINT: u32 = 0x0020_0000;
|
||||
options.custom_flags(FILE_FLAG_OPEN_REPARSE_POINT);
|
||||
}
|
||||
let mut file = options
|
||||
.open(path)
|
||||
.map_err(|error| format!("打开陶泥儿产物失败:{}:{error}", path.display()))?;
|
||||
let mut hasher = Sha256::new();
|
||||
let mut bytes = Vec::with_capacity(expected_bytes as usize);
|
||||
|
||||
Reference in New Issue
Block a user