fix(vfs/sys_write): 在进入写路径前先将用户缓冲区拷贝到内核#1821
fix(vfs/sys_write): 在进入写路径前先将用户缓冲区拷贝到内核#1821fslongjin merged 1 commit intoDragonOS-Community:masterfrom
Conversation
…ite syscall Signed-off-by: xboHodx <xbohodx2024@gmail.com>
|
@claude review |
|
Claude finished @fslongjin's task in 5m 31s —— View job Code Review for PR #1821: fix(vfs/sys_write): 在进入写路径前先将用户缓冲区拷贝到内核I'll review the changes in this PR that fixes a kernel panic when running kata-agent. Let me analyze the code changes and provide feedback. Todo list:
SummaryThe PR successfully fixes a kernel panic that occurred when Code ReviewChanges OverviewThe modifications in Before: After: For user-space calls, Correctness Assessment
Potential Issues
Recommendations
VerificationThe fix aligns with the PR's analysis and should eliminate the Approval: ✅ The PR can be merged as-is. Future improvements (performance, abstraction) can be addressed separately. --- | |
这个 PR 修复了 DragonOS 运行 kata-agent 时触发的一处内核 panic。
问题分析
sys_write(2) 之前会把“直接借用的用户态缓冲区切片”传入 VFS 写路径。对于 pipe fd,pipe::write_at()
会先获取自旋锁,再去读取这段用户缓冲区。如果此时源用户页还没有 fault in,内核就会在持有 pipe 自旋锁的情况下
进入 filemap_fault,最终带着 preempt_count=1 进入阻塞等待路径,并在 schedule() 处触发断言 panic。
这个 PR 将 sys_write 的用户态写入路径改为:先通过受保护的用户缓冲区接口把数据拷贝到内核 Vec,然后再调用
do_write()。这样 VFS/pipe 等后续路径只会访问内核内存,不会再在持锁状态下触碰用户页。
修复前的路径大致是:
这意味着:如果用户缓冲区对应页面还未建立映射或需要缺页处理,就可能在持有 spinlock 的情况下触发页错误,这是
不允许的。
修复方式
在 kernel/src/filesystem/vfs/syscall/sys_write.rs 中:
对于内核态发起的写请求,仍然保留原有直接读取路径。
修复效果
这说明本 PR 已经从根本上修复了这次内核 bug。
:不再 panic,kata-agent 能输出自身日志并继续执行到新的用户态错误
更加合适的处理
现在的处理会多一次拷贝,影响性能。
参考linux中,将用户态引用包装成一个带类型信息的 iov_iter,明确告诉后续路径:
若是要这样处理的话得重构 VFS 写接口,让写路径能区分 user buffer 和 kernel buffer,并且用类似 iov_iter / UserBuffer 的抽象把这个语义一路保留下去