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

Commit 2c4dadbb authored by rbandi's avatar rbandi
Browse files

HID: qvr: Fix for potential heap buffer overflow



Value of sensor->calib_data_len could be changed between
the reads causing potential heap buffer overflow.
When a 0 length is passed to kzalloc, non-NULL pointer
is returned, but this pointer is invalid.

Change-Id: Ie6ed76f63f7a433728e2292222ba9716c3a02635
Signed-off-by: default avatarrbandi <rohitbandi@codeaurora.org>
parent b482a807
Loading
Loading
Loading
Loading
+16 −7
Original line number Diff line number Diff line
@@ -145,7 +145,7 @@ static int read_calibration_len(void)
	return sensor->calib_data_len;
}

static uint8_t *read_calibration_data(void)
static uint8_t *read_calibration_data(int calib_data_len)
{
	struct qvr_external_sensor *sensor = &qvr_external_sensor;
	__u8 *hid_buf;
@@ -153,7 +153,7 @@ static uint8_t *read_calibration_data(void)
	uint8_t read_len;
	uint8_t *complete_data = NULL;

	if (sensor->calib_data_len < 0) {
	if (calib_data_len <= 0) {
		pr_err("%s: calibration data len missing\n", __func__);
		return NULL;
	}
@@ -165,13 +165,13 @@ static uint8_t *read_calibration_data(void)
	hid_buf[0] = QVR_HID_REPORT_ID_CAL;
	hid_buf[1] = QVR_CMD_ID_CALIBRATION_BLOCK_DATA;

	complete_data = kzalloc(sensor->calib_data_len, GFP_KERNEL);
	complete_data = kzalloc(calib_data_len, GFP_KERNEL);
	if (complete_data == NULL) {
		kfree(hid_buf);
		return NULL;
	}
	total_read_len = 0;
	while (total_read_len < sensor->calib_data_len) {
	while (total_read_len < calib_data_len) {
		sensor->calib_data_recv = 0;
		ret = hid_hw_raw_request(sensor->hdev, hid_buf[0],
			hid_buf,
@@ -193,7 +193,14 @@ static uint8_t *read_calibration_data(void)
			return NULL;
		}
		read_len = sensor->calib_data_pkt[2];
		if (total_read_len > sensor->calib_data_len - read_len) {

		if (read_len <= 0) {
			pr_err("%s:Viewer returned non positve length\n", __func__);
			kfree(hid_buf);
			kfree(complete_data);
			return NULL;
		}
		if (total_read_len > calib_data_len - read_len) {
			kfree(hid_buf);
			kfree(complete_data);
			return NULL;
@@ -543,6 +550,7 @@ static long qvr_external_sensor_ioctl(struct file *file, unsigned int cmd,
	struct qvr_external_sensor *sensor = &qvr_external_sensor;
	struct qvr_calib_data data;
	uint8_t *calib_data;
	int lcalib_data_len;
	void __user *argp = (void __user *)arg;
	int ret;

@@ -568,13 +576,14 @@ static long qvr_external_sensor_ioctl(struct file *file, unsigned int cmd,
			return -EFAULT;
		return 0;
	case QVR_READ_CALIB_DATA:
		lcalib_data_len = sensor->calib_data_len;
		sensor->calib_data_recv = 0;
		calib_data = read_calibration_data();
		calib_data = read_calibration_data(lcalib_data_len);
		if (calib_data == NULL)
			return -ENOMEM;
		data.data_ptr = (__u64)arg;
		if (copy_to_user(u64_to_user_ptr(data.data_ptr), calib_data,
				sensor->calib_data_len)) {
				lcalib_data_len)) {
			kfree(calib_data);
			return -EFAULT;
		}