Merge branch 'android-msm-pixel-4.9-qt-qpr1' into android-msm-pixel-4.9-qt-qpr2
Mar 2020.1
Bug: 147118103
Change-Id: I0e5a7869e63d083068baf3d8aad5a4b1c61885c3
Signed-off-by: Eva Huang <evahuang@google.com>
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 3b39c54..acab11d 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3486,7 +3486,7 @@ static void binder_transaction(struct binder_proc *proc,
binder_size_t parent_offset;
struct binder_fd_array_object *fda =
to_binder_fd_array_object(hdr);
- size_t num_valid = (buffer_offset - off_start_offset) *
+ size_t num_valid = (buffer_offset - off_start_offset) /
sizeof(binder_size_t);
struct binder_buffer_object *parent =
binder_validate_ptr(target_proc, t->buffer,
@@ -3560,7 +3560,7 @@ static void binder_transaction(struct binder_proc *proc,
t->buffer->user_data + sg_buf_offset;
sg_buf_offset += ALIGN(bp->length, sizeof(u64));
- num_valid = (buffer_offset - off_start_offset) *
+ num_valid = (buffer_offset - off_start_offset) /
sizeof(binder_size_t);
ret = binder_fixup_parent(t, thread, bp,
off_start_offset,
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index a799fdf..f74a4d2 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -985,6 +985,7 @@ void extract_dci_pkt_rsp(unsigned char *buf, int len, int data_source,
unsigned char *temp = buf;
int save_req_uid = 0;
struct diag_dci_pkt_rsp_header_t pkt_rsp_header;
+ int header_len = sizeof(struct diag_dci_pkt_rsp_header_t);
if (!buf) {
pr_err("diag: Invalid pointer in %s\n", __func__);
@@ -1045,14 +1046,12 @@ void extract_dci_pkt_rsp(unsigned char *buf, int len, int data_source,
mutex_lock(&rsp_buf->data_mutex);
/*
* Check if we can fit the data in the rsp buffer. The total length of
- * the rsp is the rsp length (write_len) + DCI_PKT_RSP_TYPE header (int)
- * + field for length (int) + delete_flag (uint8_t)
+ * the rsp is the rsp length (write_len) + dci response packet header
+ * length (sizeof(struct diag_dci_pkt_rsp_header_t))
*/
- if ((rsp_buf->data_len + 9 + rsp_len) > rsp_buf->capacity) {
+ if ((rsp_buf->data_len + header_len + rsp_len) > rsp_buf->capacity) {
pr_alert("diag: create capacity for pkt rsp\n");
- rsp_buf->capacity += 9 + rsp_len;
- temp_buf = krealloc(rsp_buf->data, rsp_buf->capacity,
- GFP_KERNEL);
+ temp_buf = vzalloc(rsp_buf->capacity + header_len + rsp_len);
if (!temp_buf) {
pr_err("diag: DCI realloc failed\n");
mutex_unlock(&rsp_buf->data_mutex);
@@ -1060,6 +1059,10 @@ void extract_dci_pkt_rsp(unsigned char *buf, int len, int data_source,
mutex_unlock(&driver->dci_mutex);
return;
}
+ rsp_buf->capacity += header_len + rsp_len;
+ if (rsp_buf->capacity > rsp_buf->data_len)
+ memcpy(temp_buf, rsp_buf->data, rsp_buf->data_len);
+ vfree(rsp_buf->data);
rsp_buf->data = temp_buf;
}
@@ -1069,9 +1072,8 @@ void extract_dci_pkt_rsp(unsigned char *buf, int len, int data_source,
pkt_rsp_header.length = rsp_len + sizeof(int);
pkt_rsp_header.delete_flag = delete_flag;
pkt_rsp_header.uid = save_req_uid;
- memcpy(rsp_buf->data + rsp_buf->data_len, &pkt_rsp_header,
- sizeof(struct diag_dci_pkt_rsp_header_t));
- rsp_buf->data_len += sizeof(struct diag_dci_pkt_rsp_header_t);
+ memcpy(rsp_buf->data + rsp_buf->data_len, &pkt_rsp_header, header_len);
+ rsp_buf->data_len += header_len;
memcpy(rsp_buf->data + rsp_buf->data_len, temp, rsp_len);
rsp_buf->data_len += rsp_len;
rsp_buf->data_source = data_source;
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 795ceb6..bac4a2f 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2019, 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
@@ -641,7 +641,8 @@ static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len,
struct diag_build_mask_req_t *req = NULL;
struct diag_msg_build_mask_t rsp;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) {
+ if (!src_buf || !dest_buf || dest_len <= 0 ||
+ src_len < sizeof(struct diag_build_mask_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d\n",
__func__, src_buf, src_len, dest_buf, dest_len);
return -EINVAL;
@@ -702,8 +703,8 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 ||
+ !mask_info || (src_len < sizeof(struct diag_build_mask_req_t))) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -781,8 +782,8 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ (src_len < sizeof(struct diag_msg_build_mask_t))) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -866,7 +867,9 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
break;
}
mask_size = mask_size * sizeof(uint32_t);
- memcpy(mask->ptr + offset, src_buf + header_len, mask_size);
+ if (mask_size && src_len >= header_len + mask_size)
+ memcpy(mask->ptr + offset, src_buf + header_len,
+ mask_size);
mutex_unlock(&mask->lock);
mask_info->status = DIAG_CTRL_MASK_VALID;
break;
@@ -929,8 +932,8 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ (src_len < sizeof(struct diag_msg_config_rsp_t))) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1053,8 +1056,8 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
mutex_lock(&driver->md_session_lock);
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &event_mask : info->event_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ src_len < sizeof(struct diag_event_mask_config_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1077,7 +1080,8 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
}
mutex_lock(&mask_info->lock);
- memcpy(mask_info->ptr, src_buf + header_len, mask_len);
+ if (src_len >= header_len + mask_len)
+ memcpy(mask_info->ptr, src_buf + header_len, mask_len);
mask_info->status = DIAG_CTRL_MASK_VALID;
mutex_unlock(&mask_info->lock);
mutex_unlock(&driver->md_session_lock);
@@ -1126,8 +1130,8 @@ static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len,
mutex_lock(&driver->md_session_lock);
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &event_mask : info->event_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || src_len <= sizeof(uint8_t) ||
+ dest_len <= 0 || !mask_info) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1200,8 +1204,8 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &log_mask : info->log_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ src_len < sizeof(struct diag_log_config_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1342,8 +1346,8 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &log_mask : info->log_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
+ if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
+ src_len < sizeof(struct diag_log_config_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1417,7 +1421,7 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
mask->range_tools = mask_size;
}
req->num_items = mask->num_items_tools;
- if (mask_size > 0)
+ if (mask_size > 0 && src_len >= read_len + mask_size)
memcpy(mask->ptr, src_buf + read_len, mask_size);
DIAG_LOG(DIAG_DEBUG_MASKS,
"copying log mask, e %d num %d range %d size %d\n",
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 60e318e..919757d 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1165,15 +1165,19 @@ static int diag_process_userspace_remote(int proc, void *buf, int len)
}
#endif
-static int mask_request_validate(unsigned char mask_buf[])
+static int mask_request_validate(unsigned char mask_buf[], int len)
{
uint8_t packet_id;
uint8_t subsys_id;
uint16_t ss_cmd;
+ if (len <= 0)
+ return 0;
packet_id = mask_buf[0];
if (packet_id == DIAG_CMD_DIAG_SUBSYS_DELAY) {
+ if (len < 2*sizeof(uint8_t) + sizeof(uint16_t))
+ return 0;
subsys_id = mask_buf[1];
ss_cmd = *(uint16_t *)(mask_buf + 2);
switch (subsys_id) {
@@ -1189,6 +1193,8 @@ static int mask_request_validate(unsigned char mask_buf[])
return 0;
}
} else if (packet_id == 0x4B) {
+ if (len < 2*sizeof(uint8_t) + sizeof(uint16_t))
+ return 0;
subsys_id = mask_buf[1];
ss_cmd = *(uint16_t *)(mask_buf + 2);
/* Packets with SSID which are allowed */
@@ -3040,7 +3046,8 @@ static int diag_user_process_raw_data(const char __user *buf, int len)
}
/* Check for proc_type */
- remote_proc = diag_get_remote(*(int *)user_space_data);
+ if (len >= sizeof(int))
+ remote_proc = diag_get_remote(*(int *)user_space_data);
if (remote_proc) {
token_offset = sizeof(int);
if (len <= MIN_SIZ_ALLOW) {
@@ -3054,7 +3061,7 @@ static int diag_user_process_raw_data(const char __user *buf, int len)
}
if (driver->mask_check) {
if (!mask_request_validate(user_space_data +
- token_offset)) {
+ token_offset, len)) {
pr_alert("diag: mask request Invalid\n");
diagmem_free(driver, user_space_data, mempool);
user_space_data = NULL;
@@ -3132,7 +3139,7 @@ static int diag_user_process_userspace_data(const char __user *buf, int len)
/* Check masks for On-Device logging */
if (driver->mask_check) {
if (!mask_request_validate(driver->user_space_data_buf +
- token_offset)) {
+ token_offset, len)) {
pr_alert("diag: mask request Invalid\n");
return -EFAULT;
}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index 012a15a..664fd315 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, 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
@@ -1098,6 +1098,9 @@ static ssize_t debugfs_dump_info_read(struct file *file,
"\tClock master = %s\n",
display->ctrl[display->clk_master_idx].ctrl->name);
+ if (len > user_len)
+ len = user_len;
+
if (copy_to_user(user_buf, buf, len)) {
kfree(buf);
return -EFAULT;
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index a634d98..c26ab8f 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, 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
@@ -1411,6 +1411,22 @@ int adreno_dispatcher_queue_cmds(struct kgsl_device_private *dev_priv,
user_ts = *timestamp;
+ /*
+ * If there is only one drawobj in the array and it is of
+ * type SYNCOBJ_TYPE, skip comparing user_ts as it can be 0
+ */
+ if (!(count == 1 && drawobj[0]->type == SYNCOBJ_TYPE) &&
+ (drawctxt->base.flags & KGSL_CONTEXT_USER_GENERATED_TS)) {
+ /*
+ * User specified timestamps need to be greater than the last
+ * issued timestamp in the context
+ */
+ if (timestamp_cmp(drawctxt->timestamp, user_ts) >= 0) {
+ spin_unlock(&drawctxt->lock);
+ return -ERANGE;
+ }
+ }
+
for (i = 0; i < count; i++) {
switch (drawobj[i]->type) {
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 7d4b70a..1a9a2db 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -3336,11 +3336,15 @@ long kgsl_ioctl_sparse_phys_alloc(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
struct kgsl_process_private *process = dev_priv->process_priv;
+ struct kgsl_device *device = dev_priv->device;
struct kgsl_sparse_phys_alloc *param = data;
struct kgsl_mem_entry *entry;
int ret;
int id;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
ret = _sparse_alloc_param_sanity_check(param->size, param->pagesize);
if (ret)
return ret;
@@ -3419,9 +3423,13 @@ long kgsl_ioctl_sparse_phys_free(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
struct kgsl_process_private *process = dev_priv->process_priv;
+ struct kgsl_device *device = dev_priv->device;
struct kgsl_sparse_phys_free *param = data;
struct kgsl_mem_entry *entry;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
entry = kgsl_sharedmem_find_id_flags(process, param->id,
KGSL_MEMFLAGS_SPARSE_PHYS);
if (entry == NULL)
@@ -3451,10 +3459,14 @@ long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
struct kgsl_process_private *private = dev_priv->process_priv;
+ struct kgsl_device *device = dev_priv->device;
struct kgsl_sparse_virt_alloc *param = data;
struct kgsl_mem_entry *entry;
int ret;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
ret = _sparse_alloc_param_sanity_check(param->size, param->pagesize);
if (ret)
return ret;
@@ -3494,9 +3506,13 @@ long kgsl_ioctl_sparse_virt_free(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
struct kgsl_process_private *process = dev_priv->process_priv;
+ struct kgsl_device *device = dev_priv->device;
struct kgsl_sparse_virt_free *param = data;
struct kgsl_mem_entry *entry = NULL;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
entry = kgsl_sharedmem_find_id_flags(process, param->id,
KGSL_MEMFLAGS_SPARSE_VIRT);
if (entry == NULL)
@@ -3843,6 +3859,7 @@ long kgsl_ioctl_sparse_bind(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
struct kgsl_process_private *private = dev_priv->process_priv;
+ struct kgsl_device *device = dev_priv->device;
struct kgsl_sparse_bind *param = data;
struct kgsl_sparse_binding_object obj;
struct kgsl_mem_entry *virt_entry;
@@ -3851,6 +3868,9 @@ long kgsl_ioctl_sparse_bind(struct kgsl_device_private *dev_priv,
int ret = 0;
int i = 0;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
ptr = (void __user *) (uintptr_t) param->list;
if (param->size > sizeof(struct kgsl_sparse_binding_object) ||
@@ -3906,6 +3926,9 @@ long kgsl_ioctl_gpu_sparse_command(struct kgsl_device_private *dev_priv,
long result;
unsigned int i = 0;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
/* Make sure sparse and syncpoint count isn't too big */
if (param->numsparse > KGSL_MAX_SPARSE ||
param->numsyncs > KGSL_MAX_SYNCPOINTS)
@@ -4661,6 +4684,9 @@ int kgsl_device_platform_probe(struct kgsl_device *device)
/* Initialize logging first, so that failures below actually print. */
kgsl_device_debugfs_init(device);
+ /* Disable the sparse ioctl invocation as they are not used */
+ device->flags &= ~KGSL_FLAG_SPARSE;
+
status = kgsl_pwrctrl_init(device);
if (status)
goto error;
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index c8c6456..585ad20 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2019, 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
@@ -66,6 +66,7 @@ enum kgsl_event_results {
};
#define KGSL_FLAG_WAKE_ON_TOUCH BIT(0)
+#define KGSL_FLAG_SPARSE BIT(1)
/*
* "list" of event types for ftrace symbolic magic
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 37a6526..6752b0f 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, 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
@@ -40,6 +40,7 @@
#define FIRMWARE_SIZE 0X00A00000
#define REG_ADDR_OFFSET_BITMASK 0x000FFFFF
#define QDSS_IOVA_START 0x80001000
+#define MIN_PAYLOAD_SIZE 3
static struct hal_device_data hal_ctxt;
@@ -2969,25 +2970,55 @@ static void __flush_debug_queue(struct venus_hfi_device *device, u8 *packet)
log_level = VIDC_ERR;
}
+#define SKIP_INVALID_PKT(pkt_size, payload_size, pkt_hdr_size) ({ \
+ if (pkt_size < pkt_hdr_size || \
+ payload_size < MIN_PAYLOAD_SIZE || \
+ payload_size > \
+ (pkt_size - pkt_hdr_size + sizeof(u8))) { \
+ dprintk(VIDC_ERR, \
+ "%s: invalid msg size - %d\n", \
+ __func__, pkt->msg_size); \
+ continue; \
+ } \
+ })
+
while (!__iface_dbgq_read(device, packet)) {
- struct hfi_msg_sys_coverage_packet *pkt =
- (struct hfi_msg_sys_coverage_packet *) packet;
+ struct hfi_packet_header *pkt =
+ (struct hfi_packet_header *) packet;
+
+ if (pkt->size < sizeof(struct hfi_packet_header)) {
+ dprintk(VIDC_ERR, "Invalid pkt size - %s\n",
+ __func__);
+ continue;
+ }
if (pkt->packet_type == HFI_MSG_SYS_COV) {
+ struct hfi_msg_sys_coverage_packet *pkt =
+ (struct hfi_msg_sys_coverage_packet *) packet;
int stm_size = 0;
+ SKIP_INVALID_PKT(pkt->size,
+ pkt->msg_size, sizeof(*pkt));
+
stm_size = stm_log_inv_ts(0, 0,
pkt->rg_msg_data, pkt->msg_size);
if (stm_size == 0)
dprintk(VIDC_ERR,
"In %s, stm_log returned size of 0\n",
__func__);
- } else {
+
+ } else if (pkt->packet_type == HFI_MSG_SYS_DEBUG) {
struct hfi_msg_sys_debug_packet *pkt =
(struct hfi_msg_sys_debug_packet *) packet;
+
+ SKIP_INVALID_PKT(pkt->size,
+ pkt->msg_size, sizeof(*pkt));
+
+ pkt->rg_msg_data[pkt->msg_size-1] = '\0';
dprintk(log_level, "%s", pkt->rg_msg_data);
}
}
+#undef SKIP_INVALID_PKT
if (local_packet)
kfree(packet);
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index dd94a88..77a2cc0 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, 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
@@ -900,6 +900,11 @@ struct vidc_hal_session_cmd_pkt {
u32 session_id;
};
+struct hfi_packet_header {
+ u32 size;
+ u32 packet_type;
+};
+
struct hfi_cmd_sys_init_packet {
u32 size;
u32 packet_type;
diff --git a/drivers/media/platform/msm/vidc_3x/venus_hfi.c b/drivers/media/platform/msm/vidc_3x/venus_hfi.c
index b83606a..d30eaa6 100644
--- a/drivers/media/platform/msm/vidc_3x/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc_3x/venus_hfi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, 2018-2019 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
@@ -38,6 +38,7 @@
#define FIRMWARE_SIZE 0X00A00000
#define REG_ADDR_OFFSET_BITMASK 0x000FFFFF
#define QDSS_IOVA_START 0x80001000
+#define MIN_PAYLOAD_SIZE 3
static struct hal_device_data hal_ctxt;
@@ -3382,24 +3383,55 @@ static void __flush_debug_queue(struct venus_hfi_device *device, u8 *packet)
local_packet = true;
}
+#define SKIP_INVALID_PKT(pkt_size, payload_size, pkt_hdr_size) ({ \
+ if (pkt_size < pkt_hdr_size || \
+ payload_size < MIN_PAYLOAD_SIZE || \
+ payload_size > \
+ (pkt_size - pkt_hdr_size + sizeof(u8))) { \
+ dprintk(VIDC_ERR, \
+ "%s: invalid msg size - %d\n", \
+ __func__, pkt->msg_size); \
+ continue; \
+ } \
+ })
+
while (!__iface_dbgq_read(device, packet)) {
- struct hfi_msg_sys_coverage_packet *pkt =
- (struct hfi_msg_sys_coverage_packet *) packet;
+ struct hfi_packet_header *pkt =
+ (struct hfi_packet_header *) packet;
+
+ if (pkt->size < sizeof(struct hfi_packet_header)) {
+ dprintk(VIDC_ERR, "Invalid pkt size - %s\n",
+ __func__);
+ continue;
+ }
+
if (pkt->packet_type == HFI_MSG_SYS_COV) {
+ struct hfi_msg_sys_coverage_packet *pkt =
+ (struct hfi_msg_sys_coverage_packet *) packet;
int stm_size = 0;
+ SKIP_INVALID_PKT(pkt->size,
+ pkt->msg_size, sizeof(*pkt));
+
stm_size = stm_log_inv_ts(0, 0,
pkt->rg_msg_data, pkt->msg_size);
if (stm_size == 0)
dprintk(VIDC_ERR,
"In %s, stm_log returned size of 0\n",
__func__);
- } else {
+
+ } else if (pkt->packet_type == HFI_MSG_SYS_DEBUG) {
struct hfi_msg_sys_debug_packet *pkt =
(struct hfi_msg_sys_debug_packet *) packet;
+
+ SKIP_INVALID_PKT(pkt->size,
+ pkt->msg_size, sizeof(*pkt));
+
+ pkt->rg_msg_data[pkt->msg_size-1] = '\0';
dprintk(VIDC_FW, "%s", pkt->rg_msg_data);
}
}
+#undef SKIP_INVALID_PKT
if (local_packet)
kfree(packet);
diff --git a/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h
index 39904a5..c09cf84c 100644
--- a/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, 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
@@ -974,6 +974,11 @@ struct vidc_hal_session_cmd_pkt {
u32 session_id;
};
+struct hfi_packet_header {
+ u32 size;
+ u32 packet_type;
+};
+
struct hfi_cmd_sys_init_packet {
u32 size;
u32 packet_type;
diff --git a/drivers/soc/qcom/secure_buffer.c b/drivers/soc/qcom/secure_buffer.c
index 1c8bc51..b691df6 100644
--- a/drivers/soc/qcom/secure_buffer.c
+++ b/drivers/soc/qcom/secure_buffer.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2011 Google, Inc
- * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017,2019, 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
@@ -55,8 +55,8 @@ struct dest_vm_and_perm_info {
u32 ctx_size;
};
-static void *qcom_secure_mem;
-#define QCOM_SECURE_MEM_SIZE (512*1024)
+#define BATCH_MAX_SIZE SZ_2M
+#define BATCH_MAX_SECTIONS 32
static int secure_buffer_change_chunk(u32 chunks,
u32 nchunks,
@@ -215,42 +215,67 @@ populate_dest_info(int *dest_vmids, int nelements, int *dest_perms,
}
/* Must hold secure_buffer_mutex while allocated buffer is in use */
-static struct mem_prot_info *get_info_list_from_table(struct sg_table *table,
- size_t *size_in_bytes)
+static unsigned int get_batches_from_sgl(struct mem_prot_info *sg_table_copy,
+ struct scatterlist *sgl,
+ struct scatterlist **next_sgl)
{
- int i;
- struct scatterlist *sg;
- struct mem_prot_info *info;
- size_t size;
+ u64 batch_size = 0;
+ unsigned int i = 0;
+ struct scatterlist *curr_sgl = sgl;
- size = table->nents * sizeof(*info);
+ /* Ensure no zero size batches */
+ do {
+ sg_table_copy[i].addr = page_to_phys(sg_page(curr_sgl));
+ sg_table_copy[i].size = curr_sgl->length;
+ batch_size += sg_table_copy[i].size;
+ curr_sgl = sg_next(curr_sgl);
+ i++;
+ } while (curr_sgl && i < BATCH_MAX_SECTIONS &&
+ curr_sgl->length + batch_size < BATCH_MAX_SIZE);
- if (size >= QCOM_SECURE_MEM_SIZE) {
- pr_err("%s: Not enough memory allocated. Required size %zd\n",
- __func__, size);
- return NULL;
- }
-
- if (!qcom_secure_mem) {
- pr_err("%s is not functional as qcom_secure_mem is not allocated.\n",
- __func__);
- return NULL;
- }
-
- /* "Allocate" it */
- info = qcom_secure_mem;
-
- for_each_sg(table->sgl, sg, table->nents, i) {
- info[i].addr = page_to_phys(sg_page(sg));
- info[i].size = sg->length;
- }
-
- *size_in_bytes = size;
- return info;
+ *next_sgl = curr_sgl;
+ return i;
}
-#define BATCH_MAX_SIZE SZ_2M
-#define BATCH_MAX_SECTIONS 32
+static int batched_hyp_assign(struct sg_table *table, struct scm_desc *desc)
+{
+ unsigned int entries_size;
+ unsigned int batch_start = 0;
+ unsigned int batches_processed;
+ struct scatterlist *curr_sgl = table->sgl;
+ struct scatterlist *next_sgl;
+ int ret = 0;
+ struct mem_prot_info *sg_table_copy = kcalloc(BATCH_MAX_SECTIONS,
+ sizeof(*sg_table_copy),
+ GFP_KERNEL);
+
+ if (!sg_table_copy)
+ return -ENOMEM;
+
+ while (batch_start < table->nents) {
+ batches_processed = get_batches_from_sgl(sg_table_copy,
+ curr_sgl, &next_sgl);
+ curr_sgl = next_sgl;
+ entries_size = batches_processed * sizeof(*sg_table_copy);
+ dmac_flush_range(sg_table_copy,
+ (void *)sg_table_copy + entries_size);
+ desc->args[0] = virt_to_phys(sg_table_copy);
+ desc->args[1] = entries_size;
+
+ ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP,
+ MEM_PROT_ASSIGN_ID), desc);
+ if (ret) {
+ pr_info("%s: Failed to assign memory protection, ret = %d\n",
+ __func__, ret);
+ break;
+ }
+
+ batch_start += batches_processed;
+ }
+
+ kfree(sg_table_copy);
+ return ret;
+}
int hyp_assign_table(struct sg_table *table,
u32 *source_vm_list, int source_nelems,
@@ -263,11 +288,10 @@ int hyp_assign_table(struct sg_table *table,
size_t source_vm_copy_size;
struct dest_vm_and_perm_info *dest_vm_copy;
size_t dest_vm_copy_size;
- struct mem_prot_info *sg_table_copy;
- size_t sg_table_copy_size;
- int batch_start, batch_end;
- u64 batch_size;
+ if (!table || !table->sgl || !source_vm_list || !source_nelems ||
+ !dest_vmids || !dest_perms || !dest_nelems)
+ return -EINVAL;
/*
* We can only pass cache-aligned sizes to hypervisor, so we need
@@ -285,19 +309,11 @@ int hyp_assign_table(struct sg_table *table,
&dest_vm_copy_size);
if (!dest_vm_copy) {
ret = -ENOMEM;
- goto out_free;
+ goto out_free_source;
}
mutex_lock(&secure_buffer_mutex);
- sg_table_copy = get_info_list_from_table(table, &sg_table_copy_size);
- if (!sg_table_copy) {
- ret = -ENOMEM;
- goto out_unlock;
- }
-
- desc.args[0] = virt_to_phys(sg_table_copy);
- desc.args[1] = sg_table_copy_size;
desc.args[2] = virt_to_phys(source_vm_copy);
desc.args[3] = source_vm_copy_size;
desc.args[4] = virt_to_phys(dest_vm_copy);
@@ -309,50 +325,14 @@ int hyp_assign_table(struct sg_table *table,
dmac_flush_range(source_vm_copy,
(void *)source_vm_copy + source_vm_copy_size);
- dmac_flush_range(sg_table_copy,
- (void *)sg_table_copy + sg_table_copy_size);
dmac_flush_range(dest_vm_copy,
(void *)dest_vm_copy + dest_vm_copy_size);
- batch_start = 0;
- while (batch_start < table->nents) {
- /* Ensure no size zero batches */
- batch_size = sg_table_copy[batch_start].size;
- batch_end = batch_start + 1;
- while (1) {
- u64 size;
+ ret = batched_hyp_assign(table, &desc);
- if (batch_end >= table->nents)
- break;
- if (batch_end - batch_start >= BATCH_MAX_SECTIONS)
- break;
-
- size = sg_table_copy[batch_end].size;
- if (size + batch_size >= BATCH_MAX_SIZE)
- break;
-
- batch_size += size;
- batch_end++;
- }
-
- desc.args[0] = virt_to_phys(&sg_table_copy[batch_start]);
- desc.args[1] = (batch_end - batch_start) *
- sizeof(sg_table_copy[0]);
-
- ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP,
- MEM_PROT_ASSIGN_ID), &desc);
- if (ret) {
- pr_info("%s: Failed to assign memory protection, ret = %d\n",
- __func__, ret);
- break;
- }
- batch_start = batch_end;
- }
-
-out_unlock:
mutex_unlock(&secure_buffer_mutex);
kfree(dest_vm_copy);
-out_free:
+out_free_source:
kfree(source_vm_copy);
return ret;
}
@@ -435,23 +415,3 @@ bool msm_secure_v2_is_supported(void)
return (scm_get_feat_version(FEATURE_ID_CP) >=
MAKE_CP_VERSION(1, 1, 0));
}
-
-static int __init alloc_secure_shared_memory(void)
-{
- int ret = 0;
- dma_addr_t dma_handle;
-
- qcom_secure_mem = kzalloc(QCOM_SECURE_MEM_SIZE, GFP_KERNEL);
- if (!qcom_secure_mem) {
- /* Fallback to CMA-DMA memory */
- qcom_secure_mem = dma_alloc_coherent(NULL, QCOM_SECURE_MEM_SIZE,
- &dma_handle, GFP_KERNEL);
- if (!qcom_secure_mem) {
- pr_err("Couldn't allocate memory for secure use-cases. hyp_assign_table will not work\n");
- return -ENOMEM;
- }
- }
-
- return ret;
-}
-pure_initcall(alloc_secure_shared_memory);
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index d9baac6..a866332 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -424,6 +424,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
dwc->ep0_usb_req.request.length = sizeof(*response_pkt);
dwc->ep0_usb_req.request.buf = dwc->setup_buf;
dwc->ep0_usb_req.request.complete = dwc3_ep0_status_cmpl;
+ dwc->ep0_usb_req.request.dma = DMA_ERROR_CODE;
return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
}
@@ -760,6 +761,7 @@ static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
dwc->ep0_usb_req.request.length = dep->endpoint.maxpacket;
dwc->ep0_usb_req.request.buf = dwc->setup_buf;
dwc->ep0_usb_req.request.complete = dwc3_ep0_set_sel_cmpl;
+ dwc->ep0_usb_req.request.dma = DMA_ERROR_CODE;
return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
}
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index d3e5269..195fd68 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, 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
@@ -998,7 +998,8 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p,
static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id)
{
struct buf_data *pcmds = file->private_data;
- int blen, len, i;
+ unsigned int len;
+ int blen, i;
char *buf, *bufp, *bp;
struct dsi_ctrl_hdr *dchdr;
@@ -1042,7 +1043,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id)
while (len >= sizeof(*dchdr)) {
dchdr = (struct dsi_ctrl_hdr *)bp;
dchdr->dlen = ntohs(dchdr->dlen);
- if (dchdr->dlen > len || dchdr->dlen < 0) {
+ if (dchdr->dlen > (len - sizeof(*dchdr)) || dchdr->dlen < 0) {
pr_err("%s: dtsi cmd=%x error, len=%d\n",
__func__, dchdr->dtype, dchdr->dlen);
kfree(buf);