summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorLiav A <liavalb@gmail.com>2023-02-22 20:11:03 +0200
committerSam Atkins <atkinssj@gmail.com>2023-02-23 09:33:54 +0000
commitb19dc8a9b61fc88ed9abfd6d0f82c308350eff59 (patch)
tree2970bafe7111df54021dfed5d6bbbdf08ba7a8bb /Kernel
parent40bfaff133164e17dbe714a05829c4ce5286e07b (diff)
downloadserenity-b19dc8a9b61fc88ed9abfd6d0f82c308350eff59.zip
Kernel: Prevent out-of-bounds read/write in VirtIO GPU3DDevice::ioctl
Before doing a check if offset_in_region + num_bytes of the transfer descriptor are together more than NUM_TRANSFER_REGION_PAGES * PAGE_SIZE, check that addition of both of these parameters will not simply overflow which could lead to out-of-bounds read/write. Fixes #17518.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Graphics/VirtIOGPU/GPU3DDevice.cpp12
1 files changed, 6 insertions, 6 deletions
diff --git a/Kernel/Graphics/VirtIOGPU/GPU3DDevice.cpp b/Kernel/Graphics/VirtIOGPU/GPU3DDevice.cpp
index 5d66a92c9d..c1fc61fccb 100644
--- a/Kernel/Graphics/VirtIOGPU/GPU3DDevice.cpp
+++ b/Kernel/Graphics/VirtIOGPU/GPU3DDevice.cpp
@@ -73,16 +73,16 @@ ErrorOr<void> VirtIOGPU3DDevice::ioctl(OpenFileDescription& description, unsigne
auto& transfer_buffer_region = TRY(get_context_for_description(description))->transfer_buffer_region();
auto user_transfer_descriptor = static_ptr_cast<VirGLTransferDescriptor const*>(arg);
auto transfer_descriptor = TRY(copy_typed_from_user(user_transfer_descriptor));
+ if (Checked<size_t>::addition_would_overflow(transfer_descriptor.offset_in_region, transfer_descriptor.num_bytes)) {
+ return EOVERFLOW;
+ }
+ if (transfer_descriptor.offset_in_region + transfer_descriptor.num_bytes > NUM_TRANSFER_REGION_PAGES * PAGE_SIZE) {
+ return EOVERFLOW;
+ }
if (transfer_descriptor.direction == VIRGL_DATA_DIR_GUEST_TO_HOST) {
- if (transfer_descriptor.offset_in_region + transfer_descriptor.num_bytes > NUM_TRANSFER_REGION_PAGES * PAGE_SIZE) {
- return EOVERFLOW;
- }
auto target = transfer_buffer_region.vaddr().offset(transfer_descriptor.offset_in_region).as_ptr();
return copy_from_user(target, transfer_descriptor.data, transfer_descriptor.num_bytes);
} else if (transfer_descriptor.direction == VIRGL_DATA_DIR_HOST_TO_GUEST) {
- if (transfer_descriptor.offset_in_region + transfer_descriptor.num_bytes > NUM_TRANSFER_REGION_PAGES * PAGE_SIZE) {
- return EOVERFLOW;
- }
auto source = transfer_buffer_region.vaddr().offset(transfer_descriptor.offset_in_region).as_ptr();
return copy_to_user(transfer_descriptor.data, source, transfer_descriptor.num_bytes);
} else {