Преглед изворни кода

fix[dfs_v1]: prevent vnode ref underflow and double release on close/fd release

wdfk-prog пре 1 месец
родитељ
комит
2b95c3409c
2 измењених фајлова са 9 додато и 5 уклоњено
  1. 5 2
      components/dfs/dfs_v1/src/dfs.c
  2. 4 3
      components/dfs/dfs_v1/src/dfs_file.c

+ 5 - 2
components/dfs/dfs_v1/src/dfs.c

@@ -414,13 +414,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)
             {
                 rt_free(vnode);
-                fd_slot->vnode = RT_NULL;
             }
         }
         rt_free(fd_slot);

+ 4 - 3
components/dfs/dfs_v1/src/dfs_file.c

@@ -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;
@@ -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)
         {
             /* remove from hash */
             rt_list_remove(&vnode->list);
-            fd->vnode = NULL;
 
             if (vnode->path != vnode->fullpath)
             {