Skip to content

fix(starry-kernel): reject private mmap faults past eof#1534

Merged
ZR233 merged 1 commit into
rcore-os:devfrom
ZR233:codex/xkernel-mmap-private-eof
Jul 8, 2026
Merged

fix(starry-kernel): reject private mmap faults past eof#1534
ZR233 merged 1 commit into
rcore-os:devfrom
ZR233:codex/xkernel-mmap-private-eof

Conversation

@ZR233

@ZR233 ZR233 commented Jul 7, 2026

Copy link
Copy Markdown
Member

问题

对照 openkylin/x-kernel 已合并的 !433,本仓库普通文件 MAP_PRIVATE 映射在 fault 到文件 EOF 之后的页面时仍会分配零页。这会把应当视为无效访问的 EOF 之后区域静默映射出来。

修改

  • 为 COW file-backed fault-in 统一计算本次可读取长度。
  • 对普通 MAP_PRIVATE 映射(file_end == None)使用真实文件长度作为有效边界:页起始 offset 已到 EOF 时返回 BadAddress,跨 EOF 时只读取文件内剩余字节。
  • 保留 ELF loader 传入 file_end = Some(...) 时的零填充语义,避免影响程序段 BSS/tail zero-fill。
  • 增加 axtest 覆盖 EOF 拒绝、跨 EOF 截断、loader 零填充保留三种路径。

本次冲突处理

  • 已 rebase 到最新 rcore-os/tgoskits:dev
  • 冲突仅出现在 axtest_exports.rsaxtest_kernel.rs,处理方式是保留 dev 上已有的 pipe/fcntl axtest,并追加本 PR 的 private mmap EOF axtest。

验证

  • 红灯验证:cargo xtask ktest qemu -p starry-kernel --test axtest_kernel,新增用例先失败,AXTEST_SUMMARY pass=4 fail=1
  • 修复后初次验证:cargo xtask ktest qemu -p starry-kernel --test axtest_kernelAXTEST_SUMMARY pass=5 fail=0AXTEST_SUITE_OK
  • rebase 冲突处理后:cargo xtask ktest qemu -p starry-kernel --test axtest_kernelAXTEST_SUMMARY pass=8 fail=0AXTEST_SUITE_OK
  • rebase 冲突处理后:cargo xtask clippy --package starry-kernel,17/17 checks passed。

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审查结论:APPROVE ✅

变更概述

本 PR 修复了 StarryOS MAP_PRIVATE 文件映射在 fault 到 EOF 之后页面时的行为:旧代码使用 u64::MAX 作为有效边界,导致 EOF 之后的区域被静默映射为零页;新代码使用真实文件长度 file.len() 作为边界,页起始 offset 已到 EOF 时返回 BadAddress,跨 EOF 时只读取文件内剩余字节。同时保留 ELF loader 传入 file_end = Some(...) 时的零填充语义(BSS/tail zero-fill)。

实现分析

  • cow_file_max_read_len:纯计算函数,根据 file_end 区分两种语义:
    • file_end = Some(end):以传入的 end 为有效边界(ELF loader 路径)
    • file_end = None(常规 MAP_PRIVATE):以 file_len 为有效边界,file_read_offset >= file_len 时返回 BadAddress
  • cow_file_max_read:在 cow_file_max_read_len 基础上增加了 file.len()? 调用。仅在 file_end.is_none() 时才调用 file.len(),避免对 ELF loader 路径产生副作用。
  • 错误处理alloc_new_atcow_file_max_read 失败时,正确调用 self.deinit_frame(frame) 释放已分配的帧后返回错误。alloc_file_run 中由于 cow_file_max_read 在帧分配之前调用,? 传播错误时无需清理。
  • 代码设计清晰,函数职责单一,与现有 CowBackend 的模式一致。

验证结果

  • cargo fmt --check:通过(无输出)
  • cargo clippy --manifest-path os/StarryOS/kernel/Cargo.toml --all-features -- -D warnings:通过
  • ✅ CI 状态:
    • Check formatting / run_host: success
    • Run sync-lint / run_container: success
    • Run spin-lint / run_container: success
    • Test with std / run_host: success
    • Test starry aarch64 qemu / run_container: success
    • Test starry loongarch64 qemu / run_container: success
    • Test starry self-hosted board orangepi-5-plus: success
    • Test starry self-hosted board visionfive2: success
    • 其他 Starry 无关的检查(axvisor/arceos/board):success 或 expected skipped
    • 无 CI 失败

测试覆盖

新增 axtest 用例 private_mmap_rejects_fault_at_file_eof 覆盖三条路径:

  1. EOF 拒绝file_len=4096, file_end=None, offset=4096BadAddress
  2. 跨 EOF 截断file_len=4096, file_end=None, offset=2048 → 可读 2048 字节 ✅
  3. Loader 零填充保留file_len=4096, file_end=Some(8192), offset=4096 → 可读 4096 字节 ✅

测试链路完整:cow.rsmod.rs#[cfg(axtest)] re-export)→ axtest_exports.rsaxtest_kernel.rs,符合项目 axtest 模式的测试发现规范。

重复/重叠 PR 分析

  • 搜索 repo:rcore-os/tgoskits type:pr mmap private eof:仅返回本 PR
  • 搜索 repo:rcore-os/tgoskits type:pr cow file backend:仅返回不相关的 #1017
  • 无重复或冲突的开放 PR。

