Browse Source

Fix some getdents bugs, drop a few flaky tests from the PASSED list.

Don Porter 7 years ago
parent
commit
1c51584792
2 changed files with 29 additions and 4 deletions
  1. 28 2
      LibOS/shim/src/sys/shim_open.c
  2. 1 2
      LibOS/shim/test/apps/ltp/PASSED

+ 28 - 2
LibOS/shim/src/sys/shim_open.c

@@ -321,6 +321,12 @@ size_t shim_do_getdents (int fd, struct linux_dirent * buf, size_t count)
         goto out;
     }
 
+    /* DEP 3/3/17: Properly handle an unlinked directory */
+    if (hdl->dentry->state & DENTRY_NEGATIVE) {
+        ret = -ENOENT;
+        goto out;
+    }
+    
     /* we are grabbing the lock because the handle content is actually
        updated */
     lock(hdl->lock);
@@ -370,7 +376,9 @@ size_t shim_do_getdents (int fd, struct linux_dirent * buf, size_t count)
 
     while (dirhdl->ptr && *dirhdl->ptr) {
         dent = *dirhdl->ptr;
-        ASSIGN_DIRENT(dent, dentry_get_name(dent), 0);
+        /* DEP 3/3/17: We need to filter negative dentries */
+        if (!(dent->state & DENTRY_NEGATIVE))
+            ASSIGN_DIRENT(dent, dentry_get_name(dent), 0);
         put_dentry(dent);
         *(dirhdl->ptr++) = NULL;
     }
@@ -380,6 +388,11 @@ size_t shim_do_getdents (int fd, struct linux_dirent * buf, size_t count)
 
 done:
     ret = bytes;
+    /* DEP 3/3/17: Properly detect EINVAL case, where buffer is too small to
+     * hold anything */
+    if (bytes == 0 && ((dirhdl->ptr && *dirhdl->ptr)
+                       || dirhdl->dotdot || dirhdl->dot))
+        ret = -EINVAL;
     unlock(hdl->lock);
 out:
     put_handle(hdl);
@@ -399,6 +412,12 @@ size_t shim_do_getdents64 (int fd, struct linux_dirent64 * buf, size_t count)
         goto out;
     }
 
+    /* DEP 3/3/17: Properly handle an unlinked directory */
+    if (hdl->dentry->state & DENTRY_NEGATIVE) {
+        ret = -ENOENT;
+        goto out;
+    }
+    
     lock(hdl->lock);
 
     struct shim_dir_handle * dirhdl = &hdl->info.dir;
@@ -439,7 +458,9 @@ size_t shim_do_getdents64 (int fd, struct linux_dirent64 * buf, size_t count)
 
     while (dirhdl->ptr && *dirhdl->ptr) {
         dent = *dirhdl->ptr;
-        ASSIGN_DIRENT(dent, dentry_get_name(dent), 0);
+        /* DEP 3/3/17: We need to filter negative dentries */
+        if (!(dent->state & DENTRY_NEGATIVE))
+            ASSIGN_DIRENT(dent, dentry_get_name(dent), 0);
         put_dentry(dent);
         *(dirhdl->ptr++) = NULL;
     }
@@ -449,6 +470,11 @@ size_t shim_do_getdents64 (int fd, struct linux_dirent64 * buf, size_t count)
 
 done:
     ret = bytes;
+    /* DEP 3/3/17: Properly detect EINVAL case, where buffer is too small to
+     * hold anything */
+    if (bytes == 0 && ((dirhdl->ptr && *dirhdl->ptr)
+                       || dirhdl->dotdot || dirhdl->dot))
+        ret = -EINVAL;
     unlock(hdl->lock);
 out:
     put_handle(hdl);

+ 1 - 2
LibOS/shim/test/apps/ltp/PASSED

@@ -135,6 +135,7 @@ getcontext01,1
 getdents02,1
 getdents02,2
 getdents02,3
+getdents02,4
 getdomainname01,1
 getdtablesize01,1
 getegid01,1
@@ -261,7 +262,6 @@ pselect01_64,6
 pselect01_64,7
 pselect01_64,8
 pselect01_64,9
-ptrace05,1
 pwrite01,1
 pwrite04,2
 read01,1
@@ -570,7 +570,6 @@ socketcall02,1
 socketcall03,1
 socketcall04,1
 sockioctl01,1
-splice02,1
 stat05,1
 string01,1
 sync01,1