Skip to content

sched: fix ABI issues and add full sched-family test suite#970

Closed
04megumi wants to merge 2 commits into
rcore-os:devfrom
04megumi:dev
Closed

sched: fix ABI issues and add full sched-family test suite#970
04megumi wants to merge 2 commits into
rcore-os:devfrom
04megumi:dev

Conversation

@04megumi

Copy link
Copy Markdown
Contributor

No description provided.

@ZCShou
ZCShou requested review from ZCShou and removed request for ZCShou May 26, 2026 11:59

@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.

Review:sched ABI 修复与测试套件

本 PR 将 sched_setscheduler/sched_getscheduler/sched_getparam 从原来的桩实现升级为真正读取/写入 task 调度策略和优先级的实现,新增了 SchedParam 结构体、权限检查 check_sched_permission,并在 TaskInner 中添加了 sched_policy/sched_priority 字段。同时新增了完整的 test-sched-family C 测试用例,覆盖 sched 系列系统调用的边界条件。整体方向正确,测试覆盖也较为全面。

但存在一个 阻塞性问题 需要修复后才能合并:

阻塞性问题

实时调度策略缺少 CAP_SYS_NICE 强制检查

check_sched_permission 在目标 task 为自身时直接返回 Ok(()),跳过所有权限检查。然而在 Linux 中,sched_setscheduler 设置 SCHED_FIFOSCHED_RR 时,即使是自身也需要 CAP_SYS_NICE 权限(除非 RLIMIT_RTPRIO 允许,而 StarryOS 尚未实现该机制)。当前实现允许任何非特权进程将自己设置为 SCHED_FIFO 优先级 99 的实时进程,这构成权限提升风险。

建议在 sys_sched_setscheduler 中,在通过 check_sched_permission 之后、设置 policy 之前,额外检查:如果 policy 为 SCHED_FIFOSCHED_RR,则要求 caller.has_cap_sys_nice() 为 true,否则返回 EPERM

非阻塞性建议

  1. SCHED_RESET_ON_FORK 被解析但未使用_reset_on_fork 被计算但从未使用,建议至少添加 // TODO 注释说明。
  2. 负 pid 返回 EINVAL 而非 ESRCHget_task_by_sched_pid 对负 pid 返回 InvalidInput(EINVAL),但 Linux 上 sched_getscheduler/sched_setscheduler 对负 pid 返回 ESRCH。测试用例也验证了这一不正确的行为。此为既有问题,不阻塞本次合并,但应在后续修复。
  3. 多个新增文件缺少末尾换行CMakeLists.txtqemu-riscv64.tomlqemu-x86_64.tomltest_framework.hmain.c 末尾缺少换行符。

重复/冲突分析

在 open PR 中未发现与 sched 系列系统调用重叠的其他 PR。base 分支上的 sys_sched_getscheduler 固定返回 SCHED_RRsys_sched_setscheduler/sys_sched_getparam 为空桩,本 PR 是该区域的首次实质性实现。

验证

  • cargo fmt --check 存在 pre-existing 的 let-chain 警告(process_cred 函数),与本 PR 无关
  • PR 变更部分的 Rust 代码格式正确
  • 新增测试位于 qemu-smp4 分组下,符合项目测试组织方式
  • TOML 配置的 success_regex/fail_regex 设计合理

Powered by glm-5.1

