diff --git a/crypto/hmac.c b/crypto/hmac.c index ade790b454e9936f3e23a7af85357686c66bae5d..758688b4bc6b46b2b976afc413598367f1cf219c 100644 --- a/crypto/hmac.c +++ b/crypto/hmac.c @@ -197,11 +197,15 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb) salg = shash_attr_alg(tb[1], 0, 0); if (IS_ERR(salg)) return PTR_ERR(salg); + alg = &salg->base; + /* The underlying hash algorithm must be unkeyed */ err = -EINVAL; + if (crypto_shash_alg_has_setkey(salg)) + goto out_put_alg; + ds = salg->digestsize; ss = salg->statesize; - alg = &salg->base; if (ds > alg->cra_blocksize || ss < alg->cra_blocksize) goto out_put_alg; diff --git a/crypto/shash.c b/crypto/shash.c index 929058a68561264c389719e26a3d22704bbbe18e..d40199f23e0d25fa8e566014fdbdcb977b48d753 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -24,11 +24,12 @@ static const struct crypto_type crypto_shash_type; -static int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, - unsigned int keylen) +int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, + unsigned int keylen) { return -ENOSYS; } +EXPORT_SYMBOL_GPL(shash_no_setkey); static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key, unsigned int keylen) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index f5ed8007247b3819f288c9f3c1c694673a6e7b08..865c85671610804950d7979598e7d4f7ea3abb20 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -62,6 +62,9 @@ up_read(¤t->mm->mmap_sem);\ } while (0) +#define FASTRPC_CTX_MAGIC (0xbeeddeed) +#define FASTRPC_CTX_MAX (256) +#define FASTRPC_CTXID_MASK (0xFF0) #define IS_CACHE_ALIGNED(x) (((x) & ((L1_CACHE_BYTES)-1)) == 0) @@ -91,6 +94,13 @@ static inline uint32_t buf_page_size(uint32_t size) return sz > PAGE_SIZE ? sz : PAGE_SIZE; } +static inline uint64_t ptr_to_uint64(void *ptr) +{ + uint64_t addr = (uint64_t)((uintptr_t)ptr); + + return addr; +} + static inline int buf_get_pages(void *addr, ssize_t sz, int nr_pages, int access, struct smq_phy_page *pages, int nr_elems, struct smq_phy_page *range) @@ -178,6 +188,8 @@ struct smq_invoke_ctx { uint32_t sc; struct overlap *overs; struct overlap **overps; + unsigned int magic; + uint64_t ctxid; }; struct smq_context_list { @@ -216,6 +228,8 @@ struct fastrpc_apps { spinlock_t wrlock; spinlock_t hlock; struct hlist_head htbl[RPC_HASH_SZ]; + spinlock_t ctxlock; + struct smq_invoke_ctx *ctxtable[FASTRPC_CTX_MAX]; }; struct fastrpc_mmap { @@ -507,9 +521,10 @@ static int context_alloc(struct fastrpc_apps *me, uint32_t kernel, struct file_data *fdata, struct smq_invoke_ctx **po) { - int err = 0, bufs, size = 0; + int err = 0, bufs, ii, size = 0; struct smq_invoke_ctx *ctx = 0; struct smq_context_list *clst = &me->clst; + struct fastrpc_ioctl_invoke *invoke = &invokefd->inv; bufs = REMOTE_SCALARS_INBUFS(invoke->sc) + @@ -562,10 +577,26 @@ static int context_alloc(struct fastrpc_apps *me, uint32_t kernel, ctx->pid = current->pid; ctx->tgid = current->tgid; init_completion(&ctx->work); + ctx->magic = FASTRPC_CTX_MAGIC; spin_lock(&clst->hlock); hlist_add_head(&ctx->hn, &clst->pending); spin_unlock(&clst->hlock); + spin_lock(&me->ctxlock); + for (ii = 0; ii < FASTRPC_CTX_MAX; ii++) { + if (!me->ctxtable[ii]) { + me->ctxtable[ii] = ctx; + ctx->ctxid = (ptr_to_uint64(ctx) & ~0xFFF)|(ii << 4); + break; + } + } + spin_unlock(&me->ctxlock); + VERIFY(err, ii < FASTRPC_CTX_MAX); + if (err) { + pr_err("adsprpc: out of context memory\n"); + goto bail; + } + *po = ctx; bail: if (ctx && err) @@ -593,6 +624,7 @@ static void context_free(struct smq_invoke_ctx *ctx, int remove) int ssrcount = ctx->fdata->ssrcount; struct fastrpc_smmu *smmu = &apps->channel[cid].smmu; struct fastrpc_buf *b; + struct fastrpc_apps *me = &gfa; int i, bufs; if (ctx->smmu) { bufs = REMOTE_SCALARS_INBUFS(ctx->sc) + @@ -614,6 +646,17 @@ static void context_free(struct smq_invoke_ctx *ctx, int remove) free_mem(b, ctx->fdata); kfree(ctx->abufs); + ctx->magic = 0; + ctx->ctxid = 0; + + spin_lock(&me->ctxlock); + for (i = 0; i < FASTRPC_CTX_MAX; i++) { + if (me->ctxtable[i] == ctx) { + me->ctxtable[i] = NULL; + break; + } + } + spin_unlock(&me->ctxlock); if (ctx->dev) { add_dev(apps, ctx->dev); if (ctx->obuf.handle != ctx->dev->buf.handle) @@ -1092,7 +1135,7 @@ static int fastrpc_invoke_send(struct fastrpc_apps *me, msg.tid = current->pid; if (kernel) msg.pid = 0; - msg.invoke.header.ctx = ctx; + msg.invoke.header.ctx = ctx->ctxid; msg.invoke.header.handle = handle; msg.invoke.header.sc = sc; msg.invoke.page.addr = buf->phys; @@ -1122,16 +1165,35 @@ static void fastrpc_deinit(void) static void fastrpc_read_handler(int cid) { struct fastrpc_apps *me = &gfa; - struct smq_invoke_rsp rsp; - int ret = 0; + struct smq_invoke_rsp rsp = {0}; + int ret = 0, err = 0; + uint32_t index; do { ret = smd_read_from_cb(me->channel[cid].chan, &rsp, sizeof(rsp)); if (ret != sizeof(rsp)) break; - context_notify_user(rsp.ctx, rsp.retval); + index = (uint32_t)((rsp.ctx & FASTRPC_CTXID_MASK) >> 4); + VERIFY(err, index < FASTRPC_CTX_MAX); + if (err) + goto bail; + + VERIFY(err, !IS_ERR_OR_NULL(me->ctxtable[index])); + if (err) + goto bail; + + VERIFY(err, ((me->ctxtable[index]->ctxid == (rsp.ctx)) && + me->ctxtable[index]->magic == FASTRPC_CTX_MAGIC)); + if (err) + goto bail; + + context_notify_user(me->ctxtable[index], rsp.retval); } while (ret == sizeof(rsp)); + +bail: + if (err) + pr_err("adsprpc: invalid response or context\n"); } static void smd_event_handler(void *priv, unsigned event) @@ -1162,6 +1224,7 @@ static int fastrpc_init(void) spin_lock_init(&me->hlock); spin_lock_init(&me->wrlock); + spin_lock_init(&me->ctxlock); mutex_init(&me->smd_mutex); context_list_ctor(&me->clst); for (i = 0; i < RPC_HASH_SZ; ++i) @@ -1399,6 +1462,12 @@ static int fastrpc_init_process(struct file_data *fdata, inbuf.pgid = current->tgid; inbuf.namelen = strlen(current->comm); inbuf.filelen = init->filelen; + if (!access_ok(0, (void const __user *)init->file, + init->filelen)) + goto bail; + if (!access_ok(1, (void const __user *)init->mem, + init->memlen)) + goto bail; VERIFY(err, 0 == map_buffer(me, fdata, init->memfd, (char *)init->mem, init->memlen, &map, &pages, &npages)); diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h index c0f8d3cc8c4e37d01f8ff09c6a951a8a90844735..c8e31369cef1667979fcf49e741311409fe3898f 100644 --- a/drivers/char/adsprpc_shared.h +++ b/drivers/char/adsprpc_shared.h @@ -137,7 +137,7 @@ struct fastrpc_ioctl_mmap { }; struct smq_null_invoke { - struct smq_invoke_ctx *ctx; /* invoke caller context */ + uint64_t ctx; /* invoke caller context */ uint32_t handle; /* handle to invoke */ uint32_t sc; /* scalars structure describing the data */ }; @@ -164,7 +164,7 @@ struct smq_msg { }; struct smq_invoke_rsp { - struct smq_invoke_ctx *ctx; /* invoke caller context */ + uint64_t ctx; /* invoke caller context */ int retval; /* invoke return value */ }; diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index c5c7b4325991868b6c31f8771a04ae0b162cd972..db9f2bcb998e851f81e3d181f2041cc12f83874f 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -806,11 +806,11 @@ static void dci_process_ctrl_status(unsigned char *buf, int len, int token) { struct diag_ctrl_dci_status *header = NULL; unsigned char *temp = buf; - uint32_t read_len = 0; + unsigned int read_len = 0; uint8_t i; int peripheral_mask, status; - if (!buf || (len < sizeof(struct diag_ctrl_dci_status))) { + if (!buf || len < 2 || (len < sizeof(struct diag_ctrl_dci_status))) { pr_err("diag: In %s, invalid buf %p or length: %d\n", __func__, buf, len); return; @@ -826,7 +826,7 @@ static void dci_process_ctrl_status(unsigned char *buf, int len, int token) read_len += sizeof(struct diag_ctrl_dci_status); for (i = 0; i < header->count; i++) { - if (read_len > len) { + if (read_len > (len - 2)) { pr_err("diag: In %s, Invalid length len: %d\n", __func__, len); return; @@ -868,7 +868,9 @@ static void dci_process_ctrl_handshake_pkt(unsigned char *buf, int len, unsigned char *temp = buf; int err = 0; - if (!buf || (len < sizeof(struct diag_ctrl_dci_handshake_pkt))) + if (!buf) + return; + if (len < 0 || len < sizeof(struct diag_ctrl_dci_handshake_pkt)) return; if (!VALID_DCI_TOKEN(token)) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c index 384167182b8dce19c18fe1e475d83953da35a4d2..165e526bf8cb6ec0da22093d89e6bfebcbfeaeda 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c @@ -1115,11 +1115,12 @@ static int msm_vfe40_start_fetch_engine(struct vfe_device *vfe_dev, vfe_dev->fetch_engine_info.bufq_handle = bufq_handle; vfe_dev->fetch_engine_info.session_id = fe_cfg->session_id; vfe_dev->fetch_engine_info.stream_id = fe_cfg->stream_id; - + mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); if (rc < 0) { pr_err("%s: No fetch buffer\n", __func__); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } @@ -1129,7 +1130,7 @@ static int msm_vfe40_start_fetch_engine(struct vfe_device *vfe_dev, msm_camera_io_w_mb(0x10000, vfe_dev->vfe_base + 0x4C); msm_camera_io_w_mb(0x20000, vfe_dev->vfe_base + 0x4C); buf->state = MSM_ISP_BUFFER_STATE_DIVERTED; - + mutex_unlock(&vfe_dev->buf_mgr->lock); return 0; } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c index 9e76344b4a52d33bd93277ed5df0ec44b9ed49db..9f1f102efd55522215a5a6de6394c0047bc69baa 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c @@ -938,10 +938,12 @@ static int msm_vfe44_fetch_engine_start(struct vfe_device *vfe_dev, vfe_dev->fetch_engine_info.session_id = fe_cfg->session_id; vfe_dev->fetch_engine_info.stream_id = fe_cfg->stream_id; + mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); if (rc < 0) { pr_err("%s: No fetch buffer\n", __func__); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } vfe_dev->fetch_engine_info.buf_idx = fe_cfg->buf_idx; @@ -954,7 +956,7 @@ static int msm_vfe44_fetch_engine_start(struct vfe_device *vfe_dev, ISP_DBG("%s: Fetch Engine ready\n", __func__); buf->state = MSM_ISP_BUFFER_STATE_DIVERTED; - + mutex_unlock(&vfe_dev->buf_mgr->lock); return 0; } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c index 22b161cc0753f2ffc1acb150272285ed7332392b..b7691dba0b1186ab7b9a18dd1684447e4d820152 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c @@ -877,10 +877,12 @@ static int msm_vfe46_start_fetch_engine(struct vfe_device *vfe_dev, vfe_dev->fetch_engine_info.session_id = fe_cfg->session_id; vfe_dev->fetch_engine_info.stream_id = fe_cfg->stream_id; + mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); if (rc < 0) { pr_err("%s: No fetch buffer\n", __func__); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } vfe_dev->fetch_engine_info.buf_idx = fe_cfg->buf_idx; @@ -893,6 +895,7 @@ static int msm_vfe46_start_fetch_engine(struct vfe_device *vfe_dev, ISP_DBG("%s:VFE%d Fetch Engine ready\n", __func__, vfe_dev->pdev->id); buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED; + mutex_unlock(&vfe_dev->buf_mgr->lock); return 0; } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c index d9a194f9996c7853fb1a57700de8f20a3acc90a5..d064924a67b1be6e648e66a7575bb222b63712b9 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c @@ -918,10 +918,12 @@ static int msm_vfe47_start_fetch_engine(struct vfe_device *vfe_dev, vfe_dev->fetch_engine_info.session_id = fe_cfg->session_id; vfe_dev->fetch_engine_info.stream_id = fe_cfg->stream_id; + mutex_lock(&vfe_dev->buf_mgr->lock); rc = vfe_dev->buf_mgr->ops->get_buf_by_index( vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf); if (rc < 0) { pr_err("%s: No fetch buffer\n", __func__); + mutex_unlock(&vfe_dev->buf_mgr->lock); return -EINVAL; } vfe_dev->fetch_engine_info.buf_idx = fe_cfg->buf_idx; @@ -934,6 +936,7 @@ static int msm_vfe47_start_fetch_engine(struct vfe_device *vfe_dev, ISP_DBG("%s:VFE%d Fetch Engine ready\n", __func__, vfe_dev->pdev->id); buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED; + mutex_unlock(&vfe_dev->buf_mgr->lock); return 0; } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 1f6bb834ecfa56cb7beee4e7eabb2b76fca2185b..880b2e85f070bea59408eb0cf1e1598897ee953f 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -2574,9 +2574,11 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) break; } case UPDATE_STREAM_REQUEST_FRAMES: { + mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_request_frame(vfe_dev, stream_info, update_info->user_stream_id, update_info->frame_id); + mutex_unlock(&vfe_dev->buf_mgr->lock); if (rc) pr_err("%s failed to request frame!\n", __func__); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index a84d0910bfeefe4856ca3606bbf9e4f55288ab5d..811eeca05bedd5d80a42675b3b5c6ec9fef13f6f 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -872,7 +872,9 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, break; case VIDIOC_MSM_ISP_CFG_STREAM: mutex_lock(&vfe_dev->core_mutex); + mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_cfg_axi_stream(vfe_dev, arg); + mutex_unlock(&vfe_dev->buf_mgr->lock); mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_AXI_HALT: @@ -882,14 +884,18 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, break; case VIDIOC_MSM_ISP_AXI_RESET: mutex_lock(&vfe_dev->core_mutex); + mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_stats_reset(vfe_dev); rc |= msm_isp_axi_reset(vfe_dev, arg); + mutex_unlock(&vfe_dev->buf_mgr->lock); mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_AXI_RESTART: mutex_lock(&vfe_dev->core_mutex); + mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_stats_restart(vfe_dev); rc |= msm_isp_axi_restart(vfe_dev, arg); + mutex_unlock(&vfe_dev->buf_mgr->lock); mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_INPUT_CFG: @@ -928,7 +934,9 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, break; case VIDIOC_MSM_ISP_CFG_STATS_STREAM: mutex_lock(&vfe_dev->core_mutex); + mutex_lock(&vfe_dev->buf_mgr->lock); rc = msm_isp_cfg_stats_stream(vfe_dev, arg); + mutex_unlock(&vfe_dev->buf_mgr->lock); mutex_unlock(&vfe_dev->core_mutex); break; case VIDIOC_MSM_ISP_UPDATE_STATS_STREAM: diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 623622e295dd8ca1e2151783ac2a5210b603a08a..aa5dcce45b764b43c8c3b5fd7dd7978a296ce283 100755 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1480,6 +1480,11 @@ static int ion_sync_for_device(struct ion_client *client, int fd) } buffer = dmabuf->priv; + if (buffer->flags & ION_FLAG_SECURE) { + pr_err("%s: cannot sync a secure dmabuf\n", __func__); + dma_buf_put(dmabuf); + return -EINVAL; + } dma_sync_sg_for_device(NULL, buffer->sg_table->sgl, buffer->sg_table->nents, DMA_BIDIRECTIONAL); dma_buf_put(dmabuf); diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c index 8e10e0cddd74fb1a54ce9e8804eeeb4a684d140f..82882625465720177ccd155b31a4fe4ed988af5f 100644 --- a/drivers/staging/android/ion/msm/msm_ion.c +++ b/drivers/staging/android/ion/msm/msm_ion.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2014,2016,2018 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 @@ -722,11 +722,11 @@ long msm_ion_custom_ioctl(struct ion_client *client, down_read(&mm->mmap_sem); - start = (unsigned long) data.flush_data.vaddr; - end = (unsigned long) data.flush_data.vaddr - + data.flush_data.length; + start = (unsigned long)data.flush_data.vaddr + + data.flush_data.offset; + end = start + data.flush_data.length; - if (start && check_vaddr_bounds(start, end)) { + if (check_vaddr_bounds(start, end)) { pr_err("%s: virtual address %p is out of bounds\n", __func__, data.flush_data.vaddr); ret = -EINVAL; diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h index 821eae8cbd8cf131bdbcc41dd46de828e700269a..0af57a99c6a1b7926710b91306623c6e392c6e0a 100644 --- a/include/crypto/internal/hash.h +++ b/include/crypto/internal/hash.h @@ -70,6 +70,14 @@ int ahash_register_instance(struct crypto_template *tmpl, struct ahash_instance *inst); void ahash_free_instance(struct crypto_instance *inst); +int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, + unsigned int keylen); + +static inline bool crypto_shash_alg_has_setkey(struct shash_alg *alg) +{ + return alg->setkey != shash_no_setkey; +} + int crypto_init_ahash_spawn(struct crypto_ahash_spawn *spawn, struct hash_alg_common *alg, struct crypto_instance *inst); diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c index b1c885297113f7d42a6f300f396dd77b2543e6e9..ffbb03e34d20ca9e60f521f567509222f8de83eb 100644 --- a/lib/asn1_decoder.c +++ b/lib/asn1_decoder.c @@ -276,6 +276,9 @@ next_op: if (unlikely(len > datalen - dp)) goto data_overrun_error; } + } else { + if (unlikely(len > datalen - dp)) + goto data_overrun_error; } if (flags & FLAG_CONS) { @@ -302,38 +305,43 @@ next_op: /* Decide how to handle the operation */ switch (op) { - case ASN1_OP_MATCH_ANY_ACT: - case ASN1_OP_COND_MATCH_ANY_ACT: - ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); - if (ret < 0) - return ret; - goto skip_data; - - case ASN1_OP_MATCH_ACT: - case ASN1_OP_MATCH_ACT_OR_SKIP: - case ASN1_OP_COND_MATCH_ACT_OR_SKIP: - ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len); - if (ret < 0) - return ret; - goto skip_data; - case ASN1_OP_MATCH: case ASN1_OP_MATCH_OR_SKIP: + case ASN1_OP_MATCH_ACT: + case ASN1_OP_MATCH_ACT_OR_SKIP: case ASN1_OP_MATCH_ANY: + case ASN1_OP_MATCH_ANY_ACT: case ASN1_OP_COND_MATCH_OR_SKIP: + case ASN1_OP_COND_MATCH_ACT_OR_SKIP: case ASN1_OP_COND_MATCH_ANY: - skip_data: + case ASN1_OP_COND_MATCH_ANY_ACT: + if (!(flags & FLAG_CONS)) { if (flags & FLAG_INDEFINITE_LENGTH) { + size_t tmp = dp; + ret = asn1_find_indefinite_length( - data, datalen, &dp, &len, &errmsg); + data, datalen, &tmp, &len, &errmsg); if (ret < 0) goto error; - } else { - dp += len; } pr_debug("- LEAF: %zu\n", len); } + + if (op & ASN1_OP_MATCH__ACT) { + unsigned char act; + + if (op & ASN1_OP_MATCH__ANY) + act = machine[pc + 1]; + else + act = machine[pc + 2]; + ret = actions[act](context, hdr, tag, data + dp, len); + if (ret < 0) + return ret; + } + + if (!(flags & FLAG_CONS)) + dp += len; pc += asn1_op_lengths[op]; goto next_op; diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index b5cfba13bd3793f722f70fc76b5fd7a8ffe911f4..b3bd200f8b420cf15d8250035a88d92eb7d660a2 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -411,6 +411,16 @@ static void hidp_del_timer(struct hidp_session *session) del_timer(&session->timer); } +static void hidp_process_report(struct hidp_session *session, int type, + const u8 *data, unsigned int len, int intr) +{ + if (len > HID_MAX_BUFFER_SIZE) + len = HID_MAX_BUFFER_SIZE; + + memcpy(session->input_buf, data, len); + hid_input_report(session->hid, type, session->input_buf, len, intr); +} + static void hidp_process_handshake(struct hidp_session *session, unsigned char param) { @@ -483,7 +493,8 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb, hidp_input_report(session, skb); if (session->hid) - hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0); + hidp_process_report(session, HID_INPUT_REPORT, + skb->data, skb->len, 0); break; case HIDP_DATA_RTYPE_OTHER: @@ -565,7 +576,8 @@ static void hidp_recv_intr_frame(struct hidp_session *session, hidp_input_report(session, skb); if (session->hid) { - hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1); + hidp_process_report(session, HID_INPUT_REPORT, + skb->data, skb->len, 1); BT_DBG("report len %d", skb->len); } } else { diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h index 6162ce8606acc8206dbc3ce437425518aee8a8c2..5e2a5d54ad25aa003473b4d1c3c86799ad07dd9e 100644 --- a/net/bluetooth/hidp/hidp.h +++ b/net/bluetooth/hidp/hidp.h @@ -24,6 +24,7 @@ #define __HIDP_H #include <linux/types.h> +#include <linux/hid.h> #include <linux/kref.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/l2cap.h> @@ -177,6 +178,9 @@ struct hidp_session { /* Used in hidp_output_raw_report() */ int output_report_success; /* boolean */ + + /* temporary input buffer */ + u8 input_buf[HID_MAX_BUFFER_SIZE]; }; /* HIDP init defines */ diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index b304648a759a418dbb3bd9b3dfb5d695783ee2c3..3bc80c7fbf8581523052cdf6318f8520c3be789e 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -340,6 +340,9 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, rt->dst.dev->mtu); return -EMSGSIZE; } + if (length < sizeof(struct iphdr)) + return -EINVAL; + if (flags&MSG_PROBE) goto out; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 0c94b3bcf0559a11015236b7cb85227c4b5bbf62..1d165d5cb6b7e46cc98f941fe8661cfddc1be3cc 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1216,14 +1216,16 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, np->cork.tclass = tclass; if (rt->dst.flags & DST_XFRM_TUNNEL) mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? - rt->dst.dev->mtu : dst_mtu(&rt->dst); + ACCESS_ONCE(rt->dst.dev->mtu) : dst_mtu(&rt->dst); else mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? - rt->dst.dev->mtu : dst_mtu(rt->dst.path); + ACCESS_ONCE(rt->dst.dev->mtu) : dst_mtu(rt->dst.path); if (np->frag_size < mtu) { if (np->frag_size) mtu = np->frag_size; } + if (mtu < IPV6_MIN_MTU) + return -EINVAL; cork->fragsize = mtu; if (dst_allfrag(rt->dst.path)) cork->flags |= IPCORK_ALLFRAG; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index c9ccdd7564d51a654e2eec1cafc183f6c13c1d89..fd5ad12d8d5f0878778ea423313c9cad0df596f8 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -616,6 +616,8 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu); return -EMSGSIZE; } + if (length < sizeof(struct ipv6hdr)) + return -EINVAL; if (flags&MSG_PROBE) goto out; diff --git a/sound/soc/codecs/wcd_cpe_core.c b/sound/soc/codecs/wcd_cpe_core.c index d80abe0642b2dc84f344c3e66ce31c42eca14fa7..b47903706cb2629d7c042eb3bb08796cdc32e190 100644 --- a/sound/soc/codecs/wcd_cpe_core.c +++ b/sound/soc/codecs/wcd_cpe_core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2015, 2018 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 @@ -1630,6 +1630,7 @@ struct wcd_cpe_core *wcd_cpe_init(const char *img_fname, init_completion(&core->online_compl); init_waitqueue_head(&core->ssr_entry.offline_poll_wait); mutex_init(&core->ssr_lock); + mutex_init(&core->session_lock); core->cpe_users = 0; /* @@ -2592,6 +2593,7 @@ static struct cpe_lsm_session *wcd_cpe_alloc_lsm_session( * If this is the first session to be allocated, * only then register the afe service. */ + WCD_CPE_GRAB_LOCK(&core->session_lock, "session_lock"); if (!wcd_cpe_lsm_session_active()) afe_register_service = true; @@ -2603,6 +2605,7 @@ static struct cpe_lsm_session *wcd_cpe_alloc_lsm_session( dev_err(core->dev, "%s: max allowed sessions already allocated\n", __func__); + WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); return NULL; } @@ -2611,6 +2614,7 @@ static struct cpe_lsm_session *wcd_cpe_alloc_lsm_session( dev_err(core->dev, "%s: Failed to enable cpe, err = %d\n", __func__, ret); + WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); return NULL; } @@ -2657,6 +2661,8 @@ static struct cpe_lsm_session *wcd_cpe_alloc_lsm_session( init_completion(&session->cmd_comp); lsm_sessions[session_id] = session; + + WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); return session; err_afe_mode_cmd: @@ -2671,6 +2677,7 @@ err_ret: err_session_alloc: wcd_cpe_vote(core, false); + WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); return NULL; } @@ -3000,9 +3007,11 @@ static int wcd_cpe_dealloc_lsm_session(void *core_handle, struct wcd_cpe_core *core = core_handle; int ret = 0; + WCD_CPE_GRAB_LOCK(&core->session_lock, "session_lock"); if (!session) { dev_err(core->dev, "%s: Invalid lsm session\n", __func__); + WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); return -EINVAL; } @@ -3013,6 +3022,7 @@ static int wcd_cpe_dealloc_lsm_session(void *core_handle, "%s: Wrong session id %d max allowed = %d\n", __func__, session->id, WCD_CPE_LSM_MAX_SESSIONS); + WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); return -EINVAL; } @@ -3033,6 +3043,7 @@ static int wcd_cpe_dealloc_lsm_session(void *core_handle, "%s: Failed to un-vote cpe, err = %d\n", __func__, ret); + WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); return ret; } diff --git a/sound/soc/codecs/wcd_cpe_core.h b/sound/soc/codecs/wcd_cpe_core.h index 050b0296b4b09ee19f93b81e6e0058dc736c133e..4a8a28caf5f7e53a46fc1b07fb617e266499736d 100644 --- a/sound/soc/codecs/wcd_cpe_core.h +++ b/sound/soc/codecs/wcd_cpe_core.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015, 2018, 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 @@ -134,6 +134,9 @@ struct wcd_cpe_core { /* mutex to protect cpe ssr status variables */ struct mutex ssr_lock; + /* mutex to protect cpe session status variables */ + struct mutex session_lock; + /* Store the calibration data needed for cpe */ struct cal_type_data *cal_data[WCD_CPE_LSM_CAL_MAX];