diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index c2fc303f34..4b6c062ed4 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -2587,14 +2587,19 @@ int Process::sys$unlink(const char* user_path, size_t path_length) return VFS::the().unlink(path.value(), current_directory()); } -int Process::sys$symlink(const char* target, const char* linkpath) +int Process::sys$symlink(const Syscall::SC_symlink_params* user_params) { - SmapDisabler disabler; - if (!validate_read_str(target)) + if (!validate_read_typed(user_params)) return -EFAULT; - if (!validate_read_str(linkpath)) - return -EFAULT; - return VFS::the().symlink(StringView(target), StringView(linkpath), current_directory()); + Syscall::SC_symlink_params params; + copy_from_user(¶ms, user_params); + auto target = get_syscall_path_argument(params.target.characters, params.target.length); + if (target.is_error()) + return target.error(); + auto linkpath = get_syscall_path_argument(params.linkpath.characters, params.linkpath.length); + if (linkpath.is_error()) + return linkpath.error(); + return VFS::the().symlink(target.value(), linkpath.value(), current_directory()); } KResultOr Process::get_syscall_path_argument(const char* user_path, size_t path_length) diff --git a/Kernel/Process.h b/Kernel/Process.h index 4520fb0a55..dc21932cb3 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -177,7 +177,7 @@ public: int sys$utime(const char* pathname, size_t path_length, const struct utimbuf*); int sys$link(const Syscall::SC_link_params*); int sys$unlink(const char* pathname, size_t path_length); - int sys$symlink(const char* target, const char* linkpath); + int sys$symlink(const Syscall::SC_symlink_params*); int sys$rmdir(const char* pathname, size_t path_length); int sys$mount(const char* device, const char* mountpoint, const char* fstype); int sys$umount(const char* mountpoint, size_t mountpoint_length); diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 6e71d141d0..b2e2c39d8f 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -345,6 +345,11 @@ struct SC_mknod_params { u32 dev; }; +struct SC_symlink_params { + StringArgument target; + StringArgument linkpath; +}; + void initialize(); int sync(); diff --git a/Libraries/LibC/unistd.cpp b/Libraries/LibC/unistd.cpp index 20d5930461..ece2124a88 100644 --- a/Libraries/LibC/unistd.cpp +++ b/Libraries/LibC/unistd.cpp @@ -361,7 +361,12 @@ int unlink(const char* pathname) int symlink(const char* target, const char* linkpath) { - int rc = syscall(SC_symlink, target, linkpath); + if (!target || !linkpath) { + errno = EFAULT; + return -1; + } + Syscall::SC_symlink_params params { { target, strlen(target) }, { linkpath, strlen(linkpath) } }; + int rc = syscall(SC_symlink, ¶ms); __RETURN_WITH_ERRNO(rc, rc, -1); }