fix(syscall,vfs): fix SIG derivative when writing partial readable buffer#1375
Merged
fslongjin merged 7 commits intoDragonOS-Community:masterfrom Nov 21, 2025
Merged
Conversation
a91605c to
b5b3f24
Compare
Contributor
There was a problem hiding this comment.
Pull Request Overview
This PR fixes a kernel panic in the pwritev system call when it encounters partially accessible memory regions (e.g., when an iovec spans across PROT_READ and PROT_NONE pages). The fix introduces VMA-based validation to check user memory accessibility before copying data, allowing partial writes to succeed instead of crashing the process.
Key changes:
- Added
user_accessible_len()function to validate user memory accessibility using VMA permissions - Modified
gather()to returnResult<Vec<u8>, SystemError>and handle partial reads gracefully - Updated syscall handlers to propagate errors from
gather()
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 13 comments.
| File | Description |
|---|---|
| kernel/src/syscall/user_access.rs | Adds user_accessible_len() function to compute contiguous accessible memory length using VMA validation |
| kernel/src/filesystem/vfs/iov.rs | Modifies gather() to check memory accessibility and support partial reads, returning errors appropriately |
| kernel/src/filesystem/vfs/syscall/sys_writev.rs | Updates to handle the new error-returning signature of gather() |
| kernel/src/filesystem/vfs/syscall/sys_pwritev.rs | Updates to handle the new error-returning signature of gather() |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
189fa17 to
666921b
Compare
WriteTest.PartialWriteSIGSEGV
fslongjin
reviewed
Nov 20, 2025
bf3583b to
f004ef6
Compare
- 引入 user_accessible_len() 以测量从给定地址 `address` 开始,能够被拷贝的最长连续字节长度(注:使用vma进行校验) - 使 IoVecs::gather 返回 Result 并仅聚合可以被读取的 `buf` 部分(注意,一旦碰到不可访问的 iov,后面的iov都会被抛弃) - 在 writev/pwritev 中传播新的 Result 以支持 gVisor 下的部分写入
- 添加了对于 IoVecs 发起的分散写入的处理方式目前处理方式的注释。 - 添加了实现分散写入依赖于文件系统对于 IoVecs 写入支持的注释。
0d66dbb to
94bb0fb
Compare
fslongjin
approved these changes
Nov 21, 2025
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Done
问题描述
实现系统调用
sys_pwritev后,再次使用 gvisor 测试时 ,测试用例WriteTest.PartialWriteSIGSEGV会出现 访问地址 0x95a000 错误码为 0b0(表示在内核中读取一个不存在的页面) 的 pagefault , 该 pagefault 会导致内核直接 杀死请求系统调用的当前用户进程。测试用例逻辑分析
测试当一个 iov 横跨
PROT_READ(第一页)和PROT_NONE的页(第二页)的时候,pwritev能否正确的将前半部分的内容写到文件中,而后半部分的内容由于会触发segv不写入(但是神奇的是,这个segv应当不会导致pwritev调用失败,也不应该终止当前进程)。怀疑原因
iov中的 第二页(PROT_NONE的页) 的时候会在 内核态访问用户非法内存地址 的时候触发 segv,而这个 segv 会直接导致进程被kill 进而终止测试。参考
测试 log
对应 Gtest 测试用例