diff --git a/AK/MappedFile.cpp b/AK/MappedFile.cpp index 68e2a7abfb6..83baecfaa4a 100644 --- a/AK/MappedFile.cpp +++ b/AK/MappedFile.cpp @@ -13,7 +13,7 @@ namespace AK { MappedFile::MappedFile(const StringView& file_name) { m_size = PAGE_SIZE; - m_fd = open(String(file_name).characters(), O_RDONLY | O_CLOEXEC); + m_fd = open_with_path_length(file_name.characters_without_null_termination(), file_name.length(), O_RDONLY | O_CLOEXEC, 0); if (m_fd != -1) { struct stat st; diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 8802cf784aa..0d8035cc7db 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1127,12 +1127,18 @@ int Process::number_of_open_file_descriptors() const return count; } -int Process::sys$open(const char* path, int options, mode_t mode) +int Process::sys$open(const Syscall::SC_open_params* params) { + if (!validate_read_typed(params)) + return -EFAULT; + auto* path = params->path; + auto path_length = params->path_length; + auto options = params->options; + auto mode = params->mode; #ifdef DEBUG_IO dbgprintf("%s(%u) sys$open(\"%s\")\n", name().characters(), pid(), path); #endif - if (!validate_read_str(path)) + if (!validate_read(path, path_length)) return -EFAULT; int fd = alloc_fd(); if (fd < 0) diff --git a/Kernel/Process.h b/Kernel/Process.h index c3205288651..59491f31cbf 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -118,7 +118,7 @@ public: pid_t sys$getpid(); pid_t sys$getppid(); mode_t sys$umask(mode_t); - int sys$open(const char* path, int options, mode_t mode = 0); + int sys$open(const Syscall::SC_open_params*); int sys$close(int fd); ssize_t sys$read(int fd, u8*, ssize_t); ssize_t sys$write(int fd, const u8*, ssize_t); diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index df301686cfc..a8b54e79d28 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -85,7 +85,7 @@ static u32 handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3 case Syscall::SC_getcwd: return current->process().sys$getcwd((char*)arg1, (size_t)arg2); case Syscall::SC_open: - return current->process().sys$open((const char*)arg1, (int)arg2, (mode_t)arg3); + return current->process().sys$open((const SC_open_params*)arg1); case Syscall::SC_write: return current->process().sys$write((int)arg1, (const u8*)arg2, (ssize_t)arg3); case Syscall::SC_close: diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 51e3dce7535..58b6e9d44e6 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -148,6 +148,13 @@ struct SC_mmap_params { const char* name { nullptr }; }; +struct SC_open_params { + const char* path; + int path_length; + int options; + u16 mode; +}; + struct SC_select_params { int nfds; fd_set* readfds; diff --git a/Libraries/LibC/unistd.cpp b/Libraries/LibC/unistd.cpp index 4744ee5f587..d4622bba1f6 100644 --- a/Libraries/LibC/unistd.cpp +++ b/Libraries/LibC/unistd.cpp @@ -166,13 +166,29 @@ int creat(const char* path, mode_t mode) return open(path, O_CREAT | O_WRONLY | O_TRUNC, mode); } +int creat_with_path_length(const char* path, size_t path_length, mode_t mode) +{ + return open_with_path_length(path, path_length, O_CREAT | O_WRONLY | O_TRUNC, mode); +} + +int open_with_path_length(const char* path, size_t path_length, int options, mode_t mode) +{ + if (path_length > INT32_MAX) { + errno = EINVAL; + return -1; + } + Syscall::SC_open_params params { path, (int)path_length, options, mode }; + int rc = syscall(SC_open, ¶ms); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + int open(const char* path, int options, ...) { va_list ap; va_start(ap, options); - int rc = syscall(SC_open, path, options, (mode_t)va_arg(ap, unsigned)); + auto mode = (mode_t)va_arg(ap, unsigned); va_end(ap); - __RETURN_WITH_ERRNO(rc, rc, -1); + return open_with_path_length(path, strlen(path), options, mode); } ssize_t read(int fd, void* buf, size_t count) diff --git a/Libraries/LibC/unistd.h b/Libraries/LibC/unistd.h index cfe5c26b26d..42235b0e636 100644 --- a/Libraries/LibC/unistd.h +++ b/Libraries/LibC/unistd.h @@ -55,6 +55,8 @@ pid_t tcgetpgrp(int fd); int tcsetpgrp(int fd, pid_t pgid); int creat(const char* path, mode_t); int open(const char* path, int options, ...); +int creat_with_path_length(const char* path, size_t path_length, mode_t); +int open_with_path_length(const char* path, size_t path_length, int options, mode_t); ssize_t read(int fd, void* buf, size_t count); ssize_t write(int fd, const void* buf, size_t count); int close(int fd); diff --git a/Libraries/LibGUI/GTextEditor.cpp b/Libraries/LibGUI/GTextEditor.cpp index 3feb6d6d78c..9661a510974 100644 --- a/Libraries/LibGUI/GTextEditor.cpp +++ b/Libraries/LibGUI/GTextEditor.cpp @@ -844,7 +844,7 @@ void GTextEditor::Line::truncate(int length) bool GTextEditor::write_to_file(const StringView& path) { - int fd = open(String(path).characters(), O_WRONLY | O_CREAT | O_TRUNC, 0666); + int fd = open_with_path_length(path.characters_without_null_termination(), path.length(), O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) { perror("open"); return false; diff --git a/SharedGraphics/Font.cpp b/SharedGraphics/Font.cpp index ec34aaab88f..b46495ad3bb 100644 --- a/SharedGraphics/Font.cpp +++ b/SharedGraphics/Font.cpp @@ -127,7 +127,7 @@ RefPtr Font::load_from_file(const StringView& path) bool Font::write_to_file(const StringView& path) { - int fd = creat(String(path).characters(), 0644); + int fd = creat_with_path_length(path.characters_without_null_termination(), path.length(), 0644); if (fd < 0) { perror("open"); return false;