-
-
Notifications
You must be signed in to change notification settings - Fork 164
fix(syscall,vfs): fix SIG derivative when writing partial readable buffer #1375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(syscall,vfs): fix SIG derivative when writing partial readable buffer #1375
Conversation
a91605c to
b5b3f24
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.PartialWriteSIGSEGVbf3583b to
f004ef6
Compare
- 引入 user_accessible_len() 以测量从给定地址 `address` 开始,能够被拷贝的最长连续字节长度(注:使用vma进行校验) - 使 IoVecs::gather 返回 Result 并仅聚合可以被读取的 `buf` 部分(注意,一旦碰到不可访问的 iov,后面的iov都会被抛弃) - 在 writev/pwritev 中传播新的 Result 以支持 gVisor 下的部分写入
- 添加了对于 IoVecs 发起的分散写入的处理方式目前处理方式的注释。 - 添加了实现分散写入依赖于文件系统对于 IoVecs 写入支持的注释。
0d66dbb to
94bb0fb
Compare
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 测试用例