From 0faabe02e568ce5b5e58c518b609252324a83269 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 22 Oct 2022 10:28:02 +0200 Subject: [PATCH] Kernel, libc: Implement O_CLOEXEC --- kernel/include/fs/FileDescriptor.h | 8 +++++++- kernel/src/fs/FileDescriptor.cpp | 7 +++++-- kernel/src/sys/exec.cpp | 6 ++++++ kernel/src/sys/stdio.cpp | 8 ++++++-- libs/libc/include/fcntl.h | 2 ++ 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/kernel/include/fs/FileDescriptor.h b/kernel/include/fs/FileDescriptor.h index bc0a6986..28b02a20 100644 --- a/kernel/include/fs/FileDescriptor.h +++ b/kernel/include/fs/FileDescriptor.h @@ -32,7 +32,7 @@ struct Descriptor ssize_t read(size_t size, char* buffer); ssize_t write(size_t size, const char* buffer); - void open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block); + void open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block, bool close_on_exec); int seek(long offset); long offset() @@ -50,6 +50,11 @@ struct Descriptor return m_able_to_block; } + bool close_on_exec() + { + return m_close_on_exec; + } + Descriptor(const Descriptor& other); Descriptor(); @@ -60,6 +65,7 @@ struct Descriptor bool m_can_read; bool m_can_write; bool m_able_to_block; + bool m_close_on_exec; VFS::Node* m_node; uint64_t m_offset; }; \ No newline at end of file diff --git a/kernel/src/fs/FileDescriptor.cpp b/kernel/src/fs/FileDescriptor.cpp index 67d83816..825552e7 100644 --- a/kernel/src/fs/FileDescriptor.cpp +++ b/kernel/src/fs/FileDescriptor.cpp @@ -7,15 +7,17 @@ Descriptor::Descriptor() : m_is_open(false) Descriptor::Descriptor(const Descriptor& other) : m_is_open(other.m_is_open), m_can_read(other.m_can_read), m_can_write(other.m_can_write), - m_able_to_block(other.m_able_to_block), m_node(other.m_node), m_offset(other.m_offset) + m_able_to_block(other.m_able_to_block), m_close_on_exec(other.m_close_on_exec), m_node(other.m_node), + m_offset(other.m_offset) { } -void Descriptor::open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block) +void Descriptor::open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block, bool close_on_exec) { m_can_read = can_read; m_can_write = can_write; m_able_to_block = able_to_block; + m_close_on_exec = close_on_exec; m_node = node; m_offset = 0; m_is_open = true; @@ -51,5 +53,6 @@ const Descriptor& Descriptor::operator=(const Descriptor& other) m_offset = other.m_offset; m_node = other.m_node; m_able_to_block = other.m_able_to_block; + m_close_on_exec = other.m_close_on_exec; return other; } \ No newline at end of file diff --git a/kernel/src/sys/exec.cpp b/kernel/src/sys/exec.cpp index d9fa8266..0e36861a 100644 --- a/kernel/src/sys/exec.cpp +++ b/kernel/src/sys/exec.cpp @@ -123,6 +123,12 @@ void sys_exec(Context* context, const char* pathname) Scheduler::reset_task(task, image); + for (int i = 0; i < TASK_MAX_FDS; i++) + { + Descriptor& file = task->files[i]; + if (file.close_on_exec()) { file.close(); } + } + task->restore_context(context); kfree(kpathname); diff --git a/kernel/src/sys/stdio.cpp b/kernel/src/sys/stdio.cpp index 8dbd35c3..790d49dc 100644 --- a/kernel/src/sys/stdio.cpp +++ b/kernel/src/sys/stdio.cpp @@ -15,6 +15,7 @@ #define OPEN_READ 1 #define OPEN_WRITE 2 #define OPEN_NONBLOCK 4 +#define OPEN_CLOEXEC 8 #define SEEK_SET 0 #define SEEK_CUR 1 @@ -181,6 +182,7 @@ void sys_open(Context* context, const char* filename, int flags) } bool able_to_block = (flags & OPEN_NONBLOCK) == 0; + bool close_on_exec = (flags & OPEN_CLOEXEC) > 0; kdbgln("open(): opening %s %s, allocated file descriptor %d", kfilename, (can_read && can_write) ? "rw" @@ -189,7 +191,7 @@ void sys_open(Context* context, const char* filename, int flags) fd); kfree(kfilename); - current_task->files[fd].open(node, can_read, can_write, able_to_block); + current_task->files[fd].open(node, can_read, can_write, able_to_block, close_on_exec); context->rax = fd; return; } @@ -225,7 +227,9 @@ void sys_read(Context* context, int fd, size_t size, char* buffer) current_task->blocking_read_info.size = size; return Scheduler::task_yield(context); } - ssize_t result = current_task->files[fd].read(size, (char*)VMM::get_physical((uint64_t)buffer)); + ssize_t result = current_task->files[fd].read( + size, (char*)VMM::get_physical((uint64_t)buffer)); // FIXME: Handle errors, and big buffers which may not be + // across continuous physical pages. context->rax = (size_t)result; return; } diff --git a/libs/libc/include/fcntl.h b/libs/libc/include/fcntl.h index a8e61756..b17e3689 100644 --- a/libs/libc/include/fcntl.h +++ b/libs/libc/include/fcntl.h @@ -9,6 +9,8 @@ #define O_RDWR 3 /* Open without blocking. */ #define O_NONBLOCK 4 +/* Close the opened file descriptor on a call to execve(). */ +#define O_CLOEXEC 8 /* Duplicate a file descriptor. */ #define F_DUPFD 0