浏览代码

Kernel: Support chdir() to a directory that's executable but not readable.

Also the superuser should be allowed to resolve any possible path without
getting tripped up by EACCES.
Andreas Kling 6 年之前
父节点
当前提交
f75eb9af16
共有 3 个文件被更改,包括 19 次插入8 次删除
  1. 4 7
      Kernel/Process.cpp
  2. 14 1
      Kernel/VirtualFileSystem.cpp
  3. 1 0
      Kernel/VirtualFileSystem.h

+ 4 - 7
Kernel/Process.cpp

@@ -1273,13 +1273,10 @@ int Process::sys$chdir(const char* path)
 {
     if (!validate_read_str(path))
         return -EFAULT;
-    int error;
-    auto descriptor = VFS::the().open(path, error, 0, 0, cwd_inode());
-    if (!descriptor)
-        return error;
-    if (!descriptor->is_directory())
-        return -ENOTDIR;
-    m_cwd = descriptor->inode();
+    auto directory_or_error = VFS::the().open_directory(String(path), cwd_inode());
+    if (directory_or_error.is_error())
+        return directory_or_error.error();
+    m_cwd = *directory_or_error.value();
     return 0;
 }
 

+ 14 - 1
Kernel/VirtualFileSystem.cpp

@@ -290,6 +290,19 @@ KResult VFS::access(const String& path, int mode, Inode& base)
     return KSuccess;
 }
 
+KResultOr<Retained<Inode>> VFS::open_directory(const String& path, Inode& base)
+{
+    auto inode_or_error = resolve_path_to_inode(path, base);
+    if (inode_or_error.is_error())
+        return inode_or_error.error();
+    auto inode = inode_or_error.value();
+    if (!inode->is_directory())
+        return KResult(-ENOTDIR);
+    if (!inode->metadata().may_execute(*current) && !current->is_superuser())
+        return KResult(-EACCES);
+    return Retained<Inode>(*inode);
+}
+
 KResult VFS::chmod(Inode& inode, mode_t mode)
 {
     if (inode.fs().is_readonly())
@@ -554,7 +567,7 @@ KResultOr<InodeIdentifier> VFS::resolve_path(const String& path, InodeIdentifier
 #endif
             return KResult(-ENOTDIR);
         }
-        if (!metadata.may_execute(*current))
+        if (!metadata.may_execute(*current) && !current->is_superuser())
             return KResult(-EACCES);
         auto parent = crumb_id;
         crumb_id = crumb_inode->lookup(part);

+ 1 - 0
Kernel/VirtualFileSystem.h

@@ -75,6 +75,7 @@ public:
     KResult access(const String& path, int mode, Inode& base);
     bool stat(const String& path, int& error, int options, Inode& base, struct stat&);
     KResult utime(const String& path, Inode& base, time_t atime, time_t mtime);
+    KResultOr<Retained<Inode>> open_directory(const String& path, Inode& base);
 
     void register_device(Device&);
     void unregister_device(Device&);