Browse Source

fix(vfs): close pipes properly, prohibit sendfile64 used on non regular files

greatbridf 1 year ago
parent
commit
35cce41a09
4 changed files with 15 additions and 20 deletions
  1. 9 8
      include/kernel/process.hpp
  2. 1 4
      include/kernel/vfs.hpp
  3. 3 2
      src/kernel/syscall.cpp
  4. 2 6
      src/kernel/vfs.cpp

+ 9 - 8
include/kernel/process.hpp

@@ -209,25 +209,26 @@ public:
         if (!iter)
             return;
 
-        iter->second->close();
         _fds.push(fd);
         arr.erase(iter);
     }
 
     constexpr void onexec()
     {
-        for (auto&& [ fd, fp ] : arr) {
-            if (fp->flags.close_on_exec)
-                close(fd);
+        for (auto iter = arr.begin(); iter != arr.end(); ) {
+            if (!iter->second->flags.close_on_exec) {
+                ++iter;
+                continue;
+            }
+            _fds.push(iter->first);
+            iter = arr.erase(iter);
         }
     }
 
     constexpr void close_all(void)
     {
-        for (auto&& [ fd, fp ] : arr) {
-            fp->close();
-            _fds.push(fd);
-        }
+        for (const auto& item : arr)
+            _fds.push(item.first);
         arr.clear();
     }
 

+ 1 - 4
include/kernel/vfs.hpp

@@ -280,7 +280,6 @@ struct file {
 
     virtual ssize_t read(char* __user buf, size_t n) = 0;
     virtual ssize_t write(const char* __user buf, size_t n) = 0;
-    virtual void close() = 0;
 
     // regular files should override this method
     virtual int getdents(char* __user buf, size_t cnt)
@@ -298,20 +297,18 @@ struct regular_file : public virtual file {
 
     virtual ssize_t read(char* __user buf, size_t n) override;
     virtual ssize_t write(const char* __user buf, size_t n) override;
-    virtual void close() override;
     virtual int getdents(char* __user buf, size_t cnt) override;
     virtual int getdents64(char* __user buf, size_t cnt) override;
 };
 
 struct fifo_file : public virtual file {
-    virtual ~fifo_file() = default;
+    virtual ~fifo_file() override;
     std::shared_ptr<pipe> ppipe;
 
     fifo_file(vfs::dentry* parent, file_flags flags, std::shared_ptr<fs::pipe> ppipe);
 
     virtual ssize_t read(char* __user buf, size_t n) override;
     virtual ssize_t write(const char* __user buf, size_t n) override;
-    virtual void close() override;
 };
 
 inline fs::vfs::dentry* fs_root;

+ 3 - 2
src/kernel/syscall.cpp

@@ -583,8 +583,9 @@ int _syscall_sendfile64(interrupt_stack* data)
     if (!out_file || !in_file)
         return -EBADF;
 
-    // TODO: check whether in_fd supports mmapping (for example,
-    //       whether it is a char device) if not, return -EINVAL
+    // TODO: check whether in_fd supports mmapping
+    if (!S_ISREG(in_file->mode) && !S_ISBLK(in_file->mode))
+        return -EINVAL;
 
     if (offset)
         not_implemented();

+ 2 - 6
src/kernel/vfs.cpp

@@ -425,7 +425,7 @@ public:
 
 fs::regular_file::regular_file(vfs::dentry* parent,
     file_flags flags, size_t cursor, inode* ind)
-    : file(S_IFREG, parent, flags), cursor(cursor), ind(ind) { }
+    : file(ind->mode, parent, flags), cursor(cursor), ind(ind) { }
 
 ssize_t fs::regular_file::read(char* __user buf, size_t n)
 {
@@ -459,8 +459,6 @@ ssize_t fs::regular_file::write(const char* __user buf, size_t n)
     return n_wrote;
 }
 
-void fs::regular_file::close(void) { } // TODO: mark inode as free
-
 int fs::regular_file::getdents(char* __user buf, size_t cnt)
 {
     if (!S_ISDIR(ind->mode))
@@ -552,15 +550,13 @@ ssize_t fs::fifo_file::write(const char* __user buf, size_t n)
     return ppipe->write(buf, n);
 }
 
-void fs::fifo_file::close(void)
+fs::fifo_file::~fifo_file()
 {
     assert(flags.read ^ flags.write);
     if (flags.read)
         ppipe->close_read();
     else
         ppipe->close_write();
-
-    ppipe.reset();
 }
 
 static std::map<dev_t, fs::blkdev_ops> blkdevs;