Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92fc7f9a authored by Mohan Srinivasan's avatar Mohan Srinivasan Committed by Amit Pundir
Browse files

ANDROID: input: keychord: Fix a slab out-of-bounds read.



Fix a slab out of bounds read in keychord_write(), detected by KASAN.

Signed-off-by: default avatarMohan Srinivasan <srmohan@google.com>
Bug: 63962952
Change-Id: Iafef48b5d7283750ac0f39f5aaa767b1c3bf2004

[AmitP: Folded following android-4.9 commit changes into this patch
        a1e4c795e1b6 ("Use %zu to print resid (size_t).")]
Signed-off-by: default avatarAmit Pundir <amit.pundir@linaro.org>
parent 4017c45e
Loading
Loading
Loading
Loading
+22 −6
Original line number Diff line number Diff line
@@ -232,9 +232,11 @@ static ssize_t keychord_write(struct file *file, const char __user *buffer,
{
	struct keychord_device *kdev = file->private_data;
	struct input_keychord *keychords = 0;
	struct input_keychord *keychord, *next, *end;
	struct input_keychord *keychord;
	int ret, i, key;
	unsigned long flags;
	size_t resid = count;
	size_t key_bytes;

	if (count < sizeof(struct input_keychord))
		return -EINVAL;
@@ -265,15 +267,29 @@ static ssize_t keychord_write(struct file *file, const char __user *buffer,
	kdev->head = kdev->tail = 0;

	keychord = keychords;
	end = (struct input_keychord *)((char *)keychord + count);

	while (keychord < end) {
		next = NEXT_KEYCHORD(keychord);
		if (keychord->count <= 0 || next > end) {
	while (resid > 0) {
		/* Is the entire keychord entry header present ? */
		if (resid < sizeof(struct input_keychord)) {
			pr_err("keychord: Insufficient bytes present for header %zu\n",
			       resid);
			goto err_unlock_return;
		}
		resid -= sizeof(struct input_keychord);
		if (keychord->count <= 0) {
			pr_err("keychord: invalid keycode count %d\n",
				keychord->count);
			goto err_unlock_return;
		}
		key_bytes = keychord->count * sizeof(keychord->keycodes[0]);
		/* Do we have all the expected keycodes ? */
		if (resid < key_bytes) {
			pr_err("keychord: Insufficient bytes present for keycount %zu\n",
			       resid);
			goto err_unlock_return;
		}
		resid -= key_bytes;

		if (keychord->version != KEYCHORD_VERSION) {
			pr_err("keychord: unsupported version %d\n",
				keychord->version);
@@ -292,7 +308,7 @@ static ssize_t keychord_write(struct file *file, const char __user *buffer,
		}

		kdev->keychord_count++;
		keychord = next;
		keychord = NEXT_KEYCHORD(keychord);
	}

	kdev->keychords = keychords;