-
Notifications
You must be signed in to change notification settings - Fork 5.3k
fix[dfs_v1]: prevent vnode ref underflow and double release on close/fd release #11119
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -412,13 +412,16 @@ void fdt_fd_release(struct dfs_fdtable* fdt, int fd) | |||||
| if (fd_slot->ref_count == 0) | ||||||
| { | ||||||
| struct dfs_vnode *vnode = fd_slot->vnode; | ||||||
| fd_slot->vnode = RT_NULL; | ||||||
| if (vnode) | ||||||
| { | ||||||
| vnode->ref_count--; | ||||||
| if (vnode->ref_count > 0) | ||||||
| { | ||||||
| vnode->ref_count--; | ||||||
| } | ||||||
| if(vnode->ref_count == 0) | ||||||
|
||||||
| if(vnode->ref_count == 0) | |
| if (vnode->ref_count == 0) |
Copilot
AI
Jan 5, 2026
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.
[Bug/错误]: Potential vnode double-free vulnerability / 潜在的 vnode 双重释放漏洞
English: While the guard if (vnode->ref_count > 0) prevents underflow, the logic here is problematic. If fdt_fd_release is called when the vnode was already freed by dfs_file_close, this could lead to use-after-free. The vnode might have already been freed in dfs_file_close at line 363, but fd_slot->vnode still holds a dangling pointer until line 415 sets it to NULL. Additionally, freeing the vnode here at line 424 without proper cleanup (removing from hash list, freeing path/fullpath) is incomplete compared to the cleanup in dfs_file_close. This inconsistency suggests a design flaw in managing vnode lifecycle across two different code paths.
中文:虽然保护条件 if (vnode->ref_count > 0) 可以防止下溢,但这里的逻辑存在问题。如果在 vnode 已被 dfs_file_close 释放后调用 fdt_fd_release,这可能导致释放后使用。vnode 可能已在 dfs_file_close 的第 363 行被释放,但 fd_slot->vnode 仍持有悬空指针,直到第 415 行将其设置为 NULL。此外,在第 424 行释放 vnode 时没有适当的清理(从哈希列表中删除、释放 path/fullpath),与 dfs_file_close 中的清理相比是不完整的。这种不一致性表明在两个不同代码路径中管理 vnode 生命周期存在设计缺陷。
The correct approach should ensure that vnode cleanup is performed in only one place with proper synchronization, or the cleanup in both places should be identical and complete.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -337,7 +337,7 @@ int dfs_file_close(struct dfs_file *fd) | |
| dfs_fm_lock(); | ||
| vnode = fd->vnode; | ||
|
|
||
| if (vnode->ref_count <= 0) | ||
| if (vnode == NULL || vnode->ref_count <= 0) | ||
| { | ||
| dfs_fm_unlock(); | ||
| return -ENXIO; | ||
|
Comment on lines
+340
to
343
|
||
|
|
@@ -348,11 +348,12 @@ int dfs_file_close(struct dfs_file *fd) | |
| result = vnode->fops->close(fd); | ||
| } | ||
|
|
||
| if (vnode->ref_count == 1) | ||
| vnode->ref_count--; | ||
| fd->vnode = NULL; | ||
| if (vnode->ref_count == 0) | ||
|
Comment on lines
+351
to
+353
|
||
| { | ||
| /* remove from hash */ | ||
| rt_list_remove(&vnode->list); | ||
| fd->vnode = NULL; | ||
|
|
||
| if (vnode->path != vnode->fullpath) | ||
| { | ||
|
|
||
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.
[Concurrency/并发]: Insufficient synchronization between dfs_file_close and fdt_fd_release / dfs_file_close 和 fdt_fd_release 之间的同步不足
English: The
dfs_file_closefunction usesdfs_fm_lock()(vnode manager lock) whilefdt_fd_releaseusesdfs_file_lock()(fd table lock). These are two different locks protecting different resources. This creates a race condition where:dfs_file_close, decrementsvnode->ref_countto 0, and starts cleaning upfdt_fd_releaseconcurrently and also tries to decrement the same vnode's ref_countThe guard
if (vnode->ref_count > 0)at line 418 only partially mitigates this - if the race occurs after the check but before the decrement, underflow can still happen.中文:
dfs_file_close函数使用dfs_fm_lock()(vnode 管理器锁),而fdt_fd_release使用dfs_file_lock()(fd 表锁)。这是两个不同的锁保护不同的资源。这会创建一个竞争条件:dfs_file_close,将vnode->ref_count递减到 0,并开始清理fdt_fd_release,也尝试递减同一个 vnode 的 ref_count第 418 行的保护条件
if (vnode->ref_count > 0)只能部分缓解这个问题 - 如果竞争发生在检查之后但递减之前,仍然可能发生下溢。A proper fix would require using the same lock (likely
dfs_fm_lock) in both functions when accessing vnode ref_count.