diff --git a/Kernel/Syscalls/readlink.cpp b/Kernel/Syscalls/readlink.cpp index 0d2d187456..1f4c0f1cae 100644 --- a/Kernel/Syscalls/readlink.cpp +++ b/Kernel/Syscalls/readlink.cpp @@ -22,11 +22,16 @@ ErrorOr Process::sys$readlink(Userspacemetadata().is_symlink()) return EINVAL; - auto link_target = TRY(description->read_entire_file()); - auto size_to_copy = min(link_target->size(), params.buffer.size); - TRY(copy_to_user(params.buffer.data, link_target->data(), size_to_copy)); + // Make sure that our assumptions about the path length hold up. + // Note that this doesn't mean that the reported size can be trusted, some inodes just report zero. + VERIFY(description->inode()->size() <= MAXPATHLEN); + + Array link_target; + auto read_bytes = TRY(description->inode()->read_until_filled_or_end(0, link_target.size(), UserOrKernelBuffer::for_kernel_buffer(link_target.data()), description)); + auto size_to_copy = min(read_bytes, params.buffer.size); + TRY(copy_to_user(params.buffer.data, link_target.data(), size_to_copy)); // Note: we return the whole size here, not the copied size. - return link_target->size(); + return read_bytes; } }