Merge branch 'android-msm-pixel-4.9-rvc' into android-msm-pixel-4.9-rvc-qpr1
Bug: 169729941
Change-Id: I8011f022f6a89ebd92c6d2c516fc9d9e10773dac
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index d696886..2e02443 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -3075,6 +3075,7 @@
kfree(new_entry);
new_entry = NULL;
}
+ put_task_struct(current);
mutex_unlock(&driver->dci_mutex);
return DIAG_DCI_NO_REG;
}
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 7a4c63c..b3f7e6f 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2473,7 +2473,7 @@
return 0;
unmap:
- if (param->type == KGSL_USER_MEM_TYPE_DMABUF) {
+ if (kgsl_memdesc_usermem_type(&entry->memdesc) == KGSL_MEM_ENTRY_ION) {
kgsl_destroy_ion(entry->priv_data);
entry->memdesc.sgt = NULL;
}
@@ -2791,7 +2791,7 @@
return result;
error_attach:
- switch (memtype) {
+ switch (kgsl_memdesc_usermem_type(&entry->memdesc)) {
case KGSL_MEM_ENTRY_ION:
kgsl_destroy_ion(entry->priv_data);
entry->memdesc.sgt = NULL;
@@ -4152,6 +4152,8 @@
if (vma->vm_flags & VM_WRITE)
return -EPERM;
+ vma->vm_flags &= ~VM_MAYWRITE;
+
if (memdesc->size != vma_size) {
KGSL_MEM_ERR(device, "memstore bad size: %d should be %llu\n",
vma_size, memdesc->size);
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 83c7d61..facccba 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -2414,6 +2414,22 @@
return addr;
}
+static bool iommu_addr_in_svm_ranges(struct kgsl_iommu_pt *pt,
+ u64 gpuaddr, u64 size)
+{
+ if ((gpuaddr >= pt->compat_va_start && gpuaddr < pt->compat_va_end) &&
+ ((gpuaddr + size) > pt->compat_va_start &&
+ (gpuaddr + size) <= pt->compat_va_end))
+ return true;
+
+ if ((gpuaddr >= pt->svm_start && gpuaddr < pt->svm_end) &&
+ ((gpuaddr + size) > pt->svm_start &&
+ (gpuaddr + size) <= pt->svm_end))
+ return true;
+
+ return false;
+}
+
static int kgsl_iommu_set_svm_region(struct kgsl_pagetable *pagetable,
uint64_t gpuaddr, uint64_t size)
{
@@ -2421,9 +2437,8 @@
struct kgsl_iommu_pt *pt = pagetable->priv;
struct rb_node *node;
- /* Make sure the requested address doesn't fall in the global range */
- if (ADDR_IN_GLOBAL(pagetable->mmu, gpuaddr) ||
- ADDR_IN_GLOBAL(pagetable->mmu, gpuaddr + size))
+ /* Make sure the requested address doesn't fall out of SVM range */
+ if (!iommu_addr_in_svm_ranges(pt, gpuaddr, size))
return -ENOMEM;
spin_lock(&pagetable->lock);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 671854f..754622f 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1407,6 +1407,17 @@
}
/*
+ * Compute the size of a report.
+ */
+static size_t hid_compute_report_size(struct hid_report *report)
+{
+ if (report->size)
+ return ((report->size - 1) >> 3) + 1;
+
+ return 0;
+}
+
+/*
* Create a report. 'data' has to be allocated using
* hid_alloc_report_buf() so that it has proper size.
*/
@@ -1418,7 +1429,7 @@
if (report->id > 0)
*data++ = report->id;
- memset(data, 0, ((report->size - 1) >> 3) + 1);
+ memset(data, 0, hid_compute_report_size(report));
for (n = 0; n < report->maxfield; n++)
hid_output_field(report->device, report->field[n], data);
}
@@ -1545,7 +1556,7 @@
csize--;
}
- rsize = ((report->size - 1) >> 3) + 1;
+ rsize = hid_compute_report_size(report);
if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE)
rsize = HID_MAX_BUFFER_SIZE - 1;
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 5dbb059..d458202 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1084,6 +1084,10 @@
}
mapped:
+ /* Mapping failed, bail out */
+ if (!bit)
+ return;
+
if (device->driver->input_mapped &&
device->driver->input_mapped(device, hidinput, field, usage,
&bit, &max) < 0) {
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 1207102..258a50e 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -567,6 +567,8 @@
case HID_UP_BUTTON:
code = BTN_MOUSE + ((usage->hid - 1) & HID_USAGE);
hid_map_usage(hi, usage, bit, max, EV_KEY, code);
+ if (!*bit)
+ return -1;
input_set_capability(hi->input, EV_KEY, code);
return 1;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 0299ad5..858915a 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1216,8 +1216,6 @@
rcvd_lstnr.sb_size))
return -EFAULT;
- data->listener.id = rcvd_lstnr.listener_id;
-
ptr_svc = __qseecom_find_svc(rcvd_lstnr.listener_id);
if (ptr_svc) {
if (ptr_svc->unregister_pending == false) {
@@ -1265,6 +1263,7 @@
new_entry->listener_in_use = false;
list_add_tail(&new_entry->list, &qseecom.registered_listener_list_head);
+ data->listener.id = rcvd_lstnr.listener_id;
pr_warn("Service %d is registered\n", rcvd_lstnr.listener_id);
return ret;
}
@@ -1333,6 +1332,11 @@
struct qseecom_registered_listener_list *ptr_svc = NULL;
struct qseecom_unregister_pending_list *entry = NULL;
+ if (data->released) {
+ pr_err("Don't unregister lsnr %d\n", data->listener.id);
+ return -EINVAL;
+ }
+
ptr_svc = __qseecom_find_svc(data->listener.id);
if (!ptr_svc) {
pr_err("Unregiser invalid listener ID %d\n", data->listener.id);
@@ -7845,9 +7849,10 @@
switch (data->type) {
case QSEECOM_LISTENER_SERVICE:
pr_debug("release lsnr svc %d\n", data->listener.id);
- free_private_data = false;
mutex_lock(&listener_access_lock);
ret = qseecom_unregister_listener(data);
+ if (!ret)
+ free_private_data = false;
data->listener.release_called = true;
mutex_unlock(&listener_access_lock);
break;
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 877bb9a..17c8bea 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -877,34 +877,49 @@
* @max: maximal valid usage->code to consider later (out parameter)
* @type: input event type (EV_KEY, EV_REL, ...)
* @c: code which corresponds to this usage and type
+ *
+ * The value pointed to by @bit will be set to NULL if either @type is
+ * an unhandled event type, or if @c is out of range for @type. This
+ * can be used as an error condition.
*/
static inline void hid_map_usage(struct hid_input *hidinput,
struct hid_usage *usage, unsigned long **bit, int *max,
- __u8 type, __u16 c)
+ __u8 type, unsigned int c)
{
struct input_dev *input = hidinput->input;
-
- usage->type = type;
- usage->code = c;
+ unsigned long *bmap = NULL;
+ unsigned int limit = 0;
switch (type) {
case EV_ABS:
- *bit = input->absbit;
- *max = ABS_MAX;
+ bmap = input->absbit;
+ limit = ABS_MAX;
break;
case EV_REL:
- *bit = input->relbit;
- *max = REL_MAX;
+ bmap = input->relbit;
+ limit = REL_MAX;
break;
case EV_KEY:
- *bit = input->keybit;
- *max = KEY_MAX;
+ bmap = input->keybit;
+ limit = KEY_MAX;
break;
case EV_LED:
- *bit = input->ledbit;
- *max = LED_MAX;
+ bmap = input->ledbit;
+ limit = LED_MAX;
break;
}
+
+ if (unlikely(c > limit || !bmap)) {
+ pr_warn_ratelimited("%s: Invalid code %d type %d\n",
+ input->name, c, type);
+ *bit = NULL;
+ return;
+ }
+
+ usage->type = type;
+ usage->code = c;
+ *max = limit;
+ *bit = bmap;
}
/**
@@ -918,7 +933,8 @@
__u8 type, __u16 c)
{
hid_map_usage(hidinput, usage, bit, max, type, c);
- clear_bit(c, *bit);
+ if (*bit)
+ clear_bit(usage->code, *bit);
}
/**