Browse Source

[LibOS] Allow inaccessible files during getdents()

Previously, if user performed getdents() on a directory containing
inaccessible files (because user doesn't have permission), whole
getdents failed with -EACCES. This is incorrect behavior: files must
still be listed. This commit fixes the root cause of this bug by
marking inaccessible files as DENTRY_NEGATIVE.
Dmitrii Kuvaiskii 5 years ago
parent
commit
05cc50945f
2 changed files with 11 additions and 6 deletions
  1. 1 1
      LibOS/shim/include/shim_fs.h
  2. 10 5
      LibOS/shim/src/fs/shim_namei.c

+ 1 - 1
LibOS/shim/include/shim_fs.h

@@ -104,7 +104,7 @@ struct shim_fs_ops {
 };
 
 #define DENTRY_VALID        0x0001  /* this dentry is verified to be valid */
-#define DENTRY_NEGATIVE     0x0002  /* negative, recently deleted */
+#define DENTRY_NEGATIVE     0x0002  /* recently deleted or inaccessible */
 #define DENTRY_RECENTLY     0x0004  /* recently used */
 #define DENTRY_PERSIST      0x0008  /* added as a persistent dentry */
 #define DENTRY_HASHED       0x0010  /* added in the dcache */

+ 10 - 5
LibOS/shim/src/fs/shim_namei.c

@@ -198,9 +198,9 @@ int lookup_dentry (struct shim_dentry * parent, const char * name, int namelen,
          * Not done in original code, so leaving for now.
          */
         if (err) {
-            if (err == -ENOENT) {
-                // Let ENOENT fall through so we can get negative dentries in
-                // the cache
+            if (err == -ENOENT || err == -EACCES) {
+                /* Non-existing files and inaccessible files are marked as
+                 * negative dentries, so they can still be cached */
                 dent->state |= DENTRY_NEGATIVE;
             } else {
 
@@ -759,8 +759,12 @@ int list_directory_dentry (struct shim_dentry *dent) {
     for ( ; d ; d = d->next) {
         struct shim_dentry * child;
         if ((ret = lookup_dentry(dent, d->name, strlen(d->name),
-                                 &child, fs)) < 0)
-            goto done_read;
+                                 &child, fs)) < 0) {
+            if (ret != -ENOENT) {
+                /* if the file is recently deleted or inaccessible, ignore it */
+                goto done_read;
+            }
+        }
 
         if (child->state & DENTRY_NEGATIVE)
             continue;
@@ -774,6 +778,7 @@ int list_directory_dentry (struct shim_dentry *dent) {
     }
 
     dent->state |= DENTRY_LISTED;
+    ret = 0;
 
 done_read:
     unlock(&dcache_lock);