aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStuart Scott <stuartscott@google.com>2017-06-07 16:26:03 -0700
committerStuart Scott <stuartscott@google.com>2017-06-07 23:28:12 +0000
commit5b0be8f02fecc35f2a71fa3d5dfd0eead8de7bea (patch)
treefbfe769b5f827a767649d6ebb728fdc8e6ed5072
parent5547b00553ad5f7c25006368244d524fb6e2f913 (diff)
parent5d70d641f4403b823310a29900b5ad264314a2ef (diff)
Merge android-msm-angler-3.10-nyc-mr2-security-next into android-msm-angler-3.10-nyc-mr2android-7.1.2_r0.26
August 2017.1 Bug: 62368622 Change-Id: I3df095e1732993310b28820c39435dd032f15f0e
-rw-r--r--drivers/crypto/msm/qcedev.c12
-rw-r--r--drivers/gpu/msm/kgsl.c2
-rw-r--r--drivers/misc/qcom/qdsp6v2/audio_utils_aio.c6
-rw-r--r--drivers/net/wireless/bcmdhd/bcmevent.c27
-rw-r--r--[-rwxr-xr-x]drivers/net/wireless/bcmdhd/include/proto/bcmeth.h1
-rw-r--r--drivers/platform/msm/ipa/ipa_rt.c6
-rw-r--r--drivers/usb/gadget/f_qc_rndis.c86
-rw-r--r--fs/f2fs/super.c26
-rw-r--r--fs/timerfd.c17
-rw-r--r--include/linux/f2fs_fs.h6
10 files changed, 153 insertions, 36 deletions
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index d3c99d1c581d..f8baf287d21f 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1722,6 +1722,12 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
err = qcedev_hash_final(&qcedev_areq, handle);
if (err)
return err;
+
+ if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
+ pr_err("Invalid sha_ctxt.diglen %d\n",
+ handle->sha_ctxt.diglen);
+ return -EINVAL;
+ }
qcedev_areq.sha_op_req.diglen = handle->sha_ctxt.diglen;
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
@@ -1750,6 +1756,12 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
err = qcedev_hash_final(&qcedev_areq, handle);
if (err)
return err;
+
+ if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
+ pr_err("Invalid sha_ctxt.diglen %d\n",
+ handle->sha_ctxt.diglen);
+ return -EINVAL;
+ }
qcedev_areq.sha_op_req.diglen = handle->sha_ctxt.diglen;
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index dbca5c79b8b1..350ad08fb53a 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2586,9 +2586,9 @@ long kgsl_ioctl_drawctxt_create(struct kgsl_device_private *dev_priv,
/* Commit the pointer to the context in context_idr */
write_lock(&device->context_lock);
idr_replace(&device->context_idr, context, context->id);
+ param->drawctxt_id = context->id;
write_unlock(&device->context_lock);
- param->drawctxt_id = context->id;
done:
mutex_unlock(&device->mutex);
return result;
diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c
index ce13118dccac..07de5a22b1ec 100644
--- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c
+++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c
@@ -831,6 +831,7 @@ static long audio_aio_process_event_req_compat(struct q6audio_aio *audio,
long rc;
struct msm_audio_event32 usr_evt_32;
struct msm_audio_event usr_evt;
+ memset(&usr_evt, 0, sizeof(struct msm_audio_event));
if (copy_from_user(&usr_evt_32, arg,
sizeof(struct msm_audio_event32))) {
@@ -840,6 +841,11 @@ static long audio_aio_process_event_req_compat(struct q6audio_aio *audio,
usr_evt.timeout_ms = usr_evt_32.timeout_ms;
rc = audio_aio_process_event_req_common(audio, &usr_evt);
+ if (rc < 0) {
+ pr_err("%s: audio process event failed, rc = %ld",
+ __func__, rc);
+ return rc;
+ }
usr_evt_32.event_type = usr_evt.event_type;
switch (usr_evt_32.event_type) {
diff --git a/drivers/net/wireless/bcmdhd/bcmevent.c b/drivers/net/wireless/bcmdhd/bcmevent.c
index b85f111bce18..7ed9739c0edd 100644
--- a/drivers/net/wireless/bcmdhd/bcmevent.c
+++ b/drivers/net/wireless/bcmdhd/bcmevent.c
@@ -209,12 +209,14 @@ int
is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype,
bcm_event_msg_u_t *out_event)
{
- uint16 len;
+ uint16 evlen;
uint16 subtype;
uint16 usr_subtype;
bcm_event_t *bcm_event;
uint8 *pktend;
+ uint8 *evend;
int err = BCME_OK;
+ uint32 data_len;
pktend = (uint8 *)pktdata + pktlen;
bcm_event = (bcm_event_t *)pktdata;
@@ -235,8 +237,9 @@ is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype,
}
/* check length in bcmeth_hdr */
- len = ntoh16_ua((void *)&bcm_event->bcm_hdr.length);
- if (((uint8 *)&bcm_event->bcm_hdr.version + len) > pktend) {
+ evlen = ntoh16_ua((void *)&bcm_event->bcm_hdr.length);
+ evend = (uint8 *)&bcm_event->bcm_hdr.version + evlen;
+ if (evend != pktend) {
err = BCME_BADLEN;
goto done;
}
@@ -257,13 +260,15 @@ is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype,
usr_subtype = ntoh16_ua((void *)&bcm_event->bcm_hdr.usr_subtype);
switch (usr_subtype) {
case BCMILCP_BCM_SUBTYPE_EVENT:
- if (pktlen < sizeof(bcm_event_t)) {
+ if ((pktlen < sizeof(bcm_event_t)) ||
+ (evend < ((uint8 *)bcm_event + sizeof(bcm_event_t)))) {
err = BCME_BADLEN;
goto done;
}
- len = sizeof(bcm_event_t) + ntoh32_ua((void *)&bcm_event->event.datalen);
- if ((uint8 *)pktdata + len > pktend) {
+ data_len = ntoh32_ua((void *)&bcm_event->event.datalen);
+ if ((sizeof(bcm_event_t) + data_len +
+ BCMILCP_BCM_SUBTYPE_EVENT_DATA_PAD) != pktlen) {
err = BCME_BADLEN;
goto done;
}
@@ -280,14 +285,16 @@ is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype,
break;
case BCMILCP_BCM_SUBTYPE_DNGLEVENT:
- if (pktlen < sizeof(bcm_dngl_event_t)) {
+ if (pktlen < sizeof(bcm_dngl_event_t) ||
+ (evend < ((uint8 *)bcm_event + sizeof(bcm_dngl_event_t)))) {
err = BCME_BADLEN;
goto done;
}
- len = sizeof(bcm_dngl_event_t) +
- ntoh16_ua((void *)&((bcm_dngl_event_t *)pktdata)->dngl_event.datalen);
- if ((uint8 *)pktdata + len > pktend) {
+ data_len = ntoh16_ua((void *)&((bcm_dngl_event_t *)pktdata)
+ ->dngl_event.datalen);
+ if ((sizeof(bcm_dngl_event_t) + data_len +
+ BCMILCP_BCM_SUBTYPE_EVENT_DATA_PAD) != pktlen) {
err = BCME_BADLEN;
goto done;
}
diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h b/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h
index 41c1b57443c7..756f594bc61d 100755..100644
--- a/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h
+++ b/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h
@@ -93,6 +93,7 @@
#define BCMILCP_BCM_SUBTYPE_DNGLEVENT 5
#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8
#define BCMILCP_BCM_SUBTYPEHDR_VERSION 0
+#define BCMILCP_BCM_SUBTYPE_EVENT_DATA_PAD 2
/* These fields are stored in network order */
typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr
diff --git a/drivers/platform/msm/ipa/ipa_rt.c b/drivers/platform/msm/ipa/ipa_rt.c
index 47767cdafa70..81c6331da8a5 100644
--- a/drivers/platform/msm/ipa/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_rt.c
@@ -1289,6 +1289,10 @@ int ipa_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup)
mutex_lock(&ipa_ctx->lock);
entry = __ipa_find_rt_tbl(lookup->ip, lookup->name);
if (entry && entry->cookie == IPA_COOKIE) {
+ if (entry->ref_cnt == ((u32)~0U)) {
+ IPAERR("fail: ref count crossed limit\n");
+ goto ret;
+ }
entry->ref_cnt++;
lookup->hdl = entry->id;
@@ -1298,6 +1302,8 @@ int ipa_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup)
result = 0;
}
+
+ret:
mutex_unlock(&ipa_ctx->lock);
return result;
diff --git a/drivers/usb/gadget/f_qc_rndis.c b/drivers/usb/gadget/f_qc_rndis.c
index 631d5261a905..4d51bf961a43 100644
--- a/drivers/usb/gadget/f_qc_rndis.c
+++ b/drivers/usb/gadget/f_qc_rndis.c
@@ -6,7 +6,7 @@
* Copyright (C) 2008 Nokia Corporation
* Copyright (C) 2009 Samsung Electronics
* Author: Michal Nazarewicz (mina86@mina86.com)
- * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017, 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
@@ -1279,8 +1279,6 @@ rndis_qc_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
rndis->port.func.suspend = rndis_qc_suspend;
rndis->port.func.resume = rndis_qc_resume;
- _rndis_qc = rndis;
-
if (rndis->xport == USB_GADGET_XPORT_BAM2BAM_IPA) {
status = rndis_ipa_init(&rndis_ipa_params);
if (status) {
@@ -1296,6 +1294,8 @@ rndis_qc_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
goto fail;
}
+ _rndis_qc = rndis;
+
return 0;
fail:
@@ -1307,74 +1307,115 @@ fail:
static int rndis_qc_open_dev(struct inode *ip, struct file *fp)
{
+ int ret = 0;
+ unsigned long flags;
pr_info("Open rndis QC driver\n");
+ spin_lock_irqsave(&rndis_lock, flags);
if (!_rndis_qc) {
pr_err("rndis_qc_dev not created yet\n");
- return -ENODEV;
+ ret = -ENODEV;
+ goto fail;
}
if (rndis_qc_lock(&_rndis_qc->open_excl)) {
pr_err("Already opened\n");
- return -EBUSY;
+ ret = -EBUSY;
+ goto fail;
}
fp->private_data = _rndis_qc;
- pr_info("rndis QC file opened\n");
+fail:
+ spin_unlock_irqrestore(&rndis_lock, flags);
- return 0;
+ if (!ret)
+ pr_info("rndis QC file opened\n");
+
+ return ret;
}
static int rndis_qc_release_dev(struct inode *ip, struct file *fp)
{
- struct f_rndis_qc *rndis = fp->private_data;
-
+ unsigned long flags;
pr_info("Close rndis QC file\n");
- rndis_qc_unlock(&rndis->open_excl);
+ spin_lock_irqsave(&rndis_lock, flags);
+
+ if (!_rndis_qc) {
+ pr_err("rndis_qc_dev not present\n");
+ spin_unlock_irqrestore(&rndis_lock, flags);
+ return -ENODEV;
+ }
+ rndis_qc_unlock(&_rndis_qc->open_excl);
+ spin_unlock_irqrestore(&rndis_lock, flags);
return 0;
}
static long rndis_qc_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
{
- struct f_rndis_qc *rndis = fp->private_data;
+ u8 qc_max_pkt_per_xfer = 0;
+ u32 qc_max_pkt_size = 0;
int ret = 0;
+ unsigned long flags;
- pr_info("Received command %d\n", cmd);
+ spin_lock_irqsave(&rndis_lock, flags);
+ if (!_rndis_qc) {
+ pr_err("rndis_qc_dev not present\n");
+ ret = -ENODEV;
+ goto fail;
+ }
- if (rndis_qc_lock(&rndis->ioctl_excl))
- return -EBUSY;
+ qc_max_pkt_per_xfer = _rndis_qc->ul_max_pkt_per_xfer;
+ qc_max_pkt_size = _rndis_qc->max_pkt_size;
+
+ if (rndis_qc_lock(&_rndis_qc->ioctl_excl)) {
+ ret = -EBUSY;
+ goto fail;
+ }
+
+ spin_unlock_irqrestore(&rndis_lock, flags);
+
+ pr_info("Received command %d\n", cmd);
switch (cmd) {
case RNDIS_QC_GET_MAX_PKT_PER_XFER:
ret = copy_to_user((void __user *)arg,
- &rndis->ul_max_pkt_per_xfer,
- sizeof(rndis->ul_max_pkt_per_xfer));
+ &qc_max_pkt_per_xfer,
+ sizeof(qc_max_pkt_per_xfer));
if (ret) {
pr_err("copying to user space failed\n");
ret = -EFAULT;
}
pr_info("Sent UL max packets per xfer %d\n",
- rndis->ul_max_pkt_per_xfer);
+ qc_max_pkt_per_xfer);
break;
case RNDIS_QC_GET_MAX_PKT_SIZE:
ret = copy_to_user((void __user *)arg,
- &rndis->max_pkt_size,
- sizeof(rndis->max_pkt_size));
+ &qc_max_pkt_size,
+ sizeof(qc_max_pkt_size));
if (ret) {
pr_err("copying to user space failed\n");
ret = -EFAULT;
}
pr_debug("Sent max packet size %d\n",
- rndis->max_pkt_size);
+ qc_max_pkt_size);
break;
default:
pr_err("Unsupported IOCTL\n");
ret = -EINVAL;
}
- rndis_qc_unlock(&rndis->ioctl_excl);
+ spin_lock_irqsave(&rndis_lock, flags);
+
+ if (!_rndis_qc) {
+ pr_err("rndis_qc_dev not present\n");
+ ret = -ENODEV;
+ goto fail;
+ }
+ rndis_qc_unlock(&_rndis_qc->ioctl_excl);
+fail:
+ spin_unlock_irqrestore(&rndis_lock, flags);
return ret;
}
@@ -1397,10 +1438,11 @@ static int rndis_qc_init(void)
pr_info("initialize rndis QC instance\n");
+ spin_lock_init(&rndis_lock);
+
ret = misc_register(&rndis_qc_device);
if (ret)
pr_err("rndis QC driver failed to register\n");
- spin_lock_init(&rndis_lock);
ret = bam_data_setup(USB_FUNC_RNDIS, RNDIS_QC_NO_PORTS);
if (ret) {
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 03ab8b830940..787d51b7b30d 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -434,6 +434,14 @@ static int sanity_check_raw_super(struct super_block *sb,
f2fs_msg(sb, KERN_INFO, "Invalid log sectors per block");
return 1;
}
+
+ if (le32_to_cpu(raw_super->segment_count) > F2FS_MAX_SEGMENT) {
+ f2fs_msg(sb, KERN_INFO,
+ "Invalid segment count (%u)",
+ le32_to_cpu(raw_super->segment_count));
+ return 1;
+ }
+
return 0;
}
@@ -442,6 +450,8 @@ static int sanity_check_ckpt(struct f2fs_sb_info *sbi)
unsigned int total, fsmeta;
struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+ unsigned int main_segs, blocks_per_seg;
+ int i;
total = le32_to_cpu(raw_super->segment_count);
fsmeta = le32_to_cpu(raw_super->segment_count_ckpt);
@@ -453,6 +463,22 @@ static int sanity_check_ckpt(struct f2fs_sb_info *sbi)
if (fsmeta >= total)
return 1;
+ main_segs = le32_to_cpu(sbi->raw_super->segment_count_main);
+ blocks_per_seg = sbi->blocks_per_seg;
+
+ for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) {
+ if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
+ le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg) {
+ return 1;
+ }
+ }
+ for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
+ if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
+ le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg) {
+ return 1;
+ }
+ }
+
if (is_set_ckpt_flags(ckpt, CP_ERROR_FLAG)) {
f2fs_msg(sbi->sb, KERN_ERR, "A bug case: need to run fsck");
return 1;
diff --git a/fs/timerfd.c b/fs/timerfd.c
index 0013142c0475..0db5b6c1b10d 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -39,6 +39,7 @@ struct timerfd_ctx {
int clockid;
struct rcu_head rcu;
struct list_head clist;
+ spinlock_t cancel_lock;
bool might_cancel;
};
@@ -111,7 +112,7 @@ void timerfd_clock_was_set(void)
rcu_read_unlock();
}
-static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
+static void __timerfd_remove_cancel(struct timerfd_ctx *ctx)
{
if (ctx->might_cancel) {
ctx->might_cancel = false;
@@ -121,6 +122,13 @@ static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
}
}
+static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
+{
+ spin_lock(&ctx->cancel_lock);
+ __timerfd_remove_cancel(ctx);
+ spin_unlock(&ctx->cancel_lock);
+}
+
static bool timerfd_canceled(struct timerfd_ctx *ctx)
{
if (!ctx->might_cancel || ctx->moffs.tv64 != KTIME_MAX)
@@ -131,6 +139,7 @@ static bool timerfd_canceled(struct timerfd_ctx *ctx)
static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
{
+ spin_lock(&ctx->cancel_lock);
if ((ctx->clockid == CLOCK_REALTIME ||
ctx->clockid == CLOCK_REALTIME_ALARM) &&
(flags & TFD_TIMER_ABSTIME) && (flags & TFD_TIMER_CANCEL_ON_SET)) {
@@ -140,9 +149,10 @@ static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
list_add_rcu(&ctx->clist, &cancel_list);
spin_unlock(&cancel_lock);
}
- } else if (ctx->might_cancel) {
- timerfd_remove_cancel(ctx);
+ } else {
+ __timerfd_remove_cancel(ctx);
}
+ spin_unlock(&ctx->cancel_lock);
}
static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)
@@ -326,6 +336,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
return -ENOMEM;
init_waitqueue_head(&ctx->wqh);
+ spin_lock_init(&ctx->cancel_lock);
ctx->clockid = clockid;
if (isalarm(ctx))
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index df6fab82f87e..fdb6cb9fe0bb 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -235,6 +235,12 @@ struct f2fs_nat_block {
#define SIT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_sit_entry))
/*
+ * F2FS uses 4 bytes to represent block address. As a result, supported size of
+ * disk is 16 TB and it equals to 16 * 1024 * 1024 / 2 segments.
+ */
+#define F2FS_MAX_SEGMENT ((16 * 1024 * 1024) / 2)
+
+/*
* Note that f2fs_sit_entry->vblocks has the following bit-field information.
* [15:10] : allocation type such as CURSEG_XXXX_TYPE
* [9:0] : valid block count