Explorar o código

Kernel: Add file permission checks to utime() syscall.

Andreas Kling %!s(int64=6) %!d(string=hai) anos
pai
achega
a624fe06b8
Modificáronse 3 ficheiros con 27 adicións e 12 borrados
  1. 3 12
      Kernel/Process.cpp
  2. 23 0
      Kernel/VirtualFileSystem.cpp
  3. 1 0
      Kernel/VirtualFileSystem.h

+ 3 - 12
Kernel/Process.cpp

@@ -1125,14 +1125,6 @@ int Process::sys$utime(const char* pathname, const utimbuf* buf)
         return -EFAULT;
         return -EFAULT;
     if (buf && !validate_read_typed(buf))
     if (buf && !validate_read_typed(buf))
         return -EFAULT;
         return -EFAULT;
-    String path(pathname);
-    int error;
-    auto descriptor = VFS::the().open(move(path), error, 0, 0, cwd_inode());
-    if (!descriptor)
-        return error;
-    auto& inode = *descriptor->inode();
-    if (inode.fs().is_readonly())
-        return -EROFS;
     time_t atime;
     time_t atime;
     time_t mtime;
     time_t mtime;
     if (buf) {
     if (buf) {
@@ -1143,11 +1135,10 @@ int Process::sys$utime(const char* pathname, const utimbuf* buf)
         mtime = now;
         mtime = now;
         atime = now;
         atime = now;
     }
     }
-    error = inode.set_atime(atime);
-    if (error)
+    int error;
+    if (!VFS::the().utime(String(pathname), error, cwd_inode(), atime, mtime))
         return error;
         return error;
-    error = inode.set_mtime(mtime);
-    return error;
+    return 0;
 }
 }
 
 
 int Process::sys$access(const char* pathname, int mode)
 int Process::sys$access(const char* pathname, int mode)

+ 23 - 0
Kernel/VirtualFileSystem.cpp

@@ -131,6 +131,29 @@ RetainPtr<FileDescriptor> VFS::open(RetainPtr<Device>&& device, int& error, int
     return FileDescriptor::create(move(device));
     return FileDescriptor::create(move(device));
 }
 }
 
 
+bool VFS::utime(const String& path, int& error, Inode& base, time_t atime, time_t mtime)
+{
+    auto descriptor = VFS::the().open(move(path), error, 0, 0, base);
+    if (!descriptor)
+        return false;
+    auto& inode = *descriptor->inode();
+    if (inode.fs().is_readonly()) {
+        error = -EROFS;
+        return false;
+    }
+    if (inode.metadata().uid != current->euid()) {
+        error = -EACCES;
+        return false;
+    }
+    error = inode.set_atime(atime);
+    if (error)
+        return false;
+    error = inode.set_mtime(mtime);
+    if (error)
+        return false;
+    return true;
+}
+
 bool VFS::stat(const String& path, int& error, int options, Inode& base, struct stat& statbuf)
 bool VFS::stat(const String& path, int& error, int options, Inode& base, struct stat& statbuf)
 {
 {
     auto inode_id = resolve_path(path, base.identifier(), error, options);
     auto inode_id = resolve_path(path, base.identifier(), error, options);

+ 1 - 0
Kernel/VirtualFileSystem.h

@@ -70,6 +70,7 @@ public:
     bool rmdir(const String& path, Inode& base, int& error);
     bool rmdir(const String& path, Inode& base, int& error);
     bool chmod(const String& path, mode_t, Inode& base, int& error);
     bool chmod(const String& path, mode_t, Inode& base, int& error);
     bool stat(const String& path, int& error, int options, Inode& base, struct stat&);
     bool stat(const String& path, int& error, int options, Inode& base, struct stat&);
+    bool utime(const String& path, int& error, Inode& base, time_t atime, time_t mtime);
 
 
     void register_device(Device&);
     void register_device(Device&);
     void unregister_device(Device&);
     void unregister_device(Device&);