diff options
-rw-r--r-- | Kernel/Process.cpp | 19 | ||||
-rw-r--r-- | Kernel/Process.h | 2 | ||||
-rw-r--r-- | Kernel/StdLib.h | 12 | ||||
-rw-r--r-- | Kernel/Syscall.h | 6 | ||||
-rw-r--r-- | Libraries/LibC/unistd.cpp | 7 |
5 files changed, 35 insertions, 11 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 896457bdec..c2fc303f34 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -3667,17 +3667,18 @@ void Process::FileDescriptionAndFlags::set(NonnullRefPtr<FileDescription>&& d, u flags = f; } -int Process::sys$mknod(const char* pathname, mode_t mode, dev_t dev) +int Process::sys$mknod(const Syscall::SC_mknod_params* user_params) { - if (!validate_read_str(pathname)) + if (!validate_read_typed(user_params)) return -EFAULT; - - if (!is_superuser()) { - if (!is_regular_file(mode) && !is_fifo(mode) && !is_socket(mode)) - return -EPERM; - } - - return VFS::the().mknod(StringView(pathname), mode & ~umask(), dev, current_directory()); + Syscall::SC_mknod_params params; + copy_from_user(¶ms, user_params); + if (!is_superuser() && !is_regular_file(params.mode) && !is_fifo(params.mode) && !is_socket(params.mode)) + return -EPERM; + auto path = get_syscall_path_argument(params.path.characters, params.path.length); + if (path.is_error()) + return path.error(); + return VFS::the().mknod(path.value(), params.mode & ~umask(), params.dev, current_directory()); } int Process::sys$dump_backtrace() diff --git a/Kernel/Process.h b/Kernel/Process.h index e1af793214..4520fb0a55 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -206,7 +206,7 @@ public: int sys$get_thread_name(int tid, char* buffer, int buffer_size); int sys$rename(const char* oldpath, const char* newpath); int sys$systrace(pid_t); - int sys$mknod(const char* pathname, mode_t, dev_t); + int sys$mknod(const Syscall::SC_mknod_params*); int sys$create_shared_buffer(int, void** buffer); int sys$share_buffer_with(int, pid_t peer_pid); int sys$share_buffer_globally(int); diff --git a/Kernel/StdLib.h b/Kernel/StdLib.h index 937ddc1f0f..07b8684627 100644 --- a/Kernel/StdLib.h +++ b/Kernel/StdLib.h @@ -36,3 +36,15 @@ void* memmove(void* dest, const void* src, size_t n); inline u16 ntohs(u16 w) { return (w & 0xff) << 8 | ((w >> 8) & 0xff); } inline u16 htons(u16 w) { return (w & 0xff) << 8 | ((w >> 8) & 0xff); } } + +template<typename T> +inline void copy_from_user(T* dest, const T* src) +{ + copy_from_user(dest, src, sizeof(T)); +} + +template<typename T> +inline void copy_to_user(T* dest, const T* src) +{ + copy_to_user(dest, src, sizeof(T)); +} diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 41ed4f6fed..6e71d141d0 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -339,6 +339,12 @@ struct SC_chown_params { u32 gid; }; +struct SC_mknod_params { + StringArgument path; + u16 mode; + u32 dev; +}; + void initialize(); int sync(); diff --git a/Libraries/LibC/unistd.cpp b/Libraries/LibC/unistd.cpp index 9ad0eb7462..20d5930461 100644 --- a/Libraries/LibC/unistd.cpp +++ b/Libraries/LibC/unistd.cpp @@ -451,7 +451,12 @@ int access(const char* pathname, int mode) int mknod(const char* pathname, mode_t mode, dev_t dev) { - int rc = syscall(SC_mknod, pathname, mode, dev); + if (!pathname) { + errno = EFAULT; + return -1; + } + Syscall::SC_mknod_params params { { pathname, strlen(pathname) }, mode, dev }; + int rc = syscall(SC_mknod, ¶ms); __RETURN_WITH_ERRNO(rc, rc, -1); } |