let caller = current().as_thread().cred();
let task = get_task_by_sched_pid(pid)?;
if task.id() == current().id() {
return Ok(());

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.

⚠️ 阻塞性问题:当目标 task 为自身时直接返回 Ok(()),跳过所有权限检查。

在 Linux 中,sched_setschedulerSCHED_FIFO/SCHED_RR 实时调度策略要求 CAP_SYS_NICE 权限,即使目标是自身进程也不例外(除非进程拥有非零 RLIMIT_RTPRIO,而 StarryOS 尚未实现该限制)。

当前实现允许任何非特权进程通过 sched_setscheduler(0, SCHED_FIFO, &{.sched_priority=99}) 将自身提升为最高优先级实时进程,构成权限提升风险。

建议修复方向
不在 check_sched_permission 中修改自检查逻辑(因为 setaffinity 对自身确实不需要权限),而是在 sys_sched_setscheduler 的 policy 校验阶段,对 SCHED_FIFO/SCHED_RR 额外检查 caller.has_cap_sys_nice()

// 在 sys_sched_setscheduler 中,match policy 之后,set_sched_policy 之前:
if matches!(policy, SCHED_FIFO | SCHED_RR) && !caller.has_cap_sys_nice() {
    return Err(AxError::PermissionDenied);
}

let _reset_on_fork = (policy & SCHED_RESET_ON_FORK) != 0;
policy &= !SCHED_RESET_ON_FORK;
let prio = user_param.sched_priority;
match policy {

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.

建议补充注释说明 SCHED_RESET_ON_FORK 已正确解析但目前未实际使用(未记录到 task 中),例如:

// TODO: SCHED_RESET_ON_FORK — 已解析,待后续 fork 时实现继承逻辑

这样后续开发者能明确知道这是待完成项而非遗漏。

cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(0, &mask);

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.

在 Linux 上,sched_getscheduler(-5) 返回 ESRCH(因为 find_process_by_pid 找不到对应进程),而非 EINVAL

StarryOS 的 get_task_by_sched_pid 将负 pid 映射为 InvalidInput(EINVAL),这是既有行为。测试用例现在显式验证了这个与 Linux 不一致的行为。

建议改为期望 ESRCH(即 CHECK_ERR(..., ESRCH, ...)),并在内核侧后续修复 get_task_by_sched_pid 使其对 sched 系列系统调用返回 ESRCH。如果不打算在本次 PR 中修复内核,至少在测试中添加注释说明当前行为与 Linux 不一致,避免后续误解。

@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.

Review:sched ABI 修复与测试套件(第二版)

本 PR 由两个 commit 组成:

  1. 16dcbc93 — 初始 sched ABI 实现与测试套件
  2. 5874f808 — 修复实时调度策略的 CAP_SYS_NICE 要求

变更概述

  • TaskInner 新增 sched_policy: AtomicI32sched_priority: AtomicI32 字段,默认值分别为 0(SCHED_NORMAL)和 0。
  • sys_sched_getscheduler 从硬编码 SCHED_RR 改为读取 task 实际调度策略。
  • sys_sched_setscheduler 从空桩实现升级为完整的参数校验:解析 SCHED_RESET_ON_FORK、校验 policy 合法性、校验优先级范围(非实时策略必须为 0,SCHED_FIFO/SCHED_RR 必须在 1..=99)、检查权限。
  • sys_sched_getparam 从空桩实现升级为读取 task 实际优先级。
  • check_sched_permission 新增通用权限检查函数(uid/euid 匹配或 CAP_SYS_NICE)。
  • 测试套件 test-sched-family 覆盖了 setaffinity/getaffinity/setscheduler/getscheduler/getparam/getpriority/sched_yield 的边界条件和错误路径,包含 EFAULT/EINVAL/ESRCH/EPERM 测试。

前次 review 阻塞问题修复确认

前次 bot review 指出的核心阻塞问题——check_sched_permission 在目标为自身时跳过权限检查导致非特权进程可提升为实时调度——已在第二个 commit 中正确修复:

sys_sched_setschedulerSCHED_FIFO/SCHED_RR 分支中独立检查 caller.has_cap_sys_nice(),与 check_sched_permission 的自检查逻辑解耦。这意味着:

  • sched_setaffinity 对自身操作不需要 CAP_SYS_NICE(与 POSIX 一致)
  • sched_setscheduler 设置实时策略始终需要 CAP_SYS_NICE(与 Linux 一致)

设计正确,阻塞问题已解决。

实现逻辑验证

  1. policy 默认值AtomicI32::new(0) 对应 SCHED_NORMAL(Linux 值为 0),正确。
  2. 优先级范围校验SCHED_NORMAL/SCHED_BATCH/SCHED_IDLE 要求 prio == 0,SCHED_FIFO/SCHED_RR 要求 prio ∈ [1, 99],与 man sched_setscheduler 一致。
  3. SchedParam 使用 bytemuck::Pod:确保从用户空间加载时的内存安全性,正确。
  4. has_cap_sys_nice() 在 StarryOS 中等价于 euid == 0:测试以 root 身份运行,CAP_SYS_NICE 检查通过,测试可正常覆盖实时策略路径。
  5. vm_write_slicesys_sched_getparam 中的使用:使用 unsafe 块构造字节 slice 并通过 vm_write_slice 写入用户空间,方式与项目既有模式一致。

非阻塞性建议

  1. _reset_on_fork 未使用:建议添加 // TODO: SCHED_RESET_ON_FORK 已解析,待 fork 时实现继承逻辑 注释,便于后续开发者明确。
  2. 负 pid 返回 EINVAL 而非 ESRCHget_task_by_sched_pid 对负 pid 返回 InvalidInput,而 Linux 返回 ESRCH。此为既有行为,测试显式验证了当前行为。建议后续在 get_task_by_sched_pid 中修复。
  3. 多个新增文件缺少末尾换行CMakeLists.txtqemu-riscv64.tomlqemu-x86_64.tomltest_framework.hmain.c 末尾缺少换行符。
  4. EPERM 测试在 root 环境下始终走 "allowed" 分支:fork 子进程的 uid 与父进程相同(root),has_cap_sys_nice() 也为 true,所以 EPERM 路径无法被覆盖。这是测试环境的固有限制,不阻塞。

重复/冲突分析

  • base 分支sys_sched_getscheduler 固定返回 SCHED_RRsys_sched_setscheduler/sys_sched_getparam 为空桩。本 PR 是该区域的首次实质性实现。
  • open PR 搜索:搜索了所有包含 "sched" 关键词的 open PR,未发现与 sched 系列系统调用重叠的其他 PR。#963(HAL 重构)、#966(FDT 处理)、#965(串口驱动)均不涉及此变更面。

本地验证

  • cargo fmt --check:仅存在 pre-existing 的 let-chain 警告(process_cred 函数,第 327-328 行),与本次 PR 变更无关。PR 变更部分格式正确。
  • 代码审查未发现逻辑错误或安全问题。

结论

第二个 commit 正确修复了前次 review 的阻塞问题,实现逻辑与 Linux/POSIX 语义一致,测试覆盖全面。建议合并且关注上述非阻塞性改进项。

Powered by glm-5.1

@04megumi 04megumi closed this by deleting the head repository May 27, 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