历史审查

本 PR 无前置审查评论。

未解决问题

无。代码正确、测试充分、CI 全绿。

残余风险

无。

Powered by deepseek-v4-pro

@mai-team-app mai-team-app Bot mentioned this pull request Jul 7, 2026
@ZR233
ZR233 force-pushed the codex/xkernel-mmap-private-eof branch from 9a1616e to 3c3c7ad Compare July 8, 2026 01:38

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审查结论:APPROVE ✅

变更概述

本 PR 修复了 StarryOS MAP_PRIVATE 文件映射在缺页 fault 到 EOF 之后页面时的行为问题:旧代码在 CowBackend::alloc_new_atalloc_file_run 中使用 u64::MAX 作为有效文件边界(file_end.map_or(u64::MAX, ...)),导致 EOF 之后的区域被静默分配零页并映射,而不是返回错误。新代码使用真实文件长度 file.len() 作为边界,页起始 offset 已到 EOF 时返回 BadAddress,跨 EOF 时只读取文件内剩余字节。同时保留 ELF loader 传入 file_end = Some(...) 时的零填充语义,避免影响程序段 BSS/tail zero-fill。

实现分析

  • cow_file_max_read_len:纯计算函数,不涉及 I/O。根据 file_end 区分两种语义:
    • file_end = Some(end):以传入的 end 为有效边界(ELF loader BSS 路径,保留零填充语语义)
    • file_end = None(常规 MAP_PRIVATE):以 file_len 为有效边界,file_read_offset >= file_len 时返回 BadAddress
  • cow_file_max_read:在 cow_file_max_read_len 基础上增加了 file.len()? 调用(仅在 file_end.is_none() 时调用),将 I/O 错误向上传播。
  • alloc_new_at:在 cow_file_max_read 失败时,正确调用 self.deinit_frame(frame) 释放已分配的帧后返回错误,避免了帧泄漏。
  • alloc_file_runcow_file_max_read 在帧分配之前调用,使用 ? 传播错误时无需清理帧资源。
  • #[cfg(axtest)] 测试函数 private_mmap_eof_check_for_test:纯单元测试,验证三个语义路径而不依赖实际文件 I/O。
  • 代码设计清晰,函数职责单一,错误处理完备,与现有 CowBackend 的模式一致。

验证结果

本地验证:

  • cargo fmt --check:通过
  • cargo clippy --manifest-path os/StarryOS/kernel/Cargo.toml --all-features -- -D warnings:通过(Finished, 无 warnings)

CI 状态(run #8368, head 3c3c7ad):

  • ✅ Check formatting / run_host: success
  • ✅ Run sync-lint / run_container: success
  • ✅ Run spin-lint / run_container: success
  • ✅ Test starry aarch64 qemu / run_container: success
  • ✅ Test starry riscv64 qemu / run_host: skipped(run_host vs run_container 互斥,合理)
  • ✅ Test starry loongarch64 qemu / run_host: skipped(同上)
  • ✅ Test starry self-hosted board orangepi-5-plus: success
  • ✅ Test starry self-hosted board visionfive2: success
  • 其他无关检查(axvisor/arceos/board):success 或 expected skipped
  • 整体 CI conclusion: success,无失败

测试覆盖

新增 axtest 用例 private_mmap_rejects_fault_at_file_eof,覆盖三条路径:

  1. EOF 拒绝file_len=4096, file_end=None, offset=4096Err(BadAddress)
  2. 跨 EOF 截断file_len=4096, file_end=None, offset=2048Ok(2048)
  3. Loader 零填充保留file_len=4096, file_end=Some(8192), offset=4096Ok(4096)

测试链路完整:cow.rs#[cfg(axtest)] pub(crate))→ mod.rs#[cfg(axtest)] re-export)→ axtest_exports.rsaxtest_kernel.rs,符合项目 axtest 模式的测试发现规范。

重复/重叠 PR 分析

  • 搜索 repo:rcore-os/tgoskits type:pr mmap private eof:仅返回本 PR #1534
  • PR #1164(已合并)修复的是 FileBackend::populate(共享映射,MAP_SHARED)的 EOF 边界问题,与本次 CowBackendMAP_PRIVATE)的修复互补,不重叠。
  • 无重复或冲突的开放 PR。

历史审查

本 PR 存在一条来自 mai-team-app[bot] 的前置 APPROVE 审查(commit 9a1616e),当时已通过格式、clippy 和 CI 验证。当前 head 3c3c7ad 为 rebase 后的新版本,冲突仅出现在 axtest_exports.rsaxtest_kernel.rs(保留 dev 上已有的 pipe/fcntl axtest 并追加本 PR 的 private mmap EOF axtest),核心逻辑文件 cow.rs 无变化。

未解决问题

无。代码正确、测试充分、CI 全绿、无 crates.io patch 依赖、无重复或冲突 PR。

Powered by deepseek-v4-pro

@ZR233
ZR233 merged commit ddbd8bf into rcore-os:dev Jul 8, 2026
56 checks passed
@ZR233
ZR233 deleted the codex/xkernel-mmap-private-eof branch July 8, 2026 03:07
This was referenced Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant