Periodic: add error handling for integer overflow

Bug: 205995773
Test: GCA, test_poc, CTS
Signed-off-by: Nick Chung <nickchung@google.com>
Change-Id: I6fecab84188511bf36f4ff8b6cf839c7ec099738
diff --git a/lwis_ioctl.c b/lwis_ioctl.c
index 7453d8b..8033da6 100644
--- a/lwis_ioctl.c
+++ b/lwis_ioctl.c
@@ -1097,6 +1097,11 @@
 	struct lwis_device *lwis_dev = client->lwis_dev;
 
 	entry_size = num_io_entries * sizeof(struct lwis_io_entry);
+	if (entry_size / sizeof(struct lwis_io_entry) != num_io_entries) {
+		dev_err(lwis_dev->dev, "Failed to prepare io entry due to integer overflow\n");
+		return -EINVAL;
+	}
+
 	k_entries = kvmalloc(entry_size, GFP_KERNEL);
 	if (!k_entries) {
 		dev_err(lwis_dev->dev, "Failed to allocate periodic io entries\n");
diff --git a/lwis_periodic_io.c b/lwis_periodic_io.c
index 061eced..6c7fed1 100644
--- a/lwis_periodic_io.c
+++ b/lwis_periodic_io.c
@@ -378,6 +378,26 @@
 		}
 	}
 
+	/* Check integer overflow.*/
+	if (info->batch_size != 0 && read_entries != 0 && read_buf_size != 0) {
+		if (SIZE_MAX / (sizeof(struct lwis_periodic_io_result) * info->batch_size) <
+			    read_entries ||
+		    SIZE_MAX / (read_entries * sizeof(struct lwis_periodic_io_result)) <
+			    info->batch_size ||
+		    SIZE_MAX / read_buf_size < info->batch_size ||
+		    SIZE_MAX - (read_entries * sizeof(struct lwis_periodic_io_result) *
+					info->batch_size +
+				read_buf_size * info->batch_size) <
+			    sizeof(struct lwis_periodic_io_response_header) ||
+		    SIZE_MAX - (read_entries * sizeof(struct lwis_periodic_io_result) *
+					info->batch_size +
+				sizeof(struct lwis_periodic_io_response_header)) <
+			    (read_buf_size * info->batch_size)) {
+			pr_err_ratelimited("Failed to prepare response due to integer overflow\n");
+			return -EINVAL;
+		}
+	}
+
 	/* Periodic io response payload consists of one response header and
 	 * batch_size of batches, each of which contains num_entries_per_period
 	 * pairs of lwis_periodic_io_result and its read_buf. */
@@ -427,10 +447,10 @@
 	int i;
 	for (i = 0; i < periodic_io->info.num_io_entries; ++i) {
 		if (periodic_io->info.io_entries[i].type == LWIS_IO_ENTRY_WRITE_BATCH) {
-			kfree(periodic_io->info.io_entries[i].rw_batch.buf);
+			kvfree(periodic_io->info.io_entries[i].rw_batch.buf);
 		}
 	}
-	kfree(periodic_io->info.io_entries);
+	kvfree(periodic_io->info.io_entries);
 
 	/* resp may not be allocated before the periodic_io is successfully
 	 * submitted */