diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2019-08-13 07:28:13 -0700 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2019-08-13 07:28:13 -0700 |
commit | 2395ba8e7c0d08538f32933de4ee5e1400948d16 (patch) | |
tree | 3ad5ca9efc2d9d8c6eb7fbef4cc04136982cf053 | |
parent | e5fa5bc754a84b0e1fbf8f24db1e788f04ac25cd (diff) | |
parent | c67c59a61a1e7f06e6a39e13a3d063b299b0ffaf (diff) |
Merge c67c59a61a1e7f06e6a39e13a3d063b299b0ffaf on remote branchLA.UM.6.8.2.r1-02100-SDM710.0
Change-Id: I6414345160fe338a3f2a8476896dcf47b56794f7
-rw-r--r-- | arch/arm64/mm/init.c | 2 | ||||
-rw-r--r-- | drivers/char/adsprpc.c | 260 | ||||
-rw-r--r-- | drivers/char/diag/diag_dci.c | 12 | ||||
-rw-r--r-- | drivers/char/diag/diag_dci.h | 4 | ||||
-rw-r--r-- | drivers/gpu/msm/kgsl_drawobj.c | 39 | ||||
-rw-r--r-- | drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c | 22 | ||||
-rw-r--r-- | drivers/media/platform/msm/vidc/hfi_response_handler.c | 184 | ||||
-rw-r--r-- | drivers/media/platform/msm/vidc_3x/hfi_response_handler.c | 167 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufs-qcom-ice.c | 36 | ||||
-rw-r--r-- | drivers/tty/serial/msm_geni_serial.c | 6 | ||||
-rw-r--r-- | fs/ext4/move_extent.c | 13 |
11 files changed, 580 insertions, 165 deletions
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 2b35b67540b9..0421d0872f95 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -271,7 +271,7 @@ void __init arm64_memblock_init(void) * memory spans, randomize the linear region as well. */ if (memstart_offset_seed > 0 && range >= ARM64_MEMSTART_ALIGN) { - range = range / ARM64_MEMSTART_ALIGN + 1; + range /= ARM64_MEMSTART_ALIGN; memstart_addr -= ARM64_MEMSTART_ALIGN * ((range * memstart_offset_seed) >> 16); } diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index ad507e3c1a65..f40a5b9c4a5c 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -60,7 +60,9 @@ #define FASTRPC_ENOSUCH 39 #define VMID_SSC_Q6 5 #define VMID_ADSP_Q6 6 -#define DEBUGFS_SIZE 1024 +#define DEBUGFS_SIZE 3072 +#define UL_SIZE 25 +#define PID_SIZE 10 #define AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME "audio_pdr_adsprpc" #define AUDIO_PDR_ADSP_SERVICE_NAME "avs/audio" @@ -404,6 +406,7 @@ struct fastrpc_file { int refcount; /* Identifies the device (MINOR_NUM_DEV / MINOR_NUM_SECURE_DEV) */ int dev_minor; + char *debug_buf; }; static struct fastrpc_apps gfa; @@ -2921,6 +2924,7 @@ static int fastrpc_file_free(struct fastrpc_file *fl) spin_lock(&fl->apps->hlock); hlist_del_init(&fl->hn); spin_unlock(&fl->apps->hlock); + kfree(fl->debug_buf); if (!fl->sctx) { kfree(fl); @@ -3109,105 +3113,208 @@ static int fastrpc_debugfs_open(struct inode *inode, struct file *filp) static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, size_t count, loff_t *position) { + struct fastrpc_apps *me = &gfa; struct fastrpc_file *fl = filp->private_data; struct hlist_node *n; - struct fastrpc_buf *buf = NULL; struct fastrpc_mmap *map = NULL; + struct fastrpc_mmap *gmaps = NULL; struct smq_invoke_ctx *ictx = NULL; - struct fastrpc_channel_ctx *chan; - struct fastrpc_session_ctx *sess; + struct fastrpc_channel_ctx *chan = NULL; unsigned int len = 0; - int i, j, ret = 0; + int i, j, sess_used = 0, ret = 0; char *fileinfo = NULL; + char single_line[UL_SIZE] = "----------------"; + char title[UL_SIZE] = "========================="; fileinfo = kzalloc(DEBUGFS_SIZE, GFP_KERNEL); if (!fileinfo) goto bail; if (fl == NULL) { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "\n%s %s %s\n", title, " CHANNEL INFO ", title); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-8s|%-9s|%-9s|%-14s|%-9s|%-13s\n", + "susbsys", "refcount", "sesscount", "issubsystemup", + "ssrcount", "session_used"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "-%s%s%s%s-\n", single_line, single_line, + single_line, single_line); for (i = 0; i < NUM_CHANNELS; i++) { + sess_used = 0; chan = &gcinfo[i]; len += scnprintf(fileinfo + len, - DEBUGFS_SIZE - len, "%s\n\n", - chan->name); + DEBUGFS_SIZE - len, "%-8s", chan->subsys); + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "|%-9d", + chan->kref.refcount.counter); len += scnprintf(fileinfo + len, - DEBUGFS_SIZE - len, "%s %d\n", - "secure:", chan->secure); + DEBUGFS_SIZE - len, "|%-9d", + chan->sesscount); len += scnprintf(fileinfo + len, - DEBUGFS_SIZE - len, "%s %d\n", - "sesscount:", chan->sesscount); + DEBUGFS_SIZE - len, "|%-14d", + chan->issubsystemup); + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "|%-9d", + chan->ssrcount); for (j = 0; j < chan->sesscount; j++) { - sess = &chan->session[j]; - len += scnprintf(fileinfo + len, - DEBUGFS_SIZE - len, - "%s%d\n\n", "SESSION", j); - len += scnprintf(fileinfo + len, - DEBUGFS_SIZE - len, - "%s %d\n", "sid:", - sess->smmu.cb); - len += scnprintf(fileinfo + len, - DEBUGFS_SIZE - len, - "%s %d\n", "SECURE:", - sess->smmu.secure); - } + sess_used += chan->session[j].used; + } + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "|%-13d\n", sess_used); + + } + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "\n%s%s%s\n", "=============", + " CMA HEAP ", "=============="); + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "%-20s|%-20s\n", "addr", "size"); + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "--%s%s---\n", + single_line, single_line); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "0x%-18llX", me->range.addr); + len += scnprintf(fileinfo + len, + DEBUGFS_SIZE - len, "|0x%-18llX\n", me->range.size); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "\n==========%s %s %s===========\n", + title, " GMAPS ", title); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20s|%-20s|%-20s|%-20s\n", + "fd", "phys", "size", "va"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s%s%s%s%s\n", single_line, single_line, + single_line, single_line, single_line); + hlist_for_each_entry_safe(gmaps, n, &me->maps, hn) { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20d|0x%-18llX|0x%-18X|0x%-20lX\n\n", + gmaps->fd, gmaps->phys, + (uint32_t)gmaps->size, + gmaps->va); + } + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20s|%-20s|%-20s|%-20s\n", + "len", "refs", "raddr", "flags"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s%s%s%s%s\n", single_line, single_line, + single_line, single_line, single_line); + hlist_for_each_entry_safe(gmaps, n, &me->maps, hn) { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "0x%-18X|%-20d|%-20lu|%-20u\n", + (uint32_t)gmaps->len, gmaps->refs, + gmaps->raddr, gmaps->flags); } } else { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %d\n\n", - "PROCESS_ID:", fl->tgid); + "\n%s %13s %d\n", "cid", ":", fl->cid); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %d\n\n", - "CHANNEL_ID:", fl->cid); + "%s %12s %d\n", "tgid", ":", fl->tgid); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %d\n\n", - "SSRCOUNT:", fl->ssrcount); + "%s %7s %d\n", "sessionid", ":", fl->sessionid); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %d\n\n", - "DEV_MINOR:", fl->dev_minor); + "%s %8s %d\n", "ssrcount", ":", fl->ssrcount); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %d\n\n", - "KERNEL MEMORY ALLOCATION:", 1); + "%s %8s %d\n", "refcount", ":", fl->refcount); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s\n", - "LIST OF CACHED BUFS:"); - spin_lock(&fl->hlock); - hlist_for_each_entry_safe(buf, n, &fl->cached_bufs, hn) { - len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %pK %s %pK %s %llx %s %lx\n", - "buf:", buf, "buf->virt:", buf->virt, - "buf->phys:", buf->phys, - "buf->dma_attr:", buf->dma_attr); + "%s %14s %d\n", "pd", ":", fl->pd); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %9s %s\n", "spdname", ":", fl->spdname); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %6s %d\n", "file_close", ":", fl->file_close); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %8s %d\n", "sharedcb", ":", fl->sharedcb); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %9s %d\n", "profile", ":", fl->profile); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %3s %d\n", "smmu.coherent", ":", + fl->sctx->smmu.coherent); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %4s %d\n", "smmu.enabled", ":", + fl->sctx->smmu.enabled); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %9s %d\n", "smmu.cb", ":", fl->sctx->smmu.cb); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %5s %d\n", "smmu.secure", ":", + fl->sctx->smmu.secure); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %5s %d\n", "smmu.faults", ":", + fl->sctx->smmu.faults); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s %s %d\n", "link.link_state", + ":", *&me->channel[fl->cid].link.link_state); + + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "\n=======%s %s %s======\n", title, + " LIST OF MAPS ", title); + + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20s|%-20s|%-20s\n", "va", "phys", "size"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s%s%s%s%s\n", + single_line, single_line, single_line, + single_line, single_line); + hlist_for_each_entry_safe(map, n, &fl->maps, hn) { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "0x%-20lX|0x%-20llX|0x%-20zu\n\n", + map->va, map->phys, + map->size); } len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "\n%s\n", - "LIST OF MAPS:"); + "%-20s|%-20s|%-20s|%-20s\n", + "len", "refs", + "raddr", "uncached"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s%s%s%s%s\n", + single_line, single_line, single_line, + single_line, single_line); hlist_for_each_entry_safe(map, n, &fl->maps, hn) { - len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %pK %s %lx %s %llx\n", - "map:", map, - "map->va:", map->va, - "map->phys:", map->phys); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20zu|%-20d|0x%-20lX|%-20d\n\n", + map->len, map->refs, map->raddr, + map->uncached); } len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "\n%s\n", - "LIST OF PENDING SMQCONTEXTS:"); + "%-20s|%-20s\n", "secure", "attr"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s%s%s%s%s\n", + single_line, single_line, single_line, + single_line, single_line); + hlist_for_each_entry_safe(map, n, &fl->maps, hn) { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20d|0x%-20lX\n\n", + map->secure, map->attr); + } + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "\n%s %s %s\n", title, + " LIST OF PENDING SMQCONTEXTS ", title); + + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20s|%-10s|%-10s|%-10s|%-20s\n", + "sc", "pid", "tgid", "used", "ctxid"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s%s%s%s%s\n", single_line, single_line, + single_line, single_line, single_line); hlist_for_each_entry_safe(ictx, n, &fl->clst.pending, hn) { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %pK %s %u %s %u %s %u\n", - "smqcontext:", ictx, - "sc:", ictx->sc, - "tid:", ictx->pid, - "handle", ictx->rpra->h); + "0x%-18X|%-10d|%-10d|%-10zu|0x%-20llX\n\n", + ictx->sc, ictx->pid, ictx->tgid, + ictx->used, ictx->ctxid); } + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "\n%s\n", - "LIST OF INTERRUPTED SMQCONTEXTS:"); - hlist_for_each_entry_safe(ictx, n, &fl->clst.interrupted, hn) { + "\n%s %s %s\n", title, + " LIST OF INTERRUPTED SMQCONTEXTS ", title); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s %pK %s %u %s %u %s %u\n", - "smqcontext:", ictx, - "sc:", ictx->sc, - "tid:", ictx->pid, - "handle", ictx->rpra->h); + "%-20s|%-10s|%-10s|%-10s|%-20s\n", + "sc", "pid", "tgid", "used", "ctxid"); + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%s%s%s%s%s\n", single_line, single_line, + single_line, single_line, single_line); + hlist_for_each_entry_safe(ictx, n, &fl->clst.interrupted, hn) { + len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, + "%-20u|%-20d|%-20d|%-20zu|0x%-20llX\n\n", + ictx->sc, ictx->pid, ictx->tgid, + ictx->used, ictx->ctxid); } spin_unlock(&fl->hlock); } @@ -3302,6 +3409,8 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) struct dentry *debugfs_file; struct fastrpc_file *fl = NULL; struct fastrpc_apps *me = &gfa; + char strpid[PID_SIZE]; + int buf_size = 0; /* * Indicates the device node opened @@ -3319,8 +3428,18 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) VERIFY(err, NULL != (fl = kzalloc(sizeof(*fl), GFP_KERNEL))); if (err) return err; - debugfs_file = debugfs_create_file(current->comm, 0644, debugfs_root, - fl, &debugfs_fops); + snprintf(strpid, PID_SIZE, "%d", current->pid); + buf_size = strlen(current->comm) + strlen("_") + strlen(strpid) + 1; + fl->debug_buf = kzalloc(buf_size, GFP_KERNEL); + if (fl->debug_buf != NULL) { + snprintf(fl->debug_buf, UL_SIZE, "%.10s%s%d", + current->comm, "_", current->pid); + debugfs_file = debugfs_create_file(fl->debug_buf, 0644, + debugfs_root, fl, &debugfs_fops); + + if (debugfs_file != NULL) + fl->debugfs_file = debugfs_file; + } context_list_ctor(&fl->clst); spin_lock_init(&fl->hlock); INIT_HLIST_HEAD(&fl->maps); @@ -3336,8 +3455,6 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) fl->dev_minor = dev_minor; fl->init_mem = NULL; - if (debugfs_file != NULL) - fl->debugfs_file = debugfs_file; fl->qos_request = 0; fl->refcount = 0; filp->private_data = fl; @@ -4226,8 +4343,8 @@ static int __init fastrpc_device_init(void) struct device *secure_dev = NULL; int err = 0, i; + debugfs_root = debugfs_create_dir("adsprpc", NULL); memset(me, 0, sizeof(*me)); - fastrpc_init(me); me->dev = NULL; me->glink = true; @@ -4283,12 +4400,11 @@ static int __init fastrpc_device_init(void) gcinfo[i].subsys, &me->channel[i].nb); } - me->client = msm_ion_client_create(DEVICE_NAME); VERIFY(err, !IS_ERR_OR_NULL(me->client)); if (err) goto device_create_bail; - debugfs_root = debugfs_create_dir("adsprpc", NULL); + return 0; device_create_bail: for (i = 0; i < NUM_CHANNELS; i++) { diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index 7f2fdd259f6d..a537cfb6aa23 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.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 @@ -2070,9 +2070,9 @@ int diag_process_dci_transaction(unsigned char *buf, int len) uint8_t *event_mask_ptr; struct diag_dci_client_tbl *dci_entry = NULL; - if (!temp) { - pr_err("diag: Invalid buffer in %s\n", __func__); - return -ENOMEM; + if (!temp || len < sizeof(int)) { + pr_err("diag: Invalid input in %s\n", __func__); + return -EINVAL; } /* This is Pkt request/response transaction */ @@ -2128,7 +2128,7 @@ int diag_process_dci_transaction(unsigned char *buf, int len) count = 0; /* iterator for extracting log codes */ while (count < num_codes) { - if (read_len >= USER_SPACE_DATA) { + if (read_len + sizeof(uint16_t) > len) { pr_err("diag: dci: Invalid length for log type in %s", __func__); mutex_unlock(&driver->dci_mutex); @@ -2242,7 +2242,7 @@ int diag_process_dci_transaction(unsigned char *buf, int len) pr_debug("diag: head of dci event mask %pK\n", event_mask_ptr); count = 0; /* iterator for extracting log codes */ while (count < num_codes) { - if (read_len >= USER_SPACE_DATA) { + if (read_len + sizeof(int) > len) { pr_err("diag: dci: Invalid length for event type in %s", __func__); mutex_unlock(&driver->dci_mutex); diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h index 61eb3f540c39..e3c7cba7d9c8 100644 --- a/drivers/char/diag/diag_dci.h +++ b/drivers/char/diag/diag_dci.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-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 @@ -27,7 +27,7 @@ #define DISABLE_LOG_MASK 0 #define MAX_EVENT_SIZE 512 #define DCI_CLIENT_INDEX_INVALID -1 -#define DCI_LOG_CON_MIN_LEN 14 +#define DCI_LOG_CON_MIN_LEN 16 #define DCI_EVENT_CON_MIN_LEN 16 #define EXT_HDR_LEN 8 diff --git a/drivers/gpu/msm/kgsl_drawobj.c b/drivers/gpu/msm/kgsl_drawobj.c index 3dbaea4a0ccb..0226b681e92d 100644 --- a/drivers/gpu/msm/kgsl_drawobj.c +++ b/drivers/gpu/msm/kgsl_drawobj.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-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 @@ -201,8 +201,13 @@ static void drawobj_sync_func(struct kgsl_device *device, trace_syncpoint_timestamp_expire(event->syncobj, event->context, event->timestamp); - drawobj_sync_expire(device, event); - kgsl_context_put(event->context); + /* + * Put down the context ref count only if + * this thread successfully clears the pending bit mask. + */ + if (drawobj_sync_expire(device, event)) + kgsl_context_put(event->context); + kgsl_drawobj_put(&event->syncobj->base); } @@ -232,33 +237,24 @@ static void drawobj_destroy_sparse(struct kgsl_drawobj *drawobj) static void drawobj_destroy_sync(struct kgsl_drawobj *drawobj) { struct kgsl_drawobj_sync *syncobj = SYNCOBJ(drawobj); - unsigned long pending = 0; unsigned int i; /* Zap the canary timer */ del_timer_sync(&syncobj->timer); /* - * Copy off the pending list and clear each pending event atomically - - * this will render any subsequent asynchronous callback harmless. - * This marks each event for deletion. If any pending fence callbacks - * run between now and the actual cancel, the associated structures - * are kfreed only in the cancel call. - */ - for_each_set_bit(i, &syncobj->pending, KGSL_MAX_SYNCPOINTS) { - if (test_and_clear_bit(i, &syncobj->pending)) - __set_bit(i, &pending); - } - - /* * Clear all pending events - this will render any subsequent async * callbacks harmless */ for (i = 0; i < syncobj->numsyncs; i++) { struct kgsl_drawobj_sync_event *event = &syncobj->synclist[i]; - /* Don't do anything if the event has already expired */ - if (!test_bit(i, &pending)) + /* + * Don't do anything if the event has already expired. + * If this thread clears the pending bit mask then it is + * responsible for doing context put. + */ + if (!test_and_clear_bit(i, &syncobj->pending)) continue; switch (event->type) { @@ -266,6 +262,11 @@ static void drawobj_destroy_sync(struct kgsl_drawobj *drawobj) kgsl_cancel_event(drawobj->device, &event->context->events, event->timestamp, drawobj_sync_func, event); + /* + * Do context put here to make sure the context is alive + * till this thread cancels kgsl event. + */ + kgsl_context_put(event->context); break; case KGSL_CMD_SYNCPOINT_TYPE_FENCE: kgsl_sync_fence_async_cancel(event->handle); @@ -278,7 +279,7 @@ static void drawobj_destroy_sync(struct kgsl_drawobj *drawobj) * If we cancelled an event, there's a good chance that the context is * on a dispatcher queue, so schedule to get it removed. */ - if (!bitmap_empty(&pending, KGSL_MAX_SYNCPOINTS) && + if (!bitmap_empty(&syncobj->pending, KGSL_MAX_SYNCPOINTS) && drawobj->device->ftbl->drawctxt_sched) drawobj->device->ftbl->drawctxt_sched(drawobj->device, drawobj->context); diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c index 70f3e04bf9c5..7796aa34fd58 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c @@ -438,17 +438,32 @@ static int32_t cam_eeprom_parse_memory_map( else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT) validate_size = sizeof(struct cam_cmd_unconditional_wait); - if (remain_buf_len < validate_size) { + if (remain_buf_len < validate_size || + *num_map >= (MSM_EEPROM_MAX_MEM_MAP_CNT * + MSM_EEPROM_MEMORY_MAP_MAX_SIZE)) { CAM_ERR(CAM_EEPROM, "not enough buffer"); return -EINVAL; } switch (cmm_hdr->cmd_type) { case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR: i2c_random_wr = (struct cam_cmd_i2c_random_wr *)cmd_buf; + + if (i2c_random_wr->header.count == 0 || + i2c_random_wr->header.count >= MSM_EEPROM_MAX_MEM_MAP_CNT || + (size_t)*num_map >= ((MSM_EEPROM_MAX_MEM_MAP_CNT * + MSM_EEPROM_MEMORY_MAP_MAX_SIZE) - + i2c_random_wr->header.count)) { + CAM_ERR(CAM_EEPROM, "OOB Error"); + return -EINVAL; + } cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_random_wr) + ((i2c_random_wr->header.count - 1) * sizeof(struct i2c_random_wr_payload)); + if (cmd_length_in_bytes > remain_buf_len) { + CAM_ERR(CAM_EEPROM, "Not enough buffer remaining"); + return -EINVAL; + } for (cnt = 0; cnt < (i2c_random_wr->header.count); cnt++) { map[*num_map + cnt].page.addr = @@ -471,6 +486,11 @@ static int32_t cam_eeprom_parse_memory_map( i2c_cont_rd = (struct cam_cmd_i2c_continuous_rd *)cmd_buf; cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_continuous_rd); + if (i2c_cont_rd->header.count >= U32_MAX - data->num_data) { + CAM_ERR(CAM_EEPROM, + "int overflow on eeprom memory block"); + return -EINVAL; + } map[*num_map].mem.addr = i2c_cont_rd->reg_addr; map[*num_map].mem.addr_type = i2c_cont_rd->header.addr_type; map[*num_map].mem.data_type = i2c_cont_rd->header.data_type; diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c index f1be1a7ddded..b255c6f1e209 100644 --- a/drivers/media/platform/msm/vidc/hfi_response_handler.c +++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c @@ -103,12 +103,22 @@ static enum msm_vidc_pixel_depth get_hal_pixel_depth(u32 hfi_bit_depth) return MSM_VIDC_BIT_DEPTH_UNSUPPORTED; } +static inline int validate_pkt_size(u32 rem_size, u32 msg_size) +{ + if (rem_size < msg_size) { + dprintk(VIDC_ERR, "%s: bad_pkt_size: %d\n", + __func__, rem_size); + return false; + } + return true; +} + static int hfi_process_sess_evt_seq_changed(u32 device_id, struct hfi_msg_event_notify_packet *pkt, struct msm_vidc_cb_info *info) { struct msm_vidc_cb_event event_notify = {0}; - int num_properties_changed; + u32 num_properties_changed, rem_size; struct hfi_frame_size *frame_sz; struct hfi_profile_level *profile_level; struct hfi_bit_depth *pixel_depth; @@ -121,11 +131,9 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, enum msm_vidc_pixel_depth luma_bit_depth, chroma_bit_depth; struct hfi_colour_space *colour_info; - if (sizeof(struct hfi_msg_event_notify_packet) > pkt->size) { - dprintk(VIDC_ERR, - "hal_process_session_init_done: bad_pkt_size\n"); + if (!validate_pkt_size(pkt->size, + sizeof(struct hfi_msg_event_notify_packet))) return -E2BIG; - } event_notify.device_id = device_id; event_notify.session_id = (void *)(uintptr_t)pkt->session_id; @@ -146,10 +154,18 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, if (num_properties_changed) { data_ptr = (u8 *) &pkt->rg_ext_event_data[0]; + rem_size = pkt->size - sizeof(struct + hfi_msg_event_notify_packet) + sizeof(u32); do { + if (!validate_pkt_size(rem_size, sizeof(u32))) + return -E2BIG; prop_id = (int) *((u32 *)data_ptr); + rem_size -= sizeof(u32); switch (prop_id) { case HFI_PROPERTY_PARAM_FRAME_SIZE: + if (!validate_pkt_size(rem_size, sizeof(struct + hfi_frame_size))) + return -E2BIG; data_ptr = data_ptr + sizeof(u32); frame_sz = (struct hfi_frame_size *) data_ptr; @@ -159,8 +175,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, frame_sz->height, frame_sz->width); data_ptr += sizeof(struct hfi_frame_size); + rem_size -= sizeof(struct hfi_frame_size); break; case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: + if (!validate_pkt_size(rem_size, sizeof(struct + hfi_profile_level))) + return -E2BIG; data_ptr = data_ptr + sizeof(u32); profile_level = (struct hfi_profile_level *) data_ptr; @@ -171,8 +191,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, profile_level->level); data_ptr += sizeof(struct hfi_profile_level); + rem_size -= sizeof(struct hfi_profile_level); break; case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH: + if (!validate_pkt_size(rem_size, sizeof(struct + hfi_bit_depth))) + return -E2BIG; data_ptr = data_ptr + sizeof(u32); pixel_depth = (struct hfi_bit_depth *) data_ptr; /* @@ -203,8 +227,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, event_notify.bit_depth, luma_bit_depth, chroma_bit_depth); data_ptr += sizeof(struct hfi_bit_depth); + rem_size -= sizeof(struct hfi_bit_depth); break; case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT: + if (!validate_pkt_size(rem_size, sizeof(struct + hfi_pic_struct))) + return -E2BIG; data_ptr = data_ptr + sizeof(u32); pic_struct = (struct hfi_pic_struct *) data_ptr; event_notify.pic_struct = @@ -214,8 +242,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, pic_struct->progressive_only); data_ptr += sizeof(struct hfi_pic_struct); + rem_size -= sizeof(struct hfi_pic_struct); break; case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE: + if (!validate_pkt_size(rem_size, sizeof(struct + hfi_colour_space))) + return -E2BIG; data_ptr = data_ptr + sizeof(u32); colour_info = (struct hfi_colour_space *) data_ptr; @@ -226,8 +258,11 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, colour_info->colour_space); data_ptr += sizeof(struct hfi_colour_space); + rem_size -= sizeof(struct hfi_colour_space); break; case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: + if (!validate_pkt_size(rem_size, sizeof(u32))) + return -E2BIG; data_ptr = data_ptr + sizeof(u32); entropy_mode = *(u32 *)data_ptr; event_notify.entropy_mode = entropy_mode; @@ -235,8 +270,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, "Entropy Mode: 0x%x\n", entropy_mode); data_ptr += sizeof(u32); + rem_size -= sizeof(u32); break; case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: + if (!validate_pkt_size(rem_size, sizeof(struct + hfi_buffer_requirements))) + return -E2BIG; data_ptr = data_ptr + sizeof(u32); buf_req = (struct hfi_buffer_requirements *) @@ -248,8 +287,13 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, event_notify.capture_buf_count); data_ptr += sizeof(struct hfi_buffer_requirements); + rem_size -= + sizeof(struct hfi_buffer_requirements); break; case HFI_INDEX_EXTRADATA_INPUT_CROP: + if (!validate_pkt_size(rem_size, sizeof(struct + hfi_index_extradata_input_crop_payload))) + return -E2BIG; data_ptr = data_ptr + sizeof(u32); crop_info = (struct hfi_index_extradata_input_crop_payload *) @@ -270,6 +314,8 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, data_ptr += sizeof(struct hfi_index_extradata_input_crop_payload); + rem_size -= sizeof(struct + hfi_index_extradata_input_crop_payload); break; default: dprintk(VIDC_ERR, @@ -722,7 +768,7 @@ static inline void copy_cap_prop( } static int hfi_fill_codec_info(u8 *data_ptr, - struct vidc_hal_sys_init_done *sys_init_done) { + struct vidc_hal_sys_init_done *sys_init_done, u32 rem_size) { u32 i; u32 codecs = 0, codec_count = 0, size = 0; struct msm_vidc_capability *capability; @@ -732,6 +778,9 @@ static int hfi_fill_codec_info(u8 *data_ptr, if (prop_id == HFI_PROPERTY_PARAM_CODEC_SUPPORTED) { struct hfi_codec_supported *prop; + if (!validate_pkt_size(rem_size - sizeof(u32), + sizeof(struct hfi_codec_supported))) + return -E2BIG; data_ptr = data_ptr + sizeof(u32); prop = (struct hfi_codec_supported *) data_ptr; sys_init_done->dec_codec_supported = @@ -739,6 +788,8 @@ static int hfi_fill_codec_info(u8 *data_ptr, sys_init_done->enc_codec_supported = prop->encoder_codec_supported; size = sizeof(struct hfi_codec_supported) + sizeof(u32); + rem_size -= + sizeof(struct hfi_codec_supported) + sizeof(u32); } else { dprintk(VIDC_WARN, "%s: prop_id %#x, expected codec_supported property\n", @@ -779,14 +830,22 @@ static int hfi_fill_codec_info(u8 *data_ptr, } sys_init_done->codec_count = codec_count; + if (!validate_pkt_size(rem_size, sizeof(u32))) + return -E2BIG; prop_id = *((u32 *)(orig_data_ptr + size)); if (prop_id == HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED) { - struct hfi_max_sessions_supported *prop = - (struct hfi_max_sessions_supported *) + struct hfi_max_sessions_supported *prop; + + if (!validate_pkt_size(rem_size - sizeof(u32), sizeof(struct + hfi_max_sessions_supported))) + return -E2BIG; + prop = (struct hfi_max_sessions_supported *) (orig_data_ptr + size + sizeof(u32)); sys_init_done->max_sessions_supported = prop->max_sessions; size += sizeof(struct hfi_max_sessions_supported) + sizeof(u32); + rem_size -= + sizeof(struct hfi_max_sessions_supported) + sizeof(u32); dprintk(VIDC_DBG, "max_sessions_supported %d\n", prop->max_sessions); } @@ -878,6 +937,21 @@ static enum vidc_status hfi_parse_init_done_properties( u32 prop_id, next_offset; u32 codecs = 0, domain = 0; +#define VALIDATE_PROPERTY_STRUCTURE_SIZE(pkt_size, property_size) ({\ + if (pkt_size < property_size) { \ + status = VIDC_ERR_BAD_PARAM; \ + break; \ + } \ +}) + +#define VALIDATE_PROPERTY_PAYLOAD_SIZE(pkt_size, payload_size, \ + property_count) ({\ + if (pkt_size/payload_size < property_count) { \ + status = VIDC_ERR_BAD_PARAM; \ + break; \ + } \ +}) + while (status == VIDC_ERR_NONE && num_properties && rem_bytes >= sizeof(u32)) { @@ -891,6 +965,10 @@ static enum vidc_status hfi_parse_init_done_properties( (struct hfi_codec_mask_supported *) (data_ptr + next_offset); + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(*prop)); + codecs = prop->codecs; domain = prop->video_domains; next_offset += sizeof(struct hfi_codec_mask_supported); @@ -903,11 +981,14 @@ static enum vidc_status hfi_parse_init_done_properties( (struct hfi_capability_supported_info *) (data_ptr + next_offset); - if ((rem_bytes - next_offset) < prop->num_capabilities * - sizeof(struct hfi_capability_supported)) { - status = VIDC_ERR_BAD_PARAM; - break; - } + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(*prop)); + VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes - + next_offset - sizeof(u32), + sizeof(struct hfi_capability_supported), + prop->num_capabilities); + next_offset += sizeof(u32) + prop->num_capabilities * sizeof(struct hfi_capability_supported); @@ -928,10 +1009,10 @@ static enum vidc_status hfi_parse_init_done_properties( char *fmt_ptr; struct hfi_uncompressed_plane_info *plane_info; - if ((rem_bytes - next_offset) < sizeof(*prop)) { - status = VIDC_ERR_BAD_PARAM; - break; - } + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(*prop)); + num_format_entries = prop->format_entries; next_offset = sizeof(*prop); fmt_ptr = (char *)&prop->rg_format_info[0]; @@ -942,11 +1023,10 @@ static enum vidc_status hfi_parse_init_done_properties( plane_info = (struct hfi_uncompressed_plane_info *) fmt_ptr; - if ((rem_bytes - next_offset) < - sizeof(*plane_info)) { - status = VIDC_ERR_BAD_PARAM; - break; - } + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(*plane_info)); + bytes_to_skip = sizeof(*plane_info) - sizeof(struct hfi_uncompressed_plane_constraints) + @@ -954,6 +1034,10 @@ static enum vidc_status hfi_parse_init_done_properties( sizeof(struct hfi_uncompressed_plane_constraints); + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + bytes_to_skip); + fmt_ptr += bytes_to_skip; next_offset += bytes_to_skip; num_format_entries--; @@ -966,6 +1050,15 @@ static enum vidc_status hfi_parse_init_done_properties( struct hfi_properties_supported *prop = (struct hfi_properties_supported *) (data_ptr + next_offset); + + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(*prop)); + VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes - + next_offset - sizeof(*prop) + + sizeof(u32), sizeof(u32), + prop->num_properties); + next_offset += sizeof(*prop) - sizeof(u32) + prop->num_properties * sizeof(u32); num_properties--; @@ -977,6 +1070,15 @@ static enum vidc_status hfi_parse_init_done_properties( (struct hfi_profile_level_supported *) (data_ptr + next_offset); + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(*prop)); + VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes - + next_offset - + sizeof(u32), + sizeof(struct hfi_profile_level), + prop->profile_count); + next_offset += sizeof(u32) + prop->profile_count * sizeof(struct hfi_profile_level); @@ -997,6 +1099,14 @@ static enum vidc_status hfi_parse_init_done_properties( } case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SUPPORTED: { + struct hfi_nal_stream_format_supported *prop = + (struct hfi_nal_stream_format_supported *) + (data_ptr + next_offset); + + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(*prop)); + next_offset += sizeof(struct hfi_nal_stream_format_supported); num_properties--; @@ -1004,12 +1114,18 @@ static enum vidc_status hfi_parse_init_done_properties( } case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT: { + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(u32)); next_offset += sizeof(u32); num_properties--; break; } case HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH: { + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(struct hfi_intra_refresh)); next_offset += sizeof(struct hfi_intra_refresh); num_properties--; @@ -1017,6 +1133,9 @@ static enum vidc_status hfi_parse_init_done_properties( } case HFI_PROPERTY_TME_VERSION_SUPPORTED: { + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(u32)); capabilities->tme_version = *((u32 *)(data_ptr + next_offset)); next_offset += @@ -1030,8 +1149,13 @@ static enum vidc_status hfi_parse_init_done_properties( __func__, data_ptr, prop_id); break; } - rem_bytes -= next_offset; - data_ptr += next_offset; + + if (rem_bytes > next_offset) { + rem_bytes -= next_offset; + data_ptr += next_offset; + } else { + rem_bytes = 0; + } } return status; @@ -1042,7 +1166,8 @@ enum vidc_status hfi_process_sys_init_done_prop_read( struct vidc_hal_sys_init_done *sys_init_done) { enum vidc_status status = VIDC_ERR_NONE; - u32 rem_bytes, bytes_read, num_properties; + int bytes_read; + u32 rem_bytes, num_properties; u8 *data_ptr; if (!pkt || !sys_init_done) { @@ -1050,6 +1175,11 @@ enum vidc_status hfi_process_sys_init_done_prop_read( "hfi_msg_sys_init_done: Invalid input\n"); return VIDC_ERR_FAIL; } + if (pkt->size < sizeof(struct hfi_msg_sys_init_done_packet)) { + dprintk(VIDC_ERR, "%s: bad_packet_size: %d\n", + __func__, pkt->size); + return VIDC_ERR_FAIL; + } rem_bytes = pkt->size - sizeof(struct hfi_msg_sys_init_done_packet) + sizeof(u32); @@ -1077,7 +1207,9 @@ enum vidc_status hfi_process_sys_init_done_prop_read( "Venus didn't set any properties in SYS_INIT_DONE"); return status; } - bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done); + bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done, rem_bytes); + if (bytes_read < 0) + return VIDC_ERR_FAIL; data_ptr += bytes_read; rem_bytes -= bytes_read; num_properties--; diff --git a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c index f8b5d1c086aa..a3b8cd23f180 100644 --- a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c +++ b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c @@ -100,12 +100,22 @@ static enum msm_vidc_pixel_depth get_hal_pixel_depth(u32 hfi_bit_depth) return MSM_VIDC_BIT_DEPTH_UNSUPPORTED; } +static inline int validate_pkt_size(u32 rem_size, u32 msg_size) +{ + if (rem_size < msg_size) { + dprintk(VIDC_ERR, "%s: bad_pkt_size: %d\n", + __func__, rem_size); + return false; + } + return true; +} + static int hfi_process_sess_evt_seq_changed(u32 device_id, struct hfi_msg_event_notify_packet *pkt, struct msm_vidc_cb_info *info) { struct msm_vidc_cb_event event_notify = {0}; - int num_properties_changed; + u32 num_properties_changed, rem_size; struct hfi_frame_size *frame_sz; struct hfi_profile_level *profile_level; struct hfi_bit_depth *pixel_depth; @@ -118,11 +128,9 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, /* Initialize pic_struct to unknown as default */ //event_notify.pic_struct = MSM_VIDC_PIC_STRUCT_UNKNOWN; - if (sizeof(struct hfi_msg_event_notify_packet) > pkt->size) { - dprintk(VIDC_ERR, - "hal_process_session_init_done: bad_pkt_size\n"); + if (!validate_pkt_size(pkt->size, + sizeof(struct hfi_msg_event_notify_packet))) return -E2BIG; - } event_notify.device_id = device_id; event_notify.session_id = (void *)(uintptr_t)pkt->session_id; @@ -143,10 +151,18 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, if (num_properties_changed) { data_ptr = (u8 *) &pkt->rg_ext_event_data[0]; + rem_size = pkt->size - sizeof(struct + hfi_msg_event_notify_packet) + sizeof(u32); do { + if (!validate_pkt_size(rem_size, sizeof(u32))) + return -E2BIG; prop_id = (int) *((u32 *)data_ptr); + rem_size -= sizeof(u32); switch (prop_id) { case HFI_PROPERTY_PARAM_FRAME_SIZE: + if (!validate_pkt_size(rem_size, sizeof(struct + hfi_frame_size))) + return -E2BIG; data_ptr = data_ptr + sizeof(u32); frame_sz = (struct hfi_frame_size *) data_ptr; @@ -156,8 +172,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, frame_sz->height, frame_sz->width); data_ptr += sizeof(struct hfi_frame_size); + rem_size -= sizeof(struct hfi_frame_size); break; case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: + if (!validate_pkt_size(rem_size, sizeof(struct + hfi_profile_level))) + return -E2BIG; data_ptr = data_ptr + sizeof(u32); profile_level = (struct hfi_profile_level *) data_ptr; @@ -166,8 +186,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, profile_level->level); data_ptr += sizeof(struct hfi_profile_level); + rem_size -= sizeof(struct hfi_profile_level); break; case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH: + if (!validate_pkt_size(rem_size, sizeof(struct + hfi_bit_depth))) + return -E2BIG; data_ptr = data_ptr + sizeof(u32); pixel_depth = (struct hfi_bit_depth *) data_ptr; /* @@ -198,8 +222,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, event_notify.bit_depth, luma_bit_depth, chroma_bit_depth); data_ptr += sizeof(struct hfi_bit_depth); + rem_size -= sizeof(struct hfi_bit_depth); break; case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT: + if (!validate_pkt_size(rem_size, sizeof(struct + hfi_pic_struct))) + return -E2BIG; data_ptr = data_ptr + sizeof(u32); pic_struct = (struct hfi_pic_struct *) data_ptr; event_notify.pic_struct = @@ -209,8 +237,12 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, pic_struct->progressive_only); data_ptr += sizeof(struct hfi_pic_struct); + rem_size -= sizeof(struct hfi_pic_struct); break; case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE: + if (!validate_pkt_size(rem_size, sizeof(struct + hfi_colour_space))) + return -E2BIG; data_ptr = data_ptr + sizeof(u32); colour_info = (struct hfi_colour_space *) data_ptr; @@ -221,6 +253,8 @@ static int hfi_process_sess_evt_seq_changed(u32 device_id, colour_info->colour_space); data_ptr += sizeof(struct hfi_colour_space); + rem_size -= sizeof(struct hfi_colour_space); + break; break; default: dprintk(VIDC_ERR, @@ -579,7 +613,7 @@ static inline void copy_cap_prop( } static int hfi_fill_codec_info(u8 *data_ptr, - struct vidc_hal_sys_init_done *sys_init_done) { + struct vidc_hal_sys_init_done *sys_init_done, u32 rem_size) { u32 i; u32 codecs = 0, codec_count = 0, size = 0; struct msm_vidc_capability *capability; @@ -589,6 +623,9 @@ static int hfi_fill_codec_info(u8 *data_ptr, if (prop_id == HFI_PROPERTY_PARAM_CODEC_SUPPORTED) { struct hfi_codec_supported *prop; + if (!validate_pkt_size(rem_size - sizeof(u32), + sizeof(struct hfi_codec_supported))) + return -E2BIG; data_ptr = data_ptr + sizeof(u32); prop = (struct hfi_codec_supported *) data_ptr; sys_init_done->dec_codec_supported = @@ -596,6 +633,8 @@ static int hfi_fill_codec_info(u8 *data_ptr, sys_init_done->enc_codec_supported = prop->encoder_codec_supported; size = sizeof(struct hfi_codec_supported) + sizeof(u32); + rem_size -= + sizeof(struct hfi_codec_supported) + sizeof(u32); } else { dprintk(VIDC_WARN, "%s: prop_id %#x, expected codec_supported property\n", @@ -636,14 +675,22 @@ static int hfi_fill_codec_info(u8 *data_ptr, } sys_init_done->codec_count = codec_count; + if (!validate_pkt_size(rem_size, sizeof(u32))) + return -E2BIG; prop_id = *((u32 *)(orig_data_ptr + size)); if (prop_id == HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED) { - struct hfi_max_sessions_supported *prop = - (struct hfi_max_sessions_supported *) + struct hfi_max_sessions_supported *prop; + + if (!validate_pkt_size(rem_size - sizeof(u32), sizeof(struct + hfi_max_sessions_supported))) + return -E2BIG; + prop = (struct hfi_max_sessions_supported *) (orig_data_ptr + size + sizeof(u32)); sys_init_done->max_sessions_supported = prop->max_sessions; size += sizeof(struct hfi_max_sessions_supported) + sizeof(u32); + rem_size -= + sizeof(struct hfi_max_sessions_supported) + sizeof(u32); dprintk(VIDC_DBG, "max_sessions_supported %d\n", prop->max_sessions); } @@ -798,6 +845,20 @@ static enum vidc_status hfi_parse_init_done_properties( { enum vidc_status status = VIDC_ERR_NONE; u32 prop_id, next_offset; +#define VALIDATE_PROPERTY_STRUCTURE_SIZE(pkt_size, property_size) ({\ + if (pkt_size < property_size) { \ + status = VIDC_ERR_BAD_PARAM; \ + break; \ + } \ +}) + +#define VALIDATE_PROPERTY_PAYLOAD_SIZE(pkt_size, payload_size, \ + property_count) ({\ + if (pkt_size/payload_size < property_count) { \ + status = VIDC_ERR_BAD_PARAM; \ + break; \ + } \ +}) while (status == VIDC_ERR_NONE && num_properties && rem_bytes >= sizeof(u32)) { @@ -811,6 +872,9 @@ static enum vidc_status hfi_parse_init_done_properties( struct hfi_codec_mask_supported *prop = (struct hfi_codec_mask_supported *) (data_ptr + next_offset); + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(*prop)); codecs = prop->codecs; domain = prop->video_domains; @@ -824,11 +888,14 @@ static enum vidc_status hfi_parse_init_done_properties( (struct hfi_capability_supported_info *) (data_ptr + next_offset); - if ((rem_bytes - next_offset) < prop->num_capabilities * - sizeof(struct hfi_capability_supported)) { - status = VIDC_ERR_BAD_PARAM; - break; - } + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(*prop)); + VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes - + next_offset - sizeof(u32), + sizeof(struct hfi_capability_supported), + prop->num_capabilities); + next_offset += sizeof(u32) + prop->num_capabilities * sizeof(struct hfi_capability_supported); @@ -849,10 +916,10 @@ static enum vidc_status hfi_parse_init_done_properties( char *fmt_ptr; struct hfi_uncompressed_plane_info *plane_info; - if ((rem_bytes - next_offset) < sizeof(*prop)) { - status = VIDC_ERR_BAD_PARAM; - break; - } + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(*prop)); + num_format_entries = prop->format_entries; next_offset = sizeof(*prop); fmt_ptr = (char *)&prop->rg_format_info[0]; @@ -863,17 +930,19 @@ static enum vidc_status hfi_parse_init_done_properties( plane_info = (struct hfi_uncompressed_plane_info *) fmt_ptr; - if ((rem_bytes - next_offset) < - sizeof(*plane_info)) { - status = VIDC_ERR_BAD_PARAM; - break; - } + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(*plane_info)); + bytes_to_skip = sizeof(*plane_info) - sizeof(struct hfi_uncompressed_plane_constraints) + plane_info->num_planes * sizeof(struct hfi_uncompressed_plane_constraints); + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + bytes_to_skip); fmt_ptr += bytes_to_skip; next_offset += bytes_to_skip; @@ -887,6 +956,13 @@ static enum vidc_status hfi_parse_init_done_properties( struct hfi_properties_supported *prop = (struct hfi_properties_supported *) (data_ptr + next_offset); + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(*prop)); + VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes - + next_offset - sizeof(*prop) + + sizeof(u32), sizeof(u32), + prop->num_properties); next_offset += sizeof(*prop) - sizeof(u32) + prop->num_properties * sizeof(u32); num_properties--; @@ -903,6 +979,9 @@ static enum vidc_status hfi_parse_init_done_properties( (struct hfi_profile_level_supported *) (data_ptr + next_offset); + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(*prop)); ptr = (char *) &prop->rg_profile_level[0]; prof_count = prop->profile_count; next_offset += sizeof(u32); @@ -915,6 +994,9 @@ static enum vidc_status hfi_parse_init_done_properties( } while (prof_count) { prof_level = (struct hfi_profile_level *)ptr; + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(*prof_level)); capability. profile_level.profile_level[count].profile = prof_level->profile; @@ -931,6 +1013,9 @@ static enum vidc_status hfi_parse_init_done_properties( } case HFI_PROPERTY_PARAM_INTERLACE_FORMAT_SUPPORTED: { + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(struct hfi_interlace_format_supported)); next_offset += sizeof(struct hfi_interlace_format_supported); num_properties--; @@ -938,6 +1023,9 @@ static enum vidc_status hfi_parse_init_done_properties( } case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SUPPORTED: { + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(struct hfi_nal_stream_format_supported)); next_offset += sizeof(struct hfi_nal_stream_format_supported); num_properties--; @@ -945,18 +1033,27 @@ static enum vidc_status hfi_parse_init_done_properties( } case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT: { + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(u32)); next_offset += sizeof(u32); num_properties--; break; } case HFI_PROPERTY_PARAM_MAX_SEQUENCE_HEADER_SIZE: { + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(u32)); next_offset += sizeof(u32); num_properties--; break; } case HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH: { + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(struct hfi_intra_refresh)); next_offset += sizeof(struct hfi_intra_refresh); num_properties--; @@ -967,13 +1064,21 @@ static enum vidc_status hfi_parse_init_done_properties( struct hfi_buffer_alloc_mode_supported *prop = (struct hfi_buffer_alloc_mode_supported *) (data_ptr + next_offset); - + VALIDATE_PROPERTY_STRUCTURE_SIZE(rem_bytes - + next_offset, + sizeof(*prop)); if (prop->num_entries >= 32) { dprintk(VIDC_ERR, "%s - num_entries: %d from f/w seems suspect\n", __func__, prop->num_entries); break; } + VALIDATE_PROPERTY_PAYLOAD_SIZE(rem_bytes - + next_offset - + sizeof(struct hfi_buffer_alloc_mode_supported) + + sizeof(u32), + sizeof(u32), + prop->num_entries); next_offset += sizeof(struct hfi_buffer_alloc_mode_supported) - sizeof(u32) + prop->num_entries * sizeof(u32); @@ -991,8 +1096,12 @@ static enum vidc_status hfi_parse_init_done_properties( __func__, data_ptr, prop_id); break; } + if (rem_bytes > next_offset) { rem_bytes -= next_offset; data_ptr += next_offset; + } else { + rem_bytes = 0; + } } return status; @@ -1003,7 +1112,8 @@ enum vidc_status hfi_process_sys_init_done_prop_read( struct vidc_hal_sys_init_done *sys_init_done) { enum vidc_status status = VIDC_ERR_NONE; - u32 rem_bytes, bytes_read, num_properties; + int bytes_read; + u32 rem_bytes, num_properties; u8 *data_ptr; u32 codecs = 0, domain = 0; @@ -1012,6 +1122,11 @@ enum vidc_status hfi_process_sys_init_done_prop_read( "hfi_msg_sys_init_done: Invalid input\n"); return VIDC_ERR_FAIL; } + if (pkt->size < sizeof(struct hfi_msg_sys_init_done_packet)) { + dprintk(VIDC_ERR, "%s: bad packet size: %d\n", + __func__, pkt->size); + return VIDC_ERR_FAIL; + } rem_bytes = pkt->size - sizeof(struct hfi_msg_sys_init_done_packet) + sizeof(u32); @@ -1039,7 +1154,9 @@ enum vidc_status hfi_process_sys_init_done_prop_read( "Venus didn't set any properties in SYS_INIT_DONE"); return status; } - bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done); + bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done, rem_bytes); + if (bytes_read < 0) + return VIDC_ERR_FAIL; data_ptr += bytes_read; rem_bytes -= bytes_read; num_properties--; diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c index d4fe6eede3b4..a2b725706667 100644 --- a/drivers/scsi/ufs/ufs-qcom-ice.c +++ b/drivers/scsi/ufs/ufs-qcom-ice.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-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 @@ -226,14 +226,17 @@ int ufs_qcom_ice_init(struct ufs_qcom_host *qcom_host) } qcom_host->dbg_print_en |= UFS_QCOM_ICE_DEFAULT_DBG_PRINT_EN; - ice_workqueue = alloc_workqueue("ice-set-key", - WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); if (!ice_workqueue) { - dev_err(ufs_dev, "%s: workqueue allocation failed.\n", + ice_workqueue = alloc_workqueue("ice-set-key", + WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); + if (!ice_workqueue) { + dev_err(ufs_dev, "%s: workqueue allocation failed.\n", __func__); - goto out; + err = -ENOMEM; + goto out; + } + INIT_WORK(&qcom_host->ice_cfg_work, ufs_qcom_ice_cfg_work); } - INIT_WORK(&qcom_host->ice_cfg_work, ufs_qcom_ice_cfg_work); out: return err; @@ -286,6 +289,17 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host, * propagate so it will be re-queued. */ if (err == -EAGAIN) { + if (!ice_workqueue) { + spin_unlock_irqrestore( + &qcom_host->ice_work_lock, + flags); + + dev_err(qcom_host->hba->dev, + "%s: error %d workqueue NULL\n", + __func__, err); + return -EINVAL; + } + dev_dbg(qcom_host->hba->dev, "%s: scheduling task for ice setup\n", __func__); @@ -405,6 +419,16 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host, * propagate so it will be re-queued. */ if (err == -EAGAIN) { + if (!ice_workqueue) { + spin_unlock_irqrestore( + &qcom_host->ice_work_lock, + flags); + + dev_err(qcom_host->hba->dev, + "%s: error %d workqueue NULL\n", + __func__, err); + return -EINVAL; + } dev_dbg(qcom_host->hba->dev, "%s: scheduling task for ice setup\n", diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index 0821084e9ab6..572fdabe8b9a 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -1936,7 +1936,7 @@ static void msm_geni_serial_set_termios(struct uart_port *uport, break; } - + uport->status &= ~(UPSTAT_AUTOCTS); /* stop bits */ if (termios->c_cflag & CSTOPB) stop_bit_len = TX_STOP_BIT_LEN_2; @@ -1944,8 +1944,10 @@ static void msm_geni_serial_set_termios(struct uart_port *uport, stop_bit_len = TX_STOP_BIT_LEN_1; /* flow control, clear the CTS_MASK bit if using flow control. */ - if (termios->c_cflag & CRTSCTS) + if (termios->c_cflag & CRTSCTS) { tx_trans_cfg &= ~UART_CTS_MASK; + uport->status |= UPSTAT_AUTOCTS; + } else tx_trans_cfg |= UART_CTS_MASK; /* status bits to ignore */ diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 578f8c33fb44..4c7ee3d0ba80 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -598,11 +598,14 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk, return -EOPNOTSUPP; } - if (ext4_encrypted_inode(orig_inode) || - ext4_encrypted_inode(donor_inode)) { - ext4_msg(orig_inode->i_sb, KERN_ERR, - "Online defrag not supported for encrypted files"); - return -EOPNOTSUPP; + if (!fscrypt_using_hardware_encryption(orig_inode) || + !fscrypt_using_hardware_encryption(donor_inode)) { + if (ext4_encrypted_inode(orig_inode) || + ext4_encrypted_inode(donor_inode)) { + ext4_msg(orig_inode->i_sb, KERN_ERR, + "Online defrag not supported for encrypted files"); + return -EOPNOTSUPP; + } } /* Protect orig and donor inodes against a truncate */ |