Browse Source

fix(dup2): newfd should not share flags(O_CLOEXEC) with oldfd

greatbridf 1 year ago
parent
commit
0c005d1b68
3 changed files with 12 additions and 7 deletions
  1. 1 1
      include/kernel/process.hpp
  2. 9 2
      src/kernel/process.cpp
  3. 2 4
      src/kernel/syscall.cpp

+ 1 - 1
include/kernel/process.hpp

@@ -212,7 +212,7 @@ public:
     constexpr void onexec()
     {
         for (auto iter = arr.begin(); iter != arr.end(); ) {
-            if (!(iter->second.flags & O_CLOEXEC)) {
+            if (!(iter->second.flags & FD_CLOEXEC)) {
                 ++iter;
                 continue;
             }

+ 9 - 2
src/kernel/process.cpp

@@ -98,7 +98,12 @@ int filearr::dup2(int old_fd, int new_fd)
 
     int fd = allocate_fd(new_fd);
     assert(fd == new_fd);
-    this->arr.emplace(new_fd, iter->second);
+
+    auto [ newiter, inserted ] = this->arr.emplace(new_fd, iter->second);
+    assert(inserted);
+
+    newiter->second.flags = 0;
+
     return new_fd;
 }
 
@@ -178,9 +183,11 @@ int filearr::open(const process &current,
             return -EISDIR;
     }
 
+    int fdflag = (flags & O_CLOEXEC) ? FD_CLOEXEC : 0;
+
     int fd = next_fd();
     auto [ _, inserted ] = arr.emplace(fd, fditem {
-        flags, std::shared_ptr<fs::file> {
+        fdflag, std::shared_ptr<fs::file> {
             new fs::regular_file(dentry->parent, {
                 .read = !(flags & O_WRONLY),
                 .write = !!(flags & (O_WRONLY | O_RDWR)),

+ 2 - 4
src/kernel/syscall.cpp

@@ -691,12 +691,10 @@ int _syscall_fcntl64(interrupt_stack* data)
 
     switch (cmd) {
     case F_SETFD:
-        return current_process->files.set_flags(
-            fd, (arg & FD_CLOEXEC) ? O_CLOEXEC : 0);
+        return current_process->files.set_flags(fd, arg);
     case F_DUPFD:
     case F_DUPFD_CLOEXEC: {
-        int flag = (cmd & F_DUPFD_CLOEXEC) ? O_CLOEXEC : 0;
-        return current_process->files.dupfd(fd, arg, flag);
+        return current_process->files.dupfd(fd, arg, FD_CLOEXEC);
     }
     default:
         not_implemented();