diff options
author | Stuart Scott <stuartscott@google.com> | 2017-06-07 16:36:17 -0700 |
---|---|---|
committer | Stuart Scott <stuartscott@google.com> | 2017-06-07 23:41:35 +0000 |
commit | d79f9df7e45efb22c20ade8d577449184c1602e3 (patch) | |
tree | 7c5e2b832f201dc345c7d25edd99ee63afb969e6 | |
parent | 038989083d8519bc87255ab798e86e68c8a066bc (diff) | |
parent | a793531b751d8c3609e2bf1a5dc2c0f10e003632 (diff) |
Merge android-msm-bullhead-3.10-nyc-mr2-security-next into android-msm-bullhead-3.10-nyc-mr2android-7.1.2_r0.27
August 2017.1
Bug: 62369032
Change-Id: Ic6ba356f3508dac66898e9e0a1fd7b809d22de6a
-rw-r--r-- | drivers/crypto/msm/qcedev.c | 12 | ||||
-rw-r--r-- | drivers/gpu/msm/kgsl.c | 2 | ||||
-rw-r--r-- | drivers/misc/qcom/qdsp6v2/audio_utils_aio.c | 6 | ||||
-rw-r--r-- | drivers/platform/msm/ipa/ipa_rt.c | 6 | ||||
-rw-r--r-- | drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 10 | ||||
-rw-r--r-- | drivers/usb/gadget/f_qc_rndis.c | 86 | ||||
-rw-r--r-- | fs/f2fs/super.c | 26 | ||||
-rw-r--r-- | fs/timerfd.c | 17 | ||||
-rw-r--r-- | include/linux/f2fs_fs.h | 6 |
9 files changed, 144 insertions, 27 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/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/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c index 2dec872e191b..c15392878444 100644 --- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -850,6 +850,7 @@ wlan_hdd_extscan_config_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_ [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW] = { .type = NLA_S32 }, [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH] = { .type = NLA_S32 }, [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE] = { .type = NLA_U32 }, }; static const struct nla_policy @@ -14475,9 +14476,16 @@ static int __wlan_hdd_change_station(struct wiphy *wiphy, StaParams.supported_oper_classes_len = params->supported_oper_classes_len; + if (params->ext_capab_len > sizeof(StaParams.extn_capability)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "received extn capabilities: %d, reset to max supported", + params->ext_capab_len); + params->ext_capab_len = sizeof(StaParams.extn_capability); + } + if (0 != params->ext_capab_len) vos_mem_copy(StaParams.extn_capability, params->ext_capab, - sizeof(StaParams.extn_capability)); + params->ext_capab_len); if (NULL != params->ht_capa) { StaParams.htcap_present = 1; 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